diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..afaf13e --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +BAZECOR +chromium +dconf +discord +EOS-arch-news.conf +EOS-arch-news-for-you.conf +EOS-greeter.conf +EOS-initial-wallpaper.XFCE +pavucontrol.ini +ristretto +systemd +Thunar +user-dirs.dirs +user-dirs.locale +xfce4 +yay +.stack-work +**/.surf/cache +xmonad-x86_64-linux +__pycache__ +**/kitty/kitty-themes diff --git a/files/.Xresources b/files/.Xresources new file mode 100644 index 0000000..dd8d905 --- /dev/null +++ b/files/.Xresources @@ -0,0 +1,72 @@ +*.background: #282828 +color5: #ff0000 + +Xcursor.size: 16 +Xcursor.theme: capitaine-cursors-light + +Xft.autohint: 0 +Xft.antialias: 1 +Xft.hinting: true +Xft.hintstyle: hintslight +Xft.dpi: 96 +Xft.rgba: rgb +Xft.lcdfilter: lcddefault + +rofi.lines: 5 +rofi.eh: 2 +rofi.padding: 200 +rofi.fullscreen: true +rofi.bw: 0 +rofi.separator-style: none +rofi.hide-scrollbar: true +rofi.color-enabled: true + +! 'background', 'border', 'separator' +rofi.color-window: argb:c82d303b, #7c8389, #1d1f21 +! State: 'bg', 'fg', 'bgalt', 'hlbg', 'hlfg' +rofi.color-normal: argb:031d1f21, #f3f4f5, argb:031d1f21, argb:031d1f21, #9575cd +rofi.color-urgent: argb:031d1f21, #f3f4f5, argb:bc303541, argb:031d1f21, #9575cd +rofi.color-active: argb:031d1f21, #f3f4f5, argb:031d1f21, argb:031d1f21, #9575cd +rofi.font: System San Francisco Display 18 + +dzen.font: -*-fixed-medium-r-s*--12-87-*-*-*-*-iso10???-1 + + + + +URxvt.font: xft:scientifica + + + + + +!URxvt.color24: #076678 +!URxvt.color66: #427b58 +!URxvt.color88: #9d0006 +!URxvt.color96: #8f3f71 +!URxvt.color100: #79740e +!URxvt.color108: #8ec07c +!URxvt.color109: #83a598 +!URxvt.color130: #af3a03 +!URxvt.color136: #b57614 +!URxvt.color142: #b8bb26 +!URxvt.color167: #fb4934 +!URxvt.color175: #d3869b +!URxvt.color208: #fe8019 +!URxvt.color214: #fabd2f +!URxvt.color223: #ebdbb2 +!URxvt.color228: #f2e5bc +!URxvt.color229: #fbf1c7 +!URxvt.color230: #f9f5d7 +!URxvt.color234: #1d2021 +!URxvt.color235: #282828 +!URxvt.color236: #32302f +!URxvt.color237: #3c3836 +!URxvt.color239: #504945 +!URxvt.color241: #665c54 +!URxvt.color243: #7c6f64 +!URxvt.color244: #928374 +!URxvt.color245: #928374 +!URxvt.color246: #a89984 +!URxvt.color248: #bdae93 +!URxvt.color250: #d5c4a1 diff --git a/files/.config/EnhancedDiscord/.eslintrc.json b/files/.config/EnhancedDiscord/.eslintrc.json new file mode 100644 index 0000000..a9fdd52 --- /dev/null +++ b/files/.config/EnhancedDiscord/.eslintrc.json @@ -0,0 +1,20 @@ +{ + "extends": "eslint:recommended", + "env": { + "browser": true, + "node": true, + "es6": true + }, + "parserOptions": { + "ecmaVersion": 8 + }, + "rules": { + "no-console": "off", + "no-unused-vars": "warn", + "no-useless-escape": "warn", + "no-empty": "warn", + "no-var": "error", + "no-mixed-spaces-and-tabs": "warn", + "prefer-const": "warn" + } +} diff --git a/files/.config/EnhancedDiscord/.github/workflows/main.yml b/files/.config/EnhancedDiscord/.github/workflows/main.yml new file mode 100644 index 0000000..a15d5c6 --- /dev/null +++ b/files/.config/EnhancedDiscord/.github/workflows/main.yml @@ -0,0 +1,12 @@ +name: Discord Source detection +on: [issues] +jobs: + autoclose: + runs-on: ubuntu-latest + steps: + - name: Autoclose Discord Source issues + uses: IndyV/IssueChecker@v1.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + issue-close-message: "@${issue.user.login} This issue was automatically closed because we don't accept issue reports from Discord Source.\nThe reason for this is because usually these issues aren't well thought out and are often duplicates.\n\nPlease take a few more minutes to create a well-made, proper issue report." + issue-pattern: "Discord Source - .Issue Report]" diff --git a/files/.config/EnhancedDiscord/.gitignore b/files/.config/EnhancedDiscord/.gitignore new file mode 100644 index 0000000..7f9edb3 --- /dev/null +++ b/files/.config/EnhancedDiscord/.gitignore @@ -0,0 +1,3 @@ +**/.vs +**/bin +**/obj diff --git a/files/.config/EnhancedDiscord/LICENSE b/files/.config/EnhancedDiscord/LICENSE new file mode 100644 index 0000000..6984d50 --- /dev/null +++ b/files/.config/EnhancedDiscord/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 joe27g + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/files/.config/EnhancedDiscord/README.md b/files/.config/EnhancedDiscord/README.md new file mode 100644 index 0000000..0ecabb3 --- /dev/null +++ b/files/.config/EnhancedDiscord/README.md @@ -0,0 +1,48 @@ +# EnhancedDiscord +A lightweight client mod designed to enhance your Discord experience without slowing down your PC. + +Support server: +Discord server +(https://discord.gg/XAvh9tq) + +#### DISCLAIMER! +> **Using EnhancedDiscord, or any other client mod, is against [Discord's Terms of Service](https://discordapp.com/terms). Use it at your own risk.** +> *It's very unlikely any action will be taken against you, but we take no responsibility if anything happens.* + +By default, this loads my theme, with some settings applied. More info [on its repo](https://github.com/joe27g/Discord-Theme). To change this, edit `plugins/style.css` or change the theme location in settings. + +You can download more quality plugins from the following repos: +- [joe27g/EnhancedDiscord-Plugins](https://github.com/joe27g/EnhancedDiscord-Plugins) +- [rauenzi/EnhancedDiscordPlugins](https://github.com/rauenzi/EnhancedDiscordPlugins) +- [jakuski/ed_plugins](https://github.com/jakuski/ed_plugins) + +If you enable "BD Plugins" in the EnhancedDiscord settings, you can also load BetterDiscord plugins. See the #faq in the support server for more details. +*Note: some BD plugins are notorious for being laggy. In general, the fewer plugins you have, the faster your client will be.* + +### Installing the easy way: + +*Currently, only Windows and Ubuntu 18.04+ are supported for the new installer, due to lack of devices to compile on* + +Go to https://enhanceddiscord.com/ and hit the 'Download' button, or if you're lazy, click [here](https://enhanceddiscord.com/EnhancedDiscord.exe). + +If you're having errors (especially related to `InteropServices`), you may need to download [.NET Framework 4.7.1](https://www.microsoft.com/en-us/download/details.aspx?id=56116). + +If you're on Linux or MacOS consider using [this install script](https://github.com/Cr3atable/LinuxED) that is specifically made for Unix. +LinuxED is unaffiliated with EnhancedDiscord so please do not request support for this script in an issue. + +### Installing the hard way: + +If the installer doesn't work for you, and you choose not to use LinuxED, you can also install it manually in just a few minutes. +To do so, see the [advanced installation guide](/advanced_installation.md). + +### Explanation of files: + +From now on, please refer to https://enhanceddiscord.com for explanations of included plugins. + +### Custom plugins + +To create your own plugin, check out [the plugin readme](/plugins.md). + +### Contributing + +Feel free to make pull requests or make your own plugins repository. If you do make your own plugins, request the 'Plugin Developer' role in the support server so you can announce your releases! diff --git a/files/.config/EnhancedDiscord/advanced_installation.md b/files/.config/EnhancedDiscord/advanced_installation.md new file mode 100644 index 0000000..4f43e4d --- /dev/null +++ b/files/.config/EnhancedDiscord/advanced_installation.md @@ -0,0 +1,26 @@ +# Installing the hard way + +#### Recommended for people that have trouble with the installers or really like wasting time. + +1. Download/clone this repo to wherever you want your ED files to reside. + +2. Find your appdata folder: +- For PC: `%appdata%/discord` +- For Mac: `~/Library/Application Support` +- For Linux: `$XDG_CONFIG_HOME/discord` or `~/.config/discord/` + - *Replace `discord` with `discordcanary` etc. as needed.* + + 3. In the appdata folder, find `/x.x.xxx/modules/discord_desktop_core/index.js`, where `x.x.xxx` is your current version of the Discord client, and open it. + + 4. At the top, add these lines: + ```js + process.env.injDir = ''; + require(`${process.env.injDir}/injection.js`); + ``` + where `` is the location of the ED folder. + + Make sure to escape paths, for example `C:\Users\\Documents\EnhancedDiscord\EnhancedDiscord` should be `C:\\Users\\\\Documents\\EnhancedDiscord\\EnhancedDiscord` + +5. Create `config.json` in your ED folder and set its contents to `{}`. + +6. Restart your Discord client and installation should be complete. diff --git a/files/.config/EnhancedDiscord/bd.css b/files/.config/EnhancedDiscord/bd.css new file mode 100644 index 0000000..cbb599b --- /dev/null +++ b/files/.config/EnhancedDiscord/bd.css @@ -0,0 +1,245 @@ +#bd-settingspane-container h2.ui-form-title { + font-size: 16px; + font-weight: 600; + line-height: 20px; + text-transform: uppercase; + display: inline-block; + margin-bottom: 20px; +} +#bd-settingspane-container h2.ui-form-title { + color: #f6f6f7; +} +.theme-light #bd-settingspane-container h2.ui-form-title { + color: #4f545c; +} + +#bd-settingspane-container .ui-switch-item { + flex-direction: column; + margin-top: 8px; +} + +#bd-settingspane-container .ui-switch-item h3 { + font-size: 16px; + font-weight: 500; + line-height: 24px; + flex: 1; +} +#bd-settingspane-container .ui-switch-item h3 { + color: #f6f6f7; +} +.theme-light #bd-settingspane-container .ui-switch-item h3 { + color: #4f545c; +} + +#bd-settingspane-container .ui-switch-item .style-description { + font-size: 14px; + font-weight: 500; + line-height: 20px; + margin-bottom: 10px; + padding-bottom: 10px; + border-bottom: 1px solid hsla(218,5%,47%,.3); +} +#bd-settingspane-container .ui-switch-item .style-description { + color: #72767d; +} +.theme-light #bd-settingspane-container .ui-switch-item .style-description { + color: rgba(114,118,125,.6); +} + +#bd-settingspane-container .ui-switch-item .ui-switch-wrapper { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + width: 44px; + height: 24px; + display: block; + flex: 0 0 auto; +} + +#bd-settingspane-container .ui-switch-item .ui-switch-wrapper input { + position: absolute; + opacity: 0; + cursor: pointer; + width: 100%; + height: 100%; + z-index: 1; +} + +#bd-settingspane-container .ui-switch-item .ui-switch-wrapper .ui-switch { + background: #7289da; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: #72767d; + border-radius: 14px; + transition: background .15s ease-in-out,box-shadow .15s ease-in-out,border .15s ease-in-out; +} + +#bd-settingspane-container .ui-switch-item .ui-switch-wrapper .ui-switch:before { + content: ''; + display: block; + width: 18px; + height: 18px; + position: absolute; + top: 3px; + left: 3px; + bottom: 3px; + background: #f6f6f7; + border-radius: 10px; + transition: all .15s ease; + box-shadow: 0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05); +} + +#bd-settingspane-container .ui-switch-item .ui-switch-wrapper .ui-switch.checked { + background: #7289da; +} + +#bd-settingspane-container .ui-switch-item .ui-switch-wrapper .ui-switch.checked:before { + transform: translateX(20px); +} + +#bd-settingspane-container .plugin-settings { + padding: 0 12px 12px 20px; +} + +@keyframes bd-modal-backdrop { + to { opacity: 0.85; } +} + +@keyframes bd-modal-anim { + to { transform: scale(1); opacity: 1; } +} + +@keyframes bd-modal-backdrop-closing { + to { opacity: 0; } +} + +@keyframes bd-modal-closing { + to { transform: scale(0.7); opacity: 0; } +} + +#bd-settingspane-container .backdrop { + animation: bd-modal-backdrop 250ms ease; + animation-fill-mode: forwards; + background-color: rgb(0, 0, 0); + transform: translateZ(0px); +} + +#bd-settingspane-container.closing .backdrop { + animation: bd-modal-backdrop-closing 200ms linear; + animation-fill-mode: forwards; + animation-delay: 50ms; + opacity: 0.85; +} + +#bd-settingspane-container.closing .modal { + animation: bd-modal-closing 250ms cubic-bezier(0.19, 1, 0.22, 1); + animation-fill-mode: forwards; + opacity: 1; + transform: scale(1); +} + +#bd-settingspane-container .modal { + animation: bd-modal-anim 250ms cubic-bezier(0.175, 0.885, 0.32, 1.275); + animation-fill-mode: forwards; + transform: scale(0.7); + transform-origin: 50% 50%; +} +/* Toast CSS */ + +.toasts { + position: fixed; + display: flex; + top: 0; + flex-direction: column; + align-items: center; + justify-content: flex-end; + pointer-events: none; + z-index: 4000; +} + +@keyframes toast-up { + from { + transform: translateY(0); + opacity: 0; + } +} + +.toast { + animation: toast-up 300ms ease; + transform: translateY(-10px); + background: #36393F; + padding: 10px; + border-radius: 5px; + box-shadow: 0 0 0 1px rgba(32,34,37,.6), 0 2px 10px 0 rgba(0,0,0,.2); + font-weight: 500; + color: #fff; + user-select: text; + font-size: 14px; + opacity: 1; + margin-top: 10px; + pointer-events: none; + user-select: none; +} + +@keyframes toast-down { + to { + transform: translateY(0px); + opacity: 0; + } +} + +.toast.closing { + animation: toast-down 200ms ease; + animation-fill-mode: forwards; + opacity: 1; + transform: translateY(-10px); +} + + +.toast.icon { + padding-left: 30px; + background-size: 20px 20px; + background-repeat: no-repeat; + background-position: 6px 50%; +} + +.toast.toast-info { + background-color: #4a90e2; +} + +.toast.toast-info.icon { + background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPiAgICA8cGF0aCBkPSJNMTIgMkM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMCAxMC00LjQ4IDEwLTEwUzE3LjUyIDIgMTIgMnptMSAxNWgtMnYtNmgydjZ6bTAtOGgtMlY3aDJ2MnoiLz48L3N2Zz4=); +} + +.toast.toast-success { + background-color: #43b581; +} + +.toast.toast-success.icon { + background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPiAgICA8cGF0aCBkPSJNMTIgMkM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMCAxMC00LjQ4IDEwLTEwUzE3LjUyIDIgMTIgMnptLTIgMTVsLTUtNSAxLjQxLTEuNDFMMTAgMTQuMTdsNy41OS03LjU5TDE5IDhsLTkgOXoiLz48L3N2Zz4=); +} +.toast.toast-danger, +.toast.toast-error { + background-color: #f04747; +} + +.toast.toast-danger.icon, +.toast.toast-error.icon { + background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTEyIDJDNi40NyAyIDIgNi40NyAyIDEyczQuNDcgMTAgMTAgMTAgMTAtNC40NyAxMC0xMFMxNy41MyAyIDEyIDJ6bTUgMTMuNTlMMTUuNTkgMTcgMTIgMTMuNDEgOC40MSAxNyA3IDE1LjU5IDEwLjU5IDEyIDcgOC40MSA4LjQxIDcgMTIgMTAuNTkgMTUuNTkgNyAxNyA4LjQxIDEzLjQxIDEyIDE3IDE1LjU5eiIvPiAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PC9zdmc+); +} + +.toast.toast-warning, +.toast.toast-warn { + background-color: #FFA600; + color: white; +} + +.toast.toast-warning.icon, +.toast.toast-warn.icon { + background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPiAgICA8cGF0aCBkPSJNMSAyMWgyMkwxMiAyIDEgMjF6bTEyLTNoLTJ2LTJoMnYyem0wLTRoLTJ2LTRoMnY0eiIvPjwvc3ZnPg==); +} diff --git a/files/.config/EnhancedDiscord/bd_shit.js b/files/.config/EnhancedDiscord/bd_shit.js new file mode 100644 index 0000000..f38188d --- /dev/null +++ b/files/.config/EnhancedDiscord/bd_shit.js @@ -0,0 +1,158 @@ +const path = require('path'); +const fs = require('fs'); +const Module = require('module').Module; +const originalRequire = Module._extensions['.js']; +const EDPlugin = require('./plugin'); + +module.exports = class BDManager { + + static async setup(currentWindow) { + this.currentWindow = currentWindow; + this.defineGlobals(); + this.jqueryElement = document.createElement('script'); + this.jqueryElement.src = `//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js`; + await new Promise(resolve => { + this.jqueryElement.onload = resolve; + document.head.appendChild(this.jqueryElement); + }); + + this.observer = new MutationObserver((mutations) => { + for (let i = 0, mlen = mutations.length; i < mlen; i++) this.fireEvent('observer', mutations[i]); + }); + this.observer.observe(document, {childList: true, subtree: true}); + + this.currentWindow.webContents.on('did-navigate-in-page', BDManager.onSwitch); + + fs.readFile(path.join(process.env.injDir, 'bd.css'), (err, text) => { + if (err) return console.error(err); + window.EDApi.injectCSS('BDManager', text); + }) + + Module._extensions['.js'] = this.pluginRequire(); + } + + static destroy() { + window.EDApi.clearCSS('BDManager'); + this.observer.disconnect(); + this.currentWindow.webContents.removeEventListener('did-navigate-in-page', BDManager.onSwitch); + this.jqueryElement.remove(); + Module._extensions['.js'] = originalRequire; + } + + static onSwitch() { + BDManager.fireEvent('onSwitch'); + } + + static extractMeta(content) { + const meta = content.split('\n')[0]; + const rawMeta = meta.substring(meta.lastIndexOf('//META') + 6, meta.lastIndexOf('*//')); + if (meta.indexOf('META') < 0) throw new Error('META was not found.'); + if (!window.EDApi.testJSON(rawMeta)) throw new Error('META could not be parsed.'); + + const parsed = JSON.parse(rawMeta); + if (!parsed.name) throw new Error('META missing name data.'); + return parsed; + } + + static pluginRequire() { + return function(moduleWrap, filename) { + if (!filename.endsWith('.plugin.js') || path.dirname(filename) !== path.resolve(process.env.injDir, 'plugins')) return Reflect.apply(originalRequire, this, arguments); + let content = fs.readFileSync(filename, 'utf8'); + if (content.charCodeAt(0) === 0xFEFF) content = content.slice(1); // Strip BOM + const meta = BDManager.extractMeta(content); + meta.filename = path.basename(filename); + content += `\nmodule.exports = ${meta.name};`; + moduleWrap._compile(content, filename); + moduleWrap.exports = BDManager.convertPlugin(new moduleWrap.exports()); + }; + } + + static fireEvent(event, ...args) { + const plugins = Object.values(window.ED.plugins); + for (let p = 0; p < plugins.length; p++) { + const plugin = plugins[p]; + if (!plugin[event] || typeof plugin[event] !== 'function') continue; + try { plugin[event](...args); } + catch (error) { throw new Error(`Could not fire ${event} for plugin ${plugin.name}.`); } + } + } + + static convertPlugin(plugin) { + const newPlugin = new EDPlugin({ + name: plugin.getName(), + load: function() {plugin.start();}, + unload: function() {plugin.stop();}, + bdplugin: plugin + }); + Object.defineProperties(newPlugin, { + name: { + enumerable: true, configurable: true, + get() {return plugin.getName();} + }, + author: { + enumerable: true, configurable: true, + get() {return plugin.getAuthor();} + }, + description: { + enumerable: true, configurable: true, + get() {return plugin.getDescription();} + } + }); + if (typeof plugin.getSettingsPanel == 'function') newPlugin.getSettingsPanel = function() {return plugin.getSettingsPanel();}; + if (typeof plugin.onSwitch == 'function') newPlugin.onSwitch = function() {return plugin.onSwitch();}; + if (typeof plugin.observer == 'function') newPlugin.observer = function(e) {return plugin.observer(e);}; + return newPlugin; + } + + static defineGlobals() { + window.bdConfig = {dataPath: process.env.injDir}; + window.bdplugins = window.bdthemes = window.pluginCookie = window.themeCookie = window.settingsCookie = {}; + window.bdpluginErrors = window.bdthemeErrors = []; + + window.bdPluginStorage = {get: window.EDApi.getData, set: window.EDApi.setData}; + window.Utils = {monkeyPatch: window.EDApi.monkeyPatch, suppressErrors: window.EDApi.suppressErrors, escapeID: window.EDApi.escapeID}; + + window.BDV2 = class V2 { + static get WebpackModules() {return {find: window.EDApi.findModule, findAll: window.EDApi.findAllModules, findByUniqueProperties: window.EDApi.findModuleByProps, findByDisplayName: window.EDApi.findModuleByDisplayName};} + static getInternalInstance(node) {return window.EDApi.getInternalInstance(node);} + static get react() {return window.EDApi.React;} + static get reactDom() {return window.EDApi.ReactDOM;} + }; + } + + static showSettingsModal(plugin) { + const baseModalClasses = window.EDApi.findModule(m => m.modal && m.inner && !m.sizeMedium) || {modal: "modal-36zFtW", inner: "inner-2VEzy9"}; + const modalClasses = window.EDApi.findModuleByProps("modal", "sizeMedium") || {modal: "backdrop-1wrmKb", sizeMedium: "sizeMedium-ctncE5", content: "content-2KoCOZ", header: "header-2nhbou", footer: "footer-30ewN8", close: "close-hhyjWJ", inner: "inner-2Z5QZX"}; + const backdrop = window.EDApi.findModuleByProps("backdrop") || {backdrop: "backdrop-1wrmKb"}; + const modalHTML = `
+
+ +
`; + + const panel = plugin.getSettingsPanel(); + if (!panel) return; + const modal = window.$(window.EDApi.formatString(modalHTML, {modalTitle: `${plugin.name} Settings`, id: `plugin-settings-${plugin.name}`})); + if (typeof panel == 'string') modal.find('.plugin-settings').html(panel); + else modal.find('.plugin-settings').append(panel); + modal.find('.backdrop, .close-button, .done-button').on('click', () => { + modal.addClass('closing'); + setTimeout(() => { modal.remove(); }, 300); + }); + modal.appendTo('#app-mount'); + } +}; diff --git a/files/.config/EnhancedDiscord/config.json b/files/.config/EnhancedDiscord/config.json new file mode 100644 index 0000000..685d85d --- /dev/null +++ b/files/.config/EnhancedDiscord/config.json @@ -0,0 +1 @@ +{"anti_track":{"enabled":false},"avatar_links":{"enabled":false},"char_count":{"enabled":false},"css_loader":{"path":"glasscord_css.css","enabled":false},"direct_download":{"enabled":false},"double_click_edit":{"enabled":false},"double_click_mention":{"enabled":false},"ed_settings":{"enabled":true},"friend_count":{"onlineOnly":false,"enabled":false},"guild_count":{"enabled":false},"hidden_channels":{"enabled":false},"quick_save":{"enabled":false},"silence":{"enabled":false},"silent_typing":{"enabled":false},"tag_all":{"enabled":false}} \ No newline at end of file diff --git a/files/.config/EnhancedDiscord/dom_shit.js b/files/.config/EnhancedDiscord/dom_shit.js new file mode 100644 index 0000000..9d21fa9 --- /dev/null +++ b/files/.config/EnhancedDiscord/dom_shit.js @@ -0,0 +1,456 @@ +const path = window.require('path'); +const fs = window.require('fs'); +const electron = window.require('electron'); +const Module = window.require('module').Module; +Module.globalPaths.push(path.resolve(electron.remote.app.getAppPath(), 'node_modules')); +const currentWindow = electron.remote.getCurrentWindow(); +if (currentWindow.__preload) require(currentWindow.__preload); + +//Get inject directory +if (!process.env.injDir) process.env.injDir = __dirname; + +//set up global functions +const c = { + log: function(msg, plugin) { + if (plugin && plugin.name) + console.log(`%c[EnhancedDiscord] %c[${plugin.name}]`, 'color: red;', `color: ${plugin.color}`, msg); + else console.log('%c[EnhancedDiscord]', 'color: red;', msg); + }, + info: function(msg, plugin) { + if (plugin && plugin.name) + console.info(`%c[EnhancedDiscord] %c[${plugin.name}]`, 'color: red;', `color: ${plugin.color}`, msg); + else console.info('%c[EnhancedDiscord]', 'color: red;', msg); + }, + warn: function(msg, plugin) { + if (plugin && plugin.name) + console.warn(`%c[EnhancedDiscord] %c[${plugin.name}]`, 'color: red;', `color: ${plugin.color}`, msg); + else console.warn('%c[EnhancedDiscord]', 'color: red;', msg); + }, + error: function(msg, plugin) { + if (plugin && plugin.name) + console.error(`%c[EnhancedDiscord] %c[${plugin.name}]`, 'color: red;', `color: ${plugin.color}`, msg); + else console.error('%c[EnhancedDiscord]', 'color: red;', msg); + }, + sleep: function(ms) { + return new Promise(resolve => { + setTimeout(resolve, ms); + }); + } +} +// config util +window.ED = { plugins: {}, version: '2.6.2' }; +Object.defineProperty(window.ED, 'config', { + get: function() { + let conf; + try{ + conf = require('./config.json'); + } catch (err) { + if(err.code !== 'MODULE_NOT_FOUND') + c.error(err); + conf = {}; + } + return conf; + }, + set: function(newSets = {}) { + let confPath; + let bDelCache; + try{ + confPath = require.resolve('./config.json'); + bDelCache = true; + } catch (err) { + if(err.code !== 'MODULE_NOT_FOUND') + c.error(err); + confPath = path.join(process.env.injDir, 'config.json'); + bDelCache = false; + } + + try { + fs.writeFileSync(confPath, JSON.stringify(newSets)); + if(bDelCache) + delete require.cache[confPath]; + } catch(err) { + c.error(err); + } + return this.config; + } +}); + +function loadPlugin(plugin) { + try { + if (plugin.preload) + console.log(`%c[EnhancedDiscord] %c[PRELOAD] %cLoading plugin %c${plugin.name}`, 'color: red;', 'color: yellow;', '', `color: ${plugin.color}`, `by ${plugin.author}...`); + else console.log(`%c[EnhancedDiscord] %cLoading plugin %c${plugin.name}`, 'color: red;', '', `color: ${plugin.color}`, `by ${plugin.author}...`); + plugin.load(); + } catch(err) { + c.error(`Failed to load:\n${err.stack}`, plugin); + } +} + +window.ED.localStorage = window.localStorage; + +process.once("loaded", async () => { + c.log(`v${window.ED.version} is running. Validating plugins...`); + + const pluginFiles = fs.readdirSync(path.join(process.env.injDir, 'plugins')); + const plugins = {}; + for (const i in pluginFiles) { + if (!pluginFiles[i].endsWith('.js') || pluginFiles[i].endsWith(".plugin.js")) continue; + let p; + const pName = pluginFiles[i].replace(/\.js$/, ''); + try { + p = require(path.join(process.env.injDir, 'plugins', pName)); + if (typeof p.name !== 'string' || typeof p.load !== 'function') { + throw new Error('Plugin must have a name and load() function.'); + } + plugins[pName] = Object.assign(p, {id: pName}); + } + catch (err) { + c.warn(`Failed to load ${pluginFiles[i]}: ${err}\n${err.stack}`, p); + } + } + for (const id in plugins) { + if (!plugins[id] || !plugins[id].name || typeof plugins[id].load !== 'function') { + c.info(`Skipping invalid plugin: ${id}`); delete plugins[id]; continue; + } + plugins[id].settings; // this will set default settings in config if necessary + } + window.ED.plugins = plugins; + c.log(`Plugins validated.`); + + while (!window.webpackJsonp) + await c.sleep(100); // wait until this is loaded in order to use it for modules + + window.ED.webSocket = window._ws; + + /* Add helper functions that make plugins easy to create */ + window.req = window.webpackJsonp.push([[], { + '__extra_id__': (module, exports, req) => module.exports = req + }, [['__extra_id__']]]); + delete window.req.m['__extra_id__']; + delete window.req.c['__extra_id__']; + + window.findModule = window.EDApi.findModule; + window.findModules = window.EDApi.findAllModules; + window.findRawModule = window.EDApi.findRawModule; + window.monkeyPatch = window.EDApi.monkeyPatch; + + while (!window.EDApi.findModule('dispatch')) + await c.sleep(100); + + c.log(`Loading preload plugins...`); + for (const id in plugins) { + if (window.ED.config[id] && window.ED.config[id].enabled == false) continue; + if (!plugins[id].preload) continue; + loadPlugin(plugins[id]); + } + + const d = {resolve: () => {}}; + window.monkeyPatch(window.findModule('dispatch'), 'dispatch', {before: b => { + // modules seem to all be loaded when RPC server loads + if (b.methodArguments[0].type === 'RPC_SERVER_READY') { + window.findModule('dispatch').dispatch.unpatch(); + d.resolve(); + } + }}); + + await new Promise(resolve => { + d.resolve = resolve; + }) + c.log(`Modules done loading (${Object.keys(window.req.c).length})`); + + if (window.ED.config.bdPlugins) { + await require('./bd_shit').setup(currentWindow); + c.log(`Preparing BD plugins...`); + for (const i in pluginFiles) { + if (!pluginFiles[i].endsWith('.js') || !pluginFiles[i].endsWith(".plugin.js")) continue; + let p; + const pName = pluginFiles[i].replace(/\.js$/, ''); + try { + p = require(path.join(process.env.injDir, 'plugins', pName)); + if (typeof p.name !== 'string' || typeof p.load !== 'function') { + throw new Error('Plugin must have a name and load() function.'); + } + plugins[pName] = Object.assign(p, {id: pName}); + } + catch (err) { + c.warn(`Failed to load ${pluginFiles[i]}: ${err}\n${err.stack}`, p); + } + } + for (const id in plugins) { + if (!plugins[id] || !plugins[id].name || typeof plugins[id].load !== 'function') { + c.info(`Skipping invalid plugin: ${id}`); delete plugins[id]; continue; + } + } + } + + c.log(`Loading plugins...`); + for (const id in plugins) { + if (window.ED.config[id] && window.ED.config[id].enabled == false) continue; + if (plugins[id].preload) continue; + if (window.ED.config[id].enabled !== true && plugins[id].disabledByDefault) { + plugins[id].settings.enabled = false; continue; + } + loadPlugin(plugins[id]); + } + + + const ht = window.EDApi.findModule('hideToken') + // prevent client from removing token from localstorage when dev tools is opened, or reverting your token if you change it + window.EDApi.monkeyPatch(ht, 'hideToken', () => {}); + window.fixedShowToken = () => { + // Only allow this to add a token, not replace it. This allows for changing of the token in dev tools. + if (!window.ED.localStorage || window.ED.localStorage.getItem("token")) return; + return window.ED.localStorage.setItem("token", '"'+ht.getToken()+'"'); + }; + window.EDApi.monkeyPatch(ht, 'showToken', window.fixedShowToken); + if (!window.ED.localStorage.getItem("token") && ht.getToken()) + window.fixedShowToken(); // prevent you from being logged out for no reason + + // change the console warning to be more fun + const wc = require('electron').remote.getCurrentWebContents(); + wc.removeAllListeners("devtools-opened"); + wc.on("devtools-opened", () => { + console.log("%cHold Up!", "color: #FF5200; -webkit-text-stroke: 2px black; font-size: 72px; font-weight: bold;"); + console.log("%cIf you're reading this, you're probably smarter than most Discord developers.", "font-size: 16px;"); + console.log("%cPasting anything in here could actually improve the Discord client.", "font-size: 18px; font-weight: bold; color: red;"); + console.log("%cUnless you understand exactly what you're doing, keep this window open to browse our bad code.", "font-size: 16px;"); + console.log("%cIf you don't understand exactly what you're doing, you should come work with us: https://discordapp.com/jobs", "font-size: 16px;"); + }); +}) + + + +/* BD/ED joint api */ +window.EDApi = window.BdApi = class EDApi { + static get React() { return this.findModuleByProps('createElement'); } + static get ReactDOM() { return this.findModuleByProps('findDOMNode'); } + + static escapeID(id) { + return id.replace(/^[^a-z]+|[^\w-]+/gi, ""); + } + + static injectCSS(id, css) { + const style = document.createElement("style"); + style.id = this.escapeID(id); + style.innerHTML = css; + document.head.append(style); + } + + static clearCSS(id) { + const element = document.getElementById(this.escapeID(id)); + if (element) element.remove(); + } + + static linkJS(id, url) { + return new Promise(resolve => { + const script = document.createElement("script"); + script.id = this.escapeID(id); + script.src = url; + script.type = "text/javascript"; + script.onload = resolve; + document.head.append(script); + }); + } + + static unlinkJS(id) { + const element = document.getElementById(this.escapeID(id)); + if (element) element.remove(); + } + + static getPlugin(name) { + const plugin = Object.values(window.ED.plugins).find(p => p.name == name); + if (!plugin) return null; + return plugin.bdplugin ? plugin.bdplugin : plugin; + } + + static alert(title, body) { + const ModalStack = this.findModuleByProps("push", "update", "pop", "popWithKey"); + const AlertModal = this.findModule(m => m.prototype && m.prototype.handleCancel && m.prototype.handleSubmit && m.prototype.handleMinorConfirm); + if (!ModalStack || !AlertModal) return window.alert(body); + ModalStack.push(function(props) { + return EDApi.React.createElement(AlertModal, Object.assign({title, body}, props)); + }); + } + + static loadData(pluginName, key) { + if (!window.ED.config[pluginName]) window.ED.config[pluginName] = {}; + return window.ED.config[pluginName][key]; + } + + static saveData(pluginName, key, data) { + if (!window.ED.config[pluginName]) window.ED.config[pluginName] = {}; + window.ED.config[pluginName][key] = data; + window.ED.config = window.ED.config; + } + + static getData(pluginName, key) { + return this.loadData(pluginName, key); + } + + static setData(pluginName, key, data) { + this.saveData(pluginName, key, data); + } + + static getInternalInstance(node) { + if (!(node instanceof window.jQuery) && !(node instanceof Element)) return undefined; + if (node instanceof window.jQuery) node = node[0]; + return node[Object.keys(node).find(k => k.startsWith("__reactInternalInstance"))]; + } + + static showToast(content, options = {}) { + if (!document.querySelector(".toasts")) { + const toastWrapper = document.createElement("div"); + toastWrapper.classList.add("toasts"); + const boundingElement = document.querySelector(".chat-3bRxxu form, #friends, .noChannel-Z1DQK7, .activityFeed-28jde9"); + toastWrapper.style.setProperty("left", boundingElement ? boundingElement.getBoundingClientRect().left + "px" : "0px"); + toastWrapper.style.setProperty("width", boundingElement ? boundingElement.offsetWidth + "px" : "100%"); + toastWrapper.style.setProperty("bottom", (document.querySelector(".chat-3bRxxu form") ? document.querySelector(".chat-3bRxxu form").offsetHeight : 80) + "px"); + document.querySelector("." + this.findModule('app').app).appendChild(toastWrapper); + } + const {type = "", icon = true, timeout = 3000} = options; + const toastElem = document.createElement("div"); + toastElem.classList.add("toast"); + if (type) toastElem.classList.add("toast-" + type); + if (type && icon) toastElem.classList.add("icon"); + toastElem.innerText = content; + document.querySelector(".toasts").appendChild(toastElem); + setTimeout(() => { + toastElem.classList.add("closing"); + setTimeout(() => { + toastElem.remove(); + if (!document.querySelectorAll(".toasts .toast").length) document.querySelector(".toasts").remove(); + }, 300); + }, timeout); + } + + static findModule(filter, silent = true) { + const moduleName = typeof filter === 'string' ? filter : null; + for (const i in window.req.c) { + if (window.req.c.hasOwnProperty(i)) { + const m = window.req.c[i].exports; + if (m && m.__esModule && m.default && (moduleName ? m.default[moduleName] : filter(m.default))) return m.default; + if (m && (moduleName ? m[moduleName] : filter(m))) return m; + } + } + if (!silent) c.warn(`Could not find module ${module}.`, {name: 'Modules', color: 'black'}) + return null; + } + + static findRawModule(filter, silent = true) { + const moduleName = typeof filter === 'string' ? filter : null; + for (const i in window.req.c) { + if (window.req.c.hasOwnProperty(i)) { + const m = window.req.c[i].exports; + if (m && m.__esModule && m.default && (moduleName ? m.default[moduleName] : filter(m.default))) + return window.req.c[i]; + if (m && (moduleName ? m[moduleName] : filter(m))) + return window.req.c[i]; + } + } + if (!silent) c.warn(`Could not find module ${module}.`, {name: 'Modules', color: 'black'}) + return null; + } + + static findAllModules(filter) { + const moduleName = typeof filter === 'string' ? filter : null; + const modules = []; + for (const i in window.req.c) { + if (window.req.c.hasOwnProperty(i)) { + const m = window.req.c[i].exports; + if (m && m.__esModule && m.default && (moduleName ? m.default[moduleName] : filter(m.default))) modules.push(m.default); + else if (m && (moduleName ? m[moduleName] : filter(m))) modules.push(m); + } + } + return modules; + } + + static findModuleByProps(...props) { + return this.findModule(module => props.every(prop => module[prop] !== undefined)); + } + + static findModuleByDisplayName(name) { + return this.findModule(module => module.displayName === name); + } + + static monkeyPatch(what, methodName, options) { + if (typeof options === 'function') { + const newOptions = {instead: options, silent: true}; + options = newOptions; + } + const {before, after, instead, once = false, silent = false, force = false} = options; + const displayName = options.displayName || what.displayName || what.name || what.constructor ? (what.constructor.displayName || what.constructor.name) : null; + if (!silent) console.log(`%c[EnhancedDiscord] %c[Modules]`, 'color: red;', `color: black;`, `Patched ${methodName} in module ${displayName || ''}:`, what); // eslint-disable-line no-console + if (!what[methodName]) { + if (force) what[methodName] = function() {}; + else return console.warn(`%c[EnhancedDiscord] %c[Modules]`, 'color: red;', `color: black;`, `Method ${methodName} doesn't exist in module ${displayName || ''}`, what); // eslint-disable-line no-console + } + const origMethod = what[methodName]; + const cancel = () => { + if (!silent) console.log(`%c[EnhancedDiscord] %c[Modules]`, 'color: red;', `color: black;`, `Unpatched ${methodName} in module ${displayName || ''}:`, what); // eslint-disable-line no-console + what[methodName] = origMethod; + }; + what[methodName] = function() { + const data = { + thisObject: this, + methodArguments: arguments, + cancelPatch: cancel, + originalMethod: origMethod, + callOriginalMethod: () => data.returnValue = data.originalMethod.apply(data.thisObject, data.methodArguments) + }; + if (instead) { + const tempRet = EDApi.suppressErrors(instead, "`instead` callback of " + what[methodName].displayName)(data); + if (tempRet !== undefined) data.returnValue = tempRet; + } + else { + if (before) EDApi.suppressErrors(before, "`before` callback of " + what[methodName].displayName)(data); + data.callOriginalMethod(); + if (after) EDApi.suppressErrors(after, "`after` callback of " + what[methodName].displayName)(data); + } + if (once) cancel(); + return data.returnValue; + }; + what[methodName].__monkeyPatched = true; + what[methodName].displayName = "patched " + (what[methodName].displayName || methodName); + what[methodName].unpatch = cancel; + return cancel; + } + + static testJSON(data) { + try { + JSON.parse(data); + return true; + } + catch (err) { + return false; + } + } + + static suppressErrors(method, description) { + return (...params) => { + try { return method(...params); } + catch (e) { console.error("Error occurred in " + description, e); } + }; + } + + static formatString(string, values) { + for (const val in values) { + string = string.replace(new RegExp(`\\{\\{${val}\\}\\}`, 'g'), values[val]); + } + return string; + } + + static isPluginEnabled(name) { + const plugins = Object.values(window.ED.plugins); + const plugin = plugins.find(p => p.id == name || p.name == name); + if (!plugin) return false; + return !(plugin.settings.enabled === false); + } + + static isThemeEnabled() { + return false; + } + + static isSettingEnabled(id) { + return window.ED.config[id]; + } +}; diff --git a/files/.config/EnhancedDiscord/glasscord_css.css b/files/.config/EnhancedDiscord/glasscord_css.css new file mode 100644 index 0000000..84261cf --- /dev/null +++ b/files/.config/EnhancedDiscord/glasscord_css.css @@ -0,0 +1,346 @@ +/* + Copyright 2020 AryToNeX + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +:root{ + /* Here you can define properties for use with Glasscord. */ + + /* Global properties */ + /* Main switch: disabling this will disable Glasscord. */ + --glasscord-enable: true; + /* Tint: it's basically a global background color. */ + --glasscord-tint: rgba(0, 0, 0, 0); + + /* Windows-specific properties */ + /* Blur mode. Available types: acrylic (strong blur), blurbehind (light blur), transparent */ + --glasscord-win-blur: acrylic; + /* Acrylic mode makes some computers pretty unresponsive when resizing/moving the window. + Should we work around it? */ + --glasscord-win-performance-mode: true; + + /* macOS-specific properties */ + /* Vibrancy mode */ + --glasscord-macos-vibrancy: hud; + + /* Linux-specific properties */ + /* Should Glasscord send a request to your window compositor to blur behind Discord's window? */ + /* It currently supports KWin only */ + --glasscord-linux-blur: false; +} + +.theme-dark{ + --background-primary: transparent; + --background-primary-alt: #36393ff0; + --background-secondary: #2f313610; + --background-secondary-chat: #2f3136a0; + --background-secondary-alt: #292b2f00; + --background-tertiary: #20222570; + --background-logo: #36393fa0; + --deprecated-card-bg: #36393f4c; + --deprecated-store-bg: #36393f00; + --background-attachments: #2f313640; + --background-search-bar: #202225a0; + --background-switcher: #2f3136ff; + --background-chatbox: #20222550; + --background-lights-out: #000; + --background-pinned: #2f3136ff; + --background-profile-expand: #2f3136ff; + --text-lights-out: #f0f0f0; + --background-titlebar: #2f313650; +} + +.theme-dark .scrollerThemed-2oenus.themedWithTrack-q8E3vB .scroller-2FKFPG::-webkit-scrollbar-track-piece { + background-color: transparent; + border: 4px solid transparent; +} + +.theme-dark .scrollerThemed-2oenus.themedWithTrack-q8E3vB .scroller-2FKFPG::-webkit-scrollbar-thumb { + background-color: #20222550; +} + +.theme-dark .container-1D34oG { + background-color: transparent; +} + +.theme-dark .card-FDVird:before { + background-color: #33363c90; +} + +.theme-dark .codeRedemptionRedirect-1wVR4b { + background-color: #2f313650; + border-color: #20222550; +} + +.theme-dark .pageWrapper-1PgVDX { + background-color: transparent; +} + +.theme-light { + --background-primary: transparent; + --background-primary-alt: #ffffffff; + --background-secondary: #f2f3f550; + --background-secondary-chat: #f2f3f5a0; + --background-secondary-alt: #ebedef00; + --background-tertiary: #e3e5e860; + --background-logo: #f2f3f5a0; + --deprecated-card-bg: #f8f9f94c; + --deprecated-store-bg: #f8f9f900; + --background-attachments: #f6f6f640; + --background-search-bar: #e3e5e8a0; + --background-switcher: #f2f3f5ff; + --background-chatbox: #e3e5e850; + --background-lights-out: #fff; + --background-pinned: #f2f3f5ff; + --background-profile-expand: #f2f3f5ff; + --text-lights-out: #202020; + --background-titlebar: #f2f3f550; + --interactive-muted: #95999d; +} + +.theme-light .scrollerThemed-2oenus.themedWithTrack-q8E3vB .scroller-2FKFPG::-webkit-scrollbar-track-piece { + background-color: transparent; + border: 4px solid transparent; +} + +.theme-light .scrollerThemed-2oenus.themedWithTrack-q8E3vB .scroller-2FKFPG::-webkit-scrollbar-thumb { + border-color: transparent; + background-color: #e3e5e850; +} + +.theme-light .container-1D34oG { + background-color: transparent; +} + +.theme-light .card-FDVird:before { + background-color: #f6f6f790; +} + +.theme-light .codeRedemptionRedirect-1wVR4b { + background-color: #f6f6f750; + border-color: #dcddde50; +} + +.theme-light .pageWrapper-1PgVDX { + background-color: transparent; +} + +.withFrame-haYltI { + height: 18px; + margin-top: 0; + padding-top: 4px; +} + +.unread-3zKkbm { + height: 4px; + width: 4px; + margin-top: -2px; + border-radius: 2px 2px 2px 2px; +} + +.jumpToPresentBar-9P20AM { + border-radius: 8px; + padding-bottom: 0; +} + +.platform-win .sidebar-2K8pFh { + border-radius: 0; +} + +.messagesPopoutWrap-1MQ1bW { + background-color: var(--background-pinned); +} + +.notice-2FJMB4 { + background-color: var(--background-secondary) !important; + border-radius: 0; + -webkit-box-shadow: none; + box-shadow: none; +} + +.appMount-3lHmkl { + background-color: transparent; +} + +.app-2rEoOp { + background-color: transparent; +} + +.attachment-33OFj0 { + background-color: var(--background-attachments) !important; +} + +.header-2o-2hj { + -webkit-box-shadow: none; + box-shadow: none; +} + +.privateChannels-1nO12o { + background-color: transparent; +} + +.root-SR8cQa { + background-color: var(--background-profile-expand); +} + +.container-PNkimc { + background-color: transparent; +} + +.inset-3sAvek { + background-color: var(--background-secondary) !important; +} + +.container-1r6BKw.themed-ANHk51 { + background-color: var(--background-secondary); +} + +.wrapper-1Rf91z { + background-color: var(--background-secondary); +} + +.childWrapper-anI2G9 { + background-color: var(--background-logo); +} + +.circleIconButton-jET_ig { + background-color: var(--background-logo); +} + +.searchBar-3dMhjb { + background-color: var(--background-search-bar); +} + +.searchBar-6Kv8R2 { + -webkit-box-shadow: none; + box-shadow: none; +} + +.searchHeader-1l-wpR { + -webkit-box-shadow: none; + box-shadow: none; +} + +.channelName-1QajIf { + background-color: transparent; +} + +.searchResult-3pzFAB:before { + background-image: none; +} + +.searchResult-3pzFAB:after { + background-image: none; +} + +.perksModal-fSYqOq { + background-color: transparent !important; +} + +.ctaBar-2UsjF2 { + background-color: var(--background-attachments) !important; +} + +.tierBody-16Chc9 { + background-color: var(--background-secondary-chat) !important; +} + +.perk-2WeBWW { + background-color: var(--background-attachments) !important; +} + +.content-yTz4x3:before { + -webkit-box-shadow: none; + box-shadow: none; +} + +.tabBody-3YRQ8W:before { + -webkit-box-shadow: none; + box-shadow: none; +} + +.container-19hC9u:before { + -webkit-box-shadow: none; + box-shadow: none; +} + +.container-xm7Ad0:before { + -webkit-box-shadow: none; + box-shadow: none; +} + +.searchBar-6Kv8R2 .searchBarComponent-32dTOx { + background-color: var(--background-search-bar); +} + +.scroller-1JbKMe { + background-color: transparent; +} + +.scroller-2TZvBN { + background-color: transparent; +} + +.quickswitcher-3JagVE { + background-color: var(--background-switcher); +} + +.wrapper-2aW0bm { + background-color: var(--background-primary-alt); +} + +.searchResultMessage-2VxO12.hit-NLlWXA { + background-color: var(--background-primary-alt); +} + +.scroller-zPkAnE { + background-color: transparent; +} + +.embedFull-2tM8-- { + background-color: var(--background-attachments); +} + +.messagesWrapper-3lZDfY { + margin-bottom: 8px; +} + +.panels-j1Uci_ { + background-color: transparent; +} + +.titleBar-AC4pGV { + background-color: var(--background-titlebar); +} + +.uploadArea-3QgLtW { + background-color: var(--background-lights-out); +} + +.backdropWithLayer-3_uhz4 { + background-color: var(--background-lights-out) !important; +} + +.backdrop-1wrmKB { + background-color: var(--background-lights-out) !important; +} + +.downloadLink-1ywL9o { + color: var(--text-lights-out) !important; +} + +.bg-AYqtMd { + -webkit-mask-image: linear-gradient(#000f, #0000) !important; +} + +.scrollableContainer-2NUZem { + background-color: var(--background-chatbox); +} diff --git a/files/.config/EnhancedDiscord/injection.js b/files/.config/EnhancedDiscord/injection.js new file mode 100644 index 0000000..e8dd74c --- /dev/null +++ b/files/.config/EnhancedDiscord/injection.js @@ -0,0 +1,41 @@ +const electron = require('electron'); +const path = require('path'); + +electron.session.defaultSession.webRequest.onHeadersReceived(function(details, callback) { + if (!details.responseHeaders["content-security-policy-report-only"] && !details.responseHeaders["content-security-policy"]) return callback({cancel: false}); + delete details.responseHeaders["content-security-policy-report-only"]; + delete details.responseHeaders["content-security-policy"]; + callback({cancel: false, responseHeaders: details.responseHeaders}); +}); + +class BrowserWindow extends electron.BrowserWindow { + constructor(originalOptions) { + if (!originalOptions || !originalOptions.webPreferences || !originalOptions.title) return super(originalOptions); + const originalPreloadScript = originalOptions.webPreferences.preload; + + // Make sure Node integration is enabled + originalOptions.webPreferences.nodeIntegration = true; + originalOptions.webPreferences.preload = path.join(process.env.injDir, 'dom_shit.js'); + originalOptions.webPreferences.transparency = true; + + super(originalOptions); + this.__preload = originalPreloadScript; + } +} + +const electron_path = require.resolve('electron'); +Object.assign(BrowserWindow, electron.BrowserWindow); // Assigns the new chrome-specific ones + +if (electron.deprecate && electron.deprecate.promisify) { + const originalDeprecate = electron.deprecate.promisify; // Grab original deprecate promisify + electron.deprecate.promisify = (originalFunction) => originalFunction ? originalDeprecate(originalFunction) : () => void 0; // Override with falsey check +} + +const newElectron = Object.assign({}, electron, {BrowserWindow}); +// Tempfix for Injection breakage due to new version of Electron on Canary (Electron 7.x) +// Found by Zerebos (Zack Rauen) +delete require.cache[electron_path].exports; +// /TempFix +require.cache[electron_path].exports = newElectron; +//const browser_window_path = require.resolve(path.resolve(electron_path, '..', '..', 'browser-window.js')); +//require.cache[browser_window_path].exports = BrowserWindow; \ No newline at end of file diff --git a/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI.sln b/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI.sln new file mode 100644 index 0000000..269eb81 --- /dev/null +++ b/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnhancedDiscordUI", "EnhancedDiscordUI\EnhancedDiscordUI.csproj", "{3639AE05-14E6-43B2-9DDB-1A3F4F52657C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3639AE05-14E6-43B2-9DDB-1A3F4F52657C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3639AE05-14E6-43B2-9DDB-1A3F4F52657C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3639AE05-14E6-43B2-9DDB-1A3F4F52657C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3639AE05-14E6-43B2-9DDB-1A3F4F52657C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI/App.config b/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI/App.config new file mode 100644 index 0000000..8fc0551 --- /dev/null +++ b/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI/EnhancedDiscordUI.csproj b/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI/EnhancedDiscordUI.csproj new file mode 100644 index 0000000..e9aec11 --- /dev/null +++ b/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI/EnhancedDiscordUI.csproj @@ -0,0 +1,138 @@ + + + + + Debug + AnyCPU + {3639AE05-14E6-43B2-9DDB-1A3F4F52657C} + WinExe + Properties + EnhancedDiscordUI + EnhancedDiscordUI + v4.7.1 + 512 + true + + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + ed.ico + + + + + + + + + + + + + + + + + + + Form + + + Form1.cs + + + + + + Form1.cs + + + ResXFileCodeGenerator + Designer + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI/Form1.Designer.cs b/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI/Form1.Designer.cs new file mode 100644 index 0000000..37720af --- /dev/null +++ b/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI/Form1.Designer.cs @@ -0,0 +1,381 @@ +namespace EnhancedDiscordUI +{ + partial class EDInstaller + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EDInstaller)); + this.InstallButton = new System.Windows.Forms.Button(); + this.Title = new System.Windows.Forms.Label(); + this.UninstallButton = new System.Windows.Forms.Button(); + this.UpdateButton = new System.Windows.Forms.Button(); + this.InstallProgress = new System.Windows.Forms.ProgressBar(); + this.StatusLabel2 = new System.Windows.Forms.Label(); + this.StatusLabel = new System.Windows.Forms.Label(); + this.StatusCloseButton = new System.Windows.Forms.Button(); + this.StatusText = new System.Windows.Forms.TextBox(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.DevButton = new System.Windows.Forms.Button(); + this.CanaryButton = new System.Windows.Forms.Button(); + this.PTBButton = new System.Windows.Forms.Button(); + this.StableButton = new System.Windows.Forms.Button(); + this.ReinjectButton = new System.Windows.Forms.Button(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.OpenFolderButton = new System.Windows.Forms.Button(); + this.BetaRadio = new System.Windows.Forms.RadioButton(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // InstallButton + // + this.InstallButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.InstallButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.InstallButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.InstallButton.ForeColor = System.Drawing.Color.WhiteSmoke; + this.InstallButton.Location = new System.Drawing.Point(155, 127); + this.InstallButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.InstallButton.Name = "InstallButton"; + this.InstallButton.Size = new System.Drawing.Size(131, 30); + this.InstallButton.TabIndex = 0; + this.InstallButton.Text = "Install"; + this.toolTip1.SetToolTip(this.InstallButton, "Downloads and injects ED into your Discord client."); + this.InstallButton.UseVisualStyleBackColor = true; + this.InstallButton.Click += new System.EventHandler(this.InstallButton_Click); + // + // Title + // + this.Title.AutoSize = true; + this.Title.Font = new System.Drawing.Font("Segoe UI Semibold", 18F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.Title.ForeColor = System.Drawing.Color.WhiteSmoke; + this.Title.Location = new System.Drawing.Point(131, 11); + this.Title.Name = "Title"; + this.Title.Size = new System.Drawing.Size(255, 41); + this.Title.TabIndex = 1; + this.Title.Text = "EnhancedDiscord"; + // + // UninstallButton + // + this.UninstallButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.UninstallButton.Enabled = false; + this.UninstallButton.FlatAppearance.BorderColor = System.Drawing.Color.WhiteSmoke; + this.UninstallButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.UninstallButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.UninstallButton.ForeColor = System.Drawing.Color.WhiteSmoke; + this.UninstallButton.Location = new System.Drawing.Point(155, 162); + this.UninstallButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.UninstallButton.Name = "UninstallButton"; + this.UninstallButton.Size = new System.Drawing.Size(131, 30); + this.UninstallButton.TabIndex = 2; + this.UninstallButton.Text = "Uninstall"; + this.toolTip1.SetToolTip(this.UninstallButton, "Uninjects ED and prompts you to delete ED\'s files."); + this.UninstallButton.UseVisualStyleBackColor = true; + this.UninstallButton.Click += new System.EventHandler(this.UninstallButton_Click); + // + // UpdateButton + // + this.UpdateButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.UpdateButton.Enabled = false; + this.UpdateButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.UpdateButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.UpdateButton.ForeColor = System.Drawing.Color.WhiteSmoke; + this.UpdateButton.Location = new System.Drawing.Point(87, 197); + this.UpdateButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.UpdateButton.Name = "UpdateButton"; + this.UpdateButton.Size = new System.Drawing.Size(131, 30); + this.UpdateButton.TabIndex = 3; + this.UpdateButton.Text = "Update"; + this.toolTip1.SetToolTip(this.UpdateButton, "Replaces the ED files with the most recent ones."); + this.UpdateButton.UseVisualStyleBackColor = true; + this.UpdateButton.Click += new System.EventHandler(this.UpdateButton_Click); + // + // InstallProgress + // + this.InstallProgress.Location = new System.Drawing.Point(12, 218); + this.InstallProgress.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.InstallProgress.Name = "InstallProgress"; + this.InstallProgress.Size = new System.Drawing.Size(415, 23); + this.InstallProgress.Style = System.Windows.Forms.ProgressBarStyle.Continuous; + this.InstallProgress.TabIndex = 5; + this.InstallProgress.Visible = false; + // + // StatusLabel2 + // + this.StatusLabel2.AutoSize = true; + this.StatusLabel2.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.StatusLabel2.ForeColor = System.Drawing.Color.WhiteSmoke; + this.StatusLabel2.Location = new System.Drawing.Point(9, 190); + this.StatusLabel2.Name = "StatusLabel2"; + this.StatusLabel2.Size = new System.Drawing.Size(89, 19); + this.StatusLabel2.TabIndex = 8; + this.StatusLabel2.Text = "Lorem ipsum"; + this.StatusLabel2.Visible = false; + // + // StatusLabel + // + this.StatusLabel.AutoSize = true; + this.StatusLabel.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.StatusLabel.ForeColor = System.Drawing.Color.WhiteSmoke; + this.StatusLabel.Location = new System.Drawing.Point(8, 167); + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(165, 28); + this.StatusLabel.TabIndex = 9; + this.StatusLabel.Text = "Installation failed."; + this.StatusLabel.Visible = false; + // + // StatusCloseButton + // + this.StatusCloseButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.StatusCloseButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.StatusCloseButton.ForeColor = System.Drawing.Color.WhiteSmoke; + this.StatusCloseButton.Location = new System.Drawing.Point(251, 128); + this.StatusCloseButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.StatusCloseButton.Name = "StatusCloseButton"; + this.StatusCloseButton.Size = new System.Drawing.Size(64, 30); + this.StatusCloseButton.TabIndex = 10; + this.StatusCloseButton.Text = "Close"; + this.StatusCloseButton.UseVisualStyleBackColor = true; + this.StatusCloseButton.Visible = false; + this.StatusCloseButton.Click += new System.EventHandler(this.StatusCloseButton_Click); + // + // StatusText + // + this.StatusText.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(31)))), ((int)(((byte)(36)))), ((int)(((byte)(36))))); + this.StatusText.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.StatusText.Font = new System.Drawing.Font("Segoe UI", 10.2F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.StatusText.ForeColor = System.Drawing.Color.WhiteSmoke; + this.StatusText.Location = new System.Drawing.Point(11, 68); + this.StatusText.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.StatusText.Multiline = true; + this.StatusText.Name = "StatusText"; + this.StatusText.ReadOnly = true; + this.StatusText.Size = new System.Drawing.Size(416, 26); + this.StatusText.TabIndex = 11; + this.StatusText.Text = "Make sure to launch Discord before installing!"; + this.StatusText.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // DevButton + // + this.DevButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.DevButton.FlatAppearance.BorderSize = 2; + this.DevButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.DevButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.DevButton.ForeColor = System.Drawing.Color.White; + this.DevButton.Image = global::EnhancedDiscordUI.Properties.Resources.discord_dev_64; + this.DevButton.ImageAlign = System.Drawing.ContentAlignment.TopCenter; + this.DevButton.Location = new System.Drawing.Point(320, 98); + this.DevButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.DevButton.Name = "DevButton"; + this.DevButton.RightToLeft = System.Windows.Forms.RightToLeft.Yes; + this.DevButton.Size = new System.Drawing.Size(91, 110); + this.DevButton.TabIndex = 15; + this.DevButton.Text = "Dev"; + this.DevButton.TextAlign = System.Drawing.ContentAlignment.BottomCenter; + this.toolTip1.SetToolTip(this.DevButton, "Discord Development (aka Local.)"); + this.DevButton.UseVisualStyleBackColor = true; + this.DevButton.Visible = false; + this.DevButton.Click += new System.EventHandler(this.DevButton_Click); + // + // CanaryButton + // + this.CanaryButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.CanaryButton.FlatAppearance.BorderSize = 2; + this.CanaryButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.CanaryButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.CanaryButton.ForeColor = System.Drawing.Color.Gold; + this.CanaryButton.Image = global::EnhancedDiscordUI.Properties.Resources.discord_canary_64; + this.CanaryButton.ImageAlign = System.Drawing.ContentAlignment.TopCenter; + this.CanaryButton.Location = new System.Drawing.Point(224, 98); + this.CanaryButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.CanaryButton.Name = "CanaryButton"; + this.CanaryButton.RightToLeft = System.Windows.Forms.RightToLeft.Yes; + this.CanaryButton.Size = new System.Drawing.Size(91, 110); + this.CanaryButton.TabIndex = 14; + this.CanaryButton.Text = "Canary"; + this.CanaryButton.TextAlign = System.Drawing.ContentAlignment.BottomCenter; + this.toolTip1.SetToolTip(this.CanaryButton, "Discord Canary"); + this.CanaryButton.UseVisualStyleBackColor = true; + this.CanaryButton.Visible = false; + this.CanaryButton.Click += new System.EventHandler(this.CanaryButton_Click); + // + // PTBButton + // + this.PTBButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.PTBButton.FlatAppearance.BorderSize = 2; + this.PTBButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.PTBButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.PTBButton.ForeColor = System.Drawing.Color.SteelBlue; + this.PTBButton.Image = global::EnhancedDiscordUI.Properties.Resources.discord_stable_64; + this.PTBButton.ImageAlign = System.Drawing.ContentAlignment.TopCenter; + this.PTBButton.Location = new System.Drawing.Point(128, 98); + this.PTBButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.PTBButton.Name = "PTBButton"; + this.PTBButton.RightToLeft = System.Windows.Forms.RightToLeft.Yes; + this.PTBButton.Size = new System.Drawing.Size(91, 110); + this.PTBButton.TabIndex = 13; + this.PTBButton.Text = "PTB"; + this.PTBButton.TextAlign = System.Drawing.ContentAlignment.BottomCenter; + this.toolTip1.SetToolTip(this.PTBButton, "Discord PTB (Public Test Build)"); + this.PTBButton.UseVisualStyleBackColor = true; + this.PTBButton.Visible = false; + this.PTBButton.Click += new System.EventHandler(this.PTBButton_Click); + // + // StableButton + // + this.StableButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.StableButton.FlatAppearance.BorderSize = 2; + this.StableButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.StableButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.StableButton.ForeColor = System.Drawing.Color.SteelBlue; + this.StableButton.Image = global::EnhancedDiscordUI.Properties.Resources.discord_stable_64; + this.StableButton.ImageAlign = System.Drawing.ContentAlignment.TopCenter; + this.StableButton.Location = new System.Drawing.Point(32, 98); + this.StableButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.StableButton.Name = "StableButton"; + this.StableButton.RightToLeft = System.Windows.Forms.RightToLeft.Yes; + this.StableButton.Size = new System.Drawing.Size(91, 110); + this.StableButton.TabIndex = 12; + this.StableButton.Text = "Stable"; + this.StableButton.TextAlign = System.Drawing.ContentAlignment.BottomCenter; + this.toolTip1.SetToolTip(this.StableButton, "Normal version of Discord."); + this.StableButton.UseVisualStyleBackColor = true; + this.StableButton.Visible = false; + this.StableButton.Click += new System.EventHandler(this.StableButton_Click); + // + // ReinjectButton + // + this.ReinjectButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.ReinjectButton.Enabled = false; + this.ReinjectButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.ReinjectButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.ReinjectButton.ForeColor = System.Drawing.Color.WhiteSmoke; + this.ReinjectButton.Location = new System.Drawing.Point(225, 197); + this.ReinjectButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.ReinjectButton.Name = "ReinjectButton"; + this.ReinjectButton.Size = new System.Drawing.Size(131, 30); + this.ReinjectButton.TabIndex = 17; + this.ReinjectButton.Text = "Reinject"; + this.toolTip1.SetToolTip(this.ReinjectButton, "Reinjects without changing your ED folder; useful after Discord updates."); + this.ReinjectButton.UseVisualStyleBackColor = true; + this.ReinjectButton.Click += new System.EventHandler(this.ReinjectButton_Click); + // + // pictureBox1 + // + this.pictureBox1.Image = global::EnhancedDiscordUI.Properties.Resources.ed_og; + this.pictureBox1.Location = new System.Drawing.Point(41, 12); + this.pictureBox1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(87, 50); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.pictureBox1.TabIndex = 4; + this.pictureBox1.TabStop = false; + // + // OpenFolderButton + // + this.OpenFolderButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.OpenFolderButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.OpenFolderButton.ForeColor = System.Drawing.Color.WhiteSmoke; + this.OpenFolderButton.Location = new System.Drawing.Point(113, 128); + this.OpenFolderButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.OpenFolderButton.Name = "OpenFolderButton"; + this.OpenFolderButton.Size = new System.Drawing.Size(125, 30); + this.OpenFolderButton.TabIndex = 16; + this.OpenFolderButton.Text = "Open Folder"; + this.OpenFolderButton.UseVisualStyleBackColor = true; + this.OpenFolderButton.Visible = false; + this.OpenFolderButton.Click += new System.EventHandler(this.OpenFolderButton_Click); + // + // BetaRadio + // + this.BetaRadio.AutoSize = true; + this.BetaRadio.Font = new System.Drawing.Font("Segoe UI", 10.2F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.BetaRadio.ForeColor = System.Drawing.SystemColors.ControlLightLight; + this.BetaRadio.Location = new System.Drawing.Point(115, 95); + this.BetaRadio.Name = "BetaRadio"; + this.BetaRadio.Size = new System.Drawing.Size(200, 27); + this.BetaRadio.TabIndex = 18; + this.BetaRadio.TabStop = true; + this.BetaRadio.Text = "Opt-in to beta version"; + this.BetaRadio.UseVisualStyleBackColor = true; + // + // EDInstaller + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(31)))), ((int)(((byte)(36)))), ((int)(((byte)(36))))); + this.ClientSize = new System.Drawing.Size(439, 254); + this.Controls.Add(this.BetaRadio); + this.Controls.Add(this.ReinjectButton); + this.Controls.Add(this.OpenFolderButton); + this.Controls.Add(this.UninstallButton); + this.Controls.Add(this.StatusCloseButton); + this.Controls.Add(this.StatusLabel); + this.Controls.Add(this.StatusLabel2); + this.Controls.Add(this.InstallProgress); + this.Controls.Add(this.pictureBox1); + this.Controls.Add(this.UpdateButton); + this.Controls.Add(this.Title); + this.Controls.Add(this.InstallButton); + this.Controls.Add(this.StatusText); + this.Controls.Add(this.StableButton); + this.Controls.Add(this.DevButton); + this.Controls.Add(this.CanaryButton); + this.Controls.Add(this.PTBButton); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.Name = "EDInstaller"; + this.Text = "EnhancedDiscord Installer"; + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button InstallButton; + private System.Windows.Forms.Label Title; + private System.Windows.Forms.Button UninstallButton; + private System.Windows.Forms.Button UpdateButton; + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.ProgressBar InstallProgress; + private System.Windows.Forms.Label StatusLabel2; + private System.Windows.Forms.Label StatusLabel; + private System.Windows.Forms.Button StatusCloseButton; + private System.Windows.Forms.TextBox StatusText; + private System.Windows.Forms.ToolTip toolTip1; + private System.Windows.Forms.Button StableButton; + private System.Windows.Forms.Button PTBButton; + private System.Windows.Forms.Button CanaryButton; + private System.Windows.Forms.Button DevButton; + private System.Windows.Forms.Button OpenFolderButton; + private System.Windows.Forms.Button ReinjectButton; + private System.Windows.Forms.RadioButton BetaRadio; + } +} + diff --git a/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI/Form1.cs b/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI/Form1.cs new file mode 100644 index 0000000..ff1f485 --- /dev/null +++ b/files/.config/EnhancedDiscord/installer/EnhancedDiscordUI/Form1.cs @@ -0,0 +1,750 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Diagnostics; +using System.IO; +using System.Net; +using System.IO.Compression; +using System.Runtime.InteropServices; + +namespace EnhancedDiscordUI +{ + public partial class EDInstaller : Form + { + private Process stableProcess; + private Process ptbProcess; + private Process canaryProcess; + private Process devProcess; + private string operation = "INSTALL"; + private string platform; + private string branch = "master"; + + public EDInstaller() + { + Logger.MakeDivider(); + Logger.Log("Starting..."); + InitializeComponent(); + if (Directory.Exists("./EnhancedDiscord")) + { + UninstallButton.Enabled = true; + UpdateButton.Enabled = true; + ReinjectButton.Enabled = true; + } + } + private void endInstallation(string reason, bool failed) + { + InstallProgress.Value = 100; + BetaRadio.Hide(); + InstallButton.Hide(); + UninstallButton.Hide(); + UpdateButton.Hide(); + ReinjectButton.Hide(); + StatusText.Hide(); + StatusLabel.Show(); + StatusLabel.Text = operation == "UPDATE" ? "Update " + (failed ? "failed" : "complete") : (operation == "UNINSTALL" ? "Unin" : "In") + "stallation " + (failed ? " failed." : "completed!"); + StatusLabel.ForeColor = failed ? Color.Red : Color.Lime; + StatusLabel2.Show(); + StatusLabel2.Text = reason; + StatusCloseButton.Show(); + if (platform != "Linux") + { + OpenFolderButton.Show(); + } + } + private void InstallButton_Click(object sender, EventArgs e) + { + if (BetaRadio.Checked) + { + branch = "beta"; + } + BetaRadio.Hide(); + InstallButton.Hide(); + UninstallButton.Hide(); + UpdateButton.Hide(); + ReinjectButton.Hide(); + StatusText.Show(); + InstallProgress.Show(); + StatusText.Text = "Finding Discord processes..."; + + Process[] stable = Process.GetProcessesByName("Discord"); + Process[] canary = Process.GetProcessesByName("DiscordCanary"); + Process[] ptb = Process.GetProcessesByName("DiscordPtb"); + Process[] dev = Process.GetProcessesByName("DiscordDevelopment"); + + List discordProcesses = new List(); + discordProcesses.AddRange(stable); + discordProcesses.AddRange(canary); + discordProcesses.AddRange(ptb); + discordProcesses.AddRange(dev); + + if (discordProcesses.Count == 0) + { + endInstallation("No Discord processes found. Please open Discord and try again.", true); return; + } + List uniqueProcesses = new List(); + // First look for processes with unique filenames that have a title + for (int i = 0; i < discordProcesses.Count; i++) + { + bool isUnique = true; + for (int j = 0; j < uniqueProcesses.Count; j++) + { + if (uniqueProcesses[j].MainModule.FileName.Equals(discordProcesses[i].MainModule.FileName)) + { + isUnique = false; break; + } + } + if (!isUnique || discordProcesses[i].MainWindowTitle == "" || discordProcesses[i].MainWindowTitle.StartsWith("Developer Tools")) continue; + + uniqueProcesses.Add(discordProcesses[i]); + } + // Then look for all processes with unique filenames + for (int i = 0; i < discordProcesses.Count; i++) + { + bool isUnique = true; + for (int j = 0; j < uniqueProcesses.Count; j++) + { + if (uniqueProcesses[j].MainModule.FileName.Equals(discordProcesses[i].MainModule.FileName)) + { + isUnique = false; break; + } + } + if (!isUnique) continue; + uniqueProcesses.Add(discordProcesses[i]); + } + StatusText.Text = "Found " + uniqueProcesses.Count + " Discord process" + (uniqueProcesses.Count == 1 ? "" : "es") + "."; + InstallProgress.Value = 10; + Process finalProcess = uniqueProcesses[0]; + if (uniqueProcesses.Count > 1) + { + // Enable selection buttons + List` + return result + }, + settingListeners: [ + { + el: "#save-css-path", + type: "click", + eHandler: function () { + //console.log(this, e.target); + const pathInput = document.getElementById("custom-css-path") + if (!pathInput) return + if (pathInput.value && module.exports.config.path.parse(pathInput.value) == false) { + const cont = this.firstElementChild + cont.innerHTML = "Invalid file." + setTimeout(() => { + try { + cont.innerHTML = "Save" + } catch (err) { + /*do nothing*/ + } + }, 3000) + return + } + const newPath = + module.exports.config.path.parse(pathInput.value) || module.exports.config.path.default + const s = module.exports.settings + if (s.path == newPath) { + const cont = this.firstElementChild + cont.innerHTML = "Path was already saved." + setTimeout(() => { + try { + cont.innerHTML = "Save" + } catch (err) { + /*do nothing*/ + } + }, 3000) + return + } + s.path = newPath + module.exports.settings = s + module.exports.unload() + module.exports.load() + const cont = this.firstElementChild + cont.innerHTML = "Saved!" + setTimeout(() => { + try { + cont.innerHTML = "Save" + } catch (err) { + /*do nothing*/ + } + }, 3000) + }, + }, + ], +}) diff --git a/files/.config/EnhancedDiscord/plugins/direct_download.js b/files/.config/EnhancedDiscord/plugins/direct_download.js new file mode 100644 index 0000000..414ffbd --- /dev/null +++ b/files/.config/EnhancedDiscord/plugins/direct_download.js @@ -0,0 +1,104 @@ +const Plugin = require('../plugin'); + +// contains modified code from https://stackoverflow.com/a/47820271 +const { dialog } = require('electron').remote; +const http = require('https'); +const fs = require('fs'); +let ttM = {}, iteM = {}; + +function saveAs(url, filename, fileExtension) { + const userChosenPath = dialog.showSaveDialog({ defaultPath: filename, title: 'Where would you like to store the stolen memes?', buttonLabel: 'Steal this meme', filters: [{ name: "Stolen meme", extensions: [fileExtension] }] }); + if (userChosenPath) { + download(url, userChosenPath, () => { + const wrap = document.createElement('div'); + wrap.className = 'theme-dark'; + const gay = document.createElement('div'); + gay.style = "position: fixed; bottom: 10%; left: calc(50% - 88px);" + gay.className = `${ttM.tooltip} ${ttM.tooltipTop} ${ttM.tooltipBlack}`; + gay.innerHTML = 'Successfully downloaded | ' + userChosenPath; + document.body.appendChild(wrap); + wrap.appendChild(gay); + setTimeout(() => wrap.remove(), 2000); + }); + } +} +function download (url, dest, cb) { + const file = fs.createWriteStream(dest); + http.get(url, function(response) { + response.pipe(file); + file.on('finish', function() { + file.close(cb); + }); + }).on('error', function(err) { + fs.unlink(dest); + if (cb) cb(err.message); + }); +} + +function addMenuItem(url, text, filename = true, fileExtension) { + const cmGroups = document.getElementsByClassName(iteM.itemGroup); + if (!cmGroups || cmGroups.length == 0) return; + + const newCmItem = document.createElement('div'); + newCmItem.className = iteM.item; + newCmItem.innerHTML = text; + + const lastGroup = cmGroups[cmGroups.length-1]; + lastGroup.appendChild(newCmItem); + newCmItem.onclick = () => saveAs(url, filename, fileExtension); +} + +// contains code modified from https://github.com/Metalloriff/BetterDiscordPlugins/blob/master/SaveTo.plugin.js + +module.exports = new Plugin({ + name: 'Direct Download', + author: 'Joe 🎸#7070', + description: `Download files Steal memes without opening a browser.`, + color: '#18770e', + + load: async function() { + this._cmClass = window.EDApi.findModule("contextMenu").contextMenu; + this._contClass = window.EDApi.findModule("embedWrapper").container; + ttM = window.EDApi.findModule('tooltipPointer'); + iteM = window.EDApi.findModule('itemBase'); + document.addEventListener("contextmenu", this.listener); + }, + listener(e) { + if (document.getElementsByClassName(this._cmClass).length == 0) setTimeout(() => module.exports.onContextMenu(e), 0); + else this.onContextMenu(e); + }, + onContextMenu(e) { + const messageGroup = e.target.closest('.'+this._contClass); + + if (e.target.localName != "a" && e.target.localName != "img" && e.target.localName != "video" && !messageGroup && !e.target.className.includes("guildIcon") && !e.target.className.includes("image-")) return; + + let saveLabel = "Download", + url = e.target.poster || e.target.style.backgroundImage.substring(e.target.style.backgroundImage.indexOf(`"`) + 1, e.target.style.backgroundImage.lastIndexOf(`"`)) || e.target.href || e.target.src; + + if (e.target.className.includes("guildIcon")) saveLabel = "Download Icon"; + else if (e.target.className.includes("image-")) saveLabel = "Download Avatar"; + + + if (!url || e.target.classList.contains("emote") || url.includes("youtube.com/watch?v=") || url.includes("youtu.be/") || url.lastIndexOf("/") > url.lastIndexOf(".")) return; + + url = url.split("?")[0]; + + url = url.replace(".webp", ".png"); + + let fileName = url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf(".")); + const fileExtension = url.substr(url.lastIndexOf(".") + 1, url.length); + + if (saveLabel.includes("Avatar") || saveLabel.includes("Icon")) url += "?size=2048"; + + if (e.target.classList.contains("emoji")) { + saveLabel = "Download Emoji"; + fileName = e.target.alt.replace(/[^A-Za-z_-]/g, ""); + } + //console.log({url, saveLabel, fileName, fileExtension}); + + setTimeout(() => addMenuItem(url, saveLabel, fileName, fileExtension), 5); + }, + unload: function() { + document.removeEventListener("contextmenu", this.listener); + } +}); diff --git a/files/.config/EnhancedDiscord/plugins/double_click_edit.js b/files/.config/EnhancedDiscord/plugins/double_click_edit.js new file mode 100644 index 0000000..d48e88a --- /dev/null +++ b/files/.config/EnhancedDiscord/plugins/double_click_edit.js @@ -0,0 +1,85 @@ +const Plugin = require('../plugin'); +let contM = {}, cM, eM, dM, mM, ewM = {}, ree; + +module.exports = new Plugin({ + name: 'Double-Click Edit', + author: 'Joe 🎸#7070', + description: 'Allows you to double-click a message to edit or hold delete + click to delete.', + color: '#ff5900', + + deletePressed: false, + load: async function() { + contM = window.EDApi.findModule(m => m.container && m.containerCozy); + cM = window.EDApi.findModule('getChannelId'); + eM = window.EDApi.findModule('startEditMessage'); + dM = window.EDApi.findModule('deleteMessage'); + mM = window.EDApi.findModule('getRawMessages'); + ewM = window.EDApi.findModule('embedWrapper'); + if (!cM || !eM || !dM || !ewM) { + return this.error('Aborted loading - Failed to find required modules!'); + } + ree = this; + + document.addEventListener("dblclick", this.editListener, false); + document.addEventListener("keydown", this.keyDownListener); + document.addEventListener("keyup", this.keyUpListener); + document.addEventListener("click", this.deleteListener); + + // allow editing in "locked" (read-only) channels + const prot = window.EDApi.findModuleByDisplayName("ChannelEditorContainer").prototype; + window.EDApi.monkeyPatch(prot, 'render', b => { + if (b.thisObject.props.type === 'edit') + b.thisObject.props.disabled = false; + return b.callOriginalMethod(b.methodArguments); + }); + }, + unload: async function() { + document.removeEventListener("dblclick", this.editListener); + document.removeEventListener("keydown", this.keyDownListener); + document.removeEventListener("keyup", this.keyUpListener); + document.removeEventListener("click", this.deleteListener); + }, + + editListener: function(e) { + const messageElem = e.target.closest('.'+contM.container); + if (!messageElem) return; + let msgObj; + try { + msgObj = messageElem.__reactInternalInstance$.return.return.memoizedProps.message; + } catch(err) { + ree.error(err); + } + if (!msgObj) return; + const channelId = cM.getChannelId(); + if (!channelId) return; + const newMsgObj = mM.getMessage(msgObj.channel_id, msgObj.id); + return eM.startEditMessage(channelId, msgObj.id, newMsgObj.content || ''); + }, + deleteListener: function(e) { + if (!ree.deletePressed) return; + + let messageElem = e.target.closest('.'+contM.container); + const wrapperElem = e.target.closest('.'+ewM.container); + if (!messageElem && wrapperElem) + messageElem = wrapperElem.parentElement.firstElementChild; + if (!messageElem) return; + let msgObj; + try { + msgObj = messageElem.__reactInternalInstance$.return.return.memoizedProps.message; + } catch(err) { + ree.error(err); + } + if (!msgObj) return; + const channelId = cM.getChannelId(); + if (!channelId) return; + return dM.deleteMessage(channelId, msgObj.id); + }, + keyUpListener: function(e) { + if (e.keyCode == 46) + ree.deletePressed = false; + }, + keyDownListener: function(e) { + if (e.keyCode == 46) + ree.deletePressed = true; + } +}); diff --git a/files/.config/EnhancedDiscord/plugins/double_click_mention.js b/files/.config/EnhancedDiscord/plugins/double_click_mention.js new file mode 100644 index 0000000..e32ef80 --- /dev/null +++ b/files/.config/EnhancedDiscord/plugins/double_click_mention.js @@ -0,0 +1,42 @@ +const Plugin = require('../plugin'); +let userM = {}, taM = {}, avM = {}, wM = {}, ree; + +module.exports = new Plugin({ + name: 'Double-Click Mention', + author: 'Joe 🎸#7070', + description: 'Allows you to double-click a user\'s name to mention them.', + color: '#00bbff', + + _userTag: '', + load: async function() { + taM = window.EDApi.findModule('textArea'); + userM = window.EDApi.findModule('username'); + avM = window.EDApi.findModule('avatar'); + wM = window.EDApi.findModule(m => m.wrapper && m.avatar); + ree = this; + + document.addEventListener("dblclick", this.doubleListener); + }, + unload: async function() { + document.removeEventListener("dblclick", this.doubleListener); + }, + + doubleListener: function(e) { + if (!e || !e.target || !e.target.parentElement) return; + let tag; + try { + if (e.target.className === userM.username) + tag = e.target.parentElement.__reactInternalInstance$.return.return.memoizedProps.message.author.tag; + else if (e.target.className === wM.wrapper && e.target.parentElement.className === avM.avatar) + tag = e.target.parentElement.__reactInternalInstance$.return.return.memoizedProps.user.tag; + } catch(err) { + ree.error(err); + tag = null; + } + if (!tag) return; + + const ta = document.querySelector('.'+taM.textArea); + if (!ta) return; + ta.value = `${ta.value ? ta.value.endsWith(' ') ? ta.value : ta.value+' ' : ''}@${tag} `; + } +}); diff --git a/files/.config/EnhancedDiscord/plugins/ed_settings.js b/files/.config/EnhancedDiscord/plugins/ed_settings.js new file mode 100644 index 0000000..26858ff --- /dev/null +++ b/files/.config/EnhancedDiscord/plugins/ed_settings.js @@ -0,0 +1,251 @@ +const Plugin = require('../plugin'); + +function makePluginToggle(opts = {}) { + const a = window.ED.classMaps.alignment; + const sw = window.ED.classMaps.switchItem; + const cb = window.ED.classMaps.checkbox; + const b = window.ED.classMaps.buttons; + const d = window.ED.classMaps.description; + const settingsButton = ``; + + return `
+
+

${opts.title}

+ ${opts.color ? `
` : ''} + ${opts.showSettingsButton ? settingsButton : ''} + ${opts.id == 'bdPlugins' ? '' : ``} +
+ +
+
+
${opts.desc ? opts.desc : 'No Description Provided +
+
`; +} + +module.exports = new Plugin({ + name: 'ED Settings', + author: 'Joe 🎸#7070', + description: 'Adds an EnhancedDiscord tab in user settings.', + color: 'darkred', + + load: async function() { + const parentThis = this; //Allow use of parent methods in sub functions + + if (!window.ED.classMaps) { + window.ED.classMaps = {}; + } + const tabsM = window.EDApi.findModule('topPill'); + const divM = window.EDApi.findModule(m => m.divider && Object.keys(m).length === 1) + const contentM = window.ED.classMaps.headers = window.EDApi.findModule('defaultMarginh2'); + const marginM = window.ED.classMaps.margins = window.EDApi.findModule('marginBottom8'); + const div = window.ED.classMaps.divider = divM ? divM.divider : ''; + const cbM = window.ED.classMaps.checkbox = window.EDApi.findModule('checkboxEnabled'); + const buttM = window.ED.classMaps.buttons = window.EDApi.findModule('lookFilled'); + const concentCol = window.EDApi.findModule('contentColumn'); + window.ED.classMaps.switchItem = window.EDApi.findModule('switchItem'); + window.ED.classMaps.alignment = window.EDApi.findModule('horizontalReverse'); + window.ED.classMaps.description = window.EDApi.findModule('formText'); + + // use this function to trigger the loading of the settings tabs. No MutationObservers this way :) + const gss = window.EDApi.findModule('getUserSettingsSections').default.prototype; + window.EDApi.monkeyPatch(gss, 'render', function() { + + const tab = document.getElementsByClassName('ed-settings'); + //console.log(tab); + if (!tab || tab.length < 1) { + const parent = document.querySelector('.' + tabsM.side); + if (!parent) { + setTimeout(() => {arguments[0].thisObject.forceUpdate();}, 100); + return arguments[0].callOriginalMethod(arguments[0].methodArguments); + } + const anchor = parent.querySelectorAll(`.${tabsM.separator}`)[3]; + if (!anchor) + return arguments[0].callOriginalMethod(arguments[0].methodArguments); + + const header = document.createElement('div'); + header.className = tabsM.header + ' ed-settings'; + header.innerHTML = 'EnhancedDiscord'; + anchor.parentNode.insertBefore(header, anchor.nextSibling); + + const pluginsTab = document.createElement('div'); + const tabClass = `${tabsM.item} ${tabsM.themed} ed-settings`; + pluginsTab.className = tabClass; + pluginsTab.innerHTML = 'Plugins'; + header.parentNode.insertBefore(pluginsTab, header.nextSibling); + + const settingsTab = document.createElement('div'); + settingsTab.className = tabClass; + settingsTab.innerHTML = 'Settings'; + pluginsTab.parentNode.insertBefore(settingsTab, pluginsTab.nextSibling); + + const sep = document.createElement('div'); + sep.className = tabsM.separator; + settingsTab.parentNode.insertBefore(sep, settingsTab.nextSibling); + + parent.onclick = function(e) { + if (!e.target.className || e.target.className.indexOf(tabsM.item) == -1 || e.target.innerHTML === 'Change Log') return; + + for (const i in tab) { + tab[i].className = (tab[i].className || '').replace(" " + tabsM.selected, '') + } + } + + pluginsTab.onclick = function(e) { + const settingsPane = document.querySelector(`.${concentCol.standardSidebarView} .${concentCol.contentColumn} > div`); + const otherTab = document.querySelector('.' + tabsM.item + '.' + tabsM.selected); + if (otherTab) { + otherTab.className = otherTab.className.replace(" " + tabsM.selected, ''); + } + this.className += ` ${tabsM.selected}`; + + if (settingsPane) { + // ED Header + settingsPane.innerHTML = `

EnhancedDiscord Plugins

`; + // Open Plugins Folder Button + settingsPane.innerHTML += ``; + // Divider + settingsPane.innerHTML += `
` + + for (const id in window.ED.plugins) { + //if (id == 'ed_settings') continue; + + settingsPane.innerHTML += makePluginToggle({id, title: window.ED.plugins[id].name, desc: window.ED.plugins[id].description, color: window.ED.plugins[id].color || 'orange', showSettingsButton: typeof window.ED.plugins[id].getSettingsPanel == 'function'}); + if (!window.ED.plugins[id].settings || window.ED.plugins[id].settings.enabled !== false) { + const cb = document.getElementById(id); + if (cb && cb.className) + cb.className = cb.className.replace(cbM.valueUnchecked, cbM.valueChecked); + } + } + + document.getElementById("ed-openPluginsFolder").onclick = function () { + const s = require("electron").shell.openItem(require("path").join(process.env.injDir, "plugins")) + if (s === false) console.error("[EnhancedDiscord] Unable to open external folder.") + } + } + e.stopPropagation(); // prevent from going to parent click handler + } + + settingsTab.onclick = function(e) { + const settingsPane = document.querySelector(`.${concentCol.standardSidebarView} .${concentCol.contentColumn} > div`); + const otherTab = document.querySelector('.' + tabsM.item + '.' + tabsM.selected); + if (otherTab) { + otherTab.className = otherTab.className.replace(" " + tabsM.selected, ''); + } + this.className += ` ${tabsM.selected}`; + + if (settingsPane) { + settingsPane.innerHTML = `

EnhancedDiscord Configuration

`; + settingsPane.innerHTML += makePluginToggle({id: 'bdPlugins', title: 'BD Plugins', desc: "Allows ED to load BD plugins natively. (Reload with ctrl+r after enabling/disabling.)"}); + + const bl = document.getElementById('bdPlugins'); + if (bl && window.ED.config.bdPlugins == true) + bl.className = bl.className.replace(cbM.valueUnchecked, cbM.valueChecked); + //console.log(st, at); + for (const id in window.ED.plugins) { + if (window.ED.plugins[id].getSettingsPanel && typeof window.ED.plugins[id].getSettingsPanel == 'function') continue; + if (!window.ED.plugins[id].config || window.ED.config[id].enabled === false || !window.ED.plugins[id].generateSettings) continue; + + settingsPane.innerHTML += `

${window.ED.plugins[id].name}

`; + + settingsPane.innerHTML += window.ED.plugins[id].generateSettings(); + + settingsPane.innerHTML += `
`; + if (window.ED.plugins[id].settingListeners) { + setTimeout(() => { // let shit render + for(const eventObject in window.ED.plugins[id].settingListeners){ + const currentSettingListener = window.ED.plugins[id].settingListeners[eventObject]; + //Check if plugin is using the old format + + if(Array.isArray(window.ED.plugins[id].settingListeners)){ + const elem = settingsPane.querySelector(currentSettingListener.el); + if (elem) + elem.addEventListener(currentSettingListener.type, currentSettingListener.eHandler); + } else { + const elem = settingsPane.querySelector(eventObject); + if (elem){ + parentThis.warn(`Plugin ${window.ED.plugins[id].name} is using a deprecated plugin format (New format: https://github.com/joe27g/EnhancedDiscord/blob/beta/plugins.md#advanced-plugin-functionality). Ignore this unless you're the plugin dev`) + elem.onclick = window.ED.plugins[id].settingListeners[eventObject]; + } + } + } + }, 5); + } + } + } + e.stopPropagation(); // prevent from going to parent click handler + } + + document.querySelector(`.${concentCol.standardSidebarView} .${concentCol.contentColumn}`).onclick = function(e) { + const parent = e.target.parentElement; + if (e.target.className && ((parent.className.indexOf && parent.className.indexOf('ed-plugin-settings') > -1) || (e.target.className.indexOf && e.target.className.indexOf('ed-plugin-settings') > -1))) { + const box = e.target.className === buttM.contents ? parent.nextElementSibling.nextElementSibling : e.target.nextElementSibling.nextElementSibling; + if (!box || !box.id || !window.ED.plugins[box.id] || box.className.indexOf(cbM.valueChecked) == -1 || !window.ED.config.bdPlugins) return; + return require('../bd_shit').showSettingsModal(window.ED.plugins[box.id]); + } + + if (e.target.className && ((parent.className.indexOf && parent.className.indexOf('ed-plugin-reload') > -1) || (e.target.className.indexOf && e.target.className.indexOf('ed-plugin-reload') > -1))) { + const button = e.target.className === buttM.contents ? e.target : e.target.firstElementChild; + const plugin = e.target.className === buttM.contents ? e.target.parentElement.nextElementSibling : e.target.nextElementSibling; + //console.log(plugin); + if (!plugin || !plugin.id || !window.ED.plugins[plugin.id] || plugin.className.indexOf(cbM.valueChecked) == -1) return; + button.innerHTML = 'Reloading...'; + try { + window.ED.plugins[plugin.id].reload(); + button.innerHTML = 'Reloaded!'; + } catch(err) { + console.error(err); + button.innerHTML = `Failed to reload (${err.name} - see console.)`; + } + setTimeout(() => { + try { button.innerHTML = 'Reload'; } catch(err){/*do nothing*/} + }, 3000); + return; + } + + if (e.target.tagName !== 'INPUT' || e.target.type !== 'checkbox' || !parent || !parent.className || !parent.id) return; + const p = window.ED.plugins[parent.id]; + if (!p && parent.id !== 'bdPlugins') return; + //console.log('settings for '+p.id, p.settings); + + if (parent.className.indexOf(cbM.valueChecked) > -1) { + if (p) { + if (p.settings.enabled === false) return; + + p.settings.enabled = false; + window.ED.plugins[parent.id].settings = p.settings; + p.unload(); + } + else { + const edc = window.ED.config; + if (!edc[parent.id]) return; + edc[parent.id] = false; + window.ED.config = edc; + } + parent.className = parent.className.replace(cbM.valueChecked, cbM.valueUnchecked); + } else { + if (p) { + if (p.settings.enabled !== false) return; + + p.settings.enabled = true; + window.ED.plugins[parent.id].settings = p.settings; + p.load(); + } + else { + const edc = window.ED.config; + if (edc[parent.id] === true) return; + edc[parent.id] = true; + window.ED.config = edc; + } + parent.className = parent.className.replace(cbM.valueUnchecked, cbM.valueChecked); + } + } + } + return arguments[0].callOriginalMethod(arguments[0].methodArguments); + }) + }, + + unload: function() { + window.EDApi.findModule('getUserSettingsSections').default.prototype.render.unpatch(); + } +}); diff --git a/files/.config/EnhancedDiscord/plugins/friend_count.js b/files/.config/EnhancedDiscord/plugins/friend_count.js new file mode 100644 index 0000000..1e18827 --- /dev/null +++ b/files/.config/EnhancedDiscord/plugins/friend_count.js @@ -0,0 +1,91 @@ +const Plugin = require('../plugin'); + +function makeToggle() { + const a = window.ED.classMaps.alignment; + const sw = window.ED.classMaps.switchItem; + const cb = window.ED.classMaps.checkbox; + const b = window.ED.classMaps.buttons; + const d = window.ED.classMaps.description; + + return `
+
+
+

Online Friends

+ + +
+ +
+
+
Only show the number of friends online rather than all friends.
+
`; +} + +module.exports = new Plugin({ + name: 'Friend Count', + author: 'Joe 🎸#7070', + description: "Adds the number of friends/online friends under the \"Home\" button in the top left.", + color: 'cornflowerblue', + + config: { + onlineOnly: {default: false} + }, + + load: async function() { + const sep = window.findModule('guildSeparator'), ms = window.findModule('modeSelectable'); + + const gg = function(b) { + if (!sep) return; + const o = (module.exports.settings || {}).onlineOnly; + const num = o ? window.findModule("getOnlineFriendCount").getOnlineFriendCount() : window.findModule("getFriendIDs").getFriendIDs().length; + + let friendCount = document.getElementById('ed_friend_count'); + if (friendCount) { + if (num === this._num) return; // don't update if # is the same as before + friendCount.innerHTML = num + (o ? ' Online' : ' Friends'); + this._num = num; + return; + } + let separator = document.querySelector(`.${sep.guildSeparator}`); + if (separator) { + friendCount = document.createElement('div'); + friendCount.className = `${ms ? ms.description+' ' : ''}${sep.listItem}`; + friendCount.innerHTML = num + (o ? ' Online' : ' Friends'); + friendCount.id = 'ed_friend_count'; + try { + separator.parentElement.insertAdjacentElement('beforebegin', friendCount); + this._num = num; + } catch(err) { + this.error(err); + } + } + }; + const x = window.findModule('getGuilds'); + findModule('subscribe').subscribe('CONNECTION_OPEN', x.getGuilds); + window.monkeyPatch(x, 'getGuilds', {silent: true, after: gg}); + }, + unload: function() { + let m = window.findModule('getGuilds').getGuilds; + if (m && m.__monkeyPatched) + m.unpatch(); + let friendCount = document.getElementById('ed_friend_count'); + if (friendCount) + friendCount.remove(); + }, + generateSettings: makeToggle, + settingListeners: [{ + el: '#fc_online', + type: 'click', + eHandler: function(e) { + const cb = window.ED.classMaps.checkbox; + module.exports.settings = {onlineOnly: !(module.exports.settings || {}).onlineOnly}; + if (module.exports.settings.onlineOnly) { + this.classList.remove(cb.valueUnchecked.split(' ')[0]); + this.classList.add(cb.valueChecked.split(' ')[0]); + } else { + this.classList.remove(cb.valueChecked.split(' ')[0]); + this.classList.add(cb.valueUnchecked.split(' ')[0]); + } + } + }] +}); diff --git a/files/.config/EnhancedDiscord/plugins/guild_count.js b/files/.config/EnhancedDiscord/plugins/guild_count.js new file mode 100644 index 0000000..ef6104f --- /dev/null +++ b/files/.config/EnhancedDiscord/plugins/guild_count.js @@ -0,0 +1,53 @@ +const Plugin = require('../plugin'); + +let sep = {}, ms = {}, gg, sub; + +module.exports = new Plugin({ + name: 'Server Count', + author: 'Joe 🎸#7070', + description: "Adds the number of servers you're currently in right above the list.", + color: 'indigo', + + load: async function() { + sep = window.EDApi.findModule('guildSeparator'); + ms = window.EDApi.findModule('modeSelectable'); + gg = window.EDApi.findModule('getGuilds'); + sub = window.EDApi.findModule('subscribe'); + + window.EDApi.monkeyPatch(gg, 'getGuilds', {after: this.refreshCount, silent: true}); + sub.subscribe('CONNECTION_OPEN', gg.getGuilds); + }, + refreshCount: function(b) { + if (!sep) return; + const num = Object.keys(b.returnValue).length; + + let guildCount = document.getElementById('ed_guild_count'); + if (guildCount) { + if (num === this._num) return; // don't update if # is the same as before + guildCount.innerHTML = num + ' Servers'; + this._num = num; + return; + } + const separator = document.querySelector(`.${sep.guildSeparator}`); + if (separator) { + guildCount = document.createElement('div'); + guildCount.className = `${ms ? ms.description+' ' : ''}${sep.listItem}`; + guildCount.innerHTML = num + ' Servers'; + guildCount.id = 'ed_guild_count'; + try { + separator.parentElement.insertAdjacentElement('beforebegin', guildCount); + this._num = num; + } catch(err) { + this.error(err); + } + } + return; + }, + unload: function() { + gg.getGuilds.unpatch(); + const guildCount = document.getElementById('ed_guild_count'); + if (guildCount) + guildCount.remove(); + sub.unsubscribe('CONNECTION_OPEN', gg.getGuilds); + } +}); diff --git a/files/.config/EnhancedDiscord/plugins/hidden_channels.js b/files/.config/EnhancedDiscord/plugins/hidden_channels.js new file mode 100644 index 0000000..9c342a0 --- /dev/null +++ b/files/.config/EnhancedDiscord/plugins/hidden_channels.js @@ -0,0 +1,220 @@ +const Plugin = require('../plugin'); + +let getChannel, g_dc, g_cat, ha, disp, chanM, fm, reb, sv, cs, csp, ghp, gs, gsr, pf, sw = {}, g = {}, ai = {}; + +// copied from Discord's minified JS +function N(e,o,l,n){let r;r||(r="function"==typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103);const t=e&&e.defaultProps,f=arguments.length-3;if(o||0===f||(o={children:void 0}),o&&t)for(const e in t)void 0===o[e]&&(o[e]=t[e]);else o||(o=t||{});if(1===f)o.children=n;else if(f>1){const e=new Array(f);for(let o=0;o