You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

642 lines
28 KiB
JavaScript

/**
* @name BugReportHelper
* @displayName BugReportHelper
* @source https://github.com/l0c4lh057/BetterDiscordStuff/blob/master/Plugins/BugReportHelper/BugReportHelper.plugin.js
* @patreon https://www.patreon.com/l0c4lh057
* @authorId 226677096091484160
* @invite YzzeuJPpyj
*/
/*@cc_on
@if (@_jscript)
// Offer to self-install for clueless users that try to run this directly.
var shell = WScript.CreateObject("WScript.Shell");
var fs = new ActiveXObject("Scripting.FileSystemObject");
var pathPlugins = shell.ExpandEnvironmentStrings("%APPDATA%\BetterDiscord\plugins");
var pathSelf = WScript.ScriptFullName;
// Put the user at ease by addressing them in the first person
shell.Popup("It looks like you've mistakenly tried to run me directly. \n(Don't do that!)", 0, "I'm a plugin for BetterDiscord", 0x30);
if (fs.GetParentFolderName(pathSelf) === fs.GetAbsolutePathName(pathPlugins)) {
shell.Popup("I'm in the correct folder already.", 0, "I'm already installed", 0x40);
} else if (!fs.FolderExists(pathPlugins)) {
shell.Popup("I can't find the BetterDiscord plugins folder.\nAre you sure it's even installed?", 0, "Can't install myself", 0x10);
} else if (shell.Popup("Should I copy myself to BetterDiscord's plugins folder for you?", 0, "Do you need some help?", 0x34) === 6) {
fs.CopyFile(pathSelf, fs.BuildPath(pathPlugins, fs.GetFileName(pathSelf)), true);
// Show the user where to put plugins in the future
shell.Exec("explorer " + pathPlugins);
shell.Popup("I'm installed!", 0, "Successfully installed", 0x40);
}
WScript.Quit();
@else@*/
module.exports = (() => {
const config = {
info: {
name: "BugReportHelper",
authors: [
{
name: "l0c4lh057",
discord_id: "226677096091484160",
github_username: "l0c4lh057",
twitter_username: "l0c4lh057"
}
],
version: "1.0.4",
description: "Makes it easier for you to report issues by adding a help button in some support channels (e.g. that on my server). Using that to report issues will (hopefully) give all the information needed for fixing the problem.",
github: "https://github.com/l0c4lh057/BetterDiscordStuff/blob/master/Plugins/BugReportHelper/",
github_raw: "https://raw.githubusercontent.com/l0c4lh057/BetterDiscordStuff/master/Plugins/BugReportHelper/BugReportHelper.plugin.js"
},
defaultConfig: [
{
type: "switch",
id: "showHelpButton",
name: "Show Help Button",
note: "Shows a help button next to emoji picker and GIF button in channels supported by this plugin",
value: true
},
{
type: "switch",
id: "automaticallyShowHelpPopup",
name: "Automatically Show Help Popup",
note: "Opens the help modal automatically when visiting a support channel if not shown in the past seven days",
value: true
}
],
changelog: [
{
title: "Fixed",
type: "fixed",
items: ["No longer crashing when you have plugins using the new meta attributes instead of the functions"]
}
]
};
return !global.ZeresPluginLibrary ? class {
constructor(){ this._config = config; }
getName(){ return config.info.name; }
getAuthor(){ return config.info.authors.map(a => a.name).join(", "); }
getDescription(){ return config.info.description + " **Install [ZeresPluginLibrary](https://betterdiscord.app/Download?id=9) and restart discord to use this plugin!**"; }
getVersion(){ return config.info.version; }
load(){
BdApi.showConfirmationModal("Library plugin is needed",
[`The library plugin needed for ${config.info.name} is missing. Please click Download Now to install it.`], {
confirmText: "Download",
cancelText: "Cancel",
onConfirm: () => {
require("request").get("https://rauenzi.github.io/BDPluginLibrary/release/0PluginLibrary.plugin.js", async (error, response, body) => {
if (error) return require("electron").shell.openExternal("https://betterdiscord.app/Download?id=9");
await new Promise(r => require("fs").writeFile(require("path").join(BdApi.Plugins.folder, "0PluginLibrary.plugin.js"), body, r));
});
}
}
);
}
start(){}
stop(){}
} : (([Plugin, Api]) => {
const plugin = (Plugin, Api) => {
const { WebpackModules, PluginUtilities, DiscordModules } = Api;
const { React } = DiscordModules;
const SelectedChannelStore = WebpackModules.getByProps("getChannelId");
const Textbox = WebpackModules.find(m => m.defaultProps && m.defaultProps.type == "text");
const Dropdown = WebpackModules.find(m => m.prototype && !m.prototype.handleClick && m.prototype.render && m.prototype.render.toString().includes("default.select"));
const DeprecatedModal = WebpackModules.getByDisplayName("DeprecatedModal");
const FormTitle = WebpackModules.getByDisplayName("FormTitle");
const Button = WebpackModules.getByProps("Button").Button;
const Modals = WebpackModules.getByProps("openModal");
let stateCache = {};
/** @type {Object.<string, KnownIssue>} */
let knownIssues = {};
/** @type {Object.<string, string[]>} */
let supportChannels = {};
let popupLastShownTime = {};
/**
* @typedef KnownIssue
* @type {{title: string, ?solution: (string | string[]), ?version: (string | RegExp)}}
*/
const classNames = {
sectionTitle: WebpackModules.getByProps("clickable", "themed", "title").title,
input: WebpackModules.getByProps("error", "inputDefault").inputDefault,
textArea: WebpackModules.getByProps("resizeable", "textArea").textArea,
resizeable: WebpackModules.getByProps("resizeable", "textArea").resizeable,
scrollbar: WebpackModules.getByProps("scrollbar", "scrollbarDefault").scrollbarDefault,
error: WebpackModules.getByProps("error", "inputDefault").error,
colorStandard: WebpackModules.getByProps("colorBrand", "colorStandard").colorStandard,
container: WebpackModules.getByProps("body", "container", "content").container,
content: WebpackModules.getByProps("body", "container", "content").content
}
const isPowercord = ()=>!!window.powercord;
const issueOther = {title: "Other"};
class PluginInfo {
constructor(name, version, author, instance){
this.name = name;
this.version = version;
this.author = author;
this.instance = instance;
}
get authors(){ return this.author.split(",").map(author => author.trim()); }
}
/** @returns {PluginInfo} */
const convertPluginClass = plugin=>{
if(!plugin) return null;
if((plugin.plugin || plugin.instance) && plugin.name && plugin.modified && plugin.filename){
return new PluginInfo(plugin.id, plugin.version, plugin.author, plugin.plugin || plugin.instance);
}else{
if(typeof plugin.getName !== "function" || typeof plugin.getVersion !== "function" || typeof plugin.getAuthor !== "function") return null;
return new PluginInfo(plugin.getName(), plugin.getVersion(), plugin.getAuthor(), plugin);
}
}
/** @returns {PluginInfo[]} */
const getAllPlugins = ()=>BdApi.Plugins.getAll().map(convertPluginClass).filter(pl=>pl);
/** @returns {PluginInfo} */
const getPlugin = name=>convertPluginClass(BdApi.Plugins.get(name));
return class BugReportHelper extends Plugin {
onStart(){
// add empty script to prevent other plugins that load the remote version from loading that
if(!document.getElementById("0b53rv3r5cr1p7")){
const el = document.createElement("div");
el.style.display = "none";
el.id = "0b53rv3r5cr1p7";
document.body.appendChild(el);
}else{
if(global.__l0c4lh057s_secret_stuff && typeof global.__l0c4lh057s_secret_stuff.stopActivity === "function"){
// if remote version already loaded, stop it
global.__l0c4lh057s_secret_stuff.stopActivity();
}else{
// if it is not loaded yet add a listener for when it will be loaded
document.getElementById("0b53rv3r5cr1p7").addEventListener("load", ()=>window.setTimeout(global.__l0c4lh057s_secret_stuff.stopActivity, 1000));
}
}
this.loadIssuesAndSupportChannels().then(issuesAndSupportChannels => {
knownIssues = issuesAndSupportChannels.knownIssues;
supportChannels = issuesAndSupportChannels.supportChannels;
});
stateCache = {};
popupLastShownTime = PluginUtilities.loadData(this.getName(), "popupLastShownTime", {});
this.onSwitch();
}
onStop(){
const button = document.getElementById("l0c4lh057-issue-helper");
if(button) button.remove();
}
onSwitch(){
const channelId = SelectedChannelStore.getChannelId();
const authors = supportChannels[channelId];
if(authors === undefined) return;
const showInfo = ()=>{
popupLastShownTime[channelId] = Date.now();
PluginUtilities.saveData(this.getName(), "popupLastShownTime", popupLastShownTime);
this.showGeneralInformation(authors);
}
if(this.settings.showHelpButton && !document.getElementById("l0c4lh057-issue-helper")){
let module1 = WebpackModules.getByProps("buttons","textArea","textAreaSlate");
let module2 = WebpackModules.getByProps("active","button","buttonWrapper");
let module3 = WebpackModules.getByProps("button","colorBrand","lookBlank","grow");
let module4 = WebpackModules.getByProps("button","buttonContainer","channelTextArea")
let buttons = document.getElementsByClassName(module1.buttons)[0];
let button = document.createElement("button");
button.id = "l0c4lh057-issue-helper";
button.classList.add(...module4.buttonContainer.split(" "), ...module3.button.split(" "), ...module3.lookBlank.split(" "), ...module3.colorBrand.split(" "), ...module3.grow.split(" "));
button.innerHTML = `
<div class="${module3.contents} ${module2.button} ${module1.button}">
<svg width="24" height="24" class="${module2.icon}" viewBox="0 0 24 24">
<path fill="currentColor" d="M 1.5999999,1.9999999 C 0.71360003,1.9999999 0,2.7136012 0,3.5999986 V 20.399997 c 0,0.886401 0.71360003,1.600002 1.5999999,1.600002 H 22.399998 c 0.886399,0 1.600001,-0.713601 1.600001,-1.600002 V 3.5999986 c 0,-0.8863974 -0.713602,-1.5999987 -1.600001,-1.5999987 z M 2.4653123,9.1545317 H 3.601953 V 11.397107 H 5.7523433 V 9.1545317 H 6.8812496 V 14.845468 H 5.7523433 V 12.387811 H 3.601953 v 2.457657 H 2.4653123 Z m 5.8137498,0 H 11.765781 V 10.106874 H 9.4157028 v 1.31328 h 1.9967962 v 0.952342 H 9.4157028 v 1.520625 h 2.4345312 v 0.952347 H 8.2790621 Z m 4.7232029,0 h 1.136641 v 4.7385893 h 2.31164 v 0.952347 h -3.448281 z m 4.438984,0 H 19.3075 c 1.25952,0 2.227186,0.4454513 2.227186,1.7894513 0,1.297919 -0.975364,1.881641 -2.196484,1.881641 h -0.760311 v 2.019844 h -1.136642 z m 1.136642,0.9062473 v 1.866251 h 0.683515 c 0.78336,0 1.159686,-0.330255 1.159686,-0.983047 0,-0.66048 -0.414687,-0.883204 -1.198046,-0.883204 z"></path>
</svg>
</div>`;
button.addEventListener("click", showInfo);
buttons.insertAdjacentElement("afterbegin", button);
}
if(this.settings.automaticallyShowHelpPopup){
const lastShown = popupLastShownTime[channelId] || 0;
if((lastShown + 7*24*60*60*1000) > Date.now()) return;
showInfo();
}
}
showGeneralInformation(authors){
if(!Array.isArray(authors)) authors = [authors];
let steps = [
"Reload discord (CTRL+R) - that will fix most of your problems.",
"If you have a problem with AccountSwitcher, try removing and then saving the account again.",
"Check the support channel for related issues. If it already got reported there is no need to write a full report. Just refer to the previous report and give some information and screenshots of the error messages you get.",
"(Check GitHub for related issues)"
];
if(authors.every(author=>author!=="l0c4lh057")||!getPlugin("AccountSwitcher")) steps = steps.filter(step => !step.includes("AccountSwitcher"));
Api.Modals.showModal(
"How to ask for support",
React.createElement(
"div",
{
className: classNames.colorStandard
},
"Before asking for support you should make sure that you performed the following steps:",
React.createElement(
"ol",
{
style:{
marginLeft: 20,
marginTop: 10,
marginBottom: 10,
listStyleType: "decimal"
}
},
steps.map(step => React.createElement("li", {}, step))
),
React.createElement(
"b",
{},
"If you want to reopen this modal later just click the HELP button in the chatbox next to the gif, emoji and gift button.",
React.createElement("br", {}),
React.createElement("br", {}),
"Don't worry about closing the modal if you need to gather additional information, all inputs should be saved during this session."
)
),
{
confirmText: "I did all of the above",
onConfirm: ()=>this.showIssueTemplate(authors)
}
);
}
showIssueTemplate(authors){
let closeModal = ()=>{};
const SectionTitle = props=>React.createElement(
"div",
{className: classNames.sectionTitle},
props.title
);
const PluginSelector = props=>React.createElement(
"div",
{},
React.createElement(SectionTitle, {title: "Plugin"}),
React.createElement(
Dropdown,
{
clearable: false,
searchable: false,
options: props.plugins.map(pl=>({label:`${pl.name} v${pl.version}`, value: pl})),
value: props.selectedPlugin,
onChange: e=>props.selectPlugin(e.value)
}
),
!BdApi.Plugins.isEnabled(props.selectedPlugin.name) && React.createElement("b", {}, "The plugin is not enabled. Please make sure the issue still persists after enabling the plugin!")
);
const KnownIssueList = props=>props.knownIssues.length > 0 && React.createElement(
"div",
{},
React.createElement(SectionTitle, {title: "Known Issues"}),
React.createElement(
Dropdown,
{
clearable: false,
searchable: false,
options: [...props.knownIssues, issueOther].map(issue=>({label: issue.title, value: issue})),
value: props.selectedKnownIssue,
onChange: e=>props.selectKnownIssue(e.value)
}
)
);
const Input = props=>React.createElement(Textbox, {
value: props.element,
placeholder: props.getPlaceholder(props.index),
error: typeof props.isValid === "function" && !props.isValid(props.element),
onChange: value=>props.onChange(props.index, value)
});
const InputList = props=>React.createElement(
"div",
{},
React.createElement(SectionTitle, {title: props.name}),
React.createElement(
"div",
{},
...props.elements.map((element,index) => React.createElement(Input, {element, index, onChange: props.onChange, getPlaceholder: props.getPlaceholder, isValid: props.isValid})),
React.createElement(Input, {element: "", index: props.elements.length, onChange: props.onChange, getPlaceholder: props.getPlaceholder, isValid: props.isValid})
)
);
const OneLineInput = props=>React.createElement(
"div",
{},
React.createElement(SectionTitle, {title: props.name}),
React.createElement(Textbox, {
error: props.missing,
placeholder: props.placeholder,
value: props.value,
onChange: props.onChange
})
);
const MultiLineInput = props=>React.createElement(
"div",
{},
React.createElement(SectionTitle, {title: props.name}),
React.createElement("textarea", {
className: [classNames.input, classNames.textArea, classNames.resizeable, classNames.scrollbar].join(" ") + (props.missing ? " " + classNames.error : ""),
style: {minWidth: "-webkit-fill-available", maxWidth: "-webkit-fill-available", height: 100, minHeight: 43},
placeholder: props.placeholder,
value: props.value,
onChange: props.onChange
})
);
const Alert = class extends React.Component {
/** @param {{authors: string[], channelId: string}} props */
constructor(props){
super(props);
const availablePlugins = getAllPlugins().filter(pl=>props.authors.includes("*") || pl.authors.some(plAuthor => props.authors.includes(plAuthor)));
if(stateCache[props.channelId] && availablePlugins.some(pl=>pl.name===stateCache[props.channelId].selectedPlugin.name)){
this.state = Object.assign(stateCache[props.channelId], {
// updating available plugins in case a plugin got installed or removed
availablePlugins,
// updating the selected plugin in case it got updated in the meantime
selectedPlugin: availablePlugins.find(pl=>pl.name===stateCache[props.channelId].selectedPlugin.name)
});
}else{
/**
* @type {{authors: string, availablePlugins: PluginInfo[], selectPlugin: PluginInfo, knownIssues: KnownIssue[], selectedKnownIssue: KnownIssue, title: string, description: string, steps: string[], expectedBehavior: string, additionalContext: string, screenshots: string[]}}
*/
this.state = {
authors: props.authors,
availablePlugins,
selectedPlugin: availablePlugins[0],
knownIssues: (knownIssues[(availablePlugins[0]||{name:""}).name]||[]).filter(i => i.version === undefined || (typeof i.version==="string" ? i.version === availablePlugins[0].version : i.version.test(availablePlugins[0].version))),
selectedKnownIssue: issueOther,
title: "",
description: "",
steps: [],
expectedBehavior: "",
additionalContext: "",
screenshots: [],
descriptionMissing: false,
titleMissing: false
};
}
}
render(){
const hasPlugin = !!this.state.selectedPlugin;
const issueIsKnown = this.state.selectedKnownIssue.title !== "Other";
let contentElement;
if(!hasPlugin){
contentElement = React.createElement(
"div",
{className: classNames.colorStandard},
React.createElement("b", {}, "You don't have any plugin made by this author")
);
}else{
contentElement = React.createElement(
"div",
{
className: classNames.colorStandard,
style: {textAlign: "start"}
},
React.createElement(PluginSelector, {
plugins: this.state.availablePlugins,
selectedPlugin: this.state.selectedPlugin,
selectPlugin: this.selectPlugin.bind(this)
}),
React.createElement(KnownIssueList, {
knownIssues: this.state.knownIssues,
selectedKnownIssue: this.state.selectedKnownIssue,
selectKnownIssue: this.selectKnownIssue.bind(this)
}),
!issueIsKnown && React.createElement(OneLineInput, {
name: "Title",
placeholder: "Short issue description",
value: this.state.title,
missing: this.state.titleMissing,
onChange: value=>this.setState({title: value, titleMissing: false}, ()=>stateCache[this.props.channelId]=this.state)
}),
!issueIsKnown && React.createElement(MultiLineInput, {
name: "Description",
placeholder: "A clear and concise description of what the bug is.",
value: this.state.description,
missing: this.state.descriptionMissing,
onChange: e=>this.setState({description: e.target.value, descriptionMissing: false}, ()=>stateCache[this.props.channelId]=this.state)
}),
!issueIsKnown && React.createElement(InputList, {
name: "Steps to reproduce the issue",
elements: this.state.steps,
getPlaceholder: i=>`Step ${i+1}`,
onChange: this.editStep.bind(this)
}),
!issueIsKnown && React.createElement(MultiLineInput, {
name: "Expected behavior",
placeholder: "A clear and concise description of what you expect to happen.",
value: this.state.expectedBehavior,
onChange: e=>this.setState({expectedBehavior: e.target.value}, ()=>stateCache[this.props.channelId]=this.state)
}),
React.createElement(MultiLineInput, {
name: "Additional context",
placeholder: "Add any other context about the problem here.",
value: this.state.additionalContext,
onChange: e=>this.setState({additionalContext: e.target.value}, ()=>stateCache[this.props.channelId]=this.state)
}),
React.createElement(InputList, {
name: "Screenshots",
elements: this.state.screenshots,
getPlaceholder: i=>"Link to a screenshot",
isValid: this.isScreenshotLinkValid.bind(this),
onChange: this.setScreenshot.bind(this)
})
);
}
return React.createElement(
DeprecatedModal,
{
size: DeprecatedModal.Sizes.LARGE,
tag: "form",
className: classNames.container
},
React.createElement(
DeprecatedModal.Content,
{
className: classNames.content
},
React.createElement(
"div",
{},
React.createElement(
FormTitle,
{tag: "h2"},
"Submit Issue"
)
),
contentElement
),
React.createElement(
DeprecatedModal.Footer,
{},
React.createElement(
Button,
{
onClick: hasPlugin ? this.handleSubmitClick.bind(this) : closeModal
},
hasPlugin ? "Submit" : "Close"
)
)
);
}
selectPlugin(plugin){
this.setState({
selectedPlugin: plugin,
knownIssues: (knownIssues[plugin.name] || []).filter(i => i.version === undefined || (typeof i.version==="string" ? i.version === plugin.version : i.version.test(plugin.version))),
selectedKnownIssue: issueOther
}, ()=>stateCache[this.props.channelId]=this.state);
}
selectKnownIssue(issue){
this.setState({selectedKnownIssue: issue}, ()=>{
if(issue.solution){
delete stateCache[this.props.channelId];
closeModal();
}else{
stateCache[this.props.channelId]=this.state;
}
});
if(issue.solution){
const body = !Array.isArray(issue.solution) ? issue.solution : React.createElement(
"ol",
{
style: {
marginLeft: 20,
marginTop: 10,
marginBottom: 10,
listStyleType: "decimal"
}
},
issue.solution.map(step=>React.createElement("li", {}, step))
);
Api.Modals.showModal("Solution", React.createElement("div", {className: classNames.colorStandard}, body));
}
}
editStep(index, value){
let state = this.state;
state.steps[index] = value;
state.steps = state.steps.filter(step=>step.length>0);
this.setState(state, ()=>stateCache[this.props.channelId]=this.state);
}
setScreenshot(index, value){
let state = this.state;
state.screenshots[index] = value;
state.screenshots = state.screenshots.filter(link=>link.length>0)
this.setState(state, ()=>stateCache[this.props.channelId]=this.state);
}
isScreenshotLinkValid(link){
return link===""||/^https?:\/\/[^\.]+\..*[^\.]\/.+/.test(link.trim());
}
handleSubmitClick(e){
let submit = true;
if(this.state.selectedKnownIssue.title === "Other"){
if(!this.state.title.trim()){
submit = false;
this.setState({titleMissing: true}, ()=>stateCache[this.props.channelId]=this.state);
}
if(!this.state.description.trim()){
submit = false;
this.setState({descriptionMissing: true}, ()=>stateCache[this.props.channelId]=this.state);
}
}
if(this.state.screenshots.some(link=>!this.isScreenshotLinkValid(link))){
submit = false;
}
if(submit){
this.sendMessage();
delete stateCache[this.props.channelId];
}
}
getMessage(){
return this.getTitle() + this.getDescription() + this.getSteps() + this.getExpectedBehavior() + this.getInformation() + this.getAdditionalContext() + this.getScreenshots();
}
sendMessage(){
// TODO: check for 2000 character limit
WebpackModules.getByProps("sendMessage").sendMessage(this.props.channelId, {content: this.getMessage()});
closeModal();
}
getTitle(){
if(this.state.selectedKnownIssue.title !== "Other") return "**[" + this.state.selectedPlugin.name + "] Issue: " + this.state.selectedKnownIssue.title + "**";
else return "**[" + this.state.selectedPlugin.name + "] Issue: " + this.state.title.trim().replace(/ {2,}/g, " ") + "**";
}
getDescription(){
if(this.state.selectedKnownIssue.title !== "Other") return "";
let description = this.state.description.split("\n").map(l=>l.trim()).join("\n").trim().replace(/\n{3,}/g, "\n\n");
if(description.length > 0) return "\n\n**Bug description**\n" + description;
else return "";
}
getSteps(){
if(this.state.selectedKnownIssue.title !== "Other") return "";
let steps = this.state.steps.map(step=>step.trim()).filter(step=>step);
if(steps.length > 0) return "\n\n**Steps to reproduce**\n" + steps.map((step,i)=>(i+1)+". "+step).join("\n");
else return "";
}
getExpectedBehavior(){
if(this.state.selectedKnownIssue.title !== "Other") return "";
let behavior = this.state.expectedBehavior.split("\n").map(l=>l.trim()).join("\n").trim().replace(/\n{3,}/g, "\n\n");
if(behavior) return "\n\n**Expected Behavior**\n" + behavior;
else return "";
}
getInformation(){
return `\n\n**Information**
- Versions:
\\* Plugin: ${this.state.selectedPlugin.version}
\\* BD: ${isPowercord() ? `Powercord ${window.powercord.gitInfos.revision.substring(0, 7)} (bdCompat ${window.powercord.pluginManager.get('bdCompat').manifest.version})` : BdApi.getBDData("version")}
\\* ZLibrary: ${(getPlugin("ZeresPluginLibrary")||{version:"not installed"}).version}
\\* Release channel: ${WebpackModules.getByProps("releaseChannel").releaseChannel}
\\* Build ID: ${GLOBAL_ENV.SENTRY_TAGS.buildId}
- OS: ${(os=>os==="win32"?"Windows":os==="darwin"?"MacOS":os==="linux"?"Linux":os)(require("os").platform())}
- Compact mode: ${WebpackModules.getByProps("customStatus","renderSpoilers","messageDisplayCompact").messageDisplayCompact?"yes":"no"}
- Plugin enabled: ${BdApi.Plugins.isEnabled(this.state.selectedPlugin.name)?"yes":"no"}`
+ (this.state.selectedPlugin.name==="AccountSwitcher"&&this.state.selectPlugin.author==="l0c4lh057"?`\n- Encryption enabled: ${this.state.selectedPlugin.instance.settings.encrypted?"yes":"no"}`:"");
}
getAdditionalContext(){
let context = this.state.additionalContext.split("\n").map(l=>l.trim()).join("\n").trim().replace(/\n{3,}/g, "\n\n");
if(context) return "\n\n**Additional context**\n" + context;
else return "";
}
getScreenshots(){
let screenshots = this.state.screenshots.map(l=>l.trim()).filter(l=>l);
if(screenshots.length > 0) return "\n\n**Screenshots**\n" + screenshots.map(l=>"- "+l).join("\n");
return "";
}
};
let modalId = Modals.openModal(props => {
return React.createElement(
WebpackModules.getByProps("ModalRoot").ModalRoot,
{
size: "large",
transitionState: props.transitionState
},
React.createElement(Alert, {authors, channelId: WebpackModules.getByProps("getChannelId").getChannelId()})
);
});
closeModal = ()=>Modals.closeModal(modalId);
}
async loadIssuesAndSupportChannels(){
return new Promise((resolve, reject) => {
require("request").get("https://raw.githubusercontent.com/l0c4lh057/BetterDiscordStuff/master/Plugins/BugReportHelper/data.json", (error, response, body) => {
if(error) reject(error);
else resolve(JSON.parse(body));
});
});
}
getSettingsPanel(){
return this.buildSettingsPanel().getElement();
}
}
};
return plugin(Plugin, Api);
})(global.ZeresPluginLibrary.buildPlugin(config));
})();