diff --git a/common/constants/ipcevents.js b/common/constants/ipcevents.js index fcdc5a5f..17b98cad 100644 --- a/common/constants/ipcevents.js +++ b/common/constants/ipcevents.js @@ -10,4 +10,5 @@ export const OPEN_DEVTOOLS = "bd-open-devtools"; export const CLOSE_DEVTOOLS = "bd-close-devtools"; export const OPEN_WINDOW = "bd-open-window"; export const INSPECT_ELEMENT = "bd-inspect-element"; -export const MINIMUM_SIZE = "bd-minimum-size"; \ No newline at end of file +export const MINIMUM_SIZE = "bd-minimum-size"; +export const DEVTOOLS_WARNING = "bd-remove-devtools-message"; \ No newline at end of file diff --git a/injector/src/modules/ipc.js b/injector/src/modules/ipc.js index 8870d44a..2dfb8fa6 100644 --- a/injector/src/modules/ipc.js +++ b/injector/src/modules/ipc.js @@ -75,6 +75,8 @@ const setMinimumSize = (event, width, height) => { window.setMinimumSize(width, height); }; +const stopDevtoolsWarning = event => event.sender.removeAllListeners("devtools-opened"); + export default class IPCMain { static registerEvents() { ipc.on(IPCEvents.GET_PATH, getPath); @@ -83,6 +85,7 @@ export default class IPCMain { ipc.on(IPCEvents.CLOSE_DEVTOOLS, closeDevTools); ipc.on(IPCEvents.INSPECT_ELEMENT, inspectElement); ipc.on(IPCEvents.MINIMUM_SIZE, setMinimumSize); + ipc.on(IPCEvents.DEVTOOLS_WARNING, stopDevtoolsWarning); ipc.handle(IPCEvents.RUN_SCRIPT, runScript); ipc.handle(IPCEvents.OPEN_WINDOW, createBrowserWindow); } diff --git a/renderer/src/builtins/builtins.js b/renderer/src/builtins/builtins.js index 64a27bd0..f3761607 100644 --- a/renderer/src/builtins/builtins.js +++ b/renderer/src/builtins/builtins.js @@ -20,4 +20,6 @@ export {default as EmoteMenu} from "./emotes/emotemenu"; export {default as Debugger} from "./developer/debugger"; export {default as ReactDevTools} from "./developer/reactdevtools"; -export {default as InspectElement} from "./developer/inspectelement"; \ No newline at end of file +export {default as InspectElement} from "./developer/inspectelement"; +export {default as StopDevToolsWarning} from "./developer/devtoolswarning"; +export {default as DebugLogs} from "./developer/debuglogs"; \ No newline at end of file diff --git a/renderer/src/builtins/developer/debuglogs.js b/renderer/src/builtins/developer/debuglogs.js new file mode 100644 index 00000000..982e5b9e --- /dev/null +++ b/renderer/src/builtins/developer/debuglogs.js @@ -0,0 +1,49 @@ +const fs = require("fs"); +const path = require("path"); +import Builtin from "../../structs/builtin"; +import DataStore from "../../modules/datastore"; +import Utilities from "../../modules/utilities"; + + +const timestamp = () => new Date().toISOString().replace("T", " ").replace("Z", ""); +const levels = ["log", "info", "warn", "error", "debug"]; + +export default new class DebugLogs extends Builtin { + get name() {return "DebugLogs";} + get category() {return "developer";} + get id() {return "debugLogs";} + + enabled() { + this.logFile = path.join(DataStore.dataFolder, "debug.log"); + this.stream = fs.createWriteStream(this.logFile, {flags: "a"}); + this.stream.write(`\n\n================= Starting Debug Log (${timestamp()}) =================\n`); + for (const level of levels) { + this.after(console, level, (_, originalArgs) => { + const data = this.sanitize(...originalArgs); + this.stream.write(`[${timestamp()}][CONSOLE:${level.toUpperCase()}] ${data}\n`); + }); + } + } + + disabled() { + this.unpatchAll(); + if (this.stream) this.stream.end(`\n\n================= Ending Debug Log (${timestamp()}) =================`); + } + + sanitize(...args) { + const sanitized = []; + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + if (typeof(arg) === "string") { + const styleCount = Utilities.occurrences(arg, "%c"); + sanitized.push(arg.replace(/%c/g, "")); + if (styleCount > 0) i += styleCount; + } + + if (typeof(arg) === "object") sanitized.push(JSON.stringify(arg)); + if (arg.message && arg.stack) sanitized.push(`${arg.message}\n${arg.stack}`); + if (typeof(arg) === "function" || typeof(arg) === "boolean" || typeof(arg) === "number") sanitized.push(arg.toString()); + } + return sanitized.join(" "); + } +}; \ No newline at end of file diff --git a/renderer/src/builtins/developer/devtoolswarning.js b/renderer/src/builtins/developer/devtoolswarning.js new file mode 100644 index 00000000..73eb45f0 --- /dev/null +++ b/renderer/src/builtins/developer/devtoolswarning.js @@ -0,0 +1,22 @@ +import Builtin from "../../structs/builtin"; +import WebpackModules from "../../modules/webpackmodules"; +// import IPC from "../../modules/ipc"; + +export default new class StopDevToolsWarning extends Builtin { + get name() {return "StopDevToolsWarning";} + get category() {return "developer";} + get id() {return "devToolsWarning";} + + enabled() { + // IPC.stopDevtoolsWarning(); + DiscordNative?.window?.setDevtoolsCallbacks(null, null); + } + + disabled() { + const devtoolsModule = WebpackModules.getByString("setDevtoolsCallbacks"); + const stringModule = WebpackModules.getByProps("Messages"); + const hideModule = WebpackModules.getModule(m => Object.keys(m).some(k => k.startsWith("hide"))); + if (!devtoolsModule || !stringModule || !hideModule) return; + devtoolsModule(stringModule, hideModule, DiscordNative); + } +}; \ No newline at end of file diff --git a/renderer/src/data/settings/config.js b/renderer/src/data/settings/config.js index 09711f4e..19254e43 100644 --- a/renderer/src/data/settings/config.js +++ b/renderer/src/data/settings/config.js @@ -54,7 +54,9 @@ export default [ settings: [ {type: "switch", id: "debuggerHotkey", value: false}, {type: "switch", id: "reactDevTools", value: false}, - {type: "switch", id: "inspectElement", value: false} + {type: "switch", id: "inspectElement", value: false}, + {type: "switch", id: "devToolsWarning", value: false}, + {type: "switch", id: "debugLogs", value: false} ] }, { diff --git a/renderer/src/data/strings.js b/renderer/src/data/strings.js index e2cfc944..8298165c 100644 --- a/renderer/src/data/strings.js +++ b/renderer/src/data/strings.js @@ -113,6 +113,14 @@ export default { inspectElement: { name: "Inspect Element Hotkey", note: "Enables the inspect element hotkey (ctrl + shift + c) that is common in most browsers" + }, + devToolsWarning: { + name: "Stop DevTools Warning", + note: "Stops Discord from printing out their \"Hold Up!\" message" + }, + debugLogs: { + name: "Debug Logs", + note: "Outputs everything from the console into the debug.log file in the BetterDiscord folder" } }, window: { diff --git a/renderer/src/modules/core.js b/renderer/src/modules/core.js index 98a9317d..3b801b15 100644 --- a/renderer/src/modules/core.js +++ b/renderer/src/modules/core.js @@ -25,23 +25,6 @@ export default new class Core { if (this.hasStarted) return; this.hasStarted = true; - // (() => { - // const fs = require("fs"); - // fs.appendFileSync("Z:\\debug.log", "\n\n\n"); - - // const toFile = orig => (...args) => { - // fs.appendFileSync("Z:\\debug.log", JSON.stringify(args) + "\n"); - // orig(...args); - // }; - - // window.ocl = console.log; - // window.oce = console.error; - // window.ocx = console.exception; - // console.log = toFile(window.ocl); - // console.error = toFile(window.oce); - // console.exception = toFile(window.ocx); - // })(); - Config.appPath = process.env.DISCORD_APP_PATH; Config.userData = process.env.DISCORD_USER_DATA; Config.dataPath = process.env.BETTERDISCORD_DATA_PATH; @@ -139,7 +122,7 @@ export default new class Core { const hasUpdate = remoteVersion > Config.version; if (!hasUpdate) return; - Modals.showConfirmationModal("Update", "There is an update, would you like to update now?", { + Modals.showConfirmationModal("Update Available", `BetterDiscord (${Config.version}) has an available update available (${remoteVersion}). Would you like to update now?`, { confirmText: "Update", cancelText: "Skip", onConfirm: () => this.update(data) @@ -151,13 +134,12 @@ export default new class Core { const asar = releaseInfo.assets.find(a => a.name === "betterdiscord.asar"); const request = require("request"); const buff = await new Promise((resolve, reject) => - request(asar.url, {encoding: null, headers: {"User-Agent": "BD Updater", "Accept": "application/octet-stream"}}, (err, resp, body) => { + request(asar.url, {encoding: null, headers: {"User-Agent": "BetterDiscord Updater", "Accept": "application/octet-stream"}}, (err, resp, body) => { if (err || resp.statusCode != 200) return reject(err || `${resp.statusCode} ${resp.statusMessage}`); return resolve(body); })); const asarPath = path.join(DataStore.baseFolder, "betterdiscord.asar"); - console.log(asarPath); const fs = require("original-fs"); fs.writeFileSync(asarPath, buff); @@ -169,7 +151,7 @@ export default new class Core { }); } catch (err) { - console.error(err); + Logger.stacktrace("Updater", "Failed to update", err); Modals.showConfirmationModal("Update Failed", "BetterDiscord failed to update. Please download the latest version of the installer from GitHub (https://github.com/BetterDiscord/Installer/releases/latest) and reinstall.", { cancelText: "" }); diff --git a/renderer/src/modules/ipc.js b/renderer/src/modules/ipc.js index c6728ebc..33323a47 100644 --- a/renderer/src/modules/ipc.js +++ b/renderer/src/modules/ipc.js @@ -39,4 +39,8 @@ export default new class IPCRenderer { setMinimumSize(width, height) { return ipc.send(IPCEvents.MINIMUM_SIZE, width, height); } + + stopDevtoolsWarning() { + return ipc.send(IPCEvents.DEVTOOLS_WARNING); + } }; \ No newline at end of file diff --git a/renderer/src/modules/utilities.js b/renderer/src/modules/utilities.js index 55b363a8..ac0a4685 100644 --- a/renderer/src/modules/utilities.js +++ b/renderer/src/modules/utilities.js @@ -58,6 +58,11 @@ export default class Utilities { }; } + static occurrences(source, substring) { + const regex = new RegExp(substring, "g"); + return (source.match(regex) || []).length; + } + static onRemoved(node, callback) { const observer = new MutationObserver((mutations) => { for (let m = 0; m < mutations.length; m++) {