├── LICENSE ├── README.md └── modules ├── backend ├── avatarDataAttribute.js ├── customCss.js ├── devMode.js ├── fucklytics.js ├── noPingReply.js └── silentTyping.js ├── customisation └── customSounds.js ├── debug └── discordDebug.js ├── fun ├── eggScrambler.js ├── expandCord.js ├── messageScrambler.js ├── owoCord.js └── rainbowCord.js ├── messages ├── censorRudeWords.js ├── copyRaw.js ├── hideBlockedMessages.js ├── noMessageDeletion.js ├── roleColoredMessages.js ├── twitchEmotes.js ├── usernameInAuthor.js └── wysiwygMessages.js ├── quick-actions ├── clearRecentGames.js ├── downloadImagesShortcut.js ├── gameActivityButton.js ├── macros.js ├── relaunch.js └── sendButton.js ├── themes ├── bloodyHellMate.js ├── comfyTheme.js ├── couveTheme.js ├── customTheme.js ├── darkerTheme.js ├── darkestTheme.js ├── draculaTheme.js ├── duvboxTheme.js ├── iFixedDiscordTheme.js ├── nordtheme.js ├── protoncord.js ├── slateTheme.js ├── solarizedDarkTheme.js └── splendidTheme.js └── ui ├── betterChannelIndicators.js ├── betterNsfw.js ├── bottomBar.js ├── deNitro.js ├── fullscreenInbox.js ├── gradientButtons.js ├── hardcodedColorFixer.js ├── hideClyde.js ├── hideMessage.js ├── hideQuickReactions.js ├── horizontalServerList.js ├── nicerUserConnections.js ├── nicknamePanel.js ├── noNotes.js ├── overlayUserPanel.js ├── powerAnimations.js ├── radialStatus.js ├── revampedUserArea.js ├── serverCount.js ├── showAllActivities.js ├── simpleStatusIcons.js ├── stickyNotes.js ├── toggleMessageButtons.js ├── userPopoutCreationDate.js ├── usrbgDefault.js ├── usrbgHeaders.js ├── vcColumns.js ├── visualTweaks.js ├── vscodeToasts.js └── webhookTags.js /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 GooseMod 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GooseMod Modules 2 | 3 | Modules for GooseMod on the Module Store. -------------------------------------------------------------------------------- /modules/backend/avatarDataAttribute.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.0'; 2 | 3 | const addAttrToEl = (el) => { 4 | const userId = el.getElementsByTagName('img')[0].src.split('/')[4]; 5 | el.setAttribute('data-user-id', userId); 6 | }; 7 | 8 | const handler = async () => { 9 | const els = document.getElementsByClassName('wrapper-3t9DeA'); 10 | 11 | for (let el of els) { 12 | if (el.getAttribute('data-user-id')) continue; 13 | 14 | addAttrToEl(el); 15 | } 16 | }; 17 | 18 | let interval; 19 | 20 | let obj = { 21 | onImport: async function () { 22 | interval = setInterval(handler, 1000); 23 | }, 24 | 25 | remove: async function () { 26 | clearInterval(interval); 27 | }, 28 | 29 | name: 'Avatar Data Attribute', 30 | description: 'Adds data attribute to avatar elements, as some CSS tweaks / modules rely on it', 31 | 32 | author: 'Ducko', 33 | 34 | version 35 | }; 36 | 37 | obj -------------------------------------------------------------------------------- /modules/backend/customCss.js: -------------------------------------------------------------------------------- 1 | const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); 2 | 3 | const version = '1.1.4'; 4 | 5 | let css = ''; 6 | let styleEl, el, highlightEl, mod; 7 | 8 | const updateCSS = (c) => { 9 | styleEl.innerHTML = ''; 10 | 11 | styleEl.appendChild(document.createTextNode(c)); 12 | }; 13 | 14 | const updateHighlight = () => { 15 | highlightEl.innerHTML = el.innerHTML; 16 | 17 | mod.highlightBlock(highlightEl); 18 | }; 19 | 20 | let obj = { 21 | onImport: async function () { 22 | styleEl = document.createElement('style'); 23 | 24 | document.head.appendChild(styleEl); 25 | 26 | el = document.createElement('div'); 27 | 28 | el.style.width = '90%'; 29 | el.style.height = '85vh'; 30 | 31 | el.style.position = 'absolute'; 32 | 33 | el.classList.add('hljs', 'css'); 34 | 35 | el.style.backgroundColor = 'var(--background-secondary)'; 36 | 37 | el.contentEditable = 'true'; 38 | 39 | el.style.fontSize = '0.875em'; 40 | el.style.lineHeight = '1.125em'; 41 | el.style.textIndent = '0'; 42 | el.style.whiteSpace = 'pre-wrap'; 43 | 44 | el.style.fontFamily = 'Consolas,Andale Mono WT,Andale Mono,Lucida Console,Lucida Sans Typewriter,DejaVu Sans Mono,Bitstream Vera Sans Mono,Liberation Mono,Nimbus Mono L,Monaco,Courier New,Courier,monospace'; 45 | 46 | highlightEl = el.cloneNode(); 47 | 48 | highlightEl.style.pointerEvents = 'none'; 49 | highlightEl.style.backgroundColor = 'transparent'; 50 | highlightEl.style.zIndex = '2'; 51 | highlightEl.contentEditable = 'false'; 52 | 53 | mod = goosemod.webpackModules.findByPropsAll('highlight')[3]; 54 | 55 | let fn = () => { 56 | css = el.innerHTML; 57 | 58 | updateHighlight(); 59 | 60 | updateCSS(el.textContent); 61 | }; 62 | 63 | el.innerHTML = css; 64 | 65 | el.oninput = fn; 66 | 67 | fn(); 68 | 69 | el.addEventListener('paste', function (e) { // Don't paste HTML / rich content, only plain text 70 | e.preventDefault() 71 | var text = e.clipboardData.getData('text/plain') 72 | document.execCommand('insertText', false, text) 73 | }); 74 | 75 | goosemodScope.settings.createItem('Custom CSS', [ 76 | `(v${version})`, 77 | 78 | { 79 | type: 'custom', 80 | element: el 81 | }, 82 | 83 | { 84 | type: 'custom', 85 | element: highlightEl 86 | } 87 | ]); 88 | }, 89 | 90 | remove: async function () { 91 | styleEl.remove(); 92 | 93 | let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'Custom CSS'); 94 | goosemodScope.settings.items.splice(goosemodScope.settings.items.indexOf(settingItem), 1); 95 | }, 96 | 97 | getSettings: () => [css], 98 | loadSettings: ([_css]) => { 99 | css = _css; // Update internal var 100 | 101 | el.innerHTML = css; // Update UI 102 | updateHighlight(); 103 | 104 | updateCSS(el.textContent); // Update actual style 105 | }, 106 | 107 | name: 'Custom CSS', 108 | description: 'Allows entering of your own custom CSS in a code editor with syntax highlighting', 109 | 110 | author: 'Ducko', 111 | 112 | version 113 | }; 114 | 115 | obj 116 | -------------------------------------------------------------------------------- /modules/backend/devMode.js: -------------------------------------------------------------------------------- 1 | let version = '3.0.1'; 2 | 3 | let obj = { 4 | onImport: async function() { 5 | goosemodScope.logger.debug('devMode', 'Enabling Developer Mode'); 6 | 7 | Object.defineProperty(goosemodScope.webpackModules.findByProps('isDeveloper'), 'isDeveloper', { configurable: true, writable: true, value: 1 }); 8 | }, 9 | 10 | remove: async function() { 11 | 12 | }, 13 | 14 | logRegionColor: 'darkgreen', 15 | 16 | name: 'Dev Mode', 17 | description: 'Enables developer mode (experiments, etc.)', 18 | 19 | author: 'Ducko', 20 | 21 | version 22 | }; 23 | 24 | obj -------------------------------------------------------------------------------- /modules/backend/fucklytics.js: -------------------------------------------------------------------------------- 1 | let version = '2.1.0'; 2 | 3 | let blocking = { 4 | 'compat': '2.1.0', 5 | 6 | 'science': true, 7 | 'sentry': true, 8 | 'crash': true 9 | }; 10 | 11 | let originals = { 12 | 'analytics': undefined, 13 | 'crash': undefined 14 | }; 15 | 16 | const setAnalytics = (val) => { 17 | if (!val) enableAnalytics(); 18 | else disableAnalytics(); 19 | }; 20 | 21 | const enableAnalytics = () => { 22 | const analyticsMod = goosemodScope.webpackModules.findByProps('getSuperPropertiesBase64'); 23 | 24 | analyticsMod.track = originals.analytics; 25 | }; 26 | 27 | const disableAnalytics = () => { 28 | const analyticsMod = goosemodScope.webpackModules.findByProps('getSuperPropertiesBase64'); 29 | 30 | originals.analytics = analyticsMod.track; 31 | analyticsMod.track = () => {}; 32 | }; 33 | 34 | const setCrash = (val) => { 35 | if (!val) enableCrash(); 36 | else disableCrash(); 37 | }; 38 | 39 | const enableCrash = () => { 40 | const crashMod = goosemodScope.webpackModules.findByProps('submitLiveCrashReport'); 41 | 42 | crashMod.submitLiveCrashReport = originals.crash; 43 | }; 44 | 45 | const disableCrash = () => { 46 | const crashMod = goosemodScope.webpackModules.findByProps('submitLiveCrashReport'); 47 | 48 | originals.crash = crashMod.submitLiveCrashReport; 49 | crashMod.submitLiveCrashReport = () => {}; 50 | }; 51 | 52 | const setSentry = (val) => { 53 | if (!val) enableSentry(); 54 | else disableSentry(); 55 | }; 56 | 57 | const enableSentry = () => { 58 | window.__SENTRY__.hub.getClient().getOptions().enabled = true; 59 | }; 60 | 61 | const disableSentry = () => { 62 | window.__SENTRY__.hub.getClient().getOptions().enabled = false; 63 | }; 64 | 65 | let obj = { 66 | onImport: async function() { 67 | setAnalytics(blocking.science); 68 | setSentry(blocking.sentry); 69 | setCrash(blocking.crash); 70 | }, 71 | 72 | onLoadingFinished: async function() { 73 | goosemodScope.settings.createItem('Fucklytics', [ 74 | `(v${version})`, 75 | 76 | { 77 | type: 'header', 78 | text: 'What to block' 79 | }, 80 | 81 | { 82 | type: 'toggle', 83 | text: 'Science (Discord API)', 84 | subtext: 'Discord\'s own analytics, most used.', 85 | onToggle: (c) => { 86 | blocking.science = c; 87 | setAnalytics(c); 88 | }, 89 | isToggled: () => blocking.science 90 | }, 91 | 92 | { 93 | type: 'toggle', 94 | text: 'Crash Reports', 95 | subtext: 'Automatically sends Discord a crash report on crash (without your consent).', 96 | onToggle: (c) => { 97 | blocking.crash = c; 98 | setCrash(c); 99 | }, 100 | isToggled: () => blocking.crash 101 | }, 102 | 103 | { 104 | type: 'toggle', 105 | text: 'Sentry', 106 | subtext: 'Used to track console / JS errors.', 107 | onToggle: (c) => { 108 | blocking.sentry = c; 109 | setSentry(c); 110 | }, 111 | isToggled: () => blocking.sentry 112 | } 113 | ]); 114 | }, 115 | 116 | remove: async function() { 117 | try { 118 | enableAnalytics(); 119 | enableSentry(); 120 | enableCrash(); 121 | } catch (e) {} 122 | 123 | let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'Fucklytics'); 124 | goosemodScope.settings.items.splice(goosemodScope.settings.items.indexOf(settingItem), 1); 125 | }, 126 | 127 | getSettings: () => [blocking], 128 | loadSettings: ([_blocking]) => { 129 | if (_blocking.compat !== version) return; 130 | 131 | blocking = _blocking; 132 | 133 | setAnalytics(blocking.science); 134 | setSentry(blocking.sentry); 135 | setCrash(blocking.crash); 136 | }, 137 | 138 | name: 'Fucklytics', 139 | description: 'Blocks Discord (Science) analytics, crash reports and Sentry', 140 | 141 | author: 'Ducko', 142 | 143 | version 144 | }; 145 | 146 | obj -------------------------------------------------------------------------------- /modules/backend/noPingReply.js: -------------------------------------------------------------------------------- 1 | let version = '1.0.0'; 2 | let unpatch; 3 | 4 | let obj = { 5 | onImport: async function() { 6 | unpatch = goosemodScope.patcher.patch(goosemodScope.webpackModules.findByProps('createPendingReply'), 'createPendingReply', (data) => { data[0].shouldMention = false}, true); 7 | }, 8 | 9 | remove: async function() { 10 | unpatch() 11 | }, 12 | 13 | name: `Disable ping reply`, 14 | description: `Disables Discord automatically pinging when you are replying`, 15 | 16 | author: 'Lith', 17 | 18 | version 19 | }; 20 | 21 | obj 22 | -------------------------------------------------------------------------------- /modules/backend/silentTyping.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.4'; 2 | 3 | let orig; 4 | 5 | let obj = { 6 | onImport: async function () { 7 | let mod = goosemodScope.webpackModules.findByProps('startTyping'); 8 | orig = mod.startTyping; 9 | 10 | mod.startTyping = () => {}; 11 | }, 12 | 13 | onLoadingFinished: async function () { 14 | }, 15 | 16 | remove: async function () { 17 | goosemodScope.webpackModules.findByProps('startTyping').startTyping = orig; 18 | }, 19 | 20 | logRegionColor: 'darkred', 21 | 22 | name: 'Silent Typing', 23 | description: 'Makes Discord not send your typing indicator', 24 | 25 | author: 'Ducko', 26 | 27 | version 28 | }; 29 | 30 | obj -------------------------------------------------------------------------------- /modules/customisation/customSounds.js: -------------------------------------------------------------------------------- 1 | const version = '1.3.11'; 2 | 3 | if (typeof window === 'undefined' || typeof window.Audio === 'undefined') { // JSON API generator evals 4 | global.window = {Audio: {}}; 5 | } 6 | 7 | let _Audio = window.Audio; 8 | 9 | let enabled = true; 10 | 11 | let fileSelectEl; 12 | let incomingCallSound, outgoingCallSound, notificationSound; 13 | let incomingCallStorage, outgoingCallStorage, notificationStorage; 14 | let incomingCallName, outgoingCallName, notificationName; 15 | 16 | const dataURItoBlobURI = (dataURI) => { // https://stackoverflow.com/a/12300351 17 | try { 18 | // convert base64 to raw binary data held in a string 19 | // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code 20 | const byteString = atob(dataURI.split(',')[1]); 21 | 22 | // separate out the mime component 23 | const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0] 24 | 25 | // write the bytes of the string to an ArrayBuffer 26 | const ab = new ArrayBuffer(byteString.length); 27 | 28 | // create a view into the buffer 29 | let ia = new Uint8Array(ab); 30 | 31 | // set the bytes of the buffer to the correct values 32 | for (let i = 0; i < byteString.length; i++) { 33 | ia[i] = byteString.charCodeAt(i); 34 | } 35 | 36 | // write the ArrayBuffer to a blob, and you're done 37 | return URL.createObjectURL(new Blob([ab], {type: mimeString})); 38 | } catch (e) { 39 | return undefined; 40 | } 41 | }; 42 | 43 | const getFileUpload = async () => { 44 | fileSelectEl.value = null; // Prevent not firing change for repeated files 45 | fileSelectEl.click(); 46 | 47 | await new Promise((res) => { 48 | fileSelectEl.onchange = () => { 49 | res(); 50 | }; 51 | }); 52 | 53 | fileSelectEl.onchange = undefined; 54 | 55 | const file = fileSelectEl.files[0]; 56 | 57 | if (file === undefined) { 58 | return undefined; 59 | } 60 | 61 | return file; 62 | }; 63 | 64 | let obj = { 65 | onImport: async function() { 66 | goosemodScope.logger.debug('customSounds', 'Overriding Audio with a proxy function'); 67 | 68 | window.Audio = function() { 69 | var audio = new _Audio(); 70 | 71 | var _play = audio.play; 72 | audio.play = function() { 73 | //console.log(this.src); 74 | 75 | if (enabled) { 76 | if (outgoingCallSound && this.src.includes('/assets/c6e92752668dde4eee5923d70441579f.mp3')) { // Outgoing Call 77 | console.log('outgoing'); 78 | this.src = outgoingCallSound; 79 | } 80 | 81 | if (incomingCallSound && this.src.includes('/assets/84a1b4e11d634dbfa1e5dd97a96de3ad.mp3')) { // Incoming Call 82 | console.log('incoming'); 83 | this.src = incomingCallSound; 84 | } 85 | 86 | if (notificationSound && this.src.includes('/assets/dd920c06a01e5bb8b09678581e29d56f.mp3')) { // Notification Sound / Ping 87 | console.log('notification'); 88 | this.src = notificationSound; 89 | } 90 | } 91 | 92 | return _play.apply(this, arguments); 93 | } 94 | 95 | return audio; 96 | }; 97 | }, 98 | 99 | onLoadingFinished: async function() { 100 | fileSelectEl = document.createElement('input'); 101 | fileSelectEl.type = 'file'; 102 | 103 | //fileSelectEl.accept = 'sound/*'; 104 | fileSelectEl.style.display = 'none'; 105 | 106 | document.body.appendChild(fileSelectEl); 107 | 108 | let items = [ 109 | { 110 | type: 'text-and-button', 111 | text: 'Incoming Call', 112 | subtext: 'Not uploaded', 113 | buttonText: 'Upload', 114 | onclick: async (el) => { 115 | el.textContent = 'Uploading...'; 116 | 117 | const file = await getFileUpload(); 118 | 119 | incomingCallSound = file === undefined ? undefined : URL.createObjectURL(file); 120 | incomingCallName = file === undefined ? undefined : file.name; 121 | 122 | items[0].subtext = file === undefined ? 'Not uploaded' : `Uploaded: ${file.name}`; 123 | 124 | goosemodScope.settings.createFromItems(); 125 | goosemodScope.openSettingItem('Custom Sounds'); 126 | 127 | if (file !== undefined) { 128 | const reader = new FileReader(); 129 | 130 | reader.onload = () => { 131 | incomingCallStorage = reader.result; 132 | }; 133 | 134 | reader.readAsDataURL(file); 135 | } 136 | } 137 | }, 138 | { 139 | type: 'text-and-button', 140 | text: 'Outgoing Call', 141 | subtext: 'Not uploaded', 142 | buttonText: 'Upload', 143 | onclick: async (el) => { 144 | el.textContent = 'Uploading...'; 145 | 146 | const file = await getFileUpload(); 147 | outgoingCallSound = file === undefined ? undefined : URL.createObjectURL(file); 148 | outgoingCallName = file === undefined ? undefined : file.name; 149 | 150 | items[1].subtext = file === undefined ? 'Not uploaded' : `Uploaded: ${file.name}`; 151 | 152 | goosemodScope.settings.createFromItems(); 153 | goosemodScope.openSettingItem('Custom Sounds'); 154 | 155 | if (file !== undefined) { 156 | const reader = new FileReader(); 157 | 158 | reader.onload = () => { 159 | outgoingCallStorage = reader.result; 160 | }; 161 | 162 | reader.readAsDataURL(file); 163 | } 164 | } 165 | }, 166 | { 167 | type: 'text-and-button', 168 | text: 'Notification Sound', 169 | subtext: 'Not uploaded', 170 | buttonText: 'Upload', 171 | onclick: async (el) => { 172 | el.textContent = 'Uploading...'; 173 | 174 | const file = await getFileUpload(); 175 | 176 | notificationSound = file === undefined ? undefined : URL.createObjectURL(file); 177 | notificationName = file === undefined ? undefined : file.name; 178 | 179 | items[2].subtext = file === undefined ? 'Not uploaded' : `Uploaded: ${file.name}`; 180 | 181 | goosemodScope.settings.createFromItems(); 182 | goosemodScope.openSettingItem('Custom Sounds'); 183 | 184 | if (file !== undefined) { 185 | const reader = new FileReader(); 186 | 187 | reader.onload = () => { 188 | notificationStorage = reader.result; 189 | }; 190 | 191 | reader.readAsDataURL(file); 192 | } 193 | } 194 | } 195 | ]; 196 | 197 | goosemodScope.settings.createItem('Custom Sounds', [ 198 | `(v${version})`, 199 | 200 | { 201 | type: 'toggle', 202 | text: 'Custom Sounds Enabled', 203 | onToggle: (c) => { enabled = c; }, 204 | isToggled: () => enabled 205 | }, 206 | 207 | { 208 | type: 'header', 209 | text: 'Sounds' 210 | }, 211 | 212 | ...items 213 | ]); 214 | }, 215 | 216 | remove: async function() { 217 | window.Audio = _Audio; 218 | 219 | fileSelectEl.remove(); 220 | 221 | let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'Custom Sounds'); 222 | goosemodScope.settings.items.splice(goosemodScope.settings.items.indexOf(settingItem), 1); 223 | }, 224 | 225 | getSettings: () => [enabled, incomingCallStorage, outgoingCallStorage, notificationStorage, incomingCallName, outgoingCallName, notificationName], 226 | loadSettings: ([_enabled, _incomingCallStorage, _outgoingCallStorage, _notificationStorage, _incomingCallName, _outgoingCallName, _notificationName]) => { 227 | enabled = _enabled; 228 | 229 | incomingCallStorage = _incomingCallStorage; 230 | outgoingCallStorage = _outgoingCallStorage; 231 | notificationStorage = _notificationStorage; 232 | 233 | incomingCallSound = incomingCallStorage === null ? undefined : dataURItoBlobURI(incomingCallStorage); 234 | outgoingCallSound = outgoingCallStorage === null ? undefined : dataURItoBlobURI(outgoingCallStorage); 235 | notificationSound = notificationStorage === null ? undefined : dataURItoBlobURI(notificationStorage); 236 | 237 | incomingCallName = _incomingCallName; 238 | outgoingCallName = _outgoingCallName; 239 | notificationName = _notificationName; 240 | 241 | let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'Custom Sounds'); 242 | 243 | settingItem[2][2].subtext = !incomingCallName ? 'Not uploaded' : `Uploaded: ${incomingCallName}`; 244 | settingItem[2][3].subtext = !outgoingCallName ? 'Not uploaded' : `Uploaded: ${outgoingCallName}`; 245 | settingItem[2][4].subtext = !notificationName ? 'Not uploaded' : `Uploaded: ${notificationName}`; 246 | 247 | //goosemodScope.settings.createFromItems(); 248 | //goosemodScope.openSettingItem('Custom Sounds'); 249 | 250 | //items[0].subtext = !incomingCallName ? 'Not uploaded' : `Uploaded: ${incomingCallName}`; 251 | //items[1].subtext = !outgoingCallName ? 'Not uploaded' : `Uploaded: ${outgoingCallName}`; 252 | //items[2].subtext = !notificationName ? 'Not uploaded' : `Uploaded: ${notificationName}`; 253 | }, 254 | 255 | logRegionColor: 'darkblue', 256 | 257 | name: 'Custom Sounds', 258 | description: 'Allows replacing Discord sounds with your own custom uploaded sounds', 259 | 260 | author: 'Ducko', 261 | 262 | version 263 | }; 264 | 265 | obj -------------------------------------------------------------------------------- /modules/debug/discordDebug.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.2'; 2 | 3 | let obj = { 4 | onImport: async function () { 5 | }, 6 | 7 | onLoadingFinished: async function () { 8 | let electronInfo = goosemodScope.webpackModules.findByProps('ua'); 9 | 10 | let moduleItems = []; 11 | let moduleVersions = goosemodScope.webpackModules.findByProps('moduleVersions').moduleVersions; 12 | 13 | for (let m in moduleVersions) { 14 | moduleItems.push({ 15 | type: 'text', 16 | text: m, 17 | subtext: moduleVersions[m] 18 | }); 19 | } 20 | 21 | goosemodScope.settings.createItem('Discord Debug', [ 22 | `(v${version})`, 23 | 24 | { 25 | type: 'header', 26 | text: 'Electron Information' 27 | }, 28 | 29 | { 30 | type: 'text', 31 | text: 'Electron', 32 | subtext: electronInfo.description 33 | }, 34 | { 35 | type: 'text', 36 | text: 'User Agent', 37 | subtext: electronInfo.ua 38 | }, 39 | { 40 | type: 'text', 41 | text: 'OS', 42 | subtext: electronInfo.os.toString() 43 | }, 44 | 45 | { 46 | type: 'header', 47 | text: 'Discord (Native) Modules' 48 | }, 49 | 50 | ...moduleItems 51 | ]); 52 | }, 53 | 54 | remove: async function () { 55 | let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'Discord Debug'); 56 | goosemodScope.settings.items.splice(goosemodScope.settings.items.indexOf(settingItem), 1); 57 | }, 58 | 59 | logRegionColor: 'darkred', 60 | 61 | name: 'Discord Debug', 62 | description: 'Setting option with debug information about Discord', 63 | 64 | author: 'Ducko (506482395269169153)', 65 | 66 | version 67 | }; 68 | 69 | obj 70 | -------------------------------------------------------------------------------- /modules/fun/eggScrambler.js: -------------------------------------------------------------------------------- 1 | let version = '1.0.3'; 2 | 3 | let interval; 4 | 5 | function scrambleMessages() { 6 | interval = setInterval(function () { 7 | let messages = document.getElementsByClassName("messageContent-2qWWxC"); 8 | 9 | for (let message of messages) { 10 | message.textContent = [...message.textContent].fill('\u{1F95A}').join(''); 11 | } 12 | }, 500); 13 | } 14 | 15 | let obj = { 16 | // Activating module 17 | onImport: async function () { 18 | goosemodScope.logger.debug('scrambleMessages', 'Starting Egg...'); 19 | scrambleMessages(); 20 | }, 21 | 22 | // Removing function 23 | remove: async function () { 24 | clearInterval(interval); 25 | }, 26 | 27 | // Random thing I don't rlly want 28 | logRegionColor: 'red', 29 | 30 | // Data 31 | name: 'Egg Scrambler', 32 | description: 'Makes discord unusable by converting all messages into eggs', 33 | 34 | author: ['Fjorge', 'Hax', 'Ducko'], 35 | 36 | version: version 37 | }; 38 | 39 | obj 40 | -------------------------------------------------------------------------------- /modules/fun/expandCord.js: -------------------------------------------------------------------------------- 1 | let version = '1.0.4'; 2 | 3 | let interval; 4 | 5 | function expand() { 6 | interval = setInterval(function () { 7 | let messages = document.getElementsByClassName("messageContent-2qWWxC"); 8 | 9 | for (let message of messages) { 10 | message.textContent = [...message.textContent].filter(e => e != " ").join(' '); 11 | } 12 | }, 5000); 13 | } 14 | 15 | let obj = { 16 | // Activating module 17 | onImport: async function () { 18 | goosemodScope.logger.debug('expandCord', 'e x p a n d i n g..'); 19 | expand(); 20 | }, 21 | 22 | // Removing function 23 | remove: async function () { 24 | clearInterval(interval); 25 | }, 26 | 27 | // Random thing I don't rlly want 28 | logRegionColor: 'blue', 29 | 30 | // Data 31 | name: '(E x p a n d)Cord', 32 | description: 'M a k e s d i s c o r d w i d e', 33 | 34 | author: ['Fjorge', 'Ducko'], 35 | 36 | version: version 37 | }; 38 | 39 | obj 40 | -------------------------------------------------------------------------------- /modules/fun/messageScrambler.js: -------------------------------------------------------------------------------- 1 | let version = '1.1.0'; 2 | 3 | let interval; 4 | 5 | function scrambleMessages() { 6 | function getRandomInt(min, max) { 7 | let minr = Math.ceil(Math.random() * (Math.floor(max) - Math.ceil(min)) + Math.ceil(min)); 8 | let maxr = Math.floor(Math.random() * (Math.floor(max) - Math.ceil(min)) + Math.ceil(min)); 9 | return Math.floor(Math.random() * (maxr - minr) + minr); 10 | } 11 | 12 | const alphabet = "j☭∁₰☭∢⁌∄so⸎௹d𑱰⚝∞ç꘏⚼i⸙⦖☊⛠∜fjw꧁↾380၍r08d꫞o༼∆AU☬H៘◎◎U﷼#H☽RH⇘☭JKD༺FSNO(!#@(*$&☍DSA9⛠8|}⸙}F⚎F꫞ç☭L⚼߷J*♮⛧∜꧅!⁌&₷⸎꘏?SF>".split(''); 13 | 14 | interval = setInterval(function () { 15 | let messages = document.getElementsByClassName("messageContent-2qWWxC"); 16 | 17 | for (let message of messages) { 18 | message.textContent = [...message.textContent].map(() => alphabet[getRandomInt(0, alphabet.length)]).join(''); 19 | } 20 | }, 500); 21 | } 22 | 23 | let obj = { 24 | // Activating module 25 | onImport: async function () { 26 | goosemodScope.logger.debug('scrambleMessages', 'Starting Scrambler...'); 27 | scrambleMessages(); 28 | }, 29 | 30 | // Removing function 31 | remove: async function () { 32 | clearInterval(interval); 33 | }, 34 | 35 | // Random thing I don't rlly want 36 | logRegionColor: 'red', 37 | 38 | // Data 39 | name: 'Message Scrambler', 40 | description: 'Makes discord unusable by converting all messages into random text', 41 | 42 | author: ['Fjorge'][0], 43 | 44 | version: version 45 | }; 46 | 47 | obj 48 | -------------------------------------------------------------------------------- /modules/fun/owoCord.js: -------------------------------------------------------------------------------- 1 | let version = "0.4"; 2 | 3 | let owointerval; 4 | function owoify() { 5 | function owocordToOwOSpeak() { 6 | this.replace(/r/g,"w").replace(/l/g,"w").replace(/R/g,"W").replace(/L/g,"W").replace("(edited)"," [Edited]"); 7 | }; 8 | 9 | owointerval = setInterval(function () { 10 | let messages = document.getElementsByClassName("messageContent-2qWWxC"); 11 | for(let message of messages) { 12 | message.textContent = owocordToOwOSpeak(message.textContent); 13 | } 14 | }, 250); 15 | } 16 | 17 | let obj = { 18 | onImport: async function () { 19 | owoify(); 20 | }, 21 | remove: async function () { 22 | clearInterval(owointerval); 23 | }, 24 | logRegionColor: 'green', 25 | name: 'OwOCord', 26 | description: 'Makes Discowd mowe owo.', 27 | author: "ComfyDev", 28 | version: version 29 | }; 30 | 31 | obj 32 | -------------------------------------------------------------------------------- /modules/fun/rainbowCord.js: -------------------------------------------------------------------------------- 1 | let version = '2.0.3'; 2 | 3 | if (typeof window === 'undefined' || typeof window.document === 'undefined' || typeof window.document.styleSheets === 'undefined') { // JSON API generator evals 4 | global.window = { document: { styleSheets: [0] } }; 5 | } 6 | 7 | let sheet = window.document.styleSheets[0]; 8 | let tweakrules = []; 9 | 10 | let tweaks = { 11 | 'rainbowMode': true 12 | }; 13 | 14 | const tweakFunctions = { 15 | 'rainbowMode': { 16 | enable: () => { 17 | tweakrules.push(sheet.insertRule(`.messageContent-2qWWxC { 18 | background: repeating-linear-gradient(45deg, violet, indigo, blue, green, yellow, orange, red); 19 | -webkit-background-clip: text; 20 | color: transparent; 21 | background-size: 800% 800%; 22 | animation: rainbow 8s ease infinite; 23 | }`, sheet.cssRules.length)); 24 | 25 | tweakrules.push(sheet.insertRule(`code.inline { 26 | color: #fff; 27 | }`, sheet.cssRules.length)); 28 | 29 | tweakrules.push(sheet.insertRule(`@keyframes rainbow { 30 | 0%{background-position:0% 50%} 31 | 50%{background-position:100% 25%} 32 | 100%{background-position:0% 50%} 33 | }`, sheet.cssRules.length)); 34 | }, 35 | 36 | disable: () => { 37 | for (let i = 0; i < tweakrules.length; i++) { 38 | sheet.deleteRule(tweakrules[i]); 39 | } 40 | } 41 | } 42 | }; 43 | 44 | const enableTweak = (tweakName) => { 45 | tweakFunctions[tweakName].enable(); 46 | 47 | tweaks[tweakName] = true; 48 | }; 49 | 50 | const disableTweak = (tweakName) => { 51 | tweakFunctions[tweakName].disable(); 52 | 53 | tweaks[tweakName] = false; 54 | }; 55 | 56 | const setTweak = (tweakName, value) => { 57 | if (value) { 58 | enableTweak(tweakName); 59 | } else { 60 | disableTweak(tweakName); 61 | } 62 | }; 63 | 64 | let obj = { 65 | onImport: async function () { 66 | goosemodScope.logger.debug('rainbowMode', 'Enabling Rainbow Tweaks'); 67 | }, 68 | 69 | onLoadingFinished: async function () { 70 | for (let t in tweaks) { 71 | if (tweaks[t] === true) enableTweak(t); 72 | } 73 | 74 | goosemodScope.settings.createItem('RainbowCord', [ 75 | `(v${version})`, 76 | 77 | { 78 | type: 'header', 79 | text: 'Themes' 80 | }, 81 | { 82 | type: 'toggle', 83 | text: 'Rainbow Mode', 84 | subtext: 'Messages are rainbow', 85 | onToggle: (c) => { setTweak('rainbowMode', c); }, 86 | isToggled: () => tweaks['rainbowMode'] 87 | } 88 | ]); 89 | }, 90 | 91 | remove: async function () { 92 | for (let t in tweaks) { 93 | if (tweaks[t] === true) disableTweak(t); 94 | } 95 | 96 | let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'RainbowCord'); 97 | goosemodScope.settings.items.splice(goosemodScope.settings.items.indexOf(settingItem), 1); 98 | }, 99 | 100 | logRegionColor: 'black', 101 | 102 | name: 'RainbowCord', 103 | description: 'Rainbow mode', 104 | 105 | author: 'Fjorge', 106 | 107 | version 108 | }; 109 | 110 | obj 111 | -------------------------------------------------------------------------------- /modules/messages/censorRudeWords.js: -------------------------------------------------------------------------------- 1 | let version = '0.1.0'; 2 | 3 | const getWantedHandler = (mod) => mod._orderedActionHandlers.MESSAGE_CREATE.find((x) => x.crwWanted === true || x.actionHandler.toString().includes('receivePushNotification')); 4 | 5 | let index = 0; 6 | 7 | let words = ['cunt', 'wanker', 'fuck', 'bitch', 'shit', 'crap', 'bollocks', 'arse', 'ass', 'piss', 'frick']; 8 | 9 | const setup = () => { 10 | const mod = goosemodScope.webpackModules.findByProps('register'); 11 | 12 | let original; 13 | try { 14 | original = getWantedHandler(mod); 15 | } catch (e) { 16 | return setTimeout(setup, 3000); 17 | } 18 | 19 | original.crwWanted = true; 20 | 21 | goosemodScope.patcher.inject('censor-rude-words', original, 'actionHandler', (args) => { 22 | for (let w of words) { 23 | if (!w.enabled) continue; 24 | 25 | args[0].message.content = args[0].message.content.replace(new RegExp(`${w.word}`, 'g'), w.censored); 26 | } 27 | 28 | return args; 29 | }, true); 30 | }; 31 | 32 | let obj = { 33 | onImport: async function () { 34 | words = words.map((x) => ({ word: x, enabled: true, censored: [...x].map((y, i) => i >= x.length / 4 && i < x.length - x.length / 4 ? '\\*' : y).join('') })); 35 | 36 | goosemodScope.settings.createItem('Censor Rude Words', [ 37 | `(v${version})`, 38 | 39 | { 40 | type: 'header', 41 | text: 'Words' 42 | }, 43 | 44 | ...words.map((x) => ({ 45 | type: 'toggle', 46 | text: x.word[0].toUpperCase() + x.word.substring(1), 47 | onToggle: (c) => { x.enabled = c; }, 48 | isToggled: () => x.enabled 49 | })) 50 | ]); 51 | }, 52 | 53 | onLoadingFinished: async function () { 54 | setup(); 55 | }, 56 | 57 | remove: async function () { 58 | goosemodScope.patcher.uninject('censor-rude-words'); 59 | }, 60 | 61 | getSettings: () => [words], 62 | loadSettings: ([_words]) => { 63 | for (let w of _words) { 64 | let local = words.find((x) => x.word === w.word); 65 | if (!local) continue; 66 | 67 | local.enabled = w.enable; 68 | } 69 | }, 70 | 71 | name: 'Censor Rude Words', 72 | description: 'Censors rude words which can be toggled in a setting item', 73 | 74 | author: 'Ducko', 75 | 76 | version 77 | }; 78 | 79 | obj 80 | 81 | -------------------------------------------------------------------------------- /modules/messages/copyRaw.js: -------------------------------------------------------------------------------- 1 | const version = "1.1.0"; 2 | 3 | let obj = { 4 | onImport: async () => { 5 | goosemodScope.patcher.contextMenu.add("message", { 6 | label: "Copy Raw", 7 | action: (_originalArgs, extraInfo) => { 8 | try { 9 | if (extraInfo.message.content == "") { 10 | return goosemodScope.showToast("Unable to copy", { type: "error" }); 11 | } 12 | 13 | DiscordNative.clipboard.copy(extraInfo.message.content); 14 | goosemodScope.showToast("Copied!", { type: "success", icon: false }); 15 | } catch (error) { 16 | goosemodScope.showToast("An error has occured!", { type: "error" }); 17 | console.error(error); 18 | } 19 | }, 20 | }); 21 | }, 22 | 23 | remove: async () => { 24 | goosemodScope.patcher.contextMenu.remove("Copy Raw"); 25 | }, 26 | 27 | name: "Copy Raw", 28 | description: "Allows you to copy messages as they were when being written.", 29 | author: "Liam The Protogen (441384103946878987)", 30 | version, 31 | }; 32 | 33 | obj 34 | -------------------------------------------------------------------------------- /modules/messages/hideBlockedMessages.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.0'; 2 | 3 | let el; 4 | 5 | const css = `.groupStart-23k01U:not(.message-2qnXI6) { 6 | display: none; 7 | }`; 8 | 9 | let obj = { 10 | onImport: async function () { 11 | el = document.createElement('style'); 12 | 13 | document.head.appendChild(el); 14 | 15 | el.appendChild(document.createTextNode(css)); 16 | }, 17 | 18 | remove: async function () { 19 | el.remove(); 20 | }, 21 | 22 | name: 'Hide Blocked Messages', 23 | description: 'Completely hides blocked messages', 24 | 25 | author: 'Ducko', 26 | 27 | version 28 | }; 29 | 30 | obj 31 | -------------------------------------------------------------------------------- /modules/messages/noMessageDeletion.js: -------------------------------------------------------------------------------- 1 | let version = '3.1.2'; 2 | 3 | let original; 4 | let interval; 5 | let deleted = []; 6 | 7 | const styleMessage = async ({ id }) => { 8 | let el = document.getElementById(`chat-messages-${id}`); 9 | if (!el) return; 10 | 11 | if (el.classList.contains('gm-deleted-message')) return; 12 | 13 | el.classList.add('gm-deleted-message'); 14 | el.style.backgroundColor = 'rgba(240, 71, 71, 0.1)'; 15 | }; 16 | 17 | const run = () => { 18 | for (let obj of deleted) { 19 | styleMessage(obj); 20 | } 21 | }; 22 | 23 | const getWantedHandler = (mod) => mod._orderedActionHandlers.MESSAGE_DELETE.find((x) => x.actionHandler.toString().includes('revealedMessageId')); 24 | 25 | let index = 0; 26 | 27 | const setup = () => { 28 | const mod = goosemodScope.webpackModules.findByProps('register'); 29 | 30 | try { 31 | original = getWantedHandler(mod); 32 | } catch (e) { 33 | // goosemodScope.showToast('No Message Deletion: Setup failed, retrying...'); 34 | return setTimeout(setup, 3000); 35 | } 36 | 37 | index = mod._orderedActionHandlers.MESSAGE_DELETE.indexOf(getWantedHandler(mod)); 38 | 39 | mod._orderedActionHandlers.MESSAGE_DELETE[index] = { 40 | actionHandler: (obj) => { 41 | // console.log(obj); 42 | 43 | if (deleted.find((x) => x.id === obj.id)) { return; } 44 | 45 | deleted.push(obj); 46 | 47 | styleMessage(obj); 48 | }, 49 | 50 | storeDidChange: function() { } 51 | }; 52 | 53 | // goosemodScope.showToast('No Message Deletion: Ready'); 54 | }; 55 | 56 | let obj = { 57 | onImport: async function () { 58 | }, 59 | 60 | onLoadingFinished: async function () { 61 | interval = setInterval(run, 300); 62 | 63 | setup(); 64 | }, 65 | 66 | remove: async function () { 67 | clearInterval(interval); 68 | 69 | for (let e of document.getElementsByClassName('gm-deleted-message')) { 70 | e.remove(); 71 | } 72 | 73 | goosemodScope.webpackModules.findByProps('register')._orderedActionHandlers.MESSAGE_DELETE[index] = original; 74 | }, 75 | 76 | logRegionColor: 'darkred', 77 | 78 | name: 'Better Message Deletion', 79 | description: 'Messages only turn red instead of completely disappearing', 80 | 81 | author: 'Ducko', 82 | 83 | version 84 | }; 85 | 86 | obj -------------------------------------------------------------------------------- /modules/messages/roleColoredMessages.js: -------------------------------------------------------------------------------- 1 | let version = '1.2.2'; 2 | 3 | let interval; 4 | 5 | function rgb2hsl(r, g, b) { 6 | r /= 255, g /= 255, b /= 255; 7 | 8 | let max = Math.max(r, g, b), min = Math.min(r, g, b); 9 | let h, s, l = (max + min) / 2; 10 | 11 | if (max === min) { 12 | h = s = 0; // achromatic 13 | } else { 14 | var d = max - min; 15 | s = l > 0.5 ? d / (2 - max - min) : d / (max + min); 16 | 17 | switch (max) { 18 | case r: h = (g - b) / d + (g < b ? 6 : 0); break; 19 | case g: h = (b - r) / d + 2; break; 20 | case b: h = (r - g) / d + 4; break; 21 | } 22 | 23 | h /= 6; 24 | } 25 | 26 | return [h * 360, s * 100, l * 100]; 27 | } 28 | 29 | let obj = { 30 | onImport: async function() { 31 | }, 32 | 33 | onLoadingFinished: async function() { 34 | interval = setInterval(() => { 35 | let els = [...document.getElementsByClassName('contents-2mQqc9')]; 36 | let lastColor = ''; 37 | for (let el of els) { 38 | let usernameEl = el.querySelector('.username-1A8OIy'); 39 | 40 | let roleColor = usernameEl && (usernameEl.style.color || 'var(--header-primary)'); 41 | 42 | if (roleColor) { 43 | let rgb = roleColor.replace('rgb(', '').replace(')', '').split(', ').map((x) => parseFloat(x)); 44 | 45 | let [h, s, l] = rgb2hsl(rgb[0], rgb[1], rgb[2]); 46 | 47 | roleColor = `hsl(${h}, ${85}%, ${75}%)`; 48 | } 49 | 50 | el.querySelector('.markup-2BOw-j').style.color = roleColor || lastColor; 51 | 52 | if (roleColor) lastColor = roleColor; 53 | } 54 | }, 100); 55 | }, 56 | 57 | remove: async function() { 58 | clearInterval(interval); 59 | 60 | let els = [...document.getElementsByClassName('contents-2mQqc9')]; // Reset message text back to normal color 61 | for (let el of els) { 62 | el.querySelector('.markup-2BOw-j').style.color = ''; //el.querySelector('.username-1A8OIy').style.color; 63 | } 64 | }, 65 | 66 | logRegionColor: 'green', 67 | 68 | name: 'Role Colored Messages', 69 | description: 'Makes message text color the same as the sender\'s role color', 70 | 71 | author: 'Ducko', 72 | 73 | version 74 | }; 75 | 76 | obj 77 | -------------------------------------------------------------------------------- /modules/messages/twitchEmotes.js: -------------------------------------------------------------------------------- 1 | let version = '2.2.3'; 2 | 3 | let globalTwitchEmotes = JSON.parse(`{"4Head":"354","ANELE":"3792","ArgieB8":"51838","ArsonNoSexy":"50","AsianGlow":"74","AthenaPMS":"32035","BabyRage":"22639","BatChest":"1905","BCouch":"83536","BCWarrior":"30","BibleThump":"86","BigBrother":"1904","BionicBunion":"24","BlargNaut":"38","bleedPurple":"62835","BloodTrail":"69","BORT":"243","BrainSlug":"881","BrokeBack":"4057","BuddhaBar":"27602","ChefFrank":"90129","cmonBruh":"84608","CoolCat":"58127","CorgiDerp":"49106","CougarHunt":"21","DAESuppy":"973","DansGame":"33","DatSheffy":"170","DBstyle":"73","deExcite":"46249","deIlluminati":"46248","DendiFace":"58135","DogFace":"1903","DOOMGuy":"54089","duDudu":"62834","EagleEye":"20","EleGiggle":"4339","FailFish":"360","FPSMarksman":"42","FrankerZ":"65","FreakinStinkin":"39","FUNgineer":"244","FunRun":"48","FuzzyOtterOO":"168","GingerPower":"32","GrammarKing":"3632","HassaanChop":"20225","HassanChop":"68","HeyGuys":"30259","HotPokket":"357","HumbleLife":"46881","ItsBoshyTime":"169","Jebaited":"90","JKanStyle":"15","JonCarnage":"26","KAPOW":"9803","Kappa":"25","KappaClaus":"74510","KappaPride":"55338","KappaRoss":"70433","KappaWealth":"81997","Keepo":"1902","KevinTurtle":"40","Kippa":"1901","Kreygasm":"41","Mau5":"30134","mcaT":"35063","MikeHogu":"81636","MingLee":"68856","MrDestructoid":"28","MVGame":"29","NinjaTroll":"45","NomNom":"90075","NoNoSpot":"44","NotATK":"34875","NotLikeThis":"58765","OhMyDog":"81103","OMGScoots":"91","OneHand":"66","OpieOP":"356","OptimizePrime":"16","OSfrog":"81248","OSkomodo":"81273","OSsloth":"81249","panicBasket":"22998","PanicVis":"3668","PartyTime":"76171","PazPazowitz":"19","PeoplesChamp":"3412","PermaSmug":"27509","PeteZaroll":"81243","PeteZarollTie":"81244","PicoMause":"27","PipeHype":"4240","PJSalt":"36","PMSTwin":"92","PogChamp":"88","Poooound":"358","PraiseIt":"38586","PRChase":"28328","PunchTrees":"47","PuppeyFace":"58136","RaccAttack":"27679","RalpherZ":"1900","RedCoat":"22","ResidentSleeper":"245","riPepperonis":"62833","RitzMitz":"4338","RuleFive":"361","SeemsGood":"64138","ShadyLulu":"52492","ShazBotstix":"87","ShibeZ":"27903","SmoocherZ":"89945","SMOrc":"52","SMSkull":"51","SoBayed":"1906","SoonerLater":"355","SriHead":"14706","SSSsss":"46","StinkyCheese":"90076","StoneLightning":"17","StrawBeary":"37","SuperVinlin":"31","SwiftRage":"34","TF2John":"1899","TheRinger":"18","TheTarFu":"70","TheThing":"7427","ThunBeast":"1898","TinyFace":"67","TooSpicy":"359","TriHard":"171","TTours":"38436","twitchRaid":"62836","UleetBackup":"49","UncleNox":"3666","UnSane":"71","VaultBoy":"54090","VoHiYo":"81274","Volcania":"166","WholeWheat":"1896","WinWaker":"167","WTRuck":"1897","WutFace":"28087","YouWHY":"4337"}`); 4 | 5 | let globalTwitchEmotesEnabled = true; 6 | 7 | let interval; 8 | 9 | let betterTTVEnabled = true; 10 | let betterTTVEmotes = []; 11 | 12 | const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); 13 | 14 | const emoteReplace = async (n, el, e, src) => { 15 | const results = n.textContent.match(new RegExp(`([\\s]|^)${e}([\\s]|$)`)); 16 | 17 | if (!results) return; 18 | 19 | const pre = n.textContent.substring(0, results.index + results[1].length); 20 | const post = n.textContent.substring(results.index + results[0].length - results[2].length); 21 | 22 | n.textContent = pre; 23 | 24 | let emojiContainerEl = document.createElement('span'); 25 | emojiContainerEl.classList.add('emojiContainer-3X8SvE'); 26 | 27 | emojiContainerEl.setAttribute('role', 'button'); 28 | emojiContainerEl.setAttribute('tabindex', '0'); 29 | 30 | let imgEl = document.createElement('img'); 31 | imgEl.src = src; 32 | 33 | imgEl.classList.add('emoji', 'jumboable'); 34 | 35 | imgEl.draggable = false; 36 | imgEl.setAttribute('aria-label', e); 37 | 38 | emojiContainerEl.appendChild(imgEl); 39 | 40 | el.insertBefore(emojiContainerEl, n.nextSibling); 41 | 42 | el.insertBefore(document.createTextNode(post), emojiContainerEl.nextSibling); 43 | } 44 | 45 | let canvasImg; 46 | 47 | let obj = { 48 | onImport: async function() { 49 | betterTTVEmotes = JSON.parse(`[{"id":"54fa928f01e468494b85b54f","code":"PedoBear","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa92ee01e468494b85b553","code":"RebeccaBlack","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa8f1401e468494b85b537","code":":tf:","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa8fce01e468494b85b53c","code":"CiGrip","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa903b01e468494b85b53f","code":"DatSauce","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa909b01e468494b85b542","code":"ForeverAlone","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa90ba01e468494b85b543","code":"GabeN","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa90f201e468494b85b545","code":"HailHelix","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa913701e468494b85b546","code":"HerbPerve","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa919901e468494b85b548","code":"iDog","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa930801e468494b85b554","code":"rStrike","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa932201e468494b85b555","code":"ShoopDaWhoop","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa9cc901e468494b85b565","code":"SwedSwag","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fab45f633595ca4c713abc","code":"M&Mjc","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fab7d2633595ca4c713abf","code":"bttvNice","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa934001e468494b85b556","code":"TopHam","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa935601e468494b85b557","code":"TwaT","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fa99b601e468494b85b55d","code":"WatChuSay","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fb603201abde735115ddb5","code":"SavageJerky","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"5622aaef3286c42e57d8e4ab","code":"Zappa","imageType":"png","userId":"54f93e618edd5fcd455f213f"},{"id":"566ca11a65dbbdab32ec0558","code":"tehPoleCat","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"566ca1a365dbbdab32ec055b","code":"AngelThump","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fbef6601abde735115de57","code":"HHydro","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fbefeb01abde735115de5b","code":"TaxiBro","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fbf00a01abde735115de5c","code":"BroBalt","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fbf02f01abde735115de5d","code":"ButterSauce","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fbf05a01abde735115de5e","code":"BaconEffect","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fbf07e01abde735115de5f","code":"SuchFraud","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fbf09c01abde735115de61","code":"CandianRage","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"54fbefc901abde735115de5a","code":"She'llBeRight","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"55028cd2135896936880fdd7","code":"D:","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"550352766f86a5b26c281ba2","code":"VisLaud","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"550b344bff8ecee922d2a3c1","code":"KaRappa","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"55189a5062e6bd0027aee082","code":"YetiZ","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"552d2fc2236a1aa17a996c5b","code":"miniJulia","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"566ca00f65dbbdab32ec0544","code":"FishMoley","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"566ca02865dbbdab32ec0547","code":"Hhhehehe","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"566ca04265dbbdab32ec054a","code":"KKona","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"566ca09365dbbdab32ec0555","code":"PoleDoge","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"553b48a21f145f087fc15ca6","code":"sosGame","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"55471c2789d53f2d12781713","code":"CruW","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"555015b77676617e17dd2e8e","code":"RarePepe","imageType":"png","userId":"54f93e618edd5fcd455f213f"},{"id":"54fbef8701abde735115de58","code":"iamsocal","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"555981336ba1901877765555","code":"haHAA","imageType":"png","userId":"54f93e3e8edd5fcd455f213d"},{"id":"55b6524154eefd53777b2580","code":"FeelsBirthdayMan","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"55f324c47f08be9f0a63cce0","code":"RonSmug","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"560577560874de34757d2dc0","code":"KappaCool","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"566c9fc265dbbdab32ec053b","code":"FeelsBadMan","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"566c9eeb65dbbdab32ec052b","code":"BasedGod","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"566c9f3b65dbbdab32ec052e","code":"bUrself","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"566c9f6365dbbdab32ec0532","code":"ConcernDoge","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"566c9fde65dbbdab32ec053e","code":"FeelsGoodMan","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"566c9ff365dbbdab32ec0541","code":"FireSpeed","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"566ca06065dbbdab32ec054e","code":"NaM","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"566ca38765dbbdab32ec0560","code":"SourPls","imageType":"gif","userId":"5561169bd6b9d206222a8c19"},{"id":"567b00c61ddbe1786688a633","code":"LuL","imageType":"png","userId":"54f93e618edd5fcd455f213f"},{"id":"56901914991f200c34ffa656","code":"SaltyCorn","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"56d937f7216793c63ec140cb","code":"FCreep","imageType":"png","userId":"5957e86c36b6a43b492d3989"},{"id":"56e9f494fff3cc5c35e5287e","code":"monkaS","imageType":"png","userId":"55bfba180baa41467919aabf"},{"id":"56f5be00d48006ba34f530a4","code":"VapeNation","imageType":"png","userId":"55583bc00c72ab1d77d8b9b7"},{"id":"56fa09f18eff3b595e93ac26","code":"ariW","imageType":"png","userId":"54ee2465b822020506c52a52"},{"id":"5709ab688eff3b595e93c595","code":"notsquishY","imageType":"png","userId":"54ee2465b822020506c52a52"},{"id":"5733ff12e72c3c0814233e20","code":"FeelsAmazingMan","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"573d38b50ffbf6cc5cc38dc9","code":"DuckerZ","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"59cf182fcbe2693d59d7bf46","code":"SqShy","imageType":"png","userId":"54ee2465b822020506c52a52"},{"id":"58d2e73058d8950a875ad027","code":"Wowee","imageType":"png","userId":"5561169bd6b9d206222a8c19"},{"id":"5dc36a8db537d747e37ac187","code":"WubTF","imageType":"png","userId":"54f93e3e8edd5fcd455f213d"},{"id":"5e76d2ab8c0f5c3723a9a87d","code":"cvR","imageType":"png","userId":"54ee2465b822020506c52a52"},{"id":"5e76d2d2d112fc372574d222","code":"cvL","imageType":"png","userId":"54ee2465b822020506c52a52"},{"id":"5e76d338d6581c3724c0f0b2","code":"cvHazmat","imageType":"png","userId":"54ee2465b822020506c52a52"},{"id":"5e76d399d6581c3724c0f0b8","code":"cvMask","imageType":"png","userId":"54ee2465b822020506c52a52"}]`); 50 | 51 | // should get latest emotes from API: however slow to request for import time, so just use "cached" version 52 | }, 53 | 54 | onLoadingFinished: async function() { 55 | interval = setInterval(async () => { 56 | let els = [...document.getElementsByClassName('messageContent-2qWWxC')]; 57 | for (let el of els) { 58 | if (globalTwitchEmotesEnabled) for (let e in globalTwitchEmotes) { 59 | if (!el.textContent.includes(e)) continue; 60 | 61 | for (let n of el.childNodes) { 62 | if (!n.textContent.includes(e)) continue; 63 | 64 | emoteReplace(n, el, e, `https://static-cdn.jtvnw.net/emoticons/v1/${globalTwitchEmotes[e]}/1.0`); // Discord SCP allows Twitch.tv emotes (because of integration) 65 | } 66 | } 67 | 68 | if (betterTTVEnabled) for (let e of betterTTVEmotes) { 69 | if (!el.textContent.includes(e.code)) continue; 70 | 71 | for (let n of el.childNodes) { 72 | if (!n.textContent.includes(e.code)) continue; 73 | 74 | emoteReplace(n, el, e.code, `https://cdn.betterttv.net/emote/${e.id}/2x.${e.imageType}`); 75 | } 76 | } 77 | } 78 | }, 500); 79 | 80 | goosemodScope.settings.createItem('Twitch Emotes', [ 81 | `(v${version})`, 82 | 83 | { 84 | type: 'header', 85 | text: 'Emote Sources' 86 | }, 87 | 88 | { 89 | type: 'toggle', 90 | text: 'Global Twitch Emotes', 91 | subtext: 'Regular global Twitch emotes', 92 | onToggle: (c) => { globalTwitchEmotesEnabled = c; }, 93 | isToggled: () => globalTwitchEmotesEnabled 94 | }, 95 | { 96 | type: 'toggle', 97 | text: 'BetterTTV Global Emotes', 98 | subtext: 'BetterTTV Global Emotes', 99 | onToggle: (c) => { betterTTVEnabled = c; }, 100 | isToggled: () => betterTTVEnabled 101 | } 102 | ]); 103 | }, 104 | 105 | remove: async function() { 106 | clearInterval(interval); 107 | 108 | let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'Twitch Emotes'); 109 | goosemodScope.settings.items.splice(goosemodScope.settings.items.indexOf(settingItem), 1); 110 | }, 111 | 112 | getSettings: () => [globalTwitchEmotesEnabled, betterTTVEnabled], 113 | loadSettings: ([_globalTwitchEmotesEnabled, _betterTTVEnabled]) => { 114 | globalTwitchEmotesEnabled = _globalTwitchEmotesEnabled; 115 | betterTTVEnabled = _betterTTVEnabled; 116 | }, 117 | 118 | logRegionColor: 'green', 119 | 120 | name: 'Twitch Emotes', 121 | description: 'Converts text into images for Twitch global emotes + BetterTTV emotes', 122 | 123 | author: 'Ducko', 124 | 125 | version 126 | }; 127 | 128 | obj -------------------------------------------------------------------------------- /modules/messages/usernameInAuthor.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.3'; 2 | 3 | let getUser, getMembers, getGuildId; 4 | let members; 5 | let intervals; 6 | 7 | const run = () => { 8 | for (let el of document.getElementsByClassName('username-1A8OIy')) { 9 | if (el.classList.contains('username-added')) continue; 10 | 11 | let nick = el.textContent; 12 | let member = members.find((x) => x.nick === nick); 13 | 14 | if (!member) continue; 15 | 16 | let user = getUser.getUser(member.userId); 17 | 18 | let usernameEl = document.createElement('span'); 19 | usernameEl.style.filter = 'brightness(0.5)'; 20 | usernameEl.style.marginLeft = '5px'; 21 | usernameEl.className = 'author-username'; 22 | 23 | usernameEl.textContent = `(${user.username})`; 24 | 25 | el.appendChild(usernameEl); 26 | 27 | el.classList.add('username-added'); 28 | } 29 | }; 30 | 31 | const updateMembers = () => { 32 | members = getMembers.getMembers(getGuildId.getGuildId()); 33 | }; 34 | 35 | let obj = { 36 | onImport: async function () { 37 | intervals = []; 38 | 39 | getUser = goosemodScope.webpackModules.findByProps('getUser'); 40 | getMembers = goosemodScope.webpackModules.findByProps('getNick'); 41 | getGuildId = goosemodScope.webpackModules.findByProps('getGuildId', 'getLastSelectedGuildId'); 42 | 43 | intervals.push(setInterval(run, 300), setInterval(updateMembers, 5000)); 44 | 45 | updateMembers(); 46 | }, 47 | 48 | onLoadingFinished: async function () { 49 | }, 50 | 51 | remove: async function () { 52 | for (let i of intervals) { 53 | clearInterval(i); 54 | } 55 | 56 | members = null; 57 | 58 | for (let el of document.getElementsByClassName('author-username')) { 59 | el.remove(); 60 | } 61 | }, 62 | 63 | logRegionColor: 'darkred', 64 | 65 | name: 'Username In Author', 66 | description: 'Adds username to message\'s author if they have a nickname', 67 | 68 | author: 'Ducko', 69 | 70 | version 71 | }; 72 | 73 | obj 74 | -------------------------------------------------------------------------------- /modules/messages/wysiwygMessages.js: -------------------------------------------------------------------------------- 1 | let version = '1.3.3'; 2 | 3 | // .messagesWrapper-1sRNjr .markup-2BOw-j 4 | let italicsEnabled = true; // 5 | let boldEnabled = true; // 6 | let underlineEnabled = true; // 7 | let strikethroughEnabled = true; // 8 | 9 | let spoilerEnabled = true; // <.spoilerText-3p6IlD> 10 | 11 | let inlineCodeEnabled = true; // 12 | let quotesEnabled = true; // 13 | 14 | if (typeof window === 'undefined' || typeof window.document === 'undefined') { // JSON API generator evals 15 | global.window = { document: { styleSheets: [0] } }; 16 | } 17 | 18 | let sheet = window.document.styleSheets[0]; 19 | 20 | function setItalics(c) { 21 | italicsEnabled = c; 22 | 23 | try { 24 | document.body.classList[c ? 'add' : 'remove']('gm-wysiwyg-italics-enabled'); 25 | } catch (e) { 26 | console.log(e); 27 | } 28 | } 29 | 30 | function setBold(c) { 31 | boldEnabled = c; 32 | 33 | try { 34 | document.body.classList[c ? 'add' : 'remove']('gm-wysiwyg-bold-enabled'); 35 | } catch (e) { 36 | console.log(e); 37 | } 38 | } 39 | 40 | function setUnderline(c) { 41 | underlineEnabled = c; 42 | 43 | try { 44 | document.body.classList[c ? 'add' : 'remove']('gm-wysiwyg-underline-enabled'); 45 | } catch (e) { 46 | console.log(e); 47 | } 48 | } 49 | 50 | function setStrikethrough(c) { 51 | strikethroughEnabled = c; 52 | 53 | try { 54 | document.body.classList[c ? 'add' : 'remove']('gm-wysiwyg-strikethrough-enabled'); 55 | } catch (e) { 56 | console.log(e); 57 | } 58 | } 59 | 60 | function setSpoiler(c) { 61 | spoilerEnabled = c; 62 | 63 | try { 64 | document.body.classList[c ? 'add' : 'remove']('gm-wysiwyg-spoiler-enabled'); 65 | } catch (e) { 66 | console.log(e); 67 | } 68 | } 69 | 70 | function setInlineCode(c) { 71 | inlineCodeEnabled = c; 72 | 73 | try { 74 | document.body.classList[c ? 'add' : 'remove']('gm-wysiwyg-inline-enabled'); 75 | } catch (e) { 76 | console.log(e); 77 | } 78 | } 79 | 80 | function setQuotes(c) { 81 | quotesEnabled = c; 82 | 83 | try { 84 | document.body.classList[c ? 'add' : 'remove']('gm-wysiwyg-quotes-enabled'); 85 | } catch (e) { 86 | console.log(e); 87 | } 88 | } 89 | 90 | let obj = { 91 | onImport: async function () { 92 | sheet.insertRule(`body.gm-wysiwyg-italics-enabled .messagesWrapper-1sRNjr .markup-2BOw-j em::before, body.gm-wysiwyg-italics-enabled .messagesWrapper-1sRNjr .markup-2BOw-j em::after { 93 | content: '*'; 94 | 95 | font-weight: 600; 96 | }`, sheet.cssRules.length); 97 | 98 | sheet.insertRule(`body.gm-wysiwyg-bold-enabled .messagesWrapper-1sRNjr .markup-2BOw-j strong::before, body.gm-wysiwyg-bold-enabled .messagesWrapper-1sRNjr .markup-2BOw-j strong::after { 99 | content: '**'; 100 | 101 | font-weight: 600; 102 | }`, sheet.cssRules.length); 103 | 104 | sheet.insertRule(`body.gm-wysiwyg-underline-enabled .messagesWrapper-1sRNjr .markup-2BOw-j u::before, body.gm-wysiwyg-underline-enabled .messagesWrapper-1sRNjr .markup-2BOw-j u::after { 105 | content: '__'; 106 | 107 | font-weight: 400; 108 | }`, sheet.cssRules.length); 109 | 110 | sheet.insertRule(`body.gm-wysiwyg-strikethrough-enabled .messagesWrapper-1sRNjr .markup-2BOw-j s::before, body.gm-wysiwyg-strikethrough-enabled .messagesWrapper-1sRNjr .markup-2BOw-j s::after { 111 | content: '~~'; 112 | 113 | font-weight: 400; 114 | 115 | }`, sheet.cssRules.length); 116 | 117 | sheet.insertRule(`body.gm-wysiwyg-spoiler-enabled .messagesWrapper-1sRNjr .markup-2BOw-j .spoilerText-3p6IlD::before, body.gm-wysiwyg-spoiler-enabled .messagesWrapper-1sRNjr .markup-2BOw-j .spoilerText-3p6IlD::after { 118 | content: '||'; 119 | 120 | font-weight: 400; 121 | }`, sheet.cssRules.length); 122 | 123 | sheet.insertRule(`body.gm-wysiwyg-inline-enabled .messagesWrapper-1sRNjr .markup-2BOw-j code.inline::before, body.gm-wysiwyg-inline-enabled .messagesWrapper-1sRNjr .markup-2BOw-j code.inline::after { 124 | content: '\`'; 125 | 126 | font-weight: 600; 127 | border-radius: 0 3px 3px 0 128 | }`, sheet.cssRules.length); 129 | 130 | sheet.insertRule(`body.gm-wysiwyg-italics-enabled .messagesWrapper-1sRNjr .markup-2BOw-j em::before, body.gm-wysiwyg-bold-enabled .messagesWrapper-1sRNjr .markup-2BOw-j strong::before, body.gm-wysiwyg-underline-enabled .messagesWrapper-1sRNjr .markup-2BOw-j u::before, body.gm-wysiwyg-strikethrough-enabled .messagesWrapper-1sRNjr .markup-2BOw-j s::before, body.gm-wysiwyg-spoiler-enabled .messagesWrapper-1sRNjr .markup-2BOw-j .spoilerText-3p6IlD::before, body.gm-wysiwyg-inline-enabled .messagesWrapper-1sRNjr .markup-2BOw-j code.inline::before { 131 | margin-right: 1px; 132 | 133 | letter-spacing: 0.004em; 134 | 135 | display: inline-block; 136 | text-decoration: none; 137 | font-style: normal; 138 | 139 | filter: brightness(0.5); 140 | }`, sheet.cssRules.length); 141 | 142 | sheet.insertRule(`body.gm-wysiwyg-italics-enabled .messagesWrapper-1sRNjr .markup-2BOw-j em::after, body.gm-wysiwyg-bold-enabled .messagesWrapper-1sRNjr .markup-2BOw-j strong::after, body.gm-wysiwyg-underline-enabled .messagesWrapper-1sRNjr .markup-2BOw-j u::after, body.gm-wysiwyg-strikethrough-enabled .messagesWrapper-1sRNjr .markup-2BOw-j s::after, body.gm-wysiwyg-spoiler-enabled .messagesWrapper-1sRNjr .markup-2BOw-j .spoilerText-3p6IlD::after, body.gm-wysiwyg-inline-enabled .messagesWrapper-1sRNjr .markup-2BOw-j code.inline::after { 143 | margin-left: 1px; 144 | 145 | letter-spacing: 0.004em; 146 | 147 | display: inline-block; 148 | text-decoration: none; 149 | font-style: normal; 150 | 151 | filter: brightness(0.5); 152 | }`, sheet.cssRules.length); 153 | 154 | sheet.insertRule(`body.gm-wysiwyg-quotes-enabled .messagesWrapper-1sRNjr .markup-2BOw-j .blockquoteContainer-U5TVEi .blockquoteDivider-2hH8H6 { 155 | width: 0; 156 | background-color: transparent; 157 | 158 | margin-right: 2px; 159 | }`, sheet.cssRules.length); 160 | 161 | sheet.insertRule(`body.gm-wysiwyg-quotes-enabled .messagesWrapper-1sRNjr .markup-2BOw-j .blockquoteContainer-U5TVEi .blockquoteDivider-2hH8H6::before { 162 | content: '>'; 163 | 164 | color: var(--text-normal); 165 | 166 | filter: brightness(0.3); 167 | font-weight: 400; 168 | 169 | display: inline-block; 170 | text-decoration: none; 171 | font-style: normal; 172 | }`, sheet.cssRules.length); 173 | }, 174 | 175 | onLoadingFinished: async function () { 176 | setItalics(true); 177 | setBold(true); 178 | setUnderline(true); 179 | setStrikethrough(true); 180 | setSpoiler(true); 181 | setInlineCode(true); 182 | setQuotes(true); 183 | 184 | goosemodScope.settings.createItem('WYSIWYG Messages', [ 185 | `(v${version})`, 186 | 187 | { 188 | type: 'header', 189 | text: 'Specific Markdown Elements' 190 | }, 191 | { 192 | type: 'toggle', 193 | text: 'Italics', 194 | subtext: '*Text*', 195 | onToggle: (c) => setItalics(c), 196 | isToggled: () => italicsEnabled 197 | }, 198 | { 199 | type: 'toggle', 200 | text: 'Bold', 201 | subtext: '**Text**', 202 | onToggle: (c) => setBold(c), 203 | isToggled: () => boldEnabled 204 | }, 205 | { 206 | type: 'toggle', 207 | text: 'Underline', 208 | subtext: '__Text__', 209 | onToggle: (c) => setUnderline(c), 210 | isToggled: () => underlineEnabled 211 | }, 212 | { 213 | type: 'toggle', 214 | text: 'Strikethrough', 215 | subtext: '~~Text~~', 216 | onToggle: (c) => setStrikethrough(c), 217 | isToggled: () => strikethroughEnabled 218 | }, 219 | { 220 | type: 'toggle', 221 | text: 'Spoilers', 222 | subtext: '||Text||', 223 | onToggle: (c) => setSpoiler(c), 224 | isToggled: () => spoilerEnabled 225 | }, 226 | { 227 | type: 'toggle', 228 | text: 'Inline Code', 229 | subtext: '`Text`', 230 | onToggle: (c) => setInlineCode(c), 231 | isToggled: () => inlineCodeEnabled 232 | }, 233 | { 234 | type: 'toggle', 235 | text: 'Quotes', 236 | subtext: '> Text', 237 | onToggle: (c) => setQuotes(c), 238 | isToggled: () => quotesEnabled 239 | } 240 | ]); 241 | }, 242 | 243 | remove: async function () { 244 | setItalics(false); 245 | setBold(false); 246 | setUnderline(false); 247 | setStrikethrough(false); 248 | setSpoiler(false); 249 | setInlineCode(false); 250 | setQuotes(false); 251 | 252 | let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'WYSIWYG Messages'); 253 | goosemodScope.settings.items.splice(goosemodScope.settings.items.indexOf(settingItem), 1); 254 | }, 255 | 256 | getSettings: () => [italicsEnabled, boldEnabled, underlineEnabled, strikethroughEnabled, spoilerEnabled, inlineCodeEnabled, quotesEnabled], 257 | loadSettings: ([_italicsEnabled, _boldEnabled, _underlineEnabled, _strikethroughEnabled, _spoilerEnabled, _inlineCodeEnabled, _quotesEnabled]) => { 258 | setItalics(_italicsEnabled); 259 | setBold(_boldEnabled); 260 | setUnderline(_underlineEnabled); 261 | setStrikethrough(_strikethroughEnabled); 262 | setSpoiler(_spoilerEnabled); 263 | setInlineCode(_inlineCodeEnabled); 264 | setQuotes(_quotesEnabled); 265 | }, 266 | 267 | logRegionColor: 'darkred', 268 | 269 | name: 'WYSIWYG Messages', 270 | description: 'Makes messages WYSIWYG-like (like in the message sending box)', 271 | 272 | author: 'Ducko', 273 | 274 | version 275 | }; 276 | 277 | obj 278 | -------------------------------------------------------------------------------- /modules/quick-actions/clearRecentGames.js: -------------------------------------------------------------------------------- 1 | let version = '1.0.2'; 2 | 3 | let obj = { 4 | onImport: async function () { 5 | if (window.localStorage === undefined) { 6 | alert('Clear Recent Games: Could not find localStorage, will not work') 7 | } 8 | }, 9 | 10 | onLoadingFinished: async function () { 11 | goosemodScope.settings.createItem('Clear Recent Games', [''], async () => { 12 | if (!(await goosemodScope.confirmDialog('Clear', 'Clear Recent Games', 'Are you sure you want to clear your recent games?'))) { 13 | return; 14 | } 15 | 16 | let c = JSON.parse(localStorage.getItem('RunningGameStore')); 17 | 18 | c.gamesSeen = []; 19 | 20 | localStorage.setItem('RunningGameStore', JSON.stringify(c)); 21 | 22 | if (await goosemodScope.confirmDialog('Reload', 'Reload Discord', 'To actually update the recent games after clearing it, Discord requires a reload. Without it, it will still look like recent games have not been cleared. This will also uninstall GooseMod due to reloading.')) { 23 | window.location.reload(); 24 | } 25 | }); 26 | }, 27 | 28 | remove: async function () { 29 | let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'Clear Recent Games'); 30 | goosemodScope.settings.items.splice(goosemodScope.settings.items.indexOf(settingItem), 1); 31 | }, 32 | 33 | logRegionColor: 'darkred', 34 | 35 | name: 'Clear Recent Games', 36 | description: 'Adds setting button which clears recent games (in "Game Activity")', 37 | 38 | author: 'Ducko', 39 | 40 | version 41 | }; 42 | 43 | obj -------------------------------------------------------------------------------- /modules/quick-actions/downloadImagesShortcut.js: -------------------------------------------------------------------------------- 1 | const version = '1.1.0'; 2 | 3 | let src; 4 | 5 | const downloadURL = async (url) => { 6 | let el = document.createElement('a'); 7 | 8 | el.href = url; 9 | el.download = url.includes('http') ? url.split('/').pop() : ''; 10 | 11 | el.style.display = 'none'; 12 | 13 | document.body.appendChild(el); 14 | 15 | el.click(); 16 | 17 | document.body.removeChild(el); 18 | }; 19 | 20 | const keypressHandler = (e) => { 21 | if (src && e.code === 'KeyD' && e.ctrlKey) { 22 | downloadURL(src); 23 | 24 | e.preventDefault(); 25 | return false; 26 | } 27 | }; 28 | 29 | const hoverHandler = (e) => { 30 | if (e.target && e.target.src) { 31 | src = e.target.src.split('?')[0]; 32 | } else { 33 | src = undefined; 34 | } 35 | }; 36 | 37 | let obj = { 38 | onImport: async function () { 39 | document.addEventListener('keypress', keypressHandler); 40 | document.addEventListener('mousemove', hoverHandler); 41 | }, 42 | 43 | remove: async function () { 44 | document.removeEventListener('keypress', keypressHandler); 45 | document.removeEventListener('mousemove', hoverHandler); 46 | }, 47 | 48 | name: 'Download Images Shortcut', 49 | description: 'Allows downloading of images by hovering overing them and pressing Ctrl+D', 50 | 51 | author: 'Ducko', 52 | 53 | version 54 | }; 55 | 56 | obj -------------------------------------------------------------------------------- /modules/quick-actions/gameActivityButton.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.3'; 2 | 3 | const enabledIcon = 4 | ''; 5 | const enabledIconHover = 6 | ''; 7 | 8 | const disabledIcon = 9 | ''; 10 | const disabledIconHover = 11 | ''; 12 | 13 | const micIconPath = `M6.7 11H5C5 12.19 5.34 13.3 5.9 14.28L7.13 13.05C6.86 12.43 6.7 11.74 6.7 11Z`; 14 | const muteIconPath = `M14.99 11C14.99 12.66 13.66 14 12 14C10.34 14 9 12.66 9 11V5C9 3.34 10.34 2 12 2C13.66 2 15 3.34 15 5L14.99 11ZM12 16.1C14.76 16.1 17.3 14 17.3 11H19C19 14.42 16.28 17.24 13 17.72V21H11V17.72C7.72 17.23 5 14.41 5 11H6.7C6.7 14 9.24 16.1 12 16.1ZM12 4C11.2 4 11 4.66667 11 5V11C11 11.3333 11.2 12 12 12C12.8 12 13 11.3333 13 11V5C13 4.66667 12.8 4 12 4Z`; 15 | 16 | let interval, btn, tooltip, gameActivity, soundReference; 17 | 18 | let removed = false; 19 | 20 | function onButtonMouseOver({ target }) { 21 | btn.firstElementChild.innerHTML = gameActivity ? enabledIconHover : disabledIconHover; 22 | 23 | const { x, y } = target.getBoundingClientRect(); 24 | const tooltipXPos = x + target.clientWidth / 2 - tooltip.offsetWidth / 2; 25 | const tooltipYPos = y - target.clientHeight - 8; // 8 being a constant amount of space to hover above the btn. 26 | 27 | tooltip.style.left = `${tooltipXPos}px`; 28 | tooltip.style.visibility = "visible"; 29 | tooltip.style.top = `${tooltipYPos}px`; 30 | 31 | tooltip.visibility = "visible"; 32 | } 33 | 34 | function onButtonMouseOut() { 35 | btn.firstElementChild.innerHTML = gameActivity ? enabledIcon : disabledIcon; 36 | tooltip.style.visibility = "hidden"; 37 | } 38 | 39 | const onToggle = () => { 40 | gameActivity = !gameActivity; 41 | 42 | const mod = goosemodScope.webpackModules.findByProps("updateRemoteSettings"); 43 | 44 | mod.updateLocalSettings({ 45 | showCurrentGame: gameActivity, 46 | }); 47 | 48 | mod.updateRemoteSettings({ 49 | showCurrentGame: gameActivity, 50 | }); 51 | 52 | btn.firstElementChild.innerHTML = gameActivity ? enabledIcon : disabledIcon; 53 | 54 | // In order to preserve the tooltipPointer but also change the message we have to do this 55 | const innerTooltipHTML = tooltip.firstElementChild.innerHTML.split("Turn"); 56 | tooltip.firstElementChild.innerHTML = `${innerTooltipHTML[0]} Turn ${gameActivity ? "off" : "on"} game activity`; 57 | 58 | btn.setAttribute("aria-checked", `${gameActivity ? "true" : "false"}`); 59 | 60 | // If enabled, play the mute / unmute sound on toggle. 61 | if (gameActivity) { 62 | soundReference.playSound("unmute", 0.4); 63 | } else { 64 | soundReference.playSound("mute", 0.4); 65 | } 66 | } 67 | 68 | const checkForChange = () => { 69 | if (removed) return; 70 | 71 | let current = goosemodScope.webpackModules.findByProps("guildPositions").showCurrentGame; 72 | if (gameActivity !== current) { 73 | gameActivity = current; 74 | 75 | btn.firstElementChild.innerHTML = gameActivity ? enabledIcon : disabledIcon; 76 | 77 | const innerTooltipHTML = tooltip.firstElementChild.innerHTML.split("Turn"); 78 | tooltip.firstElementChild.innerHTML = `${innerTooltipHTML[0]} Turn ${gameActivity ? "off" : "on"} game activity`; 79 | 80 | btn.setAttribute("aria-checked", `${gameActivity ? "true" : "false"}`); 81 | btn.addEventListener("click", onToggle); 82 | } 83 | } 84 | 85 | let obj = { 86 | onImport: async function () { 87 | const mod = goosemodScope.webpackModules.findByProps("guildPositions"); 88 | mod.addChangeListener(checkForChange); 89 | 90 | gameActivity = mod.showCurrentGame; 91 | soundReference = goosemodScope.webpackModules.findByProps("playSound"); 92 | 93 | const row = document.querySelector('[aria-label="User area"] .nameTag-3uD-yy + .directionRow-3v3tfG'); 94 | 95 | btn = row.firstElementChild.cloneNode(true); 96 | btn.firstElementChild.innerHTML = gameActivity ? enabledIcon : disabledIcon; 97 | btn.firstElementChild.style.pointerEvents = "none"; // Ignore pointer events to fix bug that was causing repeated clicks to be ignored. 98 | btn.id = "GameActivityToggleBtn"; 99 | btn.setAttribute("aria-label", "Toggle Game Activity"); 100 | btn.setAttribute("aria-checked", `${gameActivity ? "true" : "false"}`); 101 | 102 | btn.addEventListener("click", onToggle); 103 | btn.addEventListener("mouseenter", onButtonMouseOver); 104 | btn.addEventListener("mouseleave", onButtonMouseOut); 105 | 106 | row.prepend(btn); 107 | 108 | const tooltipClasses = goosemodScope.webpackModules.findByProps("tooltipBottom"); 109 | 110 | const wrapperDiv = document.createElement("div"); 111 | tooltip = wrapperDiv; 112 | 113 | wrapperDiv.style.visibility = "hidden"; 114 | wrapperDiv.style.position = "absolute"; 115 | // wrapperDiv.style.zIndex = "1003"; 116 | 117 | wrapperDiv.className = [ 118 | tooltipClasses.tooltip, 119 | tooltipClasses.tooltipTop, 120 | tooltipClasses.tooltipBlack, 121 | tooltipClasses.tooltipDisablePointerEvents, 122 | ].join(" "); 123 | 124 | const textWrapper = document.createElement("div"); 125 | 126 | textWrapper.className = tooltipClasses.tooltipContent; 127 | textWrapper.innerText = `Turn ${gameActivity ? "off" : "on"} game activity`; 128 | 129 | const bottomArrow = document.createElement("div"); 130 | bottomArrow.className = tooltipClasses.tooltipPointer; 131 | 132 | wrapperDiv.appendChild(textWrapper); 133 | wrapperDiv.appendChild(bottomArrow); 134 | document.body.appendChild(wrapperDiv); 135 | }, 136 | 137 | onLoadingFinished: async function () { 138 | }, 139 | 140 | remove: async function () { 141 | removed = true; 142 | 143 | btn.remove(); 144 | tooltip.remove(); 145 | }, 146 | 147 | logRegionColor: 'darkred', 148 | 149 | name: 'Game Activity Button', 150 | description: 'Adds button to account panel which enables / disables game activity (showing what game you are playing), idea and icon from Egrodo\'s BD plugin', 151 | 152 | author: 'Ducko', 153 | 154 | version 155 | }; 156 | 157 | obj -------------------------------------------------------------------------------- /modules/quick-actions/macros.js: -------------------------------------------------------------------------------- 1 | let originalFunc; 2 | 3 | let macros = {}; 4 | 5 | let version = '1.1.3'; 6 | 7 | const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); 8 | 9 | let obj = { 10 | onImport: async function () { 11 | let mod = goosemodScope.webpackModules.findByProps("jumpToMessage", "_sendMessage"); 12 | originalFunc = mod.sendMessage; 13 | 14 | mod.sendMessage = async function (_, message) {//_, [, message]) { 15 | if (message.content.startsWith('/m')) { 16 | let rpl = message.content.replace('/m ', ''); 17 | let name = rpl.split(' ')[0]; 18 | let content = rpl.split(' ').slice(1).join(' '); 19 | 20 | console.log(name, content); 21 | 22 | if (!content) { 23 | if (!name || name === '/m') { 24 | goosemodScope.showToast(`Syntax: "/m [macro content]" - no macro content = get macro, with macro content = set macro`, {timeout: 2000}); 25 | await sleep(2000); 26 | 27 | goosemodScope.showToast(`Your Macros:`, {timeout: 1000}); 28 | 29 | await sleep(1000); 30 | 31 | for (let t of Object.keys(macros).map((x) => `${x}: ${macros[x]}`)) { 32 | goosemodScope.showToast(t, {timeout: 1000}); 33 | await sleep(1000); 34 | } 35 | 36 | return; 37 | } 38 | 39 | if (!macros[name]) { 40 | goosemodScope.showToast(`No macro "${name}"`); 41 | 42 | return; 43 | } 44 | 45 | message.content = macros[name]; 46 | } else { 47 | macros[name] = content; 48 | 49 | goosemodScope.showToast(`Macro "${name}" saved`); 50 | 51 | return; 52 | } 53 | } 54 | 55 | return originalFunc.apply(this, arguments); 56 | }; 57 | }, 58 | 59 | remove: async function () { 60 | goosemodScope.webpackModules.findByProps("jumpToMessage", "_sendMessage").sendMessage = originalFunc; 61 | }, 62 | 63 | getSettings: () => [macros], 64 | loadSettings: ([_macros]) => { 65 | macros = _macros; 66 | }, 67 | 68 | logRegionColor: 'darkred', 69 | 70 | name: 'Macros', 71 | description: 'Allows setting and sending of macros via /m name [value]', 72 | 73 | author: 'Ducko', 74 | 75 | version 76 | }; 77 | 78 | obj -------------------------------------------------------------------------------- /modules/quick-actions/relaunch.js: -------------------------------------------------------------------------------- 1 | const version = "1.3.0"; 2 | 3 | let keydownHandler; 4 | 5 | let obj = { 6 | onImport: async () => { 7 | const createModal = async () => { 8 | const { React } = goosemodScope.webpackModules.common; 9 | const { findByDisplayName, findByProps } = goosemodScope.webpackModules; 10 | 11 | const Text = findByDisplayName("Text"); 12 | 13 | (0, findByProps("openModal").openModal)((e) => { 14 | return React.createElement( 15 | findByDisplayName("ConfirmModal"), 16 | { 17 | header: "Relaunch", 18 | confirmText: "Relaunch", 19 | cancelText: findByProps("Messages").Messages.CANCEL, 20 | onClose: () => {}, 21 | onCancel: e.onClose, 22 | onConfirm: () => { 23 | return DiscordNative.app.relaunch(); 24 | }, 25 | transitionState: e.transitionState, 26 | }, 27 | React.createElement( 28 | Text, 29 | { size: Text.Sizes.SIZE_16 }, 30 | "Are you sure you want to relaunch Discord? This will completely terminate Discord and start the updater." 31 | ) 32 | ); 33 | }); 34 | }; 35 | 36 | keydownHandler = async (event) => { 37 | if (event.code == "F4") { 38 | event.preventDefault(); 39 | createModal(); 40 | } 41 | }; 42 | 43 | goosemodScope.settings.createItem( 44 | "Relaunch", 45 | [""], 46 | async () => { 47 | createModal(); 48 | }, 49 | true 50 | ); 51 | 52 | document.addEventListener("keydown", keydownHandler); 53 | }, 54 | 55 | remove: async () => { 56 | goosemod.settings.removeItem("Relaunch"); 57 | document.removeEventListener("keydown", keydownHandler); 58 | }, 59 | 60 | name: "Relaunch", 61 | description: "Easily relaunch Discord, completely. (Press `F4` to relaunch.)", 62 | author: "441384103946878987", 63 | version, 64 | }; 65 | 66 | obj 67 | -------------------------------------------------------------------------------- /modules/quick-actions/sendButton.js: -------------------------------------------------------------------------------- 1 | const version = "1.0.0"; 2 | 3 | let settings = { 4 | mobileIcon: false, 5 | }; 6 | 7 | let unpatchChannelTextAreaButton; 8 | 9 | const setMobileIcon = (value) => { 10 | settings.mobileIcon = value; 11 | 12 | try { 13 | unpatchChannelTextAreaButton(); 14 | } catch {} 15 | 16 | unpatchChannelTextAreaButton = goosemodScope.patcher.channelTextAreaButtons.patch( 17 | "Send", 18 | settings.mobileIcon 19 | ? "https://i.imgur.com/n1TQIsQ.png" 20 | : "https://i.imgur.com/qzomTIw.png", 21 | (props) => { 22 | if ( 23 | goosemodScope.reactUtils.getReactInstance( 24 | document.querySelector(".channelTextArea-rNsIhG") 25 | ).memoizedProps.children[4].props.textValue == "" 26 | ) 27 | return goosemodScope.webpackModules 28 | .findByProps("ComponentDispatch") 29 | .ComponentDispatch.dispatch("SHAKE_APP", { 30 | duration: 200, 31 | intensity: 2, 32 | }); 33 | 34 | const textAreaWrapper = document.querySelector(".textArea-12jD-V"); 35 | const textArea = textAreaWrapper?.children[0]; 36 | 37 | const press = new KeyboardEvent("keydown", { 38 | key: "Enter", 39 | code: "Enter", 40 | which: 13, 41 | keyCode: 13, 42 | bubbles: true, 43 | }); 44 | Object.defineProperties(press, { 45 | keyCode: { value: 13 }, 46 | which: { value: 13 }, 47 | }); 48 | 49 | textArea.dispatchEvent(press); 50 | } 51 | ); 52 | }; 53 | 54 | let obj = { 55 | onImport: async () => { 56 | setMobileIcon(settings.mobileIcon); 57 | }, 58 | 59 | onLoadingFinished: async () => { 60 | goosemodScope.settings.createItem("Send Button", [ 61 | `(v${version})`, 62 | { 63 | type: "toggle", 64 | text: "Mobile Icon", 65 | subtext: 66 | "Replaces the send button's icon with an icon similair to Discord's mobile app's send button.", 67 | onToggle: (value) => setMobileIcon(value), 68 | isToggled: () => settings.mobileIcon, 69 | }, 70 | ]); 71 | }, 72 | 73 | remove: async () => { 74 | goosemodScope.settings.removeItem("Send Button"); 75 | unpatchChannelTextAreaButton(); 76 | }, 77 | 78 | getSettings: () => [settings], 79 | loadSettings: ([_settings]) => { 80 | settings = _settings; 81 | 82 | setMobileIcon(settings.mobileIcon); 83 | }, 84 | 85 | name: "Send Button", 86 | description: "Adds a send button, similair to the mobile application.", 87 | author: "441384103946878987", 88 | version, 89 | }; 90 | 91 | obj 92 | -------------------------------------------------------------------------------- /modules/themes/bloodyHellMate.js: -------------------------------------------------------------------------------- 1 | const version = "0"; 2 | 3 | let style; 4 | 5 | let obj = { 6 | onImport: async () => { 7 | style = document.createElement("style"); 8 | document.head.appendChild(style); 9 | style.appendChild( 10 | document.createTextNode( 11 | `@import url("https://raw.githack.com/MrDragonBoi/bloody-hell-mate/main/index.css")` 12 | ) 13 | ); 14 | }, 15 | 16 | remove: async () => { 17 | style.remove(); 18 | }, 19 | 20 | name: "Bloody Hell Mate", 21 | description: "Makes everything bloody red, mate!", 22 | author: "MrDragonBoi", 23 | version, 24 | }; 25 | 26 | obj 27 | -------------------------------------------------------------------------------- /modules/themes/comfyTheme.js: -------------------------------------------------------------------------------- 1 | const version = "1.1.1"; 2 | 3 | let settings = { 4 | statusIcon: false, 5 | statusMask: false, 6 | comfyAvatar: true, 7 | coloredEmoji: true, 8 | userButtons: "#096dc0", 9 | chatButtons: "#6E85D3", 10 | circles: true, 11 | tooltips: true, 12 | seperators: false, 13 | watermark: false, 14 | }; 15 | 16 | let style; 17 | 18 | let cssStatusIcon; 19 | let cssStatusMask; 20 | let cssComfyAvatar; 21 | let cssColoredEmoji; 22 | let cssUserButtons; 23 | let cssChatButtons; 24 | let cssCircles; 25 | let cssTooltips; 26 | let cssSeperators; 27 | let cssWatermark; 28 | 29 | const setStatusIcon = (value) => { 30 | if (value) { 31 | cssStatusIcon = document.createElement("style"); 32 | cssStatusIcon.appendChild( 33 | document.createTextNode(`:root { 34 | --popout-status-icon: block !important; 35 | }`) 36 | ); 37 | document.head.appendChild(cssStatusIcon); 38 | } else { 39 | try { 40 | cssStatusIcon.remove(); 41 | } catch {} 42 | } 43 | }; 44 | const setStatusMask = (value) => { 45 | if (value) { 46 | cssStatusMask = document.createElement("style"); 47 | cssStatusMask.appendChild( 48 | document.createTextNode(`:root { 49 | --popout-status-mask: url(#svg-mask-avatar-status-round-80) !important; 50 | }`) 51 | ); 52 | document.head.appendChild(cssStatusMask); 53 | } else { 54 | try { 55 | cssStatusMask.remove(); 56 | } catch {} 57 | } 58 | }; 59 | const setComfyAvatar = (value) => { 60 | if (!value) { 61 | cssComfyAvatar = document.createElement("style"); 62 | cssComfyAvatar.appendChild( 63 | document.createTextNode(`:root { 64 | --avatar-radius: 100% !important; 65 | }`) 66 | ); 67 | document.head.appendChild(cssComfyAvatar); 68 | } else { 69 | try { 70 | cssComfyAvatar.remove(); 71 | } catch {} 72 | } 73 | }; 74 | const setColoredEmoji = (value) => { 75 | if (!value) { 76 | cssColoredEmoji = document.createElement("style"); 77 | cssColoredEmoji.appendChild( 78 | document.createTextNode(`:root { 79 | --colored-emoji: grayscale(100%) !important; 80 | }`) 81 | ); 82 | document.head.appendChild(cssColoredEmoji); 83 | } else { 84 | try { 85 | cssColoredEmoji.remove(); 86 | } catch {} 87 | } 88 | }; 89 | const setUserButtons = (value) => { 90 | try { 91 | cssUserButtons.remove(); 92 | } catch {} 93 | 94 | if (value != "#096dc0") { 95 | cssUserButtons = document.createElement("style"); 96 | cssUserButtons.appendChild( 97 | document.createTextNode(`:root { 98 | --user-buttons-color: ${value} !important; 99 | }`) 100 | ); 101 | document.head.appendChild(cssUserButtons); 102 | } 103 | }; 104 | const setChatButtons = (value) => { 105 | try { 106 | cssChatButtons.remove(); 107 | } catch {} 108 | 109 | if (value != "#6E85D3") { 110 | cssChatButtons = document.createElement("style"); 111 | cssChatButtons.appendChild( 112 | document.createTextNode(`:root { 113 | --chat-buttons: ${value} !important; 114 | }`) 115 | ); 116 | document.head.appendChild(cssChatButtons); 117 | } 118 | }; 119 | const setCircles = (value) => { 120 | if (!value) { 121 | cssCircles = document.createElement("style"); 122 | cssCircles.appendChild( 123 | document.createTextNode(`:root { 124 | --role-circle: 0px !important; 125 | }`) 126 | ); 127 | document.head.appendChild(cssCircles); 128 | } else { 129 | try { 130 | cssCircles.remove(); 131 | } catch {} 132 | } 133 | }; 134 | const setTooltips = (value) => { 135 | if (!value) { 136 | cssTooltips = document.createElement("style"); 137 | cssTooltips.appendChild( 138 | document.createTextNode(`:root { 139 | --tooltips: none !important; 140 | }`) 141 | ); 142 | document.head.appendChild(cssTooltips); 143 | } else { 144 | try { 145 | cssTooltips.remove(); 146 | } catch {} 147 | } 148 | }; 149 | const setSeperators = (value) => { 150 | if (value) { 151 | cssSeperators = document.createElement("style"); 152 | cssSeperators.appendChild( 153 | document.createTextNode(`:root { 154 | --seperators: block !important; 155 | }`) 156 | ); 157 | document.head.appendChild(cssSeperators); 158 | } else { 159 | try { 160 | cssSeperators.remove(); 161 | } catch {} 162 | } 163 | }; 164 | const setWatermark = (value) => { 165 | if (value) { 166 | cssWatermark = document.createElement("style"); 167 | cssWatermark.appendChild( 168 | document.createTextNode(`:root { 169 | --discord-logo: block !important; 170 | }`) 171 | ); 172 | document.head.appendChild(cssWatermark); 173 | } else { 174 | try { 175 | cssWatermark.remove(); 176 | } catch {} 177 | } 178 | }; 179 | 180 | let obj = { 181 | onImport: async () => { 182 | style = document.createElement("style"); 183 | style.appendChild( 184 | document.createTextNode( 185 | `@import url("https://raw.githack.com/NYRI4/Comfy-theme/main/BetterDiscord/comfy.theme.css");` 186 | ) 187 | ); 188 | document.head.appendChild(style); 189 | 190 | setStatusIcon(settings.statusIcon); 191 | setStatusMask(settings.statusMask); 192 | setComfyAvatar(settings.comfyAvatar); 193 | setColoredEmoji(settings.coloredEmoji); 194 | setUserButtons(settings.userButtons); 195 | setChatButtons(settings.chatButtons); 196 | setCircles(settings.circles); 197 | setTooltips(settings.tooltips); 198 | setSeperators(settings.seperators); 199 | setWatermark(settings.watermark); 200 | }, 201 | 202 | onLoadingFinished: async () => 203 | goosemodScope.settings.createItem("Comfy Theme", [ 204 | `(v${version})`, 205 | { 206 | type: "header", 207 | text: "BetterAvatar Popout", 208 | }, 209 | { 210 | type: "toggle", 211 | text: "User Modal Status Icon", 212 | onToggle: (value) => { 213 | settings.statusIcon = value; 214 | setStatusIcon(value); 215 | }, 216 | isToggled: () => settings.statusIcon, 217 | }, 218 | { 219 | type: "toggle", 220 | text: "User Modal Status Mask", 221 | onToggle: (value) => { 222 | settings.statusMask = value; 223 | setStatusMask(value); 224 | }, 225 | isToggled: () => settings.statusMask, 226 | }, 227 | { 228 | type: "toggle", 229 | text: "Comfy User Modal Avatar", 230 | subtext: 231 | "Unfortunately, text inputs are not yet avaiable for settings. Disable to use the normal radius of user modal avatars. (Not available while user modal status masks are enabled.)", 232 | onToggle: (value) => { 233 | settings.comfyAvatar = value; 234 | setComfyAvatar(value); 235 | }, 236 | isToggled: () => settings.comfyAvatar, 237 | }, 238 | { 239 | type: "header", 240 | text: "Other Settings", 241 | }, 242 | { 243 | type: "toggle", 244 | text: "Colored Emoji Picker", 245 | onToggle: (value) => { 246 | settings.coloredEmoji = value; 247 | setColoredEmoji(value); 248 | }, 249 | isToggled: () => settings.coloredEmoji, 250 | }, 251 | { 252 | type: "text-and-color", 253 | text: "User Settings, Mute and Deafen Buttons Color", 254 | subtext: "Default: rgb(9,109,192)", 255 | oninput: (value) => { 256 | settings.userButtons = value; 257 | setUserButtons(value); 258 | }, 259 | }, 260 | { 261 | type: "text-and-color", 262 | text: "User Buttons Color", 263 | subtext: "Default: rgb(110,133,211)", 264 | oninput: (value) => { 265 | settings.chatButtons = value; 266 | setChatButtons(value); 267 | }, 268 | }, 269 | { 270 | type: "toggle", 271 | text: "Circles Next to Role Names", 272 | onToggle: (value) => { 273 | settings.circles = value; 274 | setCircles(value); 275 | }, 276 | isToggled: () => settings.circles, 277 | }, 278 | { 279 | type: "toggle", 280 | text: "Tooltips", 281 | onToggle: (value) => { 282 | settings.tooltips = value; 283 | setTooltips(value); 284 | }, 285 | isToggled: () => settings.tooltips, 286 | }, 287 | { 288 | type: "toggle", 289 | text: "Seperators", 290 | onToggle: (value) => { 291 | settings.seperators = value; 292 | setSeperators(value); 293 | }, 294 | isToggled: () => settings.seperators, 295 | }, 296 | { 297 | type: "toggle", 298 | text: "Discord Watermark", 299 | onToggle: (value) => { 300 | settings.watermark = value; 301 | setWatermark(value); 302 | }, 303 | isToggled: () => settings.watermark, 304 | }, 305 | ]), 306 | 307 | remove: async () => { 308 | goosemodScope.settings.removeItem("Comfy Theme"); 309 | 310 | style.remove(); 311 | try { 312 | cssStatusIcon.remove(); 313 | } catch {} 314 | try { 315 | cssStatusMask.remove(); 316 | } catch {} 317 | try { 318 | cssComfyAvatar.remove(); 319 | } catch {} 320 | try { 321 | cssColoredEmoji.remove(); 322 | } catch {} 323 | try { 324 | cssUserButtons.remove(); 325 | } catch {} 326 | try { 327 | cssChatButtons.remove(); 328 | } catch {} 329 | try { 330 | cssCircles.remove(); 331 | } catch {} 332 | try { 333 | cssTooltips.remove(); 334 | } catch {} 335 | try { 336 | cssSeperators.remove(); 337 | } catch {} 338 | try { 339 | cssWatermark.remove(); 340 | } catch {} 341 | }, 342 | 343 | getSettings: () => [settings], 344 | loadSettings: ([_settings]) => { 345 | settings = _settings; 346 | 347 | setStatusIcon(settings.statusIcon); 348 | setStatusMask(settings.statusMask); 349 | setComfyAvatar(settings.comfyAvatar); 350 | setColoredEmoji(settings.coloredEmoji); 351 | setUserButtons(settings.userButtons); 352 | setChatButtons(settings.chatButtons); 353 | setCircles(settings.circles); 354 | setTooltips(settings.tooltips); 355 | setSeperators(settings.seperators); 356 | setWatermark(settings.watermark); 357 | }, 358 | 359 | name: "Comfy Theme", 360 | description: "A simple, customizable, comfy theme. (Ported with the addition of settings by Liam The Protogen.)", 361 | author: ["Nyria", "Liam The Protogen (441384103946878987)"], 362 | version, 363 | }; 364 | 365 | obj 366 | -------------------------------------------------------------------------------- /modules/themes/couveTheme.js: -------------------------------------------------------------------------------- 1 | const version = "0"; 2 | 3 | let style; 4 | 5 | let obj = { 6 | onImport: async () => { 7 | style = document.createElement("style"); 8 | document.head.appendChild(style); 9 | style.appendChild( 10 | document.createTextNode( 11 | `@import url("https://raw.githack.com/A-User-s-Discord-Themes/couve-git-clone-pc-repo/master/couve.css")` 12 | ) 13 | ); 14 | }, 15 | 16 | remove: async () => { 17 | style.remove(); 18 | }, 19 | 20 | name: "Couve Theme", 21 | description: "A new look to discord", 22 | author: "A user", 23 | version, 24 | }; 25 | 26 | obj 27 | -------------------------------------------------------------------------------- /modules/themes/customTheme.js: -------------------------------------------------------------------------------- 1 | let version = '0.1.0'; 2 | 3 | let obj = { 4 | onImport: async function () { 5 | let sheet = window.document.styleSheets[0]; 6 | 7 | sheet.insertRule(`html > body.theme-custom { 8 | --background-primary: var(--background-primary-custom); 9 | --background-secondary: var(--background-secondary-custom); 10 | --background-secondary-alt: var(--background-secondary-alt-custom) 11 | --background-tertiary: var(--background-tertiary-custom); 12 | 13 | --channeltextarea-background: var(--background-tertiary); 14 | --background-message-hover: rgba(4, 4, 5, 0.07); 15 | 16 | --background-accent: var(--background-accent-custom); 17 | --background-floating: var(--background-tertiary); 18 | 19 | --scrollbar-thin-thumb: var(--brand-color); 20 | --scrollbar-auto-thumb: var(--scrollbar-thin-thumb); 21 | --scrollbar-auto-scrollbar-color-thumb: var(--scrollbar-thin-thumb); 22 | 23 | --scrollbar-auto-track: var(--background-secondary-alt); 24 | --scrollbar-auto-scrollbar-color-track: var(--scrollbar-auto-track); 25 | 26 | --brand-color: var(--brand-color-custom); 27 | --brand-color-hover: var(--brand-color-hover-custom); 28 | }`, sheet.cssRules.length); 29 | 30 | document.body.classList.add('theme-custom'); 31 | 32 | let props = ['--background-primary', '--background-secondary', '--background-secondary-alt', '--background-tertiary', '--background-accent', '--brand-color', '--brand-color-hover']; 33 | 34 | goosemodScope.settings.createItem('Custom Theme', [ 35 | `(v${version})`, 36 | 37 | ...props.map((x) => ( 38 | { 39 | type: 'text-and-color', 40 | text: x.substring(2).replace(/-/g, ' ').replace(/(^|\W)([a-z])/g, (_, space, letter) => `${space}${letter.toUpperCase()}`), 41 | oninput: (val) => { 42 | document.body.style.setProperty(`${x}-custom`, val); 43 | } 44 | } 45 | )) 46 | ]); 47 | }, 48 | 49 | remove: async function () { 50 | document.body.classList.remove('theme-custom'); 51 | 52 | let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'Custom Theme'); 53 | goosemodScope.settings.items.splice(goosemodScope.settings.items.indexOf(settingItem), 1); 54 | }, 55 | 56 | name: 'Custom Theme', 57 | description: 'Choose your own colors for your own theme', 58 | 59 | author: 'Ducko', 60 | 61 | version 62 | }; 63 | 64 | obj 65 | -------------------------------------------------------------------------------- /modules/themes/darkerTheme.js: -------------------------------------------------------------------------------- 1 | let version = '1.0.2'; 2 | 3 | let obj = { 4 | onImport: async function () { 5 | let sheet = window.document.styleSheets[0]; 6 | 7 | sheet.insertRule(`html > body.theme-darker { 8 | --background-primary: #000; 9 | --background-secondary: #111; 10 | --background-secondary-alt: #000; 11 | --background-tertiary: #222; 12 | 13 | --channeltextarea-background: #111; 14 | --background-message-hover: rgba(255,255,255,0.025); 15 | 16 | --background-accent: #222; 17 | --background-floating: #111; 18 | }`, sheet.cssRules.length); 19 | 20 | document.body.classList.add('theme-darker'); 21 | }, 22 | 23 | remove: async function () { 24 | document.body.classList.remove('theme-darker'); 25 | }, 26 | 27 | logRegionColor: 'darkred', 28 | 29 | name: 'Darker Theme', 30 | description: 'Darker theme but still with contrast', 31 | 32 | author: 'Ducko', 33 | 34 | version 35 | }; 36 | 37 | obj -------------------------------------------------------------------------------- /modules/themes/darkestTheme.js: -------------------------------------------------------------------------------- 1 | let version = '1.0.3'; 2 | 3 | let obj = { 4 | onImport: async function () { 5 | let sheet = window.document.styleSheets[0]; 6 | 7 | sheet.insertRule(`html > body.theme-darkest { 8 | --background-primary: #000; 9 | --background-secondary: #050505; 10 | --background-secondary-alt: #000; 11 | --background-tertiary: #080808; 12 | 13 | --channeltextarea-background: #080808; 14 | --background-message-hover: rgba(255,255,255,0.025); 15 | 16 | --background-accent: #111; 17 | --background-floating: #080808; 18 | }`, sheet.cssRules.length); 19 | 20 | document.body.classList.add('theme-darkest'); 21 | }, 22 | 23 | remove: async function () { 24 | document.body.classList.remove('theme-darkest'); 25 | }, 26 | 27 | logRegionColor: 'darkred', 28 | 29 | name: 'Darkest Theme', 30 | description: 'Pure dark theme', 31 | 32 | author: 'Ducko', 33 | 34 | version 35 | }; 36 | 37 | obj -------------------------------------------------------------------------------- /modules/themes/draculaTheme.js: -------------------------------------------------------------------------------- 1 | let version = '1.1.5'; 2 | 3 | let obj = { 4 | onImport: async function () { 5 | let sheet = window.document.styleSheets[0]; 6 | 7 | sheet.insertRule(`html > body.theme-dracula { 8 | --background-primary: #181920; 9 | --background-secondary: #1C1D25; 10 | --background-secondary-alt: #16171D; 11 | --background-tertiary: #1F2029; 12 | 13 | --channeltextarea-background: #1F2029; 14 | --background-message-hover: rgba(4, 4, 5, 0.07); 15 | 16 | --background-accent: #22232E; 17 | --background-floating: #1F2029; 18 | 19 | --scrollbar-thin-thumb: #9B78CC; 20 | --scrollbar-auto-thumb: #9B78CC; 21 | --scrollbar-auto-scrollbar-color-thumb: #9B78CC; 22 | 23 | --scrollbar-auto-track: #16171D; 24 | --scrollbar-auto-scrollbar-color-track: #16171D; 25 | 26 | --brand-color: #9B78CC; 27 | --brand-color-hover: #896BB5; 28 | }`, sheet.cssRules.length); 29 | 30 | document.body.classList.add('theme-dracula'); 31 | }, 32 | 33 | remove: async function () { 34 | document.body.classList.remove('theme-dracula'); 35 | }, 36 | 37 | logRegionColor: 'darkred', 38 | 39 | name: 'Dracula Theme', 40 | description: 'Based on the Dracula color scheme', 41 | 42 | author: 'Ducko', 43 | 44 | version 45 | }; 46 | 47 | obj -------------------------------------------------------------------------------- /modules/themes/duvboxTheme.js: -------------------------------------------------------------------------------- 1 | const version = '1'; 2 | 3 | let el; 4 | 5 | const css = `@import url("https://raw.githack.com/CircuitRCAY/Duvbox/master/duvbox.css");`; 6 | 7 | let obj = { 8 | onImport: async function () { 9 | el = document.createElement('style'); 10 | 11 | document.head.appendChild(el); 12 | 13 | el.appendChild(document.createTextNode(css)); 14 | }, 15 | 16 | remove: async function () { 17 | el.remove(); 18 | }, 19 | 20 | name: 'Duvbox Theme', 21 | description: 'Based on the Vim theme, named Gruvbox.', 22 | 23 | author: 'CircuitRCAY', 24 | 25 | version 26 | }; 27 | 28 | obj 29 | -------------------------------------------------------------------------------- /modules/themes/iFixedDiscordTheme.js: -------------------------------------------------------------------------------- 1 | const version = "0"; 2 | 3 | let style; 4 | 5 | let obj = { 6 | onImport: async () => { 7 | style = document.createElement("style"); 8 | document.head.appendChild(style); 9 | style.appendChild( 10 | document.createTextNode( 11 | `@import url("https://raw.githack.com/j0lol/i-fixed-discord/main/css/theme.css")` 12 | ) 13 | ); 14 | }, 15 | 16 | remove: async () => { 17 | style.remove(); 18 | }, 19 | 20 | name: '"i fixed discord" Theme', 21 | description: "Makes light theme bearable. (Use in light mode with dark sidebar enabled.)", 22 | author: "jo", 23 | version, 24 | }; 25 | 26 | obj 27 | -------------------------------------------------------------------------------- /modules/themes/nordtheme.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.0'; 2 | 3 | let obj = { 4 | onImport: async function () { 5 | let sheet = window.document.styleSheets[0]; 6 | 7 | sheet.insertRule(`html > body.theme-nord { 8 | --background-primary: #2e3440; 9 | --background-secondary: #3b4252; 10 | --background-secondary-alt: #4c566a; 11 | --background-tertiary: #434c5e; 12 | 13 | --channeltextarea-background: #4c566a; 14 | --background-message-hover: rgba(4, 4, 5, 0.07); 15 | 16 | --background-accent: #434c5e; 17 | --background-floating: #4c566a; 18 | 19 | --scrollbar-thin-thumb: #5e81ac; 20 | --scrollbar-auto-thumb: #5e81ac; 21 | --scrollbar-auto-scrollbar-color-thumb: #5e81ac; 22 | 23 | --scrollbar-auto-track: #4c566a; 24 | --scrollbar-auto-scrollbar-color-track: #4c566a; 25 | 26 | --brand-color: #5e81ac; 27 | --brand-color-hover: #81a1c1; 28 | }`, sheet.cssRules.length); 29 | 30 | document.body.classList.add('theme-nord'); 31 | }, 32 | 33 | remove: async function () { 34 | document.body.classList.remove('theme-nord'); 35 | }, 36 | 37 | name: 'Nord Theme', 38 | description: 'Based on the Nord Theme color scheme, polar night (dark blue with lighter accents)', 39 | 40 | author: 'Mattheus Roxas', 41 | 42 | version 43 | }; 44 | 45 | obj -------------------------------------------------------------------------------- /modules/themes/protoncord.js: -------------------------------------------------------------------------------- 1 | const version = "0"; 2 | 3 | let style; 4 | 5 | let obj = { 6 | onImport: async () => { 7 | style = document.createElement("style"); 8 | document.head.appendChild(style); 9 | style.appendChild( 10 | document.createTextNode( 11 | `@import url("https://giangamerino.github.io/protoncord/index.css");` 12 | ) 13 | ); 14 | }, 15 | 16 | remove: async () => { 17 | style.remove(); 18 | }, 19 | 20 | name: "Protoncord", 21 | description: "A sleek, modern UI inspired by the layout of ProtonVPN.", 22 | author: "Niko", 23 | version, 24 | }; 25 | 26 | obj 27 | -------------------------------------------------------------------------------- /modules/themes/slateTheme.js: -------------------------------------------------------------------------------- 1 | let version = '1'; 2 | 3 | let el; 4 | 5 | const css = `@import url("https://raw.githack.com/DiscordStyles/Slate/master/Slate.theme.css");`; 6 | 7 | let obj = { 8 | onImport: async function () { 9 | el = document.createElement('style'); 10 | 11 | document.head.appendChild(el); 12 | 13 | el.appendChild(document.createTextNode(css)); 14 | }, 15 | 16 | remove: async function () { 17 | el.remove(); 18 | }, 19 | 20 | name: 'Slate Theme', 21 | description: 'An optimized, consistent, and functional theme for Discord based on GitHub\'s design language.', 22 | 23 | author: ['Gibbu', 'Tropical'], 24 | 25 | version 26 | }; 27 | 28 | obj 29 | -------------------------------------------------------------------------------- /modules/themes/solarizedDarkTheme.js: -------------------------------------------------------------------------------- 1 | let version = '1.0.1'; 2 | 3 | let obj = { 4 | onImport: async function () { 5 | let sheet = window.document.styleSheets[0]; 6 | 7 | sheet.insertRule(`html > body.theme-solarizeddark { 8 | --background-primary: #002b36; 9 | --background-secondary: #073642; 10 | --background-secondary-alt: #00232C; 11 | --background-tertiary: #1E4853; 12 | 13 | --channeltextarea-background: #1E4853; 14 | --background-message-hover: rgba(255,255,255,0.025); 15 | 16 | --background-accent: #657b83; 17 | --background-floating: #1E4853; 18 | 19 | --scrollbar-thin-thumb: #b58900; 20 | --scrollbar-auto-thumb: #b58900; 21 | --scrollbar-auto-scrollbar-color-thumb: #b58900; 22 | 23 | --scrollbar-auto-track: #00232C; 24 | --scrollbar-auto-scrollbar-color-track: #00232C; 25 | 26 | --brand-color: #b58900; 27 | --brand-color-hover: #947000; 28 | }`, sheet.cssRules.length); 29 | 30 | document.body.classList.add('theme-solarizeddark'); 31 | }, 32 | 33 | remove: async function () { 34 | document.body.classList.remove('theme-solarizeddark'); 35 | }, 36 | 37 | logRegionColor: 'darkred', 38 | 39 | name: 'Solarized Dark Theme', 40 | description: 'Based on the Solarized Dark color scheme', 41 | 42 | author: 'Ducko', 43 | 44 | version 45 | }; 46 | 47 | obj -------------------------------------------------------------------------------- /modules/themes/splendidTheme.js: -------------------------------------------------------------------------------- 1 | const version = "0"; 2 | 3 | let style; 4 | 5 | let obj = { 6 | onImport: async () => { 7 | style = document.createElement("style"); 8 | document.head.appendChild(style); 9 | style.appendChild( 10 | document.createTextNode( 11 | `@import url("https://raw.githack.com/Conjuringil/Splendid/main/main.css")` 12 | ) 13 | ); 14 | }, 15 | 16 | remove: async () => { 17 | style.remove(); 18 | }, 19 | 20 | name: "Splendid Theme", 21 | description: "An absolutely splendid theme.", 22 | author: "𝙞𝙡.", 23 | version, 24 | }; 25 | 26 | obj 27 | -------------------------------------------------------------------------------- /modules/ui/betterChannelIndicators.js: -------------------------------------------------------------------------------- 1 | const version = '0'; 2 | 3 | let el; 4 | 5 | const css = `@import url("https://raw.githack.com/LuckFire/BetterChannelIndicators/main/indicators.css");`; 6 | 7 | let obj = { 8 | onImport: async function () { 9 | el = document.createElement('style'); 10 | 11 | document.head.appendChild(el); 12 | 13 | el.appendChild(document.createTextNode(css)); 14 | }, 15 | 16 | remove: async function () { 17 | el.remove(); 18 | }, 19 | 20 | name: 'Better Channel Indicators', 21 | description: 'Adds a nice touch to Discord\'s current channel indicators.', 22 | 23 | author: 'LuckFire', 24 | 25 | version 26 | }; 27 | 28 | obj -------------------------------------------------------------------------------- /modules/ui/betterNsfw.js: -------------------------------------------------------------------------------- 1 | const version = "1.0.2"; 2 | 3 | let style; 4 | let timeout; 5 | 6 | let unpatch; 7 | 8 | let obj = { 9 | onImport: async () => { 10 | style = document.createElement("style"); 11 | style.appendChild( 12 | document.createTextNode(`.chat-3bRxxu.nsfw .imageWrapper-2p5ogY { 13 | position: relative; 14 | } 15 | .chat-3bRxxu.nsfw .imageWrapper-2p5ogY.embedWrapper-lXpS3L:hover::after, .chat-3bRxxu.nsfw .imageWrapper-2p5ogY .wrapper-2TxpI8:hover::after, .chat-3bRxxu.nsfw .imageWrapper-2p5ogY.embedThumbnail-2Y84-K:hover::after { 16 | display: none; 17 | } 18 | .chat-3bRxxu.nsfw .imageWrapper-2p5ogY.embedWrapper-lXpS3L::after, .chat-3bRxxu.nsfw .imageWrapper-2p5ogY .wrapper-2TxpI8.wrapperPaused-19pWuK::after, .chat-3bRxxu.nsfw .imageWrapper-2p5ogY.embedThumbnail-2Y84-K::after { 19 | content: "NSFW"; 20 | position: absolute; 21 | display: block; 22 | left: 50%; 23 | top: 50%; 24 | background-color: rgb(240, 71, 71); 25 | color: #dcddde; 26 | font-size: 15px; 27 | font-weight: 600; 28 | padding: 8px 12px; 29 | border-radius: 20px; 30 | letter-spacing: 0.5px; 31 | transform: translate(-50%, -50%); 32 | } 33 | .chat-3bRxxu.nsfw .wrapper-2TxpI8.wrapperPaused-19pWuK:hover::after { 34 | display: none; 35 | } 36 | .chat-3bRxxu.nsfw .imageWrapper-2p5ogY img, .chat-3bRxxu.nsfw .embedVideo-3nf0O9 video, .chat-3bRxxu.nsfw .video-8eMOth { 37 | filter: blur(20px); 38 | position: relative; 39 | } 40 | .chat-3bRxxu.nsfw .imageWrapper-2p5ogY img:hover, .chat-3bRxxu.nsfw .embedVideo-3nf0O9 video:hover, .chat-3bRxxu.nsfw .video-8eMOth:hover { 41 | filter: none; 42 | } 43 | .chat-3bRxxu.nsfw .wrapperControlsHidden-35Gtol video { 44 | filter: none; 45 | } 46 | `) 47 | ); 48 | document.head.appendChild(style); 49 | 50 | const runInjection = () => { 51 | try { 52 | const { findByProps } = goosemodScope.webpackModules; 53 | 54 | unpatch = goosemodScope.patcher.patch( 55 | goosemodScope.reactUtils.getOwnerInstance( 56 | document.querySelector(`.${findByProps("chat").chat}`) 57 | ).constructor.prototype, 58 | "render", 59 | (_, res) => { 60 | if ( 61 | findByProps("getChannel").getChannel( 62 | res.props.children[1].props.children[0]?.props.channelId 63 | ).nsfw 64 | ) { 65 | res.props.children[1].props.className += " nsfw"; 66 | } 67 | 68 | return res; 69 | } 70 | ); 71 | } catch { 72 | timeout = setTimeout(runInjection, 500); 73 | } 74 | }; 75 | 76 | runInjection(); 77 | }, 78 | 79 | remove: async () => { 80 | style.remove(); 81 | clearTimeout(timeout); 82 | 83 | try { 84 | unpatch(); 85 | } catch {} 86 | }, 87 | 88 | name: "Better NSFW", 89 | description: "Blurs content in NSFW channels.", 90 | author: "441384103946878987", 91 | version, 92 | }; 93 | 94 | obj 95 | -------------------------------------------------------------------------------- /modules/ui/bottomBar.js: -------------------------------------------------------------------------------- 1 | const version = '1'; 2 | 3 | let el; 4 | 5 | const css = `@import url("https://raw.githack.com/LuckFire/BottomBar/master/bottombar.css");`; 6 | 7 | let obj = { 8 | onImport: async function () { 9 | el = document.createElement('style'); 10 | 11 | document.head.appendChild(el); 12 | 13 | el.appendChild(document.createTextNode(css)); 14 | }, 15 | 16 | remove: async function () { 17 | el.remove(); 18 | }, 19 | 20 | name: 'Bottom Bar', 21 | description: 'A nice, simple looking, bottom bar. Inspired by CapnKitten\'s Spotify Discord theme.', 22 | 23 | author: 'LuckFire', 24 | 25 | version 26 | }; 27 | 28 | obj 29 | -------------------------------------------------------------------------------- /modules/ui/deNitro.js: -------------------------------------------------------------------------------- 1 | const version = "1.0.1"; 2 | 3 | let style; 4 | const css = `.buttons-3JBrkn > button, .channel-2QD9_O[href="/store"], .item-PXvHYJ[aria-controls="Discord Nitro-tab"], .wrapper-3nSjSv, .giftAction-yhDLaW, .upsellFooter-3coAfO, .buttons-3JBrkn > .buttonContainer-28fw2U > [aria-label="Open sticker picker"], .navItem-3Wp_oJ[aria-controls="sticker-picker-tab-panel"] { 5 | display: none; 6 | }`; 7 | 8 | let obj = { 9 | onImport: async () => { 10 | style = document.createElement("style"); 11 | document.head.appendChild(style); 12 | style.appendChild(document.createTextNode(css)); 13 | }, 14 | 15 | remove: async () => { 16 | style.remove(); 17 | }, 18 | 19 | name: "De-Nitro", 20 | description: "Removes everything Nitro related.", 21 | author: "Liam The Protogen (441384103946878987)", 22 | version, 23 | }; 24 | 25 | obj 26 | -------------------------------------------------------------------------------- /modules/ui/fullscreenInbox.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Both the theme and the snippet is made by Freeplay (https://freeplay.codeberg.page) 3 | * Check out the PC and BD version: https://github.com/Freeplayg/Discord-fullscreen-inbox 4 | */ 5 | const version = "1.1.0"; 6 | 7 | let settings = { 8 | floating: true, 9 | }; 10 | 11 | let style; 12 | let css; 13 | 14 | const evaluateSettings = (value) => { 15 | if (css) style.removeChild(css); 16 | 17 | if (value) { 18 | css = document.createTextNode(`@import url("https://raw.githack.com/Freeplayg/Discord-fullscreen-inbox/main/main.css"); 19 | .recentMentionsPopout-3rCiI6 { 20 | animation: none; 21 | } 22 | .iconWrapper-2OrFZ1[aria-label="Inbox"] { 23 | position: fixed; 24 | top: 27px; 25 | left: 12px; 26 | height: 48px; 27 | width: 48px; 28 | margin: 0; 29 | background-color: var(--background-secondary); 30 | border-radius: 48px; 31 | box-shadow: var(--elevation-low); 32 | transition: border-radius .1s, background-color .1s; 33 | } 34 | .iconWrapper-2OrFZ1[aria-label="Inbox"]:hover { 35 | background-color: #7289da; 36 | border-radius: 15px; 37 | } 38 | .iconWrapper-2OrFZ1[aria-label="Inbox"]:active { 39 | transform: translateY(1px); 40 | } 41 | .iconWrapper-2OrFZ1[aria-label="Inbox"] > svg { 42 | margin: auto; 43 | height: 100%; 44 | } 45 | .iconWrapper-2OrFZ1[aria-label="Inbox"]:hover > svg { 46 | color: white !important; 47 | } 48 | .guilds-1SWlCJ .scroller-2TZvBN { 49 | padding-top: 63px !important; 50 | } 51 | .unreadMentionsIndicatorTop-gA6RCh { 52 | top: 48px; 53 | }`); 54 | style.appendChild(css); 55 | } else { 56 | css = document.createTextNode(`@import url("https://raw.githack.com/Freeplayg/Discord-fullscreen-inbox/main/main.css"); 57 | .recentMentionsPopout-3rCiI6 { 58 | animation: none; 59 | }`); 60 | style.appendChild(css); 61 | } 62 | 63 | document.head.appendChild(style); 64 | }; 65 | 66 | let obj = { 67 | onImport: async () => { 68 | style = document.createElement("style"); 69 | evaluateSettings(settings.floating); 70 | }, 71 | 72 | onLoadingFinished: async () => 73 | goosemodScope.settings.createItem("Fullscreen Inbox", [ 74 | `(v${version})`, 75 | { 76 | type: "toggle", 77 | text: "Floating Inbox Button", 78 | subtext: 79 | "Makes the inbox button float on the top left side of the screen with an appearence similair to the DMs button.", 80 | onToggle: (value) => { 81 | settings.floating = value; 82 | evaluateSettings(value); 83 | }, 84 | isToggled: () => settings.floating, 85 | }, 86 | ]), 87 | 88 | remove: async () => { 89 | goosemodScope.settings.removeItem("Fullscreen Inbox"); 90 | 91 | style.remove(); 92 | }, 93 | 94 | getSettings: () => [settings], 95 | loadSettings: ([_settings]) => { 96 | settings = _settings; 97 | evaluateSettings(settings.floating); 98 | }, 99 | 100 | name: "Fullscreen Inbox", 101 | description: "Makes the inbox appear as if it's a channel", 102 | author: ["Freeplay", "Liam The Protogen (441384103946878987)"], 103 | version, 104 | }; 105 | 106 | obj 107 | -------------------------------------------------------------------------------- /modules/ui/gradientButtons.js: -------------------------------------------------------------------------------- 1 | const version = '0'; 2 | 3 | let el; 4 | 5 | const css = `/* Menu Items (right click, server menu, message actions, ect.) */ 6 | .item-1tOPte.focused-3afm-j, .item-1tOPte:active:not(#user-context-user-volume) { 7 | color: #fff; 8 | background: linear-gradient(315deg, #495DA4 0%, #7289DA 74%); 9 | font-size: 15px; 10 | font-weight: bold; 11 | transition: 0.1s linear; 12 | } 13 | .item-1tOPte.colorPremium-p4p7qO.focused-3afm-j, .item-1tOPte.colorPremium-p4p7qO:active { 14 | color: #fff; 15 | background: linear-gradient(315deg, #8980F0 0%, #D577F0 74%); 16 | } 17 | .item-1tOPte.colorDanger-2qLCe1.focused-3afm-j, .item-1tOPte.colorDanger-2qLCe1:active { 18 | color: #fff; 19 | background: linear-gradient(315deg, #AA3738 0%, #F04747 74%) !important; 20 | } 21 | 22 | .item-1tOPte { 23 | font-weight: 500; 24 | transition: 0.1s linear; 25 | } 26 | 27 | .wrapper-2aW0bm > .button-1ZiXG9:not(.dangerous-2r8KxV):hover { 28 | color: #fff; 29 | background: linear-gradient(315deg, #495DA4 0%, #7289DA 74%); 30 | } 31 | .wrapper-2aW0bm > .button-1ZiXG9:not(.dangerous-2r8KxV):hover > img, .wrapper-2aW0bm > .button-1ZiXG9:not(.dangerous-2r8KxV):hover svg { 32 | transform: scale(1.15); 33 | transition: 0.15s linear; 34 | } 35 | .wrapper-2aW0bm > .button-1ZiXG9.dangerous-2r8KxV:hover { 36 | color: #fff; 37 | background: linear-gradient(315deg, #AA3738 0%, #F04747 74%); 38 | } 39 | .wrapper-2aW0bm > .button-1ZiXG9.dangerous-2r8KxV:hover > svg:hover { 40 | transform: scale(1.15); 41 | transition: 0.15s linear; 42 | } 43 | 44 | .wrapper-2aW0bm > div > .button-1ZiXG9:hover { 45 | color: #fff; 46 | background: linear-gradient(315deg, #495DA4 0%, #7289DA 74%); 47 | } 48 | .wrapper-2aW0bm > div > .button-1ZiXG9:hover > img, .wrapper-2aW0bm > div > .button-1ZiXG9:hover svg { 49 | transform: scale(1.15); 50 | transition: 0.15s linear; 51 | } 52 | 53 | /* Status Menu */ 54 | .status-1fhblQ:active, 55 | .status-1fhblQ + .description-2L932D:active { 56 | color: #fff; 57 | } 58 | 59 | #status-picker > div > .item-1tOPte.focused-3afm-j, #status-picker > div > .item-1tOPte:active { 60 | transition: 0.075s linear; 61 | } 62 | #status-picker > div > .item-1tOPte.focused-3afm-j > .statusItem-33LqPf > svg > foreignObject > .status-1AY8sU, #status-picker > div > .item-1tOPte:active > .statusItem-33LqPf > svg > foreignObject > .status-1AY8sU { 63 | background: #fff !important; 64 | } 65 | #status-picker > div > .item-1tOPte.focused-3afm-j#status-picker-online, #status-picker > div > .item-1tOPte:active#status-picker-online { 66 | background: linear-gradient(315deg, #264D41 0%, #43B581 74%); 67 | } 68 | #status-picker > div > .item-1tOPte.focused-3afm-j#status-picker-idle, #status-picker > div > .item-1tOPte:active#status-picker-idle { 69 | background: linear-gradient(315deg, #C2831B 0%, #FFB740 74%); 70 | } 71 | #status-picker > div > .item-1tOPte.focused-3afm-j#status-picker-dnd, #status-picker > div > .item-1tOPte:active#status-picker-dnd { 72 | background: linear-gradient(315deg, #AA3738 0%, #F04747 74%); 73 | } 74 | #status-picker > div > .item-1tOPte.focused-3afm-j#status-picker-invisible, #status-picker > div > .item-1tOPte:active#status-picker-invisible { 75 | background: linear-gradient(315deg, #373A45 0%, #747F8D 74%); 76 | } 77 | 78 | /* Server List (home, join/create, discovery, ect) */ 79 | .wrapper-1BJsBx.selected-bZ3Lue > .childWrapper-anI2G9 { 80 | background: linear-gradient(315deg, #495DA4 0%, #7289DA 74%); 81 | } 82 | .wrapper-1BJsBx.selected-bZ3Lue > .childWrapper-anI2G9 > .homeIcon-tEMBK1 { 83 | transform: scale(1.1); 84 | transition: 0.15s linear; 85 | } 86 | 87 | .wrapper-1BJsBx > .childWrapper-anI2G9 > .homeIcon-tEMBK1 { 88 | transform: scale(1); 89 | transition: 0.15s linear; 90 | } 91 | 92 | .circleIconButton-jET_ig.selected-ugP_am { 93 | background: linear-gradient(315deg, #264D41 0%, #43B581 74%); 94 | } 95 | .circleIconButton-jET_ig.selected-ugP_am > svg { 96 | transform: scale(1.25); 97 | } 98 | 99 | .circleIconButton-jET_ig > svg { 100 | transform: scale(1); 101 | } 102 | 103 | /* Settings (user, server, ect.) */ 104 | .side-8zPYf6 > .item-PXvHYJ:hover { 105 | transform: scale(1.025); 106 | transition: 0.15s linear; 107 | } 108 | .side-8zPYf6 > .item-PXvHYJ.selected-3s45Ha { 109 | background: linear-gradient(315deg, #495DA4 0%, #7289DA 74%); 110 | } 111 | .side-8zPYf6 > .item-PXvHYJ[data-item-id=DiscordNitro]:not(:hover), .side-8zPYf6 > .item-PXvHYJ[data-item-id=GUILD_PREMIUM]:not(:hover) { 112 | transform: scale(1); 113 | transition: 0s linear; 114 | } 115 | .side-8zPYf6 > .item-PXvHYJ[style="color: rgb(255, 255, 255); background-color: rgb(114, 137, 218);"] { 116 | color: #fff; 117 | background: linear-gradient(315deg, #8980F0 0%, #D577F0 74%); 118 | } 119 | 120 | .side-8zPYf6 > .item-PXvHYJ { 121 | transform: scale(1); 122 | transition: 0.15s linear; 123 | } 124 | 125 | /* Blurple Buttons */ 126 | .colorBrand-3pXr91:not(.lookOutlined-3sRXeN):not(.lookBlank-3eh9lL):not(.lookInverted-2D7oAl):not(.buttonColor-7qQbGO):not(.lookLink-9FtZy-) { 127 | background: linear-gradient(315deg, #495DA4 0%, #7289DA 74%); 128 | color: #fff; 129 | } 130 | .colorBrand-3pXr91:not(.lookOutlined-3sRXeN):not(.lookBlank-3eh9lL):not(.lookInverted-2D7oAl):not(.buttonColor-7qQbGO):not(.lookLink-9FtZy-):not([disabled]):hover { 131 | transform: scale(1.03); 132 | transition: 0.15s linear; 133 | } 134 | 135 | .colorBrand-3pXr91 { 136 | transform: scale(1); 137 | transition: 0.15s linear; 138 | } 139 | 140 | /* Grey Buttons */ 141 | .colorGrey-2DXtkV:not(.lookGhost-2Fn_0-), 142 | .colorPrimary-3b3xI6:not(.lookLink-9FtZy-):not(.lookOutlined-3sRXeN), 143 | .buttonColor-7qQbGO:not(.buttonActive-3FrkXp) { 144 | background: linear-gradient(315deg, #373A45 0%, #747F8D 74%); 145 | color: #fff; 146 | } 147 | .colorGrey-2DXtkV:not(.lookGhost-2Fn_0-):not(.fauxDisabled-2ik0Vw):hover, 148 | .colorPrimary-3b3xI6:not(.lookLink-9FtZy-):not(.lookOutlined-3sRXeN):not(.fauxDisabled-2ik0Vw):hover, 149 | .buttonColor-7qQbGO:not(.buttonActive-3FrkXp):not(.fauxDisabled-2ik0Vw):hover { 150 | transform: scale(1.03); 151 | transition: 0.15s linear; 152 | } 153 | 154 | .colorGrey-2DXtkV:not(.lookGhost-2Fn_0-), 155 | .colorPrimary-3b3xI6:not(.lookLink-9FtZy-), 156 | .buttonColor-7qQbGO { 157 | transform: scale(1); 158 | transition: 0.15s linear; 159 | } 160 | 161 | /* Green Buttons */ 162 | .colorGreen-29iAKY:not(.lookOutlined-3sRXeN), 163 | .buttonActive-3FrkXp { 164 | background: linear-gradient(315deg, #264D41 0%, #43B581 74%); 165 | color: #fff; 166 | } 167 | .colorGreen-29iAKY:not(.lookOutlined-3sRXeN):hover, 168 | .buttonActive-3FrkXp:hover { 169 | transform: scale(1.03); 170 | transition: 0.15s linear; 171 | } 172 | 173 | .colorGreen-29iAKY, 174 | .buttonActive-3FrkXp { 175 | transform: scale(1); 176 | transition: 0.15s linear; 177 | } 178 | 179 | /* Yellow Buttons */ 180 | .lookFilled-1Gx00P.colorYellow-2JqYwt { 181 | background: linear-gradient(315deg, #C2831B 0%, #FFB740 74%); 182 | color: #fff; 183 | } 184 | .lookFilled-1Gx00P.colorYellow-2JqYwt:hover { 185 | transform: scale(1.03); 186 | transition: 0.15s linear; 187 | } 188 | 189 | .lookFilled-1Gx00P.colorYellow-2JqYwt { 190 | transform: scale(1); 191 | transition: 0.15s linear; 192 | } 193 | 194 | /* Red Buttons */ 195 | .lookFilled-1Gx00P.colorRed-1TFJan { 196 | background: linear-gradient(315deg, #AA3738 0%, #F04747 74%); 197 | color: #fff; 198 | } 199 | .lookFilled-1Gx00P.colorRed-1TFJan:hover { 200 | transform: scale(1.03); 201 | transition: 0.15s linear; 202 | } 203 | 204 | .lookFilled-1Gx00P.colorRed-1TFJan { 205 | transform: scale(1); 206 | transition: 0.15s linear; 207 | }`; 208 | 209 | let obj = { 210 | onImport: async function () { 211 | el = document.createElement('style'); 212 | 213 | document.head.appendChild(el); 214 | 215 | el.appendChild(document.createTextNode(css)); 216 | }, 217 | 218 | remove: async function () { 219 | el.remove(); 220 | }, 221 | 222 | name: 'Gradient Buttons', 223 | description: 'Add some spice to your buttons with gradients!', 224 | 225 | author: 'LuckFire', 226 | 227 | version 228 | }; 229 | 230 | obj -------------------------------------------------------------------------------- /modules/ui/hardcodedColorFixer.js: -------------------------------------------------------------------------------- 1 | let version = '2.1.3'; 2 | 3 | /*const getVariablesObj = (css) => css.split(';').map((x) => x.trim()).filter((x) => x.startsWith('--')) 4 | .reduce((o, val) => { 5 | const spl = val.split(':'); 6 | return Object.assign(o, {[spl[0].replace('--', '')]: spl[1]}) 7 | }, {});*/ 8 | 9 | const getVariablesArr = (css) => css.split(';').map((x) => x.trim()).filter((x) => x.startsWith('--')) 10 | .map((x) => x.split(':')); 11 | 12 | 13 | let obj = { 14 | onImport: async function () { 15 | /*let sheet = window.document.styleSheets[0]; 16 | 17 | // Friends menu main container - fix hard coded colors 18 | sheet.insertRule(`body.hardcoded-color-fixes .container-1D34oG { 19 | background-color: var(--background-primary); 20 | }`, sheet.cssRules.length); 21 | 22 | // Autocomplete slash and mention menu - fix hard coded colors 23 | sheet.insertRule(`body.theme-darker .autocomplete-1vrmpx { 24 | background-color: var(--background-floating); 25 | }`, sheet.cssRules.length); 26 | sheet.insertRule(`body.theme-darker .selectorSelected-1_M1WV { 27 | background-color: var(--background-accent); 28 | }`, sheet.cssRules.length); 29 | 30 | // Profile popup - fix hard coded colors 31 | sheet.insertRule(`body.theme-darker .body-3iLsc4, body.theme-darker .footer-1fjuF6 { 32 | background-color: var(--background-floating); 33 | }`, sheet.cssRules.length); 34 | 35 | // Server Boost layer / page - fix hard coded colors 36 | sheet.insertRule(`body.theme-darker .perksModal-fSYqOq { 37 | background-color: var(--background-primary); 38 | }`, sheet.cssRules.length); 39 | 40 | sheet.insertRule(`body.theme-darker .tierBody-16Chc9 { 41 | background-color: var(--background-floating); 42 | }`, sheet.cssRules.length); 43 | 44 | sheet.insertRule(`body.theme-darker .perk-2WeBWW { 45 | background-color: var(--background-floating); 46 | }`, sheet.cssRules.length);*/ 47 | 48 | let ctx = document.createElement('canvas').getContext('2d'); 49 | 50 | const normaliseColor = (str) => { ctx.fillStyle = str; return ctx.fillStyle; }; 51 | const normaliseColors = (str) => str.replace(/rgb\(([0-9]+), ([0-9]+), ([0-9]+)\)/g, normaliseColor); 52 | 53 | let sheet = window.document.styleSheets[0]; 54 | 55 | let darkThemeVars = getVariablesArr([...sheet.cssRules].find((x) => x.selectorText === '.theme-dark').cssText); 56 | let lightThemeVars = getVariablesArr([...sheet.cssRules].find((x) => x.selectorText === '.theme-light').cssText); 57 | 58 | let themeVars = darkThemeVars.concat(lightThemeVars).filter((x) => !x[0].includes('scrollbar') && !x[0].includes('logo')).map((x) => { 59 | x[1] = normaliseColor(x[1]); 60 | return x; 61 | }); 62 | 63 | sheet.insertRule(`body { 64 | --brand-color: #7289da; 65 | --brand-color-hover: #677bc4; 66 | }`, sheet.cssRules.length); 67 | 68 | themeVars.push(['--brand-color', '#7289da']); 69 | themeVars.push(['--brand-color-hover', '#677bc4']); 70 | 71 | for (let rule of sheet.cssRules) { 72 | if (rule.selectorText === '.theme-light' || rule.selectorText === '.theme-dark' || rule.selectorText === 'body') continue; 73 | 74 | let normalisedText = normaliseColors(rule.cssText); 75 | let changed = false; 76 | 77 | for (let v of themeVars) { 78 | if (normalisedText.includes(v[1])) { 79 | normalisedText = normalisedText.replace(v[1], `var(${v[0]})`); 80 | changed = true; 81 | 82 | break; 83 | } 84 | } 85 | 86 | if (changed) { 87 | sheet.insertRule(`${normalisedText}`, sheet.cssRules.length); 88 | } 89 | } 90 | 91 | //document.documentElement.setAttribute('hardcoded-color-fixes', 'true'); 92 | }, 93 | 94 | remove: async function () { 95 | //document.documentElement.removeAttribute('hardcoded-color-fixes'); 96 | }, 97 | 98 | logRegionColor: 'darkred', 99 | 100 | name: 'Hardcoded Color Fixer', 101 | description: 'Changes hardcoded colors to variables - improves themes', 102 | 103 | author: 'Ducko', 104 | 105 | version 106 | }; 107 | 108 | obj -------------------------------------------------------------------------------- /modules/ui/hideClyde.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.0'; 2 | 3 | let el; 4 | 5 | const css = `.ephemeral-1PsL1r { 6 | display: none; 7 | }`; 8 | 9 | let obj = { 10 | onImport: async function () { 11 | el = document.createElement('style'); 12 | 13 | document.head.appendChild(el); 14 | 15 | el.appendChild(document.createTextNode(css)); 16 | }, 17 | 18 | remove: async function () { 19 | el.remove(); 20 | }, 21 | 22 | name: 'Hide Clyde', 23 | description: 'Hides all Clyde messages completely', 24 | 25 | author: 'Ducko', 26 | 27 | version 28 | }; 29 | 30 | obj 31 | -------------------------------------------------------------------------------- /modules/ui/hideMessage.js: -------------------------------------------------------------------------------- 1 | let version = '1.0.0'; 2 | 3 | let el; 4 | 5 | let obj = { 6 | onImport: async function () { 7 | goosemodScope.patcher.contextMenu.add('message', 8 | { 9 | label: 'Hide Message', 10 | action: (_originalArgs, extraInfo) => { 11 | document.getElementById(`chat-messages-${extraInfo.message.id}`).remove(); 12 | } 13 | } 14 | ); 15 | }, 16 | 17 | remove: async function () { 18 | goosemodScope.patcher.contextMenu.remove('Hide Message'); 19 | }, 20 | 21 | name: 'Hide Message', 22 | description: 'Adds a hide message option to all message\'s context menus which temporarily hides it', 23 | 24 | author: 'Ducko', 25 | 26 | version 27 | }; 28 | 29 | obj 30 | -------------------------------------------------------------------------------- /modules/ui/hideQuickReactions.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.0'; 2 | 3 | let el; 4 | 5 | const css = `.wrapper-3_530D { display: none; }`; 6 | 7 | let obj = { 8 | onImport: async function () { 9 | el = document.createElement('style'); 10 | 11 | document.head.appendChild(el); 12 | 13 | el.appendChild(document.createTextNode(css)); 14 | }, 15 | 16 | remove: async function () { 17 | el.remove(); 18 | }, 19 | 20 | name: 'Hide Quick Reactions', 21 | description: 'Hides the quick reactions (top 4 emoji) on the message context menus', 22 | 23 | author: 'Ducko', 24 | 25 | version 26 | }; 27 | 28 | obj -------------------------------------------------------------------------------- /modules/ui/horizontalServerList.js: -------------------------------------------------------------------------------- 1 | const version = '2.0.0'; 2 | 3 | let el; 4 | 5 | const css = `:root { --server-size: var(--HSL-server-icon-size, var(--HSL-size, 35px)); --server-spacing: var(--HSL-server-spacing, var(--HSL-spacing, 10px)); --server-container: calc(var(--server-size) + 20px);}#app-mount .base-3dtUhz { top: var(--server-container) !important; position: absolute !important; left: 0 !important;}#app-mount .sidebar-2K8pFh { border-radius: 0;}#app-mount [class*=unreadMentionsIndicator] { width: var(--server-size); padding: 0; left: 50%; transform: translateX(-50%); height: auto;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ { transform-origin: top left; transform: rotate(-90deg); height: 100vw !important; width: var(--server-container); top: var(--server-container); bottom: unset; position: absolute !important; left: 0;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .scrollerWrap-1IAIlv { width: calc(100% + 30px);}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .scroller-2TZvBN { padding-top: 0 !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .scroller-2TZvBN>div[style]:not(.listItem-2P_4kh) { height: auto !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .scroller-2TZvBN>div[style]:not(.listItem-2P_4kh)[style*="height: 0px"] { padding-top: 1px;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .svg-1X37T1,#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .wrapper-25eVIn,#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .guildsError-b7zR5H,#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .placeholderMask-3K9THS { width: var(--server-size); height: var(--server-size);}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [role=group] { height: auto !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] { transform: rotate(90deg) translateY(-50%); height: var(--server-size); width: 4px; top: calc(var(--server-size) / -1 + var(--server-size) / 2 - 8px) !important; margin-left: -2px;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span { height: 100% !important; width: 4px !important; transform: scale(0, 1) !important; transition: 0.15s ease !important; margin-left: 0; border-radius: 0 4px 4px 0;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 0"] { transform: scale(1, 0.24) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 1"] { transform: scale(1, 0.24) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 2"] { transform: scale(1, 0.24) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 3"] { transform: scale(1, 0.24) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 4"] { transform: scale(1, 0.24) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 5"] { transform: scale(1, 0.24) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 6"] { transform: scale(1, 0.24) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 7"] { transform: scale(1, 0.24) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 8"] { transform: scale(1, 0.24) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 9"] { transform: scale(1, 0.7) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 10"] { transform: scale(1, 0.7) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 11"] { transform: scale(1, 0.7) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 12"] { transform: scale(1, 0.7) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 13"] { transform: scale(1, 0.7) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 14"] { transform: scale(1, 0.7) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 15"] { transform: scale(1, 0.7) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 16"] { transform: scale(1, 0.7) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 17"] { transform: scale(1, 0.7) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 18"] { transform: scale(1, 0.7) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 19"] { transform: scale(1, 0.7) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 20"] { transform: scale(1, 0.7) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 21"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 22"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 23"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 24"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 25"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 26"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 27"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 28"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 29"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 30"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 31"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 32"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 33"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 34"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 35"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 36"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 37"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 38"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 39"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ [class*=pill] span[style*="height: 40"] { transform: scale(1, 1) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .wrapper-sa6paO { height: var(--server-size) !important;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .listItem-2P_4kh { width: var(--server-size); transform: rotate(90deg); margin: var(--server-spacing) 10px; position: unset;}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .guildSeparator-3s64Iy { transform: rotate(90deg); width: var(--server-size);}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .wrapper-21YSNc { width: var(--server-container);}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .expandedFolderBackground-2sPsd- { width: var(--server-size); left: 50%; border-radius: 10px; transform: translateX(-50%);}#app-mount .wrapper-1Rf91z.guilds-1SWlCJ .folder-21wGz3 { background: transparent;}#app-mount .listItemTooltip-CDcY8J { position: absolute; max-width: unset; white-space: nowrap; margin-left: calc(var(--server-size) / -1 - 20px); top: calc(var(--server-size) - 10px);}#app-mount .listItemTooltip-CDcY8J .tooltipPointer-3ZfirK { transform: rotate(180deg); top: -5px; right: unset; left: 13px; z-index: 1;}#app-mount .friendsOnline-2JkivW { position: absolute; transform: translate(-50%, 50%); top: calc(-50% + var(--server-spacing)); left: calc(-50%); width: calc(var(--server-size) + var(--server-spacing)); display: flex; justify-content: center;}#app-mount .guilds-1SWlCJ.content-Pph8t6 { position: absolute !important; top: calc(var(--server-container) * 2) !important;}#app-mount .guilds-1SWlCJ.content-Pph8t6:not(.closed-j55_T-)+.base-3dtUhz { top: calc(var(--server-container) * 2) !important;}#app-mount .guilds-1SWlCJ .frame-oXWS21.listItem-2P_4kh { height: var(--server-size) !important;}#app-mount .guilds-1SWlCJ .frame-oXWS21.listItem-2P_4kh .wrapper-1BJsBx { height: 100% !important;}#app-mount .guilds-1SWlCJ .frame-oXWS21.listItem-2P_4kh .button-Jt-tIg { width: 100%; height: 100% !important; border-radius: 50%; padding: 2px; font-size: 10px; box-sizing: border-box; text-align: center;}html.platform-osx #app-mount .typeMacOS-3EmCyP { width: 100%;}html.platform-osx #app-mount .base-3dtUhz { top: calc(var(--server-container) + 30px) !important;}html.platform-osx #app-mount #pluginNotice { top: 32px; z-index: 100000 !important;}body.foldercontentopened .base-3dtUhz { transition: 0.2s ease !important;}:root { --HSL-server-icon-size: 40px; --HSL-server-spacing: 10px; }`; 6 | 7 | let obj = { 8 | onImport: async function () { 9 | el = document.createElement('style'); 10 | 11 | document.head.appendChild(el); 12 | 13 | el.appendChild(document.createTextNode(css)); 14 | }, 15 | 16 | remove: async function () { 17 | el.remove(); 18 | }, 19 | 20 | name: 'Horizontal Server List', 21 | description: 'Moves the server list from the left to the top of Discord.', 22 | 23 | author: 'Gibbu', 24 | 25 | version 26 | }; 27 | 28 | obj -------------------------------------------------------------------------------- /modules/ui/nicerUserConnections.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.3'; 2 | 3 | let el; 4 | 5 | const css = `.connectedAccount-36nQx7 { 6 | background-color: rbga(0, 0, 0, 0); 7 | border-width: 0; 8 | } 9 | 10 | .connectedAccount-36nQx7 > .connectedAccountIcon-3P3V6F { 11 | z-index: 1; 12 | } 13 | 14 | .connectedAccount-36nQx7 > .connectedAccountIcon-3P3V6F + .connectedAccountNameInner-1phBvE::after { 15 | --box-shadow: -2px 0 0 0; 16 | content: ""; 17 | position: absolute; 18 | border-radius: 1px 3px 3px 1px; 19 | margin-left: -35px; 20 | height: 46px; 21 | width: 44%; 22 | } 23 | 24 | .connectedAccount-36nQx7 > .connectedAccountNameInner-1phBvE + a.anchor-3Z-8Bb { 25 | z-index: 1; 26 | } 27 | 28 | .connectedAccount-36nQx7 > .connectedAccountNameInner-1phBvE > .connectedAccountName-f8AEe2, .connectedAccount-36nQx7 > .connectedAccountNameInner-1phBvE > .connectedAccountName-f8AEe2 + span { 29 | z-index: 1; 30 | } 31 | 32 | .connectedAccount-36nQx7 > .connectedAccountNameInner-1phBvE > .connectedAccountName-f8AEe2 > .flowerStarContainer-3zDVtj > svg > path, .connectedAccount-36nQx7 > .connectedAccountNameInner-1phBvE > .connectedAccountName-f8AEe2 + span > .flowerStarContainer-3zDVtj > svg > path { 33 | fill: #fff; 34 | opacity: 0.4; 35 | } 36 | 37 | /* Discord Default */ 38 | .connectedAccountIcon-3P3V6F[alt*="GitHub"] + .connectedAccountNameInner-1phBvE { 39 | /* Github */; 40 | } 41 | 42 | .connectedAccountIcon-3P3V6F[alt*="GitHub"] + .connectedAccountNameInner-1phBvE::after { 43 | background-color: #24292E; 44 | box-shadow: var(--box-shadow) #d9dadb; 45 | } 46 | 47 | .connectedAccountIcon-3P3V6F[alt*="Twitch"] + .connectedAccountNameInner-1phBvE { 48 | /* Twitch */; 49 | } 50 | 51 | .connectedAccountIcon-3P3V6F[alt*="Twitch"] + .connectedAccountNameInner-1phBvE::after { 52 | background-color: #3a2b5f; 53 | box-shadow: var(--box-shadow) #9059F6; 54 | } 55 | 56 | .connectedAccountIcon-3P3V6F[alt*="Steam"] + .connectedAccountNameInner-1phBvE { 57 | /* Steam */; 58 | } 59 | 60 | .connectedAccountIcon-3P3V6F[alt*="Steam"] + .connectedAccountNameInner-1phBvE::after { 61 | background-color: #171A21; 62 | box-shadow: var(--box-shadow) #3b587c; 63 | } 64 | 65 | .connectedAccountIcon-3P3V6F[alt*="Spotify"] + .connectedAccountNameInner-1phBvE { 66 | /* Spotify */; 67 | } 68 | 69 | .connectedAccountIcon-3P3V6F[alt*="Spotify"] + .connectedAccountNameInner-1phBvE::after { 70 | background-color: #138139; 71 | box-shadow: var(--box-shadow) #1ED760; 72 | } 73 | 74 | .connectedAccountIcon-3P3V6F[alt*="Twitter"] + .connectedAccountNameInner-1phBvE { 75 | /* Twitter */; 76 | } 77 | 78 | .connectedAccountIcon-3P3V6F[alt*="Twitter"] + .connectedAccountNameInner-1phBvE::after { 79 | background-color: #0c5886; 80 | box-shadow: var(--box-shadow) #76C5F5; 81 | } 82 | 83 | .connectedAccountIcon-3P3V6F[alt*="Reddit"] + .connectedAccountNameInner-1phBvE { 84 | /* Reddit */; 85 | } 86 | 87 | .connectedAccountIcon-3P3V6F[alt*="Reddit"] + .connectedAccountNameInner-1phBvE::after { 88 | background-color: #81340e; 89 | box-shadow: var(--box-shadow) #FF6314; 90 | } 91 | 92 | .connectedAccountIcon-3P3V6F[alt*="YouTube"] + .connectedAccountNameInner-1phBvE { 93 | /* YouTube */; 94 | } 95 | 96 | .connectedAccountIcon-3P3V6F[alt*="YouTube"] + .connectedAccountNameInner-1phBvE::after { 97 | background-color: #6d1616; 98 | box-shadow: var(--box-shadow) #EE0F0F; 99 | } 100 | 101 | .connectedAccountIcon-3P3V6F[alt*="Battle"] + .connectedAccountNameInner-1phBvE { 102 | /* Blizzard/Battle.net */; 103 | } 104 | 105 | .connectedAccountIcon-3P3V6F[alt*="Battle"] + .connectedAccountNameInner-1phBvE::after { 106 | background-color: #175266; 107 | box-shadow: var(--box-shadow) #3AB1DA; 108 | } 109 | 110 | .connectedAccountIcon-3P3V6F[alt*="Xbox"] + .connectedAccountNameInner-1phBvE { 111 | /* Xbox Live */; 112 | } 113 | 114 | .connectedAccountIcon-3P3V6F[alt*="Xbox"] + .connectedAccountNameInner-1phBvE::after { 115 | background-color: #1c632a; 116 | box-shadow: var(--box-shadow) #77BB44; 117 | } 118 | 119 | .connectedAccountIcon-3P3V6F[alt*="Facebook"] + .connectedAccountNameInner-1phBvE { 120 | /* Facebook */; 121 | } 122 | 123 | .connectedAccountIcon-3P3V6F[alt*="Facebook"] + .connectedAccountNameInner-1phBvE::after { 124 | background-color: #14223d; 125 | box-shadow: var(--box-shadow) #3A5998; 126 | } 127 | 128 | .connectedAccountIcon-3P3V6F[alt*="League of Legends"] + .connectedAccountNameInner-1phBvE { 129 | /* League of Legend (LoL) */; 130 | } 131 | 132 | .connectedAccountIcon-3P3V6F[alt*="League of Legends"] + .connectedAccountNameInner-1phBvE::after { 133 | background-color: #424491; 134 | box-shadow: var(--box-shadow) #676AE6; 135 | } 136 | 137 | .connectedAccountIcon-3P3V6F[alt*="Skype"] + .connectedAccountNameInner-1phBvE { 138 | /* Skype */; 139 | } 140 | 141 | .connectedAccountIcon-3P3V6F[alt*="Skype"] + .connectedAccountNameInner-1phBvE::after { 142 | background-color: #424491; 143 | box-shadow: var(--box-shadow) #676AE6; 144 | } 145 | 146 | /* Better User Connections Plugin Support */ 147 | .connectedAccountIcon-3P3V6F[alt*="GitLab"] + .connectedAccountNameInner-1phBvE { 148 | /* GitLab */; 149 | } 150 | 151 | .connectedAccountIcon-3P3V6F[alt*="GitLab"] + .connectedAccountNameInner-1phBvE::after { 152 | background-color: #8f2b1b; 153 | box-shadow: var(--box-shadow) #FCA326; 154 | } 155 | 156 | .connectedAccountIcon-3P3V6F[alt*="Minecraft"] + .connectedAccountNameInner-1phBvE { 157 | /* Minecraft */; 158 | } 159 | 160 | .connectedAccountIcon-3P3V6F[alt*="Minecraft"] + .connectedAccountNameInner-1phBvE::after { 161 | background-color: #2a4911; 162 | box-shadow: var(--box-shadow) #70B237; 163 | } 164 | 165 | /* discord.bio Plugin Support */ 166 | .connectedAccountIcon-3P3V6F[alt*="discord.bio"] + .connectedAccountNameInner-1phBvE::after { 167 | background-color: #3d4870; 168 | box-shadow: var(--box-shadow) #7289da; 169 | }`; 170 | 171 | let obj = { 172 | onImport: async function () { 173 | el = document.createElement('style'); 174 | 175 | document.head.appendChild(el); 176 | 177 | el.appendChild(document.createTextNode(css)); 178 | }, 179 | 180 | remove: async function () { 181 | el.remove(); 182 | }, 183 | 184 | name: 'Nicer User Connections', 185 | description: 'Adds a bit of a boom-shaka-laka to those user connections.', 186 | 187 | author: 'LuckFire', 188 | 189 | version 190 | }; 191 | 192 | obj 193 | -------------------------------------------------------------------------------- /modules/ui/nicknamePanel.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.3'; 2 | 3 | const getCurrentNickname = () => (getNick.getNick(getGuildId.getGuildId(), user.id) || user.username); 4 | 5 | let interval, el, hoverEl, user, getNick, getGuildId; 6 | 7 | let hovering = false; 8 | 9 | const run = () => { 10 | if (hovering) return; 11 | 12 | el.textContent = getCurrentNickname(); 13 | }; 14 | 15 | const mouseEnter = () => { 16 | hovering = true; 17 | el.textContent = user.username; 18 | }; 19 | 20 | const mouseLeave = () => { 21 | hovering = false; 22 | el.textContent = getCurrentNickname(); 23 | }; 24 | 25 | let obj = { 26 | onImport: async function () { 27 | interval = setInterval(run, 300); 28 | 29 | el = document.querySelector('[aria-label="User area"] .title-eS5yk3'); 30 | 31 | hoverEl = el.parentElement.parentElement; 32 | 33 | hoverEl.addEventListener('mouseenter', mouseEnter); 34 | hoverEl.addEventListener('mouseleave', mouseLeave); 35 | 36 | user = goosemodScope.webpackModules.findByProps('getCurrentUser').getCurrentUser(); 37 | 38 | getNick = goosemodScope.webpackModules.findByProps('getNick'); 39 | getGuildId = goosemodScope.webpackModules.findByProps('getGuildId', 'getLastSelectedGuildId'); 40 | }, 41 | 42 | onLoadingFinished: async function () { 43 | }, 44 | 45 | remove: async function () { 46 | clearInterval(interval); 47 | 48 | hoverEl.removeEventListener('mouseenter', mouseEnter); 49 | hoverEl.removeEventListener('mouseleave', mouseLeave); 50 | }, 51 | 52 | logRegionColor: 'darkred', 53 | 54 | name: 'Nickname Panel', 55 | description: 'Shows nickname in account panel instead of username (but still username on hover), idea based on Zerebos\' BD plugin "AccountDetailsPlus"', 56 | 57 | author: 'Ducko', 58 | 59 | version 60 | }; 61 | 62 | obj 63 | -------------------------------------------------------------------------------- /modules/ui/noNotes.js: -------------------------------------------------------------------------------- 1 | const version = "1.0.0"; 2 | 3 | let style; 4 | 5 | let obj = { 6 | onImport: async () => { 7 | style = document.createElement("style"); 8 | document.head.appendChild(style); 9 | style.appendChild( 10 | document.createTextNode(`.userInfoSectionHeader-CBvMDh, .note-QfFU8y { 11 | display: none; 12 | } 13 | .infoScroller-3EYYns > .userInfoSection-2acyCx:first-of-type { 14 | margin-top: -45px; 15 | } 16 | .topSectionNormal-2-vo2m { 17 | z-index: 10; 18 | }`) 19 | ); 20 | }, 21 | 22 | remove: async () => { 23 | style.remove(); 24 | }, 25 | 26 | name: "No Notes", 27 | description: "Hides the notes on user profile modals. (Does not apply to the user popout.)", 28 | author: "Liam The Protogen (441384103946878987)", 29 | version, 30 | }; 31 | 32 | obj 33 | -------------------------------------------------------------------------------- /modules/ui/overlayUserPanel.js: -------------------------------------------------------------------------------- 1 | let version = '2.1.1'; 2 | 3 | if (typeof window === 'undefined' || typeof window.document === 'undefined') { // JSON API generator evals 4 | global.window = { document: { styleSheets: [0] } }; 5 | } 6 | 7 | let sheet = window.document.styleSheets[0]; 8 | 9 | let el; 10 | 11 | let obj = { 12 | onImport: async function () { 13 | sheet.insertRule(`body.user-panel-columns [aria-label="User area"] .container-3baos1 { 14 | flex-wrap: wrap; 15 | }`, sheet.cssRules.length); 16 | 17 | sheet.insertRule(`body.user-panel-columns [aria-label="User area"] .avatarWrapper-2yR4wp { 18 | transform: translate(0, 35%); 19 | }`, sheet.cssRules.length); 20 | 21 | sheet.insertRule(`body.user-panel-columns [aria-label="User area"] .nameTag-3uD-yy { 22 | width: 80%; 23 | flex-grow: 0; 24 | 25 | transform: translate(0, 35%); 26 | }`, sheet.cssRules.length); 27 | 28 | sheet.insertRule(`body.user-panel-columns [aria-label="User area"] .nameTag-3uD-yy + .directionRow-3v3tfG { 29 | margin: auto; 30 | 31 | padding: 3px; 32 | border-radius: 4px 0 0 0; 33 | 34 | transform: scale(1.3) translate(15.5%, -153%); 35 | 36 | background-color: var(--background-secondary-alt); 37 | 38 | z-index: 1; 39 | }`, sheet.cssRules.length); 40 | 41 | sheet.insertRule(`body.user-panel-columns [aria-label="User area"] .wrapper-24pKcD > * { 42 | margin-bottom: 50px; 43 | z-index: 2; 44 | }`, sheet.cssRules.length); 45 | 46 | document.body.classList.add('user-panel-columns'); 47 | 48 | sheet.insertRule(`body.user-panel-columns [aria-label="User area"] .nameTag-3uD-yy + .directionRow-3v3tfG .upc-divider { 49 | width: 0px; 50 | 51 | border-left: 1px solid var(--background-tertiary); 52 | 53 | background-color: unset; 54 | 55 | margin: 3px; 56 | margin-left: 3.3px; 57 | }`, sheet.cssRules.length); 58 | 59 | el = document.createElement('div'); 60 | el.className = 'upc-divider'; 61 | 62 | let settingsButtonEl = document.querySelector('[aria-label="User area"] .nameTag-3uD-yy + .directionRow-3v3tfG [aria-label="User Settings"]'); 63 | settingsButtonEl.parentElement.insertBefore(el, settingsButtonEl); 64 | }, 65 | 66 | remove: async function () { 67 | document.body.classList.remove('user-panel-columns'); 68 | 69 | el.remove(); 70 | }, 71 | 72 | logRegionColor: 'darkred', 73 | 74 | name: 'Overlay User Panel', 75 | description: 'Overlays user panel buttons (mute, deafen, etc.) to above the user panel to the right', 76 | 77 | author: 'Ducko', 78 | 79 | version 80 | }; 81 | 82 | obj -------------------------------------------------------------------------------- /modules/ui/radialStatus.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.0'; 2 | 3 | let el; 4 | 5 | const css = `#app-mount .wrapper-3t9DeA svg:not(:root) { overflow: visible;}#app-mount .wrapper-3t9DeA foreignObject { -webkit-mask: none; mask: none;}#app-mount .wrapper-3t9DeA .dots-3Bkt3k circle:nth-child(1) { cy: -8 !important; cx: -8.5 !important;}#app-mount .wrapper-3t9DeA .dots-3Bkt3k circle:nth-child(2) { cy: -8 !important; cx: -2.25 !important;}#app-mount .wrapper-3t9DeA .dots-3Bkt3k circle:nth-child(3) { cy: -8 !important; cx: 4 !important;}#app-mount .wrapper-3t9DeA .mask-1l8v16 > rect[x="22"] { x: 0; y: 0;}#app-mount .wrapper-3t9DeA .cursorDefault-dsQJ1n rect { x: -49; y: -53;}#app-mount .wrapper-3t9DeA .pointerEvents-2zdfdO[x="14.5"] { fill: rgba(0, 0, 0, 0.5) !important; width: 30px; height: 30px; x: 1; y: 1;}#app-mount .wrapper-3t9DeA > svg > foreignObject img { border-radius: var(--rs-avatar-shape);}#app-mount .wrapper-3t9DeA > svg > foreignObject:not(:only-child) img { -webkit-clip-path: inset(calc(var(--rs-small-spacing) + 1px) calc(var(--rs-small-spacing) + 1px) round var(--rs-avatar-shape)); clip-path: inset(calc(var(--rs-small-spacing) + 1px) calc(var(--rs-small-spacing) + 1px) round var(--rs-avatar-shape));}#app-mount .wrapper-3t9DeA svg[width="25"][height="15"] > rect { rx: calc(var(--rs-avatar-shape) * 2) !important; ry: calc(var(--rs-avatar-shape) * 2) !important;}#app-mount .wrapper-3t9DeA rect { x: 0; y: 0; width: 100%; height: 100%; -webkit-mask: none; mask: none; display: block !important; rx: var(--rs-avatar-shape) !important; ry: var(--rs-avatar-shape) !important; fill: transparent !important; stroke-width: var(--rs-width);}#app-mount .wrapper-3t9DeA rect[fill="#43b581"], #app-mount .wrapper-3t9DeA rect[fill="rgba(67, 181, 129, 1)"], #app-mount .wrapper-3t9DeA rect[mask*=online] { stroke: var(--rs-online-color);}#app-mount .wrapper-3t9DeA rect[fill="#faa61a"], #app-mount .wrapper-3t9DeA rect[fill="rgba(250, 166, 26, 1)"], #app-mount .wrapper-3t9DeA rect[mask*=idle] { stroke: var(--rs-idle-color);}#app-mount .wrapper-3t9DeA rect[fill="#f04747"], #app-mount .wrapper-3t9DeA rect[fill="rgba(240, 71, 71, 1)"], #app-mount .wrapper-3t9DeA rect[mask*=dnd] { stroke: var(--rs-dnd-color);}#app-mount .wrapper-3t9DeA rect[fill="#593695"], #app-mount .wrapper-3t9DeA rect[mask*=streaming] { stroke: var(--rs-streaming-color);}#app-mount .wrapper-3t9DeA rect[fill="#747f8d"], #app-mount .wrapper-3t9DeA rect[mask*=offline], #app-mount .wrapper-3t9DeA rect[fill=NaN] { stroke: var(--rs-offline-color);}#app-mount .wrapper-3t9DeA rect[mask*=invisible], #app-mount .wrapper-3t9DeA rect[fill="rgba(116, 127, 141, 1)"] { stroke: var(--rs-invisible-color);}#app-mount .wrapper-3t9DeA rect[x="16"] { width: 24px; height: 24px;}#app-mount .wrapper-3t9DeA rect[x="28"] { width: 40px; height: 40px; overflow: visible;}#app-mount .wrapper-3t9DeA[style*="width: 80px;"] { position: relative; margin-right: 0 !important;}#app-mount .wrapper-3t9DeA[style*="width: 80px;"] rect { width: 80px; height: 80px; pointer-events: none;}#app-mount .wrapper-3t9DeA[style*="width: 80px;"] img { -webkit-clip-path: inset(calc(var(--rs-large-spacing) + 1px) calc(var(--rs-large-spacing) + 1px) round var(--rs-avatar-shape)); clip-path: inset(calc(var(--rs-large-spacing) + 1px) calc(var(--rs-large-spacing) + 1px) round var(--rs-avatar-shape));}#app-mount .wrapper-3t9DeA[style*="width: 80px;"][style*="width:80px;"]:after { left: unset; right: -2px; top: unset; bottom: -2px; transform: none;}#app-mount .wrapper-3t9DeA[style*="width: 32px;"] rect { width: 32px; height: 32px; x: -14.5; y: -17; position: relative; z-index: 0;}#app-mount .avatarHint-1qgaV3 foreignObject { -webkit-mask: none; mask: none;}#app-mount .avatarHint-1qgaV3 .avatarHintInner-Dco91E { border-radius: var(--rs-avatar-shape) !important; padding-top: 0; width: calc(100% - var(--rs-width) * 4); height: calc(100% - var(--rs-width) * 4); margin-top: calc(var(--rs-width) + 2px); margin-left: calc(var(--rs-width) + 2px);}#app-mount .message-1PNnaP .mask-1l8v16 img { -webkit-clip-path: circle(calc(19px - var(--rs-small-spacing))); clip-path: circle(calc(19px - var(--rs-small-spacing)));}#app-mount .memberOffline-2lN7gt img { -webkit-clip-path: none !important; clip-path: none !important;}#app-mount .header-QKLPzZ .wrapper-3t9DeA { margin-right: 20px !important;}#app-mount .offline-3nJYBR img { -webkit-clip-path: none !important; clip-path: none !important;}#app-mount .wrapper-3t9DeA foreignObject[mask*=mobile] { width: calc(100% + 4px);}#app-mount .wrapper-3t9DeA foreignObject[mask*=mobile][width="32"] img { width: 32px;}#app-mount .wrapper-3t9DeA foreignObject[mask*=mobile][width="80"] img { width: 80px;}#app-mount .wrapper-3t9DeA foreignObject[mask*=mobile]:after { content: ""; -webkit-mask: url('data:image/svg+xml; utf-8,') center/8px no-repeat; display: block; position: absolute; width: 10px; height: 14px; top: 50%; transform: translateY(-50%); right: 0; background: var(--rs-online-color); z-index: 1;}#app-mount .wrapper-3t9DeA:before { content: none !important;}:root { --rs-small-spacing: 2px; --rs-large-spacing: 3px; --rs-width: 2px; --rs-avatar-shape: 50%; --rs-online-color: #43b581; --rs-idle-color: #faa61a; --rs-dnd-color: #f04747; --rs-offline-color: #636b75; --rs-streaming-color: #643da7; --rs-invisible-color: #747f8d; }`; 6 | 7 | let obj = { 8 | onImport: async function () { 9 | el = document.createElement('style'); 10 | 11 | document.head.appendChild(el); 12 | 13 | el.appendChild(document.createTextNode(css)); 14 | }, 15 | 16 | remove: async function () { 17 | el.remove(); 18 | }, 19 | 20 | name: 'RadialStatus', 21 | description: 'Changes the status icons to wrap around the avatar.', 22 | 23 | author: 'Gibbu', 24 | 25 | version 26 | }; 27 | 28 | obj -------------------------------------------------------------------------------- /modules/ui/revampedUserArea.js: -------------------------------------------------------------------------------- 1 | const version = '0'; 2 | 3 | let el; 4 | 5 | const css = `@import url("https://raw.githack.com/LuckFire/RevampedUserArea/main/index.css");`; 6 | 7 | let obj = { 8 | onImport: async function () { 9 | el = document.createElement('style'); 10 | 11 | document.head.appendChild(el); 12 | 13 | el.appendChild(document.createTextNode(css)); 14 | }, 15 | 16 | remove: async function () { 17 | el.remove(); 18 | }, 19 | 20 | name: 'RevampedUserArea', 21 | description: 'A compact, better looking user area.', 22 | 23 | author: 'LuckFire', 24 | 25 | version 26 | }; 27 | 28 | obj -------------------------------------------------------------------------------- /modules/ui/serverCount.js: -------------------------------------------------------------------------------- 1 | const version = "1.0.0"; 2 | 3 | let style; 4 | 5 | const { inject, uninject } = goosemodScope.patcher; 6 | const { findByProps } = goosemodScope.webpackModules; 7 | 8 | const forceUpdate = () => { 9 | const { tutorialContainer } = findByProps("homeIcon"); 10 | goosemodScope.reactUtils 11 | .getOwnerInstance(document.querySelector(`.${tutorialContainer}`)) 12 | .forceUpdate(); 13 | }; 14 | 15 | let obj = { 16 | onImport: async () => { 17 | style = document.createElement("style"); 18 | style.appendChild( 19 | document.createTextNode(`.gm-serverCount { 20 | font-size: 10px; 21 | font-weight: 500; 22 | line-height: 1.3; 23 | text-align: center; 24 | text-transform: uppercase; 25 | white-space: normal; 26 | width: 64px; 27 | word-wrap: normal; 28 | color: var(--text-muted); 29 | }`) 30 | ); 31 | document.head.appendChild(style); 32 | 33 | const { DefaultHomeButton } = findByProps("DefaultHomeButton"); 34 | inject( 35 | "gm-serverCount", 36 | DefaultHomeButton.prototype, 37 | "render", 38 | (_, res) => { 39 | if (!Array.isArray(res)) { 40 | res = [res]; 41 | } 42 | 43 | const { getGuilds } = findByProps("getGuilds"); 44 | const guilds = Object.keys(getGuilds()).length; 45 | 46 | const { React } = goosemodScope.webpackModules.common; 47 | const { listItem } = findByProps("listItem"); 48 | const { Messages } = findByProps("Messages"); 49 | res.push( 50 | React.createElement( 51 | "div", 52 | { 53 | className: listItem, 54 | }, 55 | React.createElement( 56 | "div", 57 | { 58 | id: "gm-serverCount", 59 | className: ["gm-serverCount"], 60 | }, 61 | `${Messages.SERVERS} — ${guilds}` 62 | ) 63 | ) 64 | ); 65 | 66 | return res; 67 | } 68 | ); 69 | 70 | forceUpdate(); 71 | }, 72 | 73 | remove: async () => { 74 | uninject("gm-serverCount"); 75 | style.remove(); 76 | forceUpdate(); 77 | }, 78 | 79 | name: "Server Count", 80 | description: "Shows how many servers you're in.", 81 | author: "Liam The Protogen (441384103946878987)", 82 | version, 83 | }; 84 | 85 | obj 86 | -------------------------------------------------------------------------------- /modules/ui/showAllActivities.js: -------------------------------------------------------------------------------- 1 | let version = "1.0.0"; 2 | 3 | let style; 4 | 5 | const { inject, uninject } = goosemodScope.patcher; 6 | 7 | let obj = { 8 | onImport: async () => { 9 | style = document.createElement("style"); 10 | style.appendChild( 11 | document.createTextNode(`.allactivities-left { 12 | margin-right: 8px; 13 | } 14 | .allactivities-right { 15 | margin-left: 8px; 16 | } 17 | .allactivities-margin { 18 | margin-top: 12px; 19 | } 20 | .allactivities-margin2 { 21 | margin-top: 22px; 22 | }`) 23 | ); 24 | document.head.appendChild(style); 25 | 26 | let temp; 27 | const filterActivities = (a, i) => { 28 | if (i == 0) temp = []; 29 | if (temp.includes(a.application_id || a.name)) return false; 30 | temp.push(a.application_id || a.name); 31 | return a.type != 4; 32 | }; 33 | 34 | const { 35 | find, 36 | findByProps, 37 | findByDisplayName, 38 | } = goosemodScope.webpackModules; 39 | const { getActivities } = await findByProps("getActivities"); 40 | const { getGame } = await findByProps("getGame", "getGameByName"); 41 | const UserActivity = await findByDisplayName("UserActivity"); 42 | 43 | inject( 44 | "gm-show-all-activities-pre", 45 | UserActivity.prototype, 46 | "render", 47 | function (args) { 48 | if (this.props.__saa) return args; 49 | 50 | const activities = getActivities(this.props.user.id).filter( 51 | filterActivities 52 | ); 53 | if (!activities || !activities.length) return args; 54 | 55 | if (!this.state) 56 | this.state = { activity: activities.indexOf(this.props.activity) }; 57 | else { 58 | const activity = activities[this.state.activity]; 59 | if (!activity) return args; 60 | 61 | this.props.activity = activity; 62 | this.props.game = getGame(activity.application_id); 63 | 64 | if (this.state.activity > 0 && this.props.streamingGuild) { 65 | this.props._streamingGuild = this.props.streamingGuild; 66 | delete this.props.streamingGuild; 67 | } else if (this.state.activity === 0 && this.props._streamingGuild) 68 | this.props.streamingGuild = this.props._streamingGuild; 69 | } 70 | return args; 71 | }, 72 | true 73 | ); 74 | 75 | const { React } = goosemodScope.webpackModules.common; 76 | const { Messages } = await findByProps("Messages"); 77 | const classes = await findByProps("iconButtonSize"); 78 | const Tooltip = await findByProps("TooltipContainer").TooltipContainer; 79 | const Button = await find((m) => m.DropdownSizes); 80 | 81 | inject( 82 | "gm-show-all-activities", 83 | UserActivity.prototype, 84 | "render", 85 | function (_, res) { 86 | if (this.props.__saa || (this.state && this.state.activity > 0)) { 87 | const actions = goosemodScope.reactUtils.findInReactTree( 88 | res, 89 | (c) => c && c.onOpenConnections 90 | ); 91 | if (actions) { 92 | actions.activity = this.props.activity; 93 | delete actions.applicationStream; 94 | } 95 | } 96 | 97 | if (this.props.__saa) { 98 | res = res.props.children; 99 | return res; 100 | } 101 | 102 | const activities = getActivities(this.props.user.id).filter( 103 | filterActivities 104 | ); 105 | if ( 106 | (res && res.props && !res.props.children) || 107 | !activities || 108 | !activities.length 109 | ) 110 | return res; 111 | 112 | const { children } = res.props.children[1].props; 113 | const marginClass = 114 | this.props.activity.details || this.props.activity.state 115 | ? ` allactivities-margin${ 116 | this.props.activity.type == 1 && 117 | this.props.source == "Profile Modal" 118 | ? "2" 119 | : "" 120 | }` 121 | : ""; 122 | 123 | if (this.state.activity != 0) 124 | children.unshift( 125 | React.createElement( 126 | Tooltip, 127 | { 128 | className: `allactivities-left${marginClass}`, 129 | text: Messages.PAGINATION_PREVIOUS, 130 | }, 131 | React.createElement( 132 | Button, 133 | { 134 | className: classes.iconButtonSize, 135 | size: Button.Sizes.MIN, 136 | color: Button.Colors.WHITE, 137 | look: Button.Looks.OUTLINED, 138 | onClick: () => 139 | this.setState({ activity: this.state.activity - 1 }), 140 | }, 141 | React.createElement( 142 | "div", 143 | { 144 | className: "contents-18-Yxp", 145 | }, 146 | React.createElement( 147 | "div", 148 | { 149 | className: 150 | "flex-1xMQg5 flex-1O1GKY horizontal-1ae9ci horizontal-2EEEnY flex-1O1GKY directionRow-3v3tfG justifyStart-2NDFzi alignCenter-1dQNNs noWrap-3jynv6", 151 | style: { flex: "1 1 auto" }, 152 | }, 153 | React.createElement( 154 | "svg", 155 | { 156 | "aria-hidden": "false", 157 | width: "24", 158 | height: "24", 159 | className: "flexChild-faoVW3 left-3d-3Co", 160 | viewBox: "0 0 24 24", 161 | style: { flex: "1 1 auto" }, 162 | }, 163 | React.createElement("polygon", { 164 | fill: "currentColor", 165 | "fill-rule": "nonzero", 166 | points: 167 | "13 20 11 20 11 8 5.5 13.5 4.08 12.08 12 4.16 19.92 12.08 18.5 13.5 13 8", 168 | }) 169 | ) 170 | ) 171 | ) 172 | ) 173 | ) 174 | ); 175 | if (this.state.activity < activities.length - 1) 176 | children.push( 177 | React.createElement( 178 | Tooltip, 179 | { 180 | className: `allactivities-right${marginClass}`, 181 | text: Messages.NEXT, 182 | }, 183 | React.createElement( 184 | Button, 185 | { 186 | className: classes.iconButtonSize, 187 | size: Button.Sizes.MIN, 188 | color: Button.Colors.WHITE, 189 | look: Button.Looks.OUTLINED, 190 | onClick: () => 191 | this.setState({ activity: this.state.activity + 1 }), 192 | }, 193 | React.createElement( 194 | "div", 195 | { 196 | className: "contents-18-Yxp", 197 | }, 198 | React.createElement( 199 | "div", 200 | { 201 | className: 202 | "flex-1xMQg5 flex-1O1GKY horizontal-1ae9ci horizontal-2EEEnY flex-1O1GKY directionRow-3v3tfG justifyStart-2NDFzi alignCenter-1dQNNs noWrap-3jynv6", 203 | style: { flex: "1 1 auto" }, 204 | }, 205 | React.createElement( 206 | "svg", 207 | { 208 | "aria-hidden": "false", 209 | width: "24", 210 | height: "24", 211 | className: "flexChild-faoVW3 right-1C2enk", 212 | viewBox: "0 0 24 24", 213 | style: { flex: "1 1 auto" }, 214 | }, 215 | React.createElement("polygon", { 216 | fill: "currentColor", 217 | "fill-rule": "nonzero", 218 | points: 219 | "13 20 11 20 11 8 5.5 13.5 4.08 12.08 12 4.16 19.92 12.08 18.5 13.5 13 8", 220 | }) 221 | ) 222 | ) 223 | ) 224 | ) 225 | ) 226 | ); 227 | return res; 228 | } 229 | ); 230 | }, 231 | 232 | remove: async () => { 233 | uninject("gm-show-all-activities-pre"); 234 | uninject("gm-show-all-activities"); 235 | style.remove(); 236 | }, 237 | 238 | name: "Show All Activities", 239 | description: "See every status a user has enabled.", 240 | author: ["Juby210", "Liam The Protogen (441384103946878987)"], 241 | version, 242 | }; 243 | 244 | obj 245 | -------------------------------------------------------------------------------- /modules/ui/simpleStatusIcons.js: -------------------------------------------------------------------------------- 1 | let version = '1.0.0'; 2 | 3 | let obj = { 4 | onImport: async function () { 5 | let sheet = window.document.styleSheets[0]; 6 | 7 | sheet.insertRule(`body.simple-status-icons .pointerEvents-2zdfdO:not([mask="url(#svg-mask-status-online-mobile)"]) { 8 | mask: url(#svg-mask-status-online) !important; 9 | }`, sheet.cssRules.length); 10 | 11 | document.body.classList.add('simple-status-icons'); 12 | }, 13 | 14 | remove: async function () { 15 | document.body.classList.remove('simple-status-icons'); 16 | }, 17 | 18 | name: 'Simple Status Icons', 19 | description: 'Makes all status icons circular instead of shapes for Idle and Do Not Disturb (but keeps mobile a phone outline)', 20 | 21 | author: 'Ducko', 22 | 23 | version 24 | }; 25 | 26 | obj -------------------------------------------------------------------------------- /modules/ui/stickyNotes.js: -------------------------------------------------------------------------------- 1 | const version = '2.2.0'; 2 | 3 | let newStickyKeybindFunction; 4 | 5 | let moduleData = { 6 | settings: { 7 | openNoteOnLoad: true 8 | } 9 | }; 10 | 11 | function injMod() { 12 | moduleData.setSetting = (setting, value) => { 13 | if (moduleData.settings[setting]) { 14 | moduleData.settings[setting] = value; 15 | }; 16 | }; 17 | 18 | let noteCount = 0; 19 | 20 | moduleData.newSticky = (becomeActive = true) => { 21 | let mousePosition; 22 | let offset = [0,0]; 23 | let isDown = false; 24 | 25 | let div = document.createElement("div"); 26 | div.classList.add('goosemod-sticky-note', 'goosemod-sticky-note-asset', `goosemod-sticky-note-number-${noteCount}`); 27 | div.style.position = "absolute"; 28 | div.style.left = "0px"; 29 | div.style.top = "0px"; 30 | div.style.width = "100px"; 31 | div.style.height = "100px"; 32 | 33 | //To get standard discord look 34 | //Making the div boxes to house the stuff 35 | let noteContainerElContainer = document.createElement('div'); 36 | noteContainerElContainer.classList.add('layerContainer-yqaFcK'); 37 | 38 | let noteContainerElLayer = document.createElement('div'); 39 | noteContainerElLayer.classList.add('layer-2KE1M9'); 40 | 41 | let noteContainerEl = document.createElement('div'); 42 | noteContainerEl.classList.add("focusLock-Ns3yie"); 43 | noteContainerEl.setAttribute('role', 'dialog'); 44 | noteContainerEl.setAttribute('aria-label', 'Sticky Note'); 45 | noteContainerEl.setAttribute('tabindex', '-1'); 46 | noteContainerEl.setAttribute('aria-model', 'true'); 47 | 48 | let noteContainerElRoot = document.createElement('div'); 49 | noteContainerElRoot.classList.add("root-1gCeng", "small-3iVZYw", "fullscreenOnMobile-1bD22y"); 50 | noteContainerElRoot.style.opacity = '1'; 51 | noteContainerElRoot.style.transform = 'scale(1)'; 52 | 53 | //Header stuff 54 | let noteContainerElHeaderDiv = document.createElement('div'); 55 | noteContainerElHeaderDiv.classList.add('flex-1xMQg5', 'flex-1O1GKY', 'horizontal-1ae9ci', 'horizontal-2EEEnY', 'flex-1O1GKY', 'directionRow-3v3tfG', 'justifyStart-2NDFzi', 'alignCenter-1dQNNs', 'noWrap-3jynv6', 'header-1TKi98'); 56 | noteContainerElHeaderDiv.style.flex = '0 0 auto'; 57 | 58 | let noteContainerElHeaderH = document.createElement('h4'); 59 | noteContainerElHeaderH.classList.add("colorStandard-2KCXvj", "size14-e6ZScH", "h4-AQvcAz", "title-3sZWYQ", "defaultColor-1_ajX0", "defaultMarginh4-2vWMG5"); 60 | noteContainerElHeaderH.textContent = "Sticky Note"; 61 | 62 | let noteContainerElHeaderN = document.createElement('h2'); 63 | noteContainerElHeaderN.classList.add("colorStandard-2KCXvj", "size14-e6ZScH", "h4-AQvcAz", "defaultColor-1_ajX0", "defaultMarginh4-2vWMG5", "clickable-3rdHwn"); 64 | noteContainerElHeaderN.textContent = "🞣"; 65 | noteContainerElHeaderN.setAttribute('style', 'display: flex; font-size: 25px; color: #B9BBBE; align-items: center; margin-right: 5px;'); 66 | 67 | let noteContainerElHeaderX = document.createElement('h2'); 68 | noteContainerElHeaderX.classList.add("colorStandard-2KCXvj", "size14-e6ZScH", "h4-AQvcAz", "defaultColor-1_ajX0", "defaultMarginh4-2vWMG5", "clickable-3rdHwn"); 69 | noteContainerElHeaderX.textContent = "⨯"; 70 | noteContainerElHeaderX.setAttribute('style', 'display: flex; font-size: 29px; color: #B9BBBE; align-items: center'); 71 | 72 | //Body stuff 73 | let noteContainerElBody = document.createElement('div'); 74 | noteContainerElBody.classList.add('content-1LAB8Z', 'content-mK72R6', 'thin-1ybCId', 'scrollerBase-289Jih'); 75 | noteContainerElBody.setAttribute('dir', 'ltr'); 76 | noteContainerElBody.style.overflow = 'hidden scroll'; 77 | noteContainerElBody.style.paddingRight = '8px'; 78 | 79 | let noteContainerElBodyText = document.createElement('div'); 80 | noteContainerElBodyText.classList.add('markup-2BOw-j', 'scrollableContainer-2NUZem', 'webkit-HjD9Er'); 81 | noteContainerElBodyText.setAttribute('aria-multiline', 'true'); 82 | noteContainerElBodyText.setAttribute('data-can-focus', 'true'); 83 | noteContainerElBodyText.setAttribute('data-slate-editor', 'true'); 84 | noteContainerElBodyText.setAttribute('contenteditable', 'true'); 85 | noteContainerElBodyText.setAttribute('autocorrect', 'off'); 86 | noteContainerElBodyText.setAttribute('spellcheck', 'true'); 87 | noteContainerElBodyText.setAttribute('role', 'textbox'); 88 | noteContainerElBodyText.setAttribute('data-gramm', 'true'); 89 | noteContainerElBodyText.setAttribute('style', 'outline: none; white-space: pre-wrap; overflow-wrap: break-word; -webkit-user-modify: read-write-plaintext-only; padding: 5px;'); 90 | 91 | //Appending root elements 92 | noteContainerElContainer.appendChild(noteContainerElLayer); 93 | noteContainerElLayer.appendChild(noteContainerEl); 94 | noteContainerEl.appendChild(noteContainerElRoot); 95 | 96 | //Appending headers 97 | noteContainerElRoot.appendChild(noteContainerElHeaderDiv); 98 | noteContainerElHeaderDiv.appendChild(noteContainerElHeaderH); 99 | noteContainerElHeaderDiv.appendChild(noteContainerElHeaderN); 100 | noteContainerElHeaderDiv.appendChild(noteContainerElHeaderX); 101 | 102 | //Appending body 103 | noteContainerElRoot.appendChild(noteContainerElBody); 104 | noteContainerElBody.appendChild(noteContainerElBodyText); 105 | 106 | // Appending root div 107 | div.appendChild(noteContainerElContainer); 108 | document.body.appendChild(div); 109 | 110 | function becomeActiveNote(moveToTop = false) { 111 | function compareNotes(n1, n2 = div) { 112 | // Returns true if they have the same class lists (de-facto same note due to the goosemod-note-number-* class) 113 | return (n1.classList.value === n2.classList.value); 114 | }; 115 | const currentActiveNote = document.getElementById("active-sticky"); 116 | // Setting the note to become focused and on top. 117 | if (currentActiveNote && !compareNotes(currentActiveNote, div)) { 118 | if (moveToTop && div.getAttribute('id') != 'active-sticky') { 119 | document.body.insertBefore(div, currentActiveNote.nextElementSibling); 120 | }; 121 | currentActiveNote.removeAttribute('id'); 122 | div.setAttribute('id', 'active-sticky'); 123 | } else if (Array.from(document.getElementsByClassName('goosemod-sticky-note')).filter(note => !compareNotes(note, div)).length <= 0) { 124 | div.setAttribute('id', 'active-sticky'); 125 | }; 126 | }; 127 | 128 | // Becoming the active note on creation 129 | if (becomeActive) { 130 | becomeActiveNote(); 131 | }; 132 | 133 | // Checking if mouse is up or down 134 | noteContainerElHeaderDiv.addEventListener('mousedown', function(e) { 135 | isDown = true; 136 | 137 | // Becoming active on click. 138 | becomeActiveNote(true); 139 | 140 | offset = [ 141 | div.offsetLeft - e.clientX, 142 | div.offsetTop - e.clientY 143 | ]; 144 | }, true); 145 | 146 | noteContainerElBody.addEventListener('click', function(e) { 147 | if (div.getAttribute('id') != 'active-sticky' && !isDown) { 148 | e.preventDefault(); 149 | becomeActiveNote(true); 150 | }; 151 | }); 152 | 153 | document.addEventListener('mouseup', function() { 154 | isDown = false; 155 | }, true); 156 | 157 | // Dragging events 158 | document.addEventListener('mousemove', function(e) { 159 | if (isDown) { 160 | e.preventDefault(); 161 | mousePosition = { 162 | 163 | x : e.clientX, 164 | y : e.clientY 165 | 166 | }; 167 | div.style.left = (mousePosition.x + offset[0]) + 'px'; 168 | div.style.top = (mousePosition.y + offset[1]) + 'px'; 169 | } 170 | }, true); 171 | 172 | 173 | // Close button events 174 | noteContainerElHeaderX.addEventListener('mouseenter', e => { 175 | noteContainerElHeaderX.style.color = "white"; 176 | }); 177 | 178 | noteContainerElHeaderX.addEventListener('mouseleave', e => { 179 | noteContainerElHeaderX.style.color = "#B9BBBE" 180 | }); 181 | 182 | noteContainerElHeaderX.addEventListener('click', e => { 183 | e.preventDefault(); 184 | const newActive = div.previousElementSibling; 185 | // Pass on active-sticky id on note close 186 | if (newActive != undefined && newActive.classList.contains('goosemod-sticky-note')) { 187 | div.removeAttribute('id'); 188 | newActive.setAttribute('id', 'active-sticky'); 189 | } 190 | div.remove(); 191 | }); 192 | 193 | // New note button events 194 | noteContainerElHeaderN.addEventListener('mouseenter', e => { 195 | noteContainerElHeaderN.style.color = "white"; 196 | }); 197 | 198 | noteContainerElHeaderN.addEventListener('mouseleave', e => { 199 | noteContainerElHeaderN.style.color = "#B9BBBE" 200 | }); 201 | 202 | noteContainerElHeaderN.addEventListener('click', e => { 203 | e.preventDefault(); 204 | moduleData.newSticky(false); 205 | }); 206 | 207 | noteCount++; 208 | return div; 209 | }; 210 | 211 | // Keybind (Ctrl+D) to open a new note. 212 | newStickyKeybindFunction = (e) => { 213 | //console.log(e.code + ' ' + e.ctrlKey) 214 | if (e.code === 'KeyD' && e.ctrlKey) { 215 | e.preventDefault(); 216 | moduleData.newSticky(); 217 | }; 218 | }; 219 | 220 | document.addEventListener('keydown', newStickyKeybindFunction); 221 | }; 222 | 223 | function rmMod() { 224 | Array.from(document.getElementsByClassName("goosemod-sticky-note-asset")).forEach((note) => note.remove()); 225 | document.removeEventListener('keydown', newStickyKeybindFunction); 226 | }; 227 | 228 | let obj = { 229 | // Importing module 230 | onImport: async function () { 231 | goosemodScope.logger.debug('Sticky Notes', 'Starting...'); 232 | injMod(); 233 | }, 234 | 235 | // Removing module 236 | remove: async function () { 237 | goosemodScope.logger.debug('Sticky Notes', 'Stopping...'); 238 | goosemod.settings.removeItem('Sticky Notes'); 239 | rmMod(); 240 | }, 241 | 242 | // Run after loading 243 | onLoadingFinished: async function () { 244 | goosemodScope.settings.createItem('Sticky Notes', [`(v${version})`, 245 | { 246 | type: 'header', 247 | text: 'Sticky Notes Settings' 248 | }, 249 | { 250 | type: 'toggle', 251 | text: 'Launch Note on Load', 252 | subtext: 'Open a sticky note automatically once the module is loaded in.', 253 | onToggle: (v) => { moduleData.setSetting('openNoteOnLoad', v) }, 254 | isToggled: () => moduleData.settings['openNoteOnLoad'] 255 | } 256 | ]); 257 | }, 258 | 259 | // Getting and setting settings 260 | getSettings: async function() { return [moduleData.settings] }, 261 | loadSettings: async function ([settings]) { 262 | moduleData.settings = settings; 263 | 264 | if (moduleData.settings['openNoteOnLoad']) { 265 | moduleData.newSticky(); 266 | }; 267 | }, 268 | 269 | // Data 270 | name: 'Sticky Notes', 271 | description: 'Allows you to create temporary sticky notes on the screen. Open new sticky notes with Ctrl+D or the New Note button.', 272 | 273 | author: ['Fjorge', 'Liam The Protogen (441384103946878987)'], 274 | 275 | version: version 276 | }; 277 | 278 | obj 279 | -------------------------------------------------------------------------------- /modules/ui/toggleMessageButtons.js: -------------------------------------------------------------------------------- 1 | const version = "1.1.0"; 2 | 3 | let settings = { 4 | buttonsToggled: true, 5 | }; 6 | 7 | const css = `body.gm-toggle-messages-buttons .buttons-3JBrkn { 8 | display: none; 9 | }`; 10 | 11 | let style; 12 | 13 | const updateContextItem = async (val) => { 14 | try { 15 | await goosemod.patcher.contextMenu.remove("toggle-message-buttons"); 16 | 17 | goosemod.patcher.contextMenu.add("textarea-context", { 18 | id: "toggle-message-buttons", 19 | label: `${val ? "Disable" : "Enable"} Buttons`, 20 | action: () => { 21 | settings.buttonsToggled = !settings.buttonsToggled; 22 | updateContextItem(settings.buttonsToggled); 23 | 24 | document.body.classList[val ? "add" : "remove"]( 25 | "gm-toggle-messages-buttons" 26 | ); 27 | }, 28 | }); 29 | } catch (err) { 30 | goosemodScope.showToast("An error has ocurred!", { type: "error" }); 31 | goosemodScope.logger.debug(err); 32 | } 33 | }; 34 | 35 | let obj = { 36 | onImport: async () => { 37 | style = document.createElement("style"); 38 | style.appendChild(document.createTextNode(css)); 39 | document.head.appendChild(style); 40 | 41 | updateContextItem(settings.buttonsToggled); 42 | }, 43 | 44 | remove: async () => { 45 | goosemodScope.patcher.contextMenu.remove("toggle-message-buttons"); 46 | document.body.classList.remove("gm-toggle-messages-buttons"); 47 | 48 | style.remove(); 49 | }, 50 | 51 | getSettings: () => [settings], 52 | loadSettings: ([_settings]) => { 53 | settings = _settings; 54 | 55 | updateContextItem(settings.buttonsToggled); 56 | document.body.classList[settings.buttonsToggled ? "remove" : "add"]( 57 | "gm-toggle-messages-buttons" 58 | ); 59 | }, 60 | 61 | name: "Toggle Message Buttons", 62 | description: "Toggles whether the buttons on the message box should appear. (Right click the message box to toggle.)", 63 | author: "Liam The Protogen (441384103946878987)", 64 | version, 65 | }; 66 | 67 | obj 68 | -------------------------------------------------------------------------------- /modules/ui/userPopoutCreationDate.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.2'; 2 | 3 | let getUser, getMembers, getGuildId; 4 | let interval; 5 | 6 | const run = () => { 7 | let popout = document.getElementsByClassName('userPopout-3XzG_A')[0]; 8 | 9 | if (!popout) return; 10 | if (popout.classList.contains('more-info-added')) return; 11 | 12 | let user = getUser.getUser(getMembers.getMembers(getGuildId.getGuildId()).find((x) => getUser.getUser(x.userId).username === popout.ariaLabel).userId); 13 | 14 | let toCloneEl = popout.getElementsByClassName('headerTagWithNickname-3IthZD')[0]; 15 | 16 | if (!toCloneEl) { 17 | let headerEl = popout.getElementsByClassName('headerTagNoNickname-ENx6no')[0]; 18 | 19 | let parentEl = document.createElement('div'); 20 | 21 | headerEl.parentElement.appendChild(parentEl); 22 | 23 | parentEl.outerHTML = `
`; 24 | 25 | toCloneEl = popout.getElementsByClassName('headerTagWithNickname-3IthZD')[0]; 26 | 27 | headerEl.parentElement.style.flexDirection = 'column'; 28 | } 29 | 30 | toCloneEl.parentElement.style.flexDirection = 'column'; 31 | 32 | let el = toCloneEl.cloneNode(false); 33 | 34 | el.textContent = `Created On: ${user.createdAt.toDateString().split(' ').slice(1).join(' ')}`; 35 | 36 | toCloneEl.parentElement.appendChild(el); 37 | 38 | popout.classList.add('more-info-added'); 39 | }; 40 | 41 | let obj = { 42 | onImport: async function () { 43 | getUser = goosemodScope.webpackModules.findByProps('getUser'); 44 | getMembers = goosemodScope.webpackModules.findByProps('getNick'); 45 | getGuildId = goosemodScope.webpackModules.findByPropsAll('getGuildId')[1]; 46 | 47 | interval = setInterval(run, 300); 48 | }, 49 | 50 | onLoadingFinished: async function () { 51 | }, 52 | 53 | remove: async function () { 54 | clearInterval(interval); 55 | }, 56 | 57 | logRegionColor: 'darkred', 58 | 59 | name: 'User Popout Creation Date', 60 | description: 'Adds user\'s creation date to popouts', 61 | 62 | author: 'Ducko', 63 | 64 | version 65 | }; 66 | 67 | obj -------------------------------------------------------------------------------- /modules/ui/usrbgDefault.js: -------------------------------------------------------------------------------- 1 | const version = '0'; 2 | 3 | let el; 4 | 5 | const css = `@import url("https://raw.githack.com/Discord-Custom-Covers/usrbg/master/snippets/modals.css"); @import url("https://raw.githack.com/Discord-Custom-Covers/usrbg/master/snippets/userPopouts.css");`; 6 | 7 | let obj = { 8 | onImport: async function () { 9 | el = document.createElement('style'); 10 | 11 | document.head.appendChild(el); 12 | 13 | el.appendChild(document.createTextNode(css)); 14 | }, 15 | 16 | remove: async function () { 17 | el.remove(); 18 | }, 19 | 20 | name: 'Usrbg - Default', 21 | description: '[Default Snippets] A pure CSS database of user requested backgrounds for Discord.', 22 | 23 | author: 'Discord Custom Covers', 24 | 25 | version 26 | }; 27 | 28 | obj -------------------------------------------------------------------------------- /modules/ui/usrbgHeaders.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.0'; 2 | 3 | let el; 4 | 5 | const css = `@import url('https://discord-custom-covers.github.io/usrbg/dist/usrbg.css'); 6 | 7 | .reduce-motion .userPopout-3XzG_A { 8 | transform:translateZ(0); 9 | } 10 | 11 | .userPopout-3XzG_A .wrapper-3t9DeA::after { 12 | content: ''; 13 | position: fixed; 14 | top: 0; 15 | left: 0; 16 | width: 100%; 17 | height: 20%; 18 | z-index: -1; 19 | pointer-events: none; 20 | opacity: .9; 21 | background-size: cover; 22 | background-repeat: no-repeat; 23 | background-position: var(--user-popout-position) center; 24 | background-image: var(--user-background); 25 | -webkit-mask-image: linear-gradient(#000, transparent); 26 | } 27 | 28 | .userPopout-3XzG_A .header-2BwW8b, 29 | .userPopout-3XzG_A .scroller-2FKFPG, 30 | .userPopout-3XzG_A .footer-1fjuF6 { 31 | z-index: 1; 32 | } 33 | 34 | :root { 35 | --usrbg-modal-x-offset:-34px; /*Distance from the avatar container to the edge of the modal (x)*/ 36 | --usrbg-modal-y-offset:-20px; /*Distance from the avatar container to the edge of the modal (y)*/ 37 | --usrbg-modal-width:600px; /*Maximum width of modal*/ 38 | --usrbg-modal-height:190px; /*Maximum height of modal*/ 39 | } 40 | .header-QKLPzZ .wrapper-3t9DeA::after { 41 | content:''; 42 | position:absolute; 43 | top:var(--usrbg-modal-x-offset); 44 | left:var(--usrbg-modal-y-offset); 45 | width:var(--usrbg-modal-width); 46 | height: var(--usrbg-modal-height); 47 | opacity:.9; 48 | z-index: -1; 49 | pointer-events:none; 50 | background: var(--user-background) center/cover no-repeat; 51 | -webkit-mask: linear-gradient(black, transparent 80%); 52 | } 53 | 54 | .headerInfo-30uryT, 55 | .tabBarItem-1b8RUP, 56 | .activity-1ythUs { 57 | z-index:1; 58 | position:relative; 59 | } 60 | 61 | .header-QKLPzZ .wrapper-3t9DeA { 62 | z-index: 0; 63 | }`; 64 | 65 | let obj = { 66 | onImport: async function () { 67 | el = document.createElement('style'); 68 | 69 | document.head.appendChild(el); 70 | 71 | el.appendChild(document.createTextNode(css)); 72 | }, 73 | 74 | remove: async function () { 75 | el.remove(); 76 | }, 77 | 78 | name: 'Usrbg - Headers', 79 | description: '[Header Snippets by Ducko] A pure CSS database of user requested backgrounds for Discord.', 80 | 81 | author: 'Discord Custom Covers', 82 | 83 | version 84 | }; 85 | 86 | obj -------------------------------------------------------------------------------- /modules/ui/vcColumns.js: -------------------------------------------------------------------------------- 1 | const version = '1.1.3'; 2 | 3 | let enabled = false; 4 | let autoCheck = true; 5 | 6 | const run = () => { 7 | if (!autoCheck) return; 8 | 9 | if (document.getElementsByClassName('rtcConnectionStatus-2-jIsi')[0]) { 10 | if (!document.body.classList.contains('voice-mode') && !enabled) { 11 | enabled = true; 12 | 13 | setEnabled(); 14 | } 15 | } else if (document.body.classList.contains('voice-mode') && enabled) { 16 | enabled = false; 17 | 18 | setEnabled(); 19 | } 20 | }; 21 | 22 | const setEnabled = () => { 23 | if (enabled && !document.body.classList.contains('voice-mode')) { 24 | document.body.classList.add('voice-mode'); 25 | } else if (!enabled) { 26 | document.body.classList.remove('voice-mode'); 27 | } 28 | }; 29 | 30 | const obj = { 31 | onImport: async function () { 32 | let sheet = window.document.styleSheets[0]; 33 | 34 | sheet.insertRule(`body.voice-mode .container-2Rl01u, body.voice-mode .chat-3bRxxu { 35 | display: inherit; 36 | }`, sheet.cssRules.length); 37 | 38 | sheet.insertRule(`body.voice-mode .sidebar-2K8pFh { 39 | width: 100%; 40 | height: 65vh; 41 | }`, sheet.cssRules.length); 42 | 43 | sheet.insertRule(`body.voice-mode .content-98HsJk { 44 | flex-direction: column; 45 | }`, sheet.cssRules.length); 46 | 47 | sheet.insertRule(`body.voice-mode [aria-label="User area"] .nameTag-3uD-yy + .directionRow-3v3tfG { 48 | transform: scale(1.5) translate(-50%, -190%); 49 | 50 | position: absolute; 51 | left: 50vw; 52 | }`, sheet.cssRules.length); 53 | 54 | sheet.insertRule(`body.voice-mode [aria-label="Disconnect"] { 55 | transform: scale(1.5) translate(-10%, 0); 56 | }`, sheet.cssRules.length); 57 | }, 58 | 59 | onLoadingFinished: async function () { 60 | goosemodScope.settings.createItem('VC Columns', [ 61 | `(v${version})`, 62 | 63 | { 64 | type: 'toggle', 65 | text: 'Auto-enable', 66 | subtext: 'Automatically enables when entering voice chat (and disables when leaving)', 67 | onToggle: (c) => { 68 | autoCheck = c; 69 | }, 70 | isToggled: () => autoCheck 71 | }, 72 | ]); 73 | 74 | interval = setInterval(run, 500); 75 | }, 76 | 77 | remove: async function () { 78 | clearInterval(interval); 79 | 80 | let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'VC Columns'); 81 | goosemodScope.settings.items.splice(goosemodScope.settings.items.indexOf(settingItem), 1); 82 | 83 | enabled = false; 84 | autoCheck = false; 85 | 86 | setEnabled(); 87 | }, 88 | 89 | getSettings: () => [autoCheck], 90 | loadSettings: ([_autoCheck]) => { 91 | autoCheck = _autoCheck; 92 | }, 93 | 94 | logRegionColor: 'darkred', 95 | 96 | name: 'VC Columns', 97 | description: 'A column UI with larger buttons for VC', 98 | 99 | author: 'Ducko', 100 | 101 | version 102 | }; 103 | 104 | obj -------------------------------------------------------------------------------- /modules/ui/visualTweaks.js: -------------------------------------------------------------------------------- 1 | let version = "2.7.0"; 2 | 3 | let obj = { 4 | onImport: async function () { 5 | goosemodScope.logger.debug("visualTweaks", "Enabling Visual Tweaks"); 6 | 7 | goosemodScope.tweaks = { 8 | removeHelpButton: true, 9 | removeEmojiUpsell: false, 10 | squareAvatars: true, 11 | noMemberlistAvatars: false, 12 | fixFolderColorPicker: true, 13 | }; 14 | 15 | let sheet = window.document.styleSheets[0]; 16 | 17 | sheet.insertRule( 18 | `body.square-avatars .avatar-1BDn8e { 19 | border-radius: 0px; 20 | }`, 21 | sheet.cssRules.length 22 | ); 23 | 24 | sheet.insertRule( 25 | `body.no-emoji-popups .container-ZRw2kD { 26 | display:none; 27 | }`, 28 | sheet.cssRules.length 29 | ); 30 | 31 | sheet.insertRule( 32 | `body.no-emoji-popups .emojiContainer-3X8SvE { 33 | cursor:default; 34 | }`, 35 | sheet.cssRules.length 36 | ); 37 | 38 | sheet.insertRule( 39 | `body.no-memberlist-avatars .avatar-3uk_u9 { 40 | width: 5px; 41 | }`, 42 | sheet.cssRules.length 43 | ); 44 | 45 | sheet.insertRule( 46 | `body.no-memberlist-avatars .avatar-3uk_u9 > div > svg > foreignObject { 47 | display: none; 48 | }`, 49 | sheet.cssRules.length 50 | ); 51 | 52 | sheet.insertRule( 53 | `body.no-memberlist-avatars .avatar-3uk_u9 > div > svg > rect { 54 | transform: translate(-22px, -10px); 55 | }`, 56 | sheet.cssRules.length 57 | ); 58 | 59 | sheet.insertRule( 60 | `body.no-help-button a[href="https://support.discord.com"] > div[role="button"] { 61 | display: none; 62 | }`, 63 | sheet.cssRules.length 64 | ); 65 | 66 | sheet.insertRule( 67 | `body.fix-folder-color-picker .container-3sNMIc { 68 | flex-wrap: inherit 69 | }`, 70 | sheet.cssRules.length 71 | ); 72 | 73 | let tweakFunctions = { 74 | removeHelpButton: { 75 | enable: () => { 76 | document.body.classList.add("no-help-button"); 77 | // document.querySelector('a[href="https://support.discord.com"] > div[role="button"]').parentElement.style.display = 'none'; 78 | }, 79 | 80 | disable: () => { 81 | document.body.classList.remove("no-help-button"); 82 | // document.querySelector('a[href="https://support.discord.com"] > div[role="button"]').parentElement.style.display = 'flex'; 83 | }, 84 | }, 85 | 86 | removeEmojiUpsell: { 87 | enable: () => { 88 | document.body.classList.add("no-emoji-popups"); 89 | }, 90 | 91 | disable: () => { 92 | document.body.classList.remove("no-emoji-popups"); 93 | }, 94 | }, 95 | 96 | squareAvatars: { 97 | enable: () => { 98 | document.body.classList.add("square-avatars"); 99 | }, 100 | 101 | disable: () => { 102 | document.body.classList.remove("square-avatars"); 103 | }, 104 | }, 105 | 106 | noMemberlistAvatars: { 107 | enable: () => { 108 | document.body.classList.add("no-memberlist-avatars"); 109 | }, 110 | 111 | disable: () => { 112 | document.body.classList.remove("no-memberlist-avatars"); 113 | }, 114 | }, 115 | 116 | fixFolderColorPicker: { 117 | enable: () => { 118 | document.body.classList.add("fix-folder-color-picker"); 119 | }, 120 | 121 | disable: () => { 122 | document.body.classList.remove("fix-folder-color-picker"); 123 | }, 124 | }, 125 | }; 126 | 127 | goosemodScope.enableTweak = (tweakName) => { 128 | tweakFunctions[tweakName].enable(); 129 | 130 | goosemodScope.tweaks[tweakName] = true; 131 | }; 132 | 133 | goosemodScope.disableTweak = (tweakName) => { 134 | tweakFunctions[tweakName].disable(); 135 | 136 | goosemodScope.tweaks[tweakName] = false; 137 | }; 138 | 139 | goosemodScope.setTweak = (tweakName, value) => { 140 | if (value === true) { 141 | goosemodScope.enableTweak(tweakName); 142 | } else { 143 | goosemodScope.disableTweak(tweakName); 144 | } 145 | }; 146 | }, 147 | 148 | onLoadingFinished: async function () { 149 | for (let t in goosemodScope.tweaks) { 150 | if (goosemodScope.tweaks[t] === true) goosemodScope.enableTweak(t); 151 | } 152 | 153 | goosemodScope.settings.createItem("Visual Tweaks", [ 154 | `(v${version})`, 155 | 156 | { 157 | type: "header", 158 | text: "Individual Minor Tweaks", 159 | }, 160 | { 161 | type: "toggle", 162 | text: "Hide Help Button", 163 | subtext: "Hides the help button in the top right corner", 164 | onToggle: (c) => { 165 | goosemodScope.setTweak("removeHelpButton", c); 166 | }, 167 | isToggled: () => goosemodScope.tweaks["removeHelpButton"], 168 | }, 169 | { 170 | type: "toggle", 171 | text: "Disable Emoji Click Pop-up", 172 | subtext: "Disables the pop-up when clicking emojis", 173 | onToggle: (c) => { 174 | goosemodScope.setTweak("removeEmojiUpsell", c); 175 | }, 176 | isToggled: () => goosemodScope.tweaks["removeEmojiUpsell"], 177 | }, 178 | { 179 | type: "toggle", 180 | text: "Square Avatars", 181 | subtext: 182 | "Makes avatars for messages square instead of circle (cozy only)", 183 | onToggle: (c) => { 184 | goosemodScope.setTweak("squareAvatars", c); 185 | }, 186 | isToggled: () => goosemodScope.tweaks["squareAvatars"], 187 | }, 188 | { 189 | type: "toggle", 190 | text: "[WIP] No Member List Avatars", 191 | subtext: "Hides avatars in the member list", 192 | onToggle: (c) => { 193 | goosemodScope.setTweak("noMemberlistAvatars", c); 194 | }, 195 | isToggled: () => goosemodScope.tweaks["noMemberlistAvatars"], 196 | }, 197 | { 198 | type: "toggle", 199 | text: "Fix Folder Color Picker", 200 | subtext: "Fixes the folder color picker being misaligned.", 201 | onToggle: (c) => { 202 | goosemodScope.setTweak("fixFolderColorPicker", c); 203 | }, 204 | isToggled: () => goosemodScope.tweaks["fixFolderColorPicker"], 205 | }, 206 | ]); 207 | }, 208 | 209 | remove: async function () { 210 | for (let t in goosemodScope.tweaks) { 211 | if (goosemodScope.tweaks[t] === true) goosemodScope.disableTweak(t); 212 | } 213 | 214 | let settingItem = goosemodScope.settings.items.find( 215 | (x) => x[1] === "Visual Tweaks" 216 | ); 217 | goosemodScope.settings.items.splice( 218 | goosemodScope.settings.items.indexOf(settingItem), 219 | 1 220 | ); 221 | }, 222 | 223 | getSettings: async function () { 224 | return [goosemodScope.tweaks]; 225 | }, 226 | loadSettings: async function ([_tweaks]) { 227 | goosemodScope.tweaks = _tweaks; 228 | 229 | for (let t in goosemodScope.tweaks) { 230 | try { 231 | // Some tweaks might have been removed so wrap in try catch 232 | goosemodScope.setTweak(t, goosemodScope.tweaks[t]); 233 | } catch (e) { 234 | console.log(e); 235 | } 236 | } 237 | }, 238 | 239 | logRegionColor: "darkred", 240 | 241 | name: "Visual Tweaks", 242 | description: "A variety of minor visual tweaks", 243 | 244 | author: ["Ducko", "Fjorge", "Liam The Protogen"], 245 | 246 | version, 247 | }; 248 | 249 | obj 250 | -------------------------------------------------------------------------------- /modules/ui/vscodeToasts.js: -------------------------------------------------------------------------------- 1 | const version = '1.0.0'; 2 | 3 | let el; 4 | 5 | const css = `.gm-toast { 6 | position: absolute; 7 | right: 30px; 8 | bottom: 5px; 9 | 10 | box-shadow: var(--elevation-high); 11 | 12 | border-radius: 0; 13 | background: var(--channeltextarea-background); 14 | font-size: 20px; 15 | }`; 16 | 17 | let obj = { 18 | onImport: async function () { 19 | el = document.createElement('style'); 20 | 21 | document.head.appendChild(el); 22 | 23 | el.appendChild(document.createTextNode(css)); 24 | }, 25 | 26 | remove: async function () { 27 | el.remove(); 28 | }, 29 | 30 | name: 'VSCode-like Toasts', 31 | description: 'Makes GooseMod toasts similar to VSCode\'s (in the bottom right above the message box and larger)', 32 | 33 | author: 'Ducko', 34 | 35 | version 36 | }; 37 | 38 | obj -------------------------------------------------------------------------------- /modules/ui/webhookTags.js: -------------------------------------------------------------------------------- 1 | const version = "1.0.0"; 2 | 3 | const { inject, uninject } = goosemodScope.patcher; 4 | 5 | let obj = { 6 | onImport: async () => { 7 | const { findByProps, common } = goosemodScope.webpackModules; 8 | const MessageTimestamp = findByProps("MessageTimestamp"); 9 | const botTagRegularClasses = findByProps("botTagRegular"); 10 | const botTagClasses = findByProps("botTagCozy"); 11 | const remClasses = findByProps("rem"); 12 | 13 | inject("gm-webhookTags", MessageTimestamp, "default", (args, res) => { 14 | const msg = args[0].message; 15 | 16 | if ( 17 | msg.webhookId != null && 18 | msg.messageReference == null && 19 | msg.author.discriminator == "0000" 20 | ) { 21 | args[0].message.author.bot = false; 22 | 23 | const header = goosemodScope.reactUtils.findInReactTree( 24 | res, 25 | (e) => 26 | Array.isArray(e?.props?.children) && 27 | e.props.children.find((c) => c?.props?.message) 28 | ); 29 | header.props.children.push( 30 | common.React.createElement( 31 | "span", 32 | { 33 | className: `${botTagClasses.botTagCozy} ${botTagClasses.botTagCompact} ${botTagRegularClasses.botTagRegular} ${remClasses.rem}`, 34 | }, 35 | common.React.createElement( 36 | "div", 37 | { 38 | className: botTagRegularClasses.botText, 39 | }, 40 | "WEBHOOK" 41 | ) 42 | ) 43 | ); 44 | } 45 | 46 | return res; 47 | }); 48 | }, 49 | 50 | remove: async () => { 51 | uninject("gm-webhookTags"); 52 | }, 53 | 54 | name: "Webhook Tags", 55 | description: "Replace bot tags with webhook tags for webhook messages.", 56 | author: "Ben855", 57 | version, 58 | }; 59 | 60 | obj 61 | --------------------------------------------------------------------------------