/** * @name MoreMessageConfirmations * @author Ahlawat * @authorId 1025214794766221384 * @version 1.1.1 * @invite SgKSKyh9gY * @description Add warnings before sending messages in certain scenarios. * @website https://tharki-god.github.io/ * @source https://github.com/Tharki-God/BetterDiscordPlugins * @updateUrl https://tharki-god.github.io/BetterDiscordPlugins/MoreMessageConfirmations.plugin.js */ /*@cc_on @if (@_jscript) var shell = WScript.CreateObject("WScript.Shell"); var fs = new ActiveXObject("Scripting.FileSystemObject"); var pathPlugins = shell.ExpandEnvironmentStrings("%APPDATA%\\BetterDiscord\\plugins"); var pathSelf = WScript.ScriptFullName; 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 move myself to BetterDiscord's plugins folder for you?", 0, "Do you need some help?", 0x34) === 6) { fs.MoveFile(pathSelf, fs.BuildPath(pathPlugins, fs.GetFileName(pathSelf))); shell.Exec("explorer " + pathPlugins); shell.Popup("I'm installed!", 0, "Successfully installed", 0x40); } WScript.Quit(); @else@*/ module.exports = ((_) => { const config = { info: { name: "MoreMessageConfirmations", authors: [ { name: "Ahlawat", discord_id: "1025214794766221384", github_username: "Tharki-God", }, ], version: "1.1.1", description: "Add warnings before sending messages in certain scenarios.", github: "https://github.com/Tharki-God/BetterDiscordPlugins", github_raw: "https://tharki-god.github.io/BetterDiscordPlugins/MoreMessageConfirmations.plugin.js", }, changelog: [ { title: "v0.0.1", items: ["Idea in mind"], }, { title: "v0.0.5", items: ["Base Model"], }, { title: "Initial Release v1.0.0", items: [ "This is the initial release of the plugin :)", "Mommy loves me ψ(`∇´)ψ", ], }, { title: "v1.0.1", items: ["Corrected text."], }, ], main: "MoreMessageConfirmations.plugin.js", }; const RequiredLibs = [{ window: "ZeresPluginLibrary", filename: "0PluginLibrary.plugin.js", external: "https://rauenzi.github.io/BDPluginLibrary/release/0PluginLibrary.plugin.js", downloadUrl: "https://rauenzi.github.io/BDPluginLibrary/release/0PluginLibrary.plugin.js" }, { window: "BunnyLib", filename: "1BunnyLib.plugin.js", external: "https://github.com/Tharki-God/BetterDiscordPlugins", downloadUrl: "https://tharki-god.github.io/BetterDiscordPlugins/1BunnyLib.plugin.js" }, ]; class handleMissingLibrarys { load() { for (const Lib of RequiredLibs.filter(lib => !window.hasOwnProperty(lib.window))) BdApi.showConfirmationModal( "Library Missing", `The library plugin (${Lib.window}) needed for ${config.info.name} is missing. Please click Download Now to install it.`, { confirmText: "Download Now", cancelText: "Cancel", onConfirm: () => this.downloadLib(Lib), } ); } async downloadLib(Lib) { const fs = require("fs"); const path = require("path"); const { Plugins } = BdApi; const LibFetch = await fetch( Lib.downloadUrl ); if (!LibFetch.ok) return this.errorDownloadLib(Lib); const LibContent = await LibFetch.text(); try { await fs.writeFile( path.join(Plugins.folder, Lib.filename), LibContent, (err) => { if (err) return this.errorDownloadLib(Lib); } ); } catch (err) { return this.errorDownloadLib(Lib); } } errorDownloadZLib(Lib) { const { shell } = require("electron"); BdApi.showConfirmationModal( "Error Downloading", [ `${Lib.window} download failed. Manually install plugin library from the link below.`, ], { confirmText: "Download", cancelText: "Cancel", onConfirm: () => { shell.openExternal( Lib.external ); }, } ); } start() { } stop() { } } return RequiredLibs.some(m => !window.hasOwnProperty(m.window)) ? handleMissingLibrarys : (([Plugin, ZLibrary]) => { const { Utilities, PluginUpdater, Logger, Patcher, Settings: { SettingPanel, Slider, SettingGroup, Switch }, } = ZLibrary; const { LibraryModules: { ChannelPermissionStore, DiscordConstants, WarningPopoutModule } } = BunnyLib.build(config); const defaultSettings = { slowModeConfirmation: true, slowmodeTrigger: 600, uploadConfirmation: true, uploadTrigger: 3, mentionConfirmation: true, mentionTrigger: 3, }; return class MessageConfirmations extends Plugin { constructor() { super(); this.settings = Utilities.loadData( config.info.name, "settings", defaultSettings ); } checkForUpdates() { try { PluginUpdater.checkForUpdate( config.info.name, config.info.version, config.info.github_raw ); } catch (err) { Logger.err("Plugin Updater could not be reached.", err); } } start() { this.checkForUpdates(); this.addWarnings(); } addWarnings() { Patcher.instead( WarningPopoutModule, "v", (_, [args], res) => new Promise(async (resolve) => { const mentions = this.getMentions(args.content); if ( this.settings["slowModeConfirmation"] && !this.hasPermissions(args.channel) && this.settings["slowmodeTrigger"] <= args?.channel?.rateLimitPerUser ) return args.openWarningPopout({ analyticsType: config.info.name, animation: undefined, channel: args.channel, onCancel: () => { resolve({ valid: false, failureReason: "dont_slow_me", }); }, onConfirm: () => { resolve({ valid: true }); }, popoutText: { body: "This will put you in Slowmode. Do you want to continue?", footer: `Slowmode duration: ${this.toDaysMinutesSeconds( args.channel.rateLimitPerUser )}!`, }, }); if ( this.settings["uploadConfirmation"] && this.settings["uploadTrigger"] <= args?.uploads?.length ) return args.openWarningPopout({ analyticsType: config.info.name, animation: undefined, channel: args.channel, onCancel: () => { resolve({ valid: false, failureReason: "dont_upload_now", }); }, onConfirm: () => { resolve({ valid: true }); }, popoutText: { body: "This will upload the selected files. Do you want to continue?", footer: `Amount of files: ${args.uploads.length}!`, }, }); if ( this.settings["mentionConfirmation"] && this.settings["mentionTrigger"] <= mentions?.length ) return args.openWarningPopout({ analyticsType: config.info.name, animation: undefined, channel: args.channel, onCancel: () => { resolve({ valid: false, failureReason: "dont_mention_now", }); }, onConfirm: () => { resolve({ valid: true }); }, popoutText: { body: `This will mention people. Do you want to continue?`, footer: `Amount of mentions: ${mentions?.length}!`, }, }); resolve(await res(args)); }) ); } hasPermissions(channel) { return ( ChannelPermissionStore.can( DiscordConstants.Plq.MANAGE_MESSAGES, channel ) || ChannelPermissionStore.can( DiscordConstants.Plq.MANAGE_CHANNELS, channel ) ); } toDaysMinutesSeconds(totalSeconds) { const seconds = Math.floor(totalSeconds % 60); const minutes = Math.floor((totalSeconds % 3600) / 60); const hours = Math.floor((totalSeconds % (3600 * 24)) / 3600); const days = Math.floor(totalSeconds / (3600 * 24)); const secondsStr = this.makeHumanReadable(seconds, "second"); const minutesStr = this.makeHumanReadable(minutes, "minute"); const hoursStr = this.makeHumanReadable(hours, "hour"); const daysStr = this.makeHumanReadable(days, "day"); return `${daysStr}${hoursStr}${minutesStr}${secondsStr}`.replace( /,\s*$/, "" ); } makeHumanReadable(num, singular) { return num > 0 ? num + (num === 1 ? ` ${singular}, ` : ` ${singular}s, `) : ""; } getMentions(text) { return [...text.matchAll(/<@!?(\d+)>/g)] .map((m) => m[1]) } onStop() { Patcher.unpatchAll(); } getSettingsPanel() { return SettingPanel.build( this.saveSettings.bind(this), new SettingGroup("Slowmode", { collapsible: true, shown: false, }).append( new Switch( "Show confirmation", "Whether to show a confirmation dialog for sending a message in a channel in which slowmode applies to you.", this.settings["slowModeConfirmation"], (e) => { this.settings["slowModeConfirmation"] = e; } ), new Slider( "Slowmode trigger", "The minimum duration of slowmode, in minutes, to get a confirmation prompt.", 30, 1800, this.settings["slowmodeTrigger"], (e) => { this.settings["slowmodeTrigger"] = e; }, { onValueRender: (value) => { return this.toDaysMinutesSeconds(value); }, } ) ), new SettingGroup("File upload", { collapsible: true, shown: false, }).append( new Switch( "Show confirmation", "Whether to show a confirmation dialog for uploading files.", this.settings["uploadConfirmation"], (e) => { this.settings["uploadConfirmation"] = e; } ), new Slider( "File amount", "The minimum amount of files to get a confirmation prompt.", 1, 10, this.settings["uploadTrigger"], (e) => { this.settings["uploadTrigger"] = Math.floor(e); }, { onValueRender: (value) => { return Math.floor(value); }, } ) ), new SettingGroup("User mentions", { collapsible: true, shown: false, }).append( new Switch( "Show confirmation", "Whether to show a confirmation dialog for mentioning users.", this.settings["mentionConfirmation"], (e) => { this.settings["mentionConfirmation"] = e; } ), new Slider( "Amount of mentions", "The minimum amount of user mentions to get a confirmation prompt.", 1, 10, this.settings["mentionTrigger"], (e) => { this.settings["mentionTrigger"] = Math.floor(e); }, { onValueRender: (value) => { return Math.floor(value); }, } ) ) ); } saveSettings() { Utilities.saveData(config.info.name, "settings", this.settings); } }; })(ZLibrary.buildPlugin(config)); })(); /*@end@*/