Injector v4.0.0: Rewrite to not use global / window, more tweaks (see changelog)

pull/8/head
Oj18 4 years ago
parent 7159000abe
commit 8157a5d87b

@ -1,5 +1,16 @@
# GooseMod Changelog
## v4.0.0
- ### Tweaks
- Hid local reinstall option (and divider) as it is mostly useless / never used
- ### Backend
- Rewrote to not use global / window object - fixes many potential bugs and is more secure
- Moved some misc. settings options into goosemod.settings instead of bloating the parent scope
- Module functions are no longer binded to goosemod scope, instead it is avaliable as an object in the module eval
## v3.2.1
- ### Features

22
dist/index.js vendored

File diff suppressed because one or more lines are too long

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

@ -10,24 +10,36 @@ import cspBypasser from './util/discord/cspBypasser';
import showToast from './ui/toast';
import confirmDialog from './ui/modals/confirm';
import { startLoadingScreen, stopLoadingScreen, updateLoadingScreen } from './ui/loading';
import { startLoadingScreen, stopLoadingScreen, updateLoadingScreen, setThisScope as setThisScope1 } from './ui/loading';
import { removeModuleUI, isSettingsOpen, closeSettings, openSettings, openSettingItem, reopenSettings, injectInSettings, checkSettingsOpenInterval } from './ui/settings';
import * as Settings from './ui/settings';
// import { removeModuleUI, isSettingsOpen, closeSettings, openSettings, openSettingItem, reopenSettings, injectInSettings, checkSettingsOpenInterval, makeGooseModSettings, setThisScope as setThisScope2 } from './ui/settings';
import easterEggs from './ui/easterEggs';
import { importModule, importModules, bindHandlers, getModuleFiles, importModulesFull } from './moduleManager';
import { saveModuleSettings, clearModuleSetting, clearSettings, loadSavedModuleSetting, loadSavedModuleSettings } from './moduleSettingsStore';
import { importModule, importModules, bindHandlers, getModuleFiles, importModulesFull, setThisScope as setThisScope3 } from './moduleManager';
import { saveModuleSettings, clearModuleSetting, clearSettings, loadSavedModuleSetting, loadSavedModuleSettings, setThisScope as setThisScope4 } from './moduleSettingsStore';
import moduleStoreAPI from './moduleStore';
const scopeSetterFncs = [
setThisScope1,
Settings.setThisScope, // setThisScope2,
setThisScope3,
setThisScope4,
moduleStoreAPI.setThisScope,
cspBypasser.setThisScope,
easterEggs.setThisScope
];
const importsToAssign = {
startLoadingScreen,
stopLoadingScreen,
updateLoadingScreen,
removeModuleUI,
settings: Settings, /* removeModuleUI,
isSettingsOpen,
closeSettings,
openSettings,
@ -35,6 +47,7 @@ const importsToAssign = {
reopenSettings,
injectInSettings,
checkSettingsOpenInterval,
makeGooseModSettings, */
importModule,
importModules,
@ -59,9 +72,19 @@ const importsToAssign = {
};
const init = async function () {
if (globalThis.remove) {
globalThis.remove();
}
Object.assign(this, importsToAssign);
fixLocalStorage();
let a = 1;
for (let x of scopeSetterFncs) {
console.log(a, x);
x(this);
a++;
};
this.cspBypasser.init();
/*for (let p in toAssign) {
if (toAssign.hasOwnProperty(p)) {
@ -69,49 +92,47 @@ const init = async function () {
}
}*/
Object.assign(globalThis, importsToAssign);
this.settings.makeGooseModSettings();
// globalThis.logger = Logger;
// this.logger = Logger;
globalThis.removed = false;
this.removed = false;
globalThis.modules = {};
globalThis.disabledModules = {};
this.modules = {};
this.disabledModules = {};
globalThis.version = '3.2.1';
globalThis.versionHash = '<hash>'; // hash of built final js file is inserted here via build script
this.version = '4.0.0';
this.versionHash = '<hash>'; // hash of built final js file is inserted here via build script
globalThis.logger.debug('import.version.goosemod', `${globalThis.version} (${globalThis.versionHash})`);
this.logger.debug('import.version.goosemod', `${this.version} (${this.versionHash})`);
if (window.DiscordNative !== undefined) globalThis.logger.debug('import.version.discord', `${DiscordNative.app.getReleaseChannel()} ${DiscordNative.app.getVersion()}`);
if (window.DiscordNative !== undefined) this.logger.debug('import.version.discord', `${DiscordNative.app.getReleaseChannel()} ${DiscordNative.app.getVersion()}`);
if (window.gmUntethered) {
globalThis.untetheredVersion = window.gmUntethered.slice();
this.untetheredVersion = window.gmUntethered.slice();
// delete window.gmUntethered;
}
// globalThis.webpackModules = WebpackModules;
fixLocalStorage();
// this.webpackModules = WebpackModules;
// globalThis.showToast = showToast;
// this.showToast = showToast;
globalThis.showToast(`GooseMod v${globalThis.version} (${globalThis.versionHash.substring(0, 7)})`, {timeout: 1000});
this.showToast(`GooseMod v${this.version} (${this.versionHash.substring(0, 7)})`, {timeout: 1000});
// globalThis.messageEasterEggs = easterEggs;
// this.messageEasterEggs = easterEggs;
// globalThis.confirmDialog = confirmDialog;
// this.confirmDialog = confirmDialog;
globalThis.messageEasterEggs.interval = setInterval(globalThis.messageEasterEggs.check, 1000);
this.messageEasterEggs.interval = setInterval(this.messageEasterEggs.check, 1000);
/* Object.assign(globalThis, {
/* Object.assign(this, {
startLoadingScreen,
stopLoadingScreen,
updateLoadingScreen
});
Object.assign(globalThis, {
Object.assign(this, {
removeModuleUI,
isSettingsOpen,
closeSettings,
@ -122,11 +143,9 @@ const init = async function () {
checkSettingsOpenInterval
});
globalThis.cspBypasser = cspBypasser; */
globalThis.cspBypasser.init();
this.cspBypasser = cspBypasser; */
/* Object.assign(globalThis, {
/* Object.assign(this, {
importModule,
importModules,
bindHandlers,
@ -134,7 +153,7 @@ const init = async function () {
importModulesFull
});
Object.assign(globalThis, {
Object.assign(this, {
saveModuleSettings,
clearModuleSetting,
clearSettings,
@ -142,36 +161,36 @@ const init = async function () {
loadSavedModuleSettings
});
globalThis.moduleStoreAPI = moduleStoreAPI; */
this.moduleStoreAPI = moduleStoreAPI; */
globalThis.saveInterval = setInterval(globalThis.saveModuleSettings, 3000);
this.saveInterval = setInterval(this.saveModuleSettings, 3000);
globalThis.remove = () => {
clearInterval(globalThis.messageEasterEggs.interval);
clearInterval(globalThis.saveInterval);
clearInterval(globalThis.injectInSettings);
this.remove = () => {
clearInterval(this.messageEasterEggs.interval);
clearInterval(this.saveInterval);
clearInterval(this.checkSettingsOpenInterval);
globalThis.clearSettings();
globalThis.moduleStoreAPI.jsCache.purgeCache();
this.clearSettings();
this.moduleStoreAPI.jsCache.purgeCache();
globalThis.removed = true;
this.removed = true;
for (let p in globalThis.modules) {
if (globalThis.modules.hasOwnProperty(p) && globalThis.modules[p].remove !== undefined) {
globalThis.modules[p].remove();
for (let p in this.modules) {
if (this.modules.hasOwnProperty(p) && this.modules[p].remove !== undefined) {
this.modules[p].remove();
}
}
};
globalThis.startLoadingScreen();
this.startLoadingScreen();
globalThis.updateLoadingScreen('Getting module index from Module Store...');
this.updateLoadingScreen('Getting module index from Module Store...');
await globalThis.moduleStoreAPI.updateModules();
await this.moduleStoreAPI.updateModules();
globalThis.moduleStoreAPI.updateStoreSetting();
this.moduleStoreAPI.updateStoreSetting();
globalThis.initialImport = true;
this.initialImport = true;
let toInstallModules = Object.keys(JSON.parse(localStorage.getItem('goosemodModules')) || {});
let toInstallIsDefault = false;
@ -181,7 +200,7 @@ const init = async function () {
toInstallModules = ['hardcodedColorFixer', 'draculaTheme', 'fucklytics', 'visualTweaks', 'wysiwygMessages', 'customSounds', 'devMode', 'twitchEmotes', 'noMessageDeletion'];
}
toInstallModules = toInstallModules.filter((m) => globalThis.moduleStoreAPI.modules.find((x) => x.filename === m) !== undefined);
toInstallModules = toInstallModules.filter((m) => this.moduleStoreAPI.modules.find((x) => x.filename === m) !== undefined);
let themeModule = toInstallModules.find((x) => x.toLowerCase().includes('theme'));
@ -195,35 +214,37 @@ const init = async function () {
toInstallModules.unshift(toInstallModules.splice(toInstallModules.indexOf(hardcodedColorFixerModule), 1)[0]);
}
globalThis.updateLoadingScreen(`Importing default modules from Module Store... (${toInstallIsDefault ? '(Default)' : '(Last Installed)'})`);
this.updateLoadingScreen(`Importing default modules from Module Store... (${toInstallIsDefault ? '(Default)' : '(Last Installed)'})`);
for (let m of toInstallModules) {
globalThis.updateLoadingScreen(`${globalThis.moduleStoreAPI.modules.find((x) => x.filename === m).name} - ${toInstallModules.indexOf(m) + 1}/${toInstallModules.length}`)
//globalThis.updateLoadingScreen(`Importing default modules from Module Store...<br><br>${globalThis.moduleStoreAPI.modules.find((x) => x.filename === m).name}<br>${toInstallModules.indexOf(m) + 1}/${toInstallModules.length}<br>${toInstallIsDefault ? '(Default)' : '(Last Installed)'}`);
this.updateLoadingScreen(`${this.moduleStoreAPI.modules.find((x) => x.filename === m).name} - ${toInstallModules.indexOf(m) + 1}/${toInstallModules.length}`)
//this.updateLoadingScreen(`Importing default modules from Module Store...<br><br>${this.moduleStoreAPI.modules.find((x) => x.filename === m).name}<br>${toInstallModules.indexOf(m) + 1}/${toInstallModules.length}<br>${toInstallIsDefault ? '(Default)' : '(Last Installed)'}`);
await globalThis.moduleStoreAPI.importModule(m);
await this.moduleStoreAPI.importModule(m);
}
delete globalThis.initialImport;
delete this.initialImport;
globalThis.updateLoadingScreen(`Loading saved module settings...`);
this.updateLoadingScreen(`Loading saved module settings...`);
await globalThis.loadSavedModuleSettings();
await this.loadSavedModuleSettings();
globalThis.stopLoadingScreen();
this.stopLoadingScreen();
if (globalThis.isSettingsOpen()) { // If settings are open, reopen to inject new GooseMod options
globalThis.reopenSettings();
if (this.settings.isSettingsOpen()) { // If settings are open, reopen to inject new GooseMod options
this.settings.reopenSettings();
} else {
// Only open settings (when not already open) if new user
if (!localStorage.getItem('goosemodModules')) {
globalThis.openSettings();
this.settings.openSettings();
await sleep(200);
globalThis.openSettingItem('Module Store');
this.openSettingItem('Module Store');
}
}
console.log(this);
};
init();
init.bind({})();

@ -1,67 +1,73 @@
import ab2str from './util/ab2str';
let goosemodScope = {};
export const setThisScope = (scope) => {
goosemodScope = scope;
};
export const importModule = async (f) => {
let field = f.filename.split('.').slice(0, -1).join('.'); // Get name of module via filename (taking away the file extension)
globalThis.logger.debug('import', `Importing module: "${field}"`);
goosemodScope.logger.debug('import', `Importing module: "${field}"`);
let settingItem = globalThis.settings.items.find((x) => x[1] === 'Manage Modules');
let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'Manage Modules');
if (globalThis.modules[field] !== undefined) {
globalThis.logger.debug(`import.load.module.${field}`, 'Module already imported, removing then installing new version');
if (goosemodScope.modules[field] !== undefined) {
goosemodScope.logger.debug(`import.load.module.${field}`, 'Module already imported, removing then installing new version');
await globalThis.modules[field].remove();
await goosemodScope.modules[field].remove();
settingItem[2].splice(settingItem[2].indexOf(settingItem[2].find((x) => x.text === `${globalThis.modules[field].name} (${globalThis.modules[field].version})`)), 1);
settingItem[2].splice(settingItem[2].indexOf(settingItem[2].find((x) => x.text === `${goosemodScope.modules[field].name} (${goosemodScope.modules[field].version})`)), 1);
}
if (typeof f.data === 'object') { // ArrayBuffer (UTF-8) -> String
f.data = ab2str(f.data);
}
globalThis.modules[field] = eval(f.data); // Set globalThis.modules.<module_name> to the return value of the module (an object containing handlers)
goosemodScope.modules[field] = eval(f.data); // Set goosemodScope.modules.<module_name> to the return value of the module (an object containing handlers)
globalThis.logger.debug(`import.load.module.${field}`, `Evaled module JS`);
goosemodScope.logger.debug(`import.load.module.${field}`, `Evaled module JS`);
globalThis.bindHandlers(globalThis.modules[field]); // Bind all handlers to module parent / returned object from module code
// goosemodScope.bindHandlers(goosemodScope.modules[field]); // Bind all handlers to module parent / returned object from module code
globalThis.logger.debug(`import.load.module.${field}`, `Binded handlers`);
goosemodScope.logger.debug(`import.load.module.${field}`, `Binded handlers`);
await globalThis.modules[field].onImport(); // Run the module's onImport handler
await goosemodScope.modules[field].onImport(); // Run the module's onImport handler
globalThis.logger.debug(`import.load.module.${field}`, `Ran onImport()`);
goosemodScope.logger.debug(`import.load.module.${field}`, `Ran onImport()`);
let toggleObj = {
type: 'text-and-danger-button',
text: `${globalThis.modules[field].name} <span class="description-3_Ncsb">by</span> ${globalThis.modules[field].author} <span class="description-3_Ncsb">(v${globalThis.modules[field].version})</span>`,
text: `${goosemodScope.modules[field].name} <span class="description-3_Ncsb">by</span> ${goosemodScope.modules[field].author} <span class="description-3_Ncsb">(v${goosemodScope.modules[field].version})</span>`,
buttonText: 'Remove',
subtext: globalThis.modules[field].description,
subtext: goosemodScope.modules[field].description,
onclick: (el) => {
el.textContent = 'Removing...';
globalThis.removeModuleUI(field, 'Manage Modules');
goosemodScope.settings.removeModuleUI(field, 'Manage Modules');
}
};
settingItem[2].push(toggleObj);
globalThis.logger.debug(`import.load.module.${field}`, `Added to Modules setting page`);
goosemodScope.logger.debug(`import.load.module.${field}`, `Added to Modules setting page`);
};
export const importModules = async (files) => {
globalThis.logger.debug('import', 'Looping through files');
goosemodScope.logger.debug('import', 'Looping through files');
for (let f of files) {
globalThis.importModule(f);
goosemodScope.importModule(f);
}
globalThis.logger.debug('import', 'Imported all files');
goosemodScope.logger.debug('import', 'Imported all files');
};
export const bindHandlers = (handlers) => {
for (let p in handlers) {
if (handlers.hasOwnProperty(p) && typeof handlers[p] === 'function') {
handlers[p] = handlers[p].bind(this);
handlers[p] = handlers[p].bind(goosemodScope);
}
}
@ -69,7 +75,7 @@ export const bindHandlers = (handlers) => {
};
export const getModuleFiles = async () => { // Ask for module files (one by one due to Discord restraint) until no file is chosen
globalThis.logger.debug('import.fileask', 'Asking for files');
goosemodScope.logger.debug('import.fileask', 'Asking for files');
let allFiles = [];
@ -83,7 +89,7 @@ export const getModuleFiles = async () => { // Ask for module files (one by one
allFiles.push(files[0]); // Add file to files array
}
globalThis.logger.debug('import.fileask', 'Finished asking for files');
goosemodScope.logger.debug('import.fileask', 'Finished asking for files');
return allFiles;
};
@ -94,9 +100,9 @@ export const importModulesFull = async () => {
return [];
}
let files = await globalThis.getModuleFiles();
let files = await goosemodScope.getModuleFiles();
await globalThis.importModules(files);
await goosemodScope.importModules(files);
return files;
};

@ -1,18 +1,24 @@
let goosemodScope = {};
export const setThisScope = (scope) => {
goosemodScope = scope;
};
export const saveModuleSettings = async () => {
//globalThis.logger.debug('settings', 'Saving module settings...');
//goosemodScope.logger.debug('settings', 'Saving module settings...');
let settings = JSON.parse(localStorage.getItem('goosemodModules')) || {};
for (let p in globalThis.modules) {
if (globalThis.modules.hasOwnProperty(p)) {
settings[p] = await (globalThis.modules[p].getSettings || (async () => []))();
for (let p in goosemodScope.modules) {
if (goosemodScope.modules.hasOwnProperty(p)) {
settings[p] = await (goosemodScope.modules[p].getSettings || (async () => []))();
}
}
if (JSON.stringify(JSON.parse(localStorage.getItem('goosemodModules'))) !== JSON.stringify(settings)) {
localStorage.setItem('goosemodModules', JSON.stringify(settings));
globalThis.showToast('Settings saved');
goosemodScope.showToast('Settings saved');
}
//console.log(settings);
@ -33,20 +39,19 @@ export const clearSettings = () => {
export const loadSavedModuleSetting = async (moduleName) => {
let settings = JSON.parse(localStorage.getItem('goosemodModules'));
await (globalThis.modules[moduleName].loadSettings || (async () => []))(settings[moduleName]);
await (goosemodScope.modules[moduleName].loadSettings || (async () => []))(settings[moduleName]);
};
export const loadSavedModuleSettings = async () => {
//globalThis.logger.debug('settings', 'Loading module settings...');
//goosemodScope.logger.debug('settings', 'Loading module settings...');
let settings = JSON.parse(localStorage.getItem('goosemodModules'));
if (!settings) return;
for (let p in globalThis.modules) {
if (globalThis.modules.hasOwnProperty(p) && settings.hasOwnProperty(p)) {
console.log(p, globalThis.modules[p].loadSettings, settings[p]);
await (globalThis.modules[p].loadSettings || (async () => []))(settings[p]);
for (let p in goosemodScope.modules) {
if (goosemodScope.modules.hasOwnProperty(p) && settings.hasOwnProperty(p)) {
await (goosemodScope.modules[p].loadSettings || (async () => []))(settings[p]);
}
}

@ -1,39 +1,48 @@
import { sha512 } from '../util/hash';
const JSCache = require('./jsCache');
let goosemodScope = {};
export default {
setThisScope: (scope) => {
goosemodScope = scope;
JSCache.setThisScope(scope);
},
modules: [],
apiBaseURL: 'https://goosemod-api.netlify.app',
jsCache: require('./jsCache'),
jsCache: JSCache,
updateModules: async () => {
globalThis.moduleStoreAPI.modules = (await globalThis.cspBypasser.json(`${globalThis.moduleStoreAPI.apiBaseURL}/modules.json`, false)).sort((a, b) => a.name.localeCompare(b.name));
goosemodScope.moduleStoreAPI.modules = (await goosemodScope.cspBypasser.json(`${goosemodScope.moduleStoreAPI.apiBaseURL}/modules.json`, false)).sort((a, b) => a.name.localeCompare(b.name));
},
importModule: async (moduleName) => {
const moduleInfo = globalThis.moduleStoreAPI.modules.find((x) => x.filename === moduleName);
const moduleInfo = goosemodScope.moduleStoreAPI.modules.find((x) => x.filename === moduleName);
const jsCode = await globalThis.moduleStoreAPI.jsCache.getJSForModule(moduleName);
const jsCode = await goosemodScope.moduleStoreAPI.jsCache.getJSForModule(moduleName);
const calculatedHash = await sha512(jsCode);
if (calculatedHash !== moduleInfo.hash) {
globalThis.showToast(`Cancelled importing of ${moduleName} due to hash mismatch`, {timeout: 1000});
goosemodScope.showToast(`Cancelled importing of ${moduleName} due to hash mismatch`, {timeout: 2000});
console.warn('Hash mismatch', calculatedHash, moduleInfo.hash);
return;
}
await globalThis.importModule({
await goosemodScope.importModule({
filename: `${moduleInfo.filename}.js`,
data: jsCode
});
if (globalThis.modules[moduleName].onLoadingFinished !== undefined) {
await globalThis.modules[moduleName].onLoadingFinished();
if (goosemodScope.modules[moduleName].onLoadingFinished !== undefined) {
await goosemodScope.modules[moduleName].onLoadingFinished();
}
let settingItem = globalThis.settings.items.find((x) => x[1] === 'Module Store');
let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'Module Store');
let item = settingItem[2].find((x) => x.subtext === moduleInfo.description);
@ -41,11 +50,11 @@ export default {
item.buttonText = 'Remove';
item.showToggle = true;
if (globalThis.isSettingsOpen() && !globalThis.initialImport) globalThis.settings.createFromItems();
if (goosemodScope.settings.isSettingsOpen() && !goosemodScope.initialImport) goosemodScope.settings.createFromItems();
},
moduleRemoved: async (m) => {
let item = globalThis.settings.items.find((x) => x[1] === 'Module Store')[2].find((x) => x.subtext === m.description);
let item = goosemodScope.settings.items.find((x) => x[1] === 'Module Store')[2].find((x) => x.subtext === m.description);
if (item === undefined) return;
@ -55,13 +64,13 @@ export default {
},
updateStoreSetting: () => {
let item = globalThis.settings.items.find((x) => x[1] === 'Module Store');
let item = goosemodScope.settings.items.find((x) => x[1] === 'Module Store');
item[2] = item[2].slice(0, 4);
let sortedCategories = globalThis.moduleStoreAPI.modules.reduce((cats, o) => cats.includes(o.category) ? cats : cats.concat(o.category), []).sort((a, b) => a.localeCompare(b));
let sortedCategories = goosemodScope.moduleStoreAPI.modules.reduce((cats, o) => cats.includes(o.category) ? cats : cats.concat(o.category), []).sort((a, b) => a.localeCompare(b));
let arr = Object.entries(globalThis.moduleStoreAPI.modules.reduce((cats, o) => {
let arr = Object.entries(goosemodScope.moduleStoreAPI.modules.reduce((cats, o) => {
if (!cats[o.category]) cats[o.category]=[];
cats[o.category].push(o);
return cats;
@ -82,54 +91,54 @@ export default {
item[2].push({
type: 'card',
buttonType: globalThis.modules[m.filename] ? 'danger' : 'brand',
showToggle: globalThis.modules[m.filename],
buttonType: goosemodScope.modules[m.filename] ? 'danger' : 'brand',
showToggle: goosemodScope.modules[m.filename],
text: `${m.name} <span class="description-3_Ncsb">by</span> ${m.author}`, // ` <span class="description-3_Ncsb">(v${m.version})</span>`,
subtext: m.description,
subtext2: `v${m.version}`,
buttonText: globalThis.modules[m.filename] ? 'Remove' : 'Import',
buttonText: goosemodScope.modules[m.filename] ? 'Remove' : 'Import',
onclick: async (el) => {
if (globalThis.modules[m.filename]) {
if (goosemodScope.modules[m.filename]) {
el.textContent = 'Removing...';
globalThis.removeModuleUI(m.filename, 'Module Store');
goosemodScope.settings.removeModuleUI(m.filename, 'Module Store');
return;
}
el.textContent = 'Importing...';
await globalThis.moduleStoreAPI.importModule(m.filename);
await goosemodScope.moduleStoreAPI.importModule(m.filename);
globalThis.settings.createFromItems();
globalThis.openSettingItem('Module Store');
goosemodScope.settings.createFromItems();
goosemodScope.settings.openSettingItem('Module Store');
},
isToggled: () => globalThis.modules[m.filename] !== undefined,
isToggled: () => goosemodScope.modules[m.filename] !== undefined,
onToggle: async (checked) => {
if (checked) {
globalThis.modules[m.filename] = Object.assign({}, globalThis.disabledModules[m.filename]);
delete globalThis.disabledModules[m.filename];
goosemodScope.modules[m.filename] = Object.assign({}, goosemodScope.disabledModules[m.filename]);
delete goosemodScope.disabledModules[m.filename];
await globalThis.modules[m.filename].onImport();
await goosemodScope.modules[m.filename].onImport();
await globalThis.modules[m.filename].onLoadingFinished();
await goosemodScope.modules[m.filename].onLoadingFinished();
globalThis.loadSavedModuleSetting(m.filename);
goosemodScope.loadSavedModuleSetting(m.filename);
} else {
globalThis.disabledModules[m.filename] = Object.assign({}, globalThis.modules[m.filename]);
goosemodScope.disabledModules[m.filename] = Object.assign({}, goosemodScope.modules[m.filename]);
globalThis.modules[m.filename].remove();
goosemodScope.modules[m.filename].remove();
delete globalThis.modules[m.filename];
delete goosemodScope.modules[m.filename];
globalThis.settings.createFromItems();
globalThis.openSettingItem('Module Store');
goosemodScope.settings.createFromItems();
goosemodScope.settings.openSettingItem('Module Store');
}
globalThis.settings.createFromItems();
globalThis.openSettingItem('Module Store');
goosemodScope.settings.createFromItems();
goosemodScope.settings.openSettingItem('Module Store');
}
});
}

@ -1,8 +1,14 @@
let goosemodScope = {};
export const setThisScope = (scope) => {
goosemodScope = scope;
};
export const getCache = () => JSON.parse(localStorage.getItem('goosemodJSCache') || '{}');
export const purgeCache = () => localStorage.removeItem('goosemodJSCache');
export const updateCache = (moduleName, version, js) => {
let cache = globalThis.moduleStoreAPI.jsCache.getCache();
let cache = goosemodScope.moduleStoreAPI.jsCache.getCache();
cache[moduleName] = {version, js};
@ -10,15 +16,15 @@ export const updateCache = (moduleName, version, js) => {
};
export const getJSForModule = async (moduleName) => {
const moduleInfo = globalThis.moduleStoreAPI.modules.find((x) => x.filename === moduleName);
const cache = globalThis.moduleStoreAPI.jsCache.getCache();
const moduleInfo = goosemodScope.moduleStoreAPI.modules.find((x) => x.filename === moduleName);
const cache = goosemodScope.moduleStoreAPI.jsCache.getCache();
if (cache[moduleName] && moduleInfo.version === cache[moduleName].version) {
return cache[moduleName].js;
} else {
const js = await globalThis.cspBypasser.text(moduleInfo.codeURL, false);
const js = await goosemodScope.cspBypasser.text(moduleInfo.codeURL, false);
globalThis.moduleStoreAPI.jsCache.updateCache(moduleName, moduleInfo.version, js);
goosemodScope.moduleStoreAPI.jsCache.updateCache(moduleName, moduleInfo.version, js);
return js;
}

@ -1,4 +1,10 @@
let goosemodScope = {};
export default {
setThisScope: (scope) => {
goosemodScope = scope;
},
eggs: [
{
text: 'Goose Emoji',
@ -33,14 +39,14 @@ export default {
if (!el) return;
for (let e of globalThis.messageEasterEggs.eggs) {
for (let e of goosemodScope.messageEasterEggs.eggs) {
if (el.textContent === e.text) {
if (e.cooldown) {
e.cooldown -= 1;
continue;
}
globalThis.showToast(e.message);
goosemodScope.showToast(e.message);
e.cooldown = (e.cooldown || 6) - 1;
}

@ -1,7 +1,13 @@
let loadingToast = undefined;
let goosemodScope = {};
export const setThisScope = (scope) => {
goosemodScope = scope;
};
export const startLoadingScreen = () => {
loadingToast = globalThis.showToast('Injecting GooseMod: Starting...', { timeout: 99999 });
loadingToast = goosemodScope.showToast('Injecting GooseMod: Starting...', { timeout: 99999 });
};
export const updateLoadingScreen = (tip) => {

@ -1,21 +1,28 @@
import sleep from '../util/sleep';
import ab2str from '../util/ab2str';
// import ab2str from '../util/ab2str';
let goosemodScope = {};
export const setThisScope = (scope) => {
goosemodScope = scope;
};
export const removeModuleUI = (field, where) => {
let settingItem = globalThis.settings.items.find((x) => x[1] === 'Manage Modules');
let settingItem = goosemodScope.settings.items.find((x) => x[1] === 'Manage Modules');
settingItem[2].splice(settingItem[2].indexOf(settingItem[2].find((x) => x.subtext === globalThis.modules[field].description)), 1);
settingItem[2].splice(settingItem[2].indexOf(settingItem[2].find((x) => x.subtext === goosemodScope.modules[field].description)), 1);
globalThis.moduleStoreAPI.moduleRemoved(globalThis.modules[field]);
goosemodScope.moduleStoreAPI.moduleRemoved(goosemodScope.modules[field]);
globalThis.modules[field].remove();
goosemodScope.modules[field].remove();
delete globalThis.modules[field];
delete goosemodScope.modules[field];
globalThis.clearModuleSetting(field);
goosemodScope.clearModuleSetting(field);
globalThis.settings.createFromItems();
globalThis.openSettingItem(where);
goosemodScope.settings.createFromItems();
goosemodScope.settings.openSettingItem(where);
};
export const isSettingsOpen = () => {
@ -44,15 +51,15 @@ export const openSettingItem = (name) => {
};
export const reopenSettings = async () => {
globalThis.closeSettings();
goosemodScope.settings.closeSettings();
await sleep(1000);
globalThis.openSettings();
goosemodScope.settings.openSettings();
await sleep(200);
globalThis.openSettingItem('Module Store');
goosemodScope.settings.openSettingItem('Module Store');
};
// Settings UI stuff
@ -63,7 +70,7 @@ let settingsButtonEl;
settingsButtonEl = document.querySelector('button[aria-label="User Settings"]');
while (!settingsButtonEl) {
globalThis.showToast('Failed to get settings button, retrying');
goosemodScope.showToast('Failed to get settings button, retrying');
settingsButtonEl = document.querySelector('button[aria-label="User Settings"]');
await sleep(1000);
@ -74,40 +81,40 @@ let settingsButtonEl;
let settingsLayerEl, settingsSidebarEl, settingsSidebarGooseModContainer, settingsMainEl, settingsClasses;
const settings = {
items: [],
createItem: (panelName, content, clickHandler, danger = false) => {
globalThis.settings.items.push(['item', panelName, content, clickHandler, danger]);
},
//const settings = {
export let items = [];
createHeading: (headingName) => {
globalThis.settings.items.push(['heading', headingName]);
},
export const createItem = (panelName, content, clickHandler, danger = false) => {
goosemodScope.settings.items.push(['item', panelName, content, clickHandler, danger]);
};
createSeparator: () => {
globalThis.settings.items.push(['separator']);
},
export const createHeading = (headingName) => {
goosemodScope.settings.items.push(['heading', headingName]);
};
createFromItems: () => {
settingsSidebarGooseModContainer.innerHTML = '';
export const createSeparator = () => {
goosemodScope.settings.items.push(['separator']);
};
for (let i of globalThis.settings.items) {
switch (i[0]) {
case 'item':
globalThis.settings._createItem(i[1], i[2], i[3], i[4]);
break;
case 'heading':
globalThis.settings._createHeading(i[1]);
break;
case 'separator':
globalThis.settings._createSeparator();
break;
}
export const createFromItems = () => {
settingsSidebarGooseModContainer.innerHTML = '';
for (let i of goosemodScope.settings.items) {
switch (i[0]) {
case 'item':
goosemodScope.settings._createItem(i[1], i[2], i[3], i[4]);
break;
case 'heading':
goosemodScope.settings._createHeading(i[1]);
break;
case 'separator':
goosemodScope.settings._createSeparator();
break;
}
},
}
};
_createItem: (panelName, content, clickHandler, danger = false) => {
export const _createItem = (panelName, content, clickHandler, danger = false) => {
let parentEl = document.createElement('div');
let headerEl = document.createElement('h2');
@ -845,7 +852,7 @@ const settings = {
};
settingsSidebarEl.addEventListener('click', () => {
if (globalThis.removed === true) return;
if (goosemodScope.removed === true) return;
el.classList.remove(settingsClasses['selected']);
});
@ -853,34 +860,32 @@ const settings = {
if (panelName === 'Manage Modules' && window.DiscordNative === undefined) return;
settingsSidebarGooseModContainer.appendChild(el);
},
};
_createHeading: (headingName) => {
let el = document.createElement('div');
el.className = settingsClasses['header'];
export const _createHeading = (headingName) => {
let el = document.createElement('div');
el.className = settingsClasses['header'];
el.setAttribute('tabindex', '0');
el.setAttribute('role', 'button');
el.setAttribute('tabindex', '0');
el.setAttribute('role', 'button');
el.innerText = headingName;
el.innerText = headingName;
settingsSidebarGooseModContainer.appendChild(el);
},
settingsSidebarGooseModContainer.appendChild(el);
};
_createSeparator: () => {
let el = document.createElement('div');
el.className = settingsClasses['separator'];
export const _createSeparator = () => {
let el = document.createElement('div');
el.className = settingsClasses['separator'];
settingsSidebarGooseModContainer.appendChild(el);
}
settingsSidebarGooseModContainer.appendChild(el);
};
globalThis.settings = settings;
//};
let tryingToInject = false;
export const injectInSettings = async () => {
if (globalThis.removed) return;
if (goosemodScope.removed) return;
if (tryingToInject) return;
@ -922,20 +927,20 @@ export const injectInSettings = async () => {
let versionEl = document.createElement('div');
versionEl.classList.add('colorMuted-HdFt4q', 'size12-3cLvbJ');
versionEl.textContent = `GooseMod ${globalThis.version} (${globalThis.versionHash.substring(0, 7)})`;
versionEl.textContent = `GooseMod ${goosemodScope.version} (${goosemodScope.versionHash.substring(0, 7)})`;
settingsSidebarEl.lastChild.appendChild(versionEl);
let versionElUntethered = document.createElement('div');
versionElUntethered.classList.add('colorMuted-HdFt4q', 'size12-3cLvbJ');
versionElUntethered.textContent = `GooseMod Untethered ${globalThis.untetheredVersion || 'N/A'}`;
versionElUntethered.textContent = `GooseMod Untethered ${goosemodScope.untetheredVersion || 'N/A'}`;
settingsSidebarEl.lastChild.appendChild(versionElUntethered);
settingsMainEl = settingsLayerEl.querySelector('main');
globalThis.settings.createFromItems();
goosemodScope.settings.createFromItems();
tryingToInject = false;
};
@ -945,113 +950,113 @@ export const checkSettingsOpenInterval = setInterval(async () => {
let el = document.querySelector('div[aria-label="USER_SETTINGS"]');
if (el && !el.querySelector('nav > div').classList.contains('goosemod-settings-injected')) {
await globalThis.injectInSettings();
await goosemodScope.settings.injectInSettings();
}
}, 100);
globalThis.settings.createHeading('GooseMod');
export const makeGooseModSettings = () => {
goosemodScope.settings.createHeading('GooseMod');
globalThis.settings.createItem('Manage Modules', ['',
{
type: 'button',
text: 'Import Local Modules',
onclick: async () => {
let files = await globalThis.importModulesFull();
goosemodScope.settings.createItem('Manage Modules', ['',
{
type: 'button',
text: 'Import Local Modules',
onclick: async () => {
let files = await goosemodScope.importModulesFull();
for (let f of files) {
let n = f.filename.split('.').slice(0, -1).join('.');
for (let f of files) {
let n = f.filename.split('.').slice(0, -1).join('.');
if (globalThis.modules[n].onLoadingFinished !== undefined) {
await globalThis.modules[n].onLoadingFinished();
if (goosemodScope.modules[n].onLoadingFinished !== undefined) {
await goosemodScope.modules[n].onLoadingFinished();
}
}
}
globalThis.settings.createFromItems();
globalThis.openSettingItem('Manage Modules');
goosemodScope.settings.createFromItems();
goosemodScope.settings.openSettingItem('Manage Modules');
},
},
},
{
type: 'header',
text: 'Imported Modules'
}
]);
{
type: 'header',
text: 'Imported Modules'
}
]);
globalThis.settings.createItem('Module Store', ['',
{
type: 'button',
text: 'Update Index',
onclick: async () => {
await globalThis.moduleStoreAPI.updateModules();
goosemodScope.settings.createItem('Module Store', ['',
{
type: 'button',
text: 'Update Index',
onclick: async () => {
await goosemodScope.moduleStoreAPI.updateModules();
await globalThis.moduleStoreAPI.updateStoreSetting();
await goosemodScope.moduleStoreAPI.updateStoreSetting();
globalThis.settings.createFromItems();
goosemodScope.settings.createFromItems();
globalThis.openSettingItem('Module Store');
goosemodScope.settings.openSettingItem('Module Store');
},
width: 120
},
width: 120
},
{
type: 'search',
onchange: (inp, parentEl) => {
const fuzzyReg = new RegExp(`.*${inp}.*`, 'i');
{
type: 'search',
onchange: (inp, parentEl) => {
const fuzzyReg = new RegExp(`.*${inp}.*`, 'i');
const cards = [...parentEl.children[0].children].filter((x) => !x.className && x.getElementsByClassName('description-3_Ncsb')[1]);
const cards = [...parentEl.children[0].children].filter((x) => !x.className && x.getElementsByClassName('description-3_Ncsb')[1]);
for (let c of cards) {
const name = c.getElementsByClassName('title-31JmR4')[0].childNodes[0].wholeText;
const description = c.getElementsByClassName('description-3_Ncsb')[1].innerText;
for (let c of cards) {
const name = c.getElementsByClassName('title-31JmR4')[0].childNodes[0].wholeText;
const description = c.getElementsByClassName('description-3_Ncsb')[1].innerText;
const matches = (fuzzyReg.test(name) || fuzzyReg.test(description));
const matches = (fuzzyReg.test(name) || fuzzyReg.test(description));
c.style.display = matches ? 'block' : 'none';
}
c.style.display = matches ? 'block' : 'none';
}
const visibleModules = cards.filter((x) => x.style.display !== 'none').length;
const visibleModules = cards.filter((x) => x.style.display !== 'none').length;
parentEl.getElementsByClassName('divider-3573oO')[0].parentElement.children[1].innerText = `${visibleModules} module${visibleModules !== 1 ? 's' : ''}`;
parentEl.getElementsByClassName('divider-3573oO')[0].parentElement.children[1].innerText = `${visibleModules} module${visibleModules !== 1 ? 's' : ''}`;
//globalThis.settings.items.find((x) => x[1] === 'Module Store')[2].find((x) => x.type === 'divider').text(parentEl);
//goosemodScope.settings.items.find((x) => x[1] === 'Module Store')[2].find((x) => x.type === 'divider').text(parentEl);
},
storeSpecific: true
},
storeSpecific: true
},
{
type: 'divider',
text: (parentEl) => {
return new Promise(async (res) => {
await sleep(10);
const cards = [...parentEl.children[0].children].filter((x) => !x.className && x.getElementsByClassName('description-3_Ncsb')[1] && x.style.display !== 'none');
return res(`${cards.length} modules`);
});
}
}
]);
globalThis.settings.createSeparator();
{
type: 'divider',
text: (parentEl) => {
return new Promise(async (res) => {
await sleep(10);
globalThis.settings.createItem('Uninstall', [""], async () => {
if (await globalThis.confirmDialog('Uninstall', 'Uninstall GooseMod', 'Are you sure you want to uninstall GooseMod? This is a quick uninstall, it may leave some code behind but there should be no remaining noticable changes.')) {
globalThis.closeSettings();
const cards = [...parentEl.children[0].children].filter((x) => !x.className && x.getElementsByClassName('description-3_Ncsb')[1] && x.style.display !== 'none');
globalThis.remove();
}
}, true);
if (window.DiscordNative !== undefined) {
globalThis.settings.createItem('Local Reinstall', [''], async () => {
if (await globalThis.confirmDialog('Reinstall', 'Reinstall GooseMod', 'Are you sure you want to reinstall GooseMod? This will uninstall GooseMod, then ask you for the inject.js file, then run it to reinstall.')) {
globalThis.closeSettings();
return res(`${cards.length} modules`);
});
}
}
]);
globalThis.remove();
goosemodScope.settings.createItem('Uninstall', [""], async () => {
if (await goosemodScope.confirmDialog('Uninstall', 'Uninstall GooseMod', 'Are you sure you want to uninstall GooseMod? This is a quick uninstall, it may leave some code behind but there should be no remaining noticable changes.')) {
goosemodScope.settings.closeSettings();
eval(ab2str((await DiscordNative.fileManager.openFiles())[0].data));
goosemodScope.remove();
}
}, true);
}
globalThis.settings.createSeparator();
/*if (window.DiscordNative !== undefined) {
goosemodScope.settings.createItem('Local Reinstall', [''], async () => {
if (await goosemodScope.confirmDialog('Reinstall', 'Reinstall GooseMod', 'Are you sure you want to reinstall GooseMod? This will uninstall GooseMod, then ask you for the inject.js file, then run it to reinstall.')) {
goosemodScope.settings.closeSettings();
goosemodScope.remove();
eval(ab2str((await DiscordNative.fileManager.openFiles())[0].data));
}
}, true);
}*/
goosemodScope.settings.createSeparator();
globalThis.settings.createHeading('GooseMod Modules');
goosemodScope.settings.createHeading('GooseMod Modules');
};

@ -1,11 +1,17 @@
let goosemodScope = {};
export default {
setThisScope: (scope) => {
goosemodScope = scope;
},
frame: document.createElement('iframe'),
init: async () => {
globalThis.cspBypasser.frame.src = 'discord:';
document.body.appendChild(globalThis.cspBypasser.frame);
goosemodScope.cspBypasser.frame.src = 'discord:';
document.body.appendChild(goosemodScope.cspBypasser.frame);
//await awaitIframe(globalThis.cspBypasser.frame);
//await awaitIframe(goosemodScope.cspBypasser.frame);
let script = document.createElement('script');
script.type = 'text/javascript';
@ -47,7 +53,7 @@ export default {
script.appendChild(document.createTextNode(code));
globalThis.cspBypasser.frame.contentDocument.head.appendChild(script);
goosemodScope.cspBypasser.frame.contentDocument.head.appendChild(script);
},
runCode: (code) => {
@ -56,12 +62,12 @@ export default {
script.appendChild(document.createTextNode(code));
globalThis.cspBypasser.frame.contentDocument.head.appendChild(script);
goosemodScope.cspBypasser.frame.contentDocument.head.appendChild(script);
},
json: (url, useCORSProxy = true) => {
return new Promise((res) => {
globalThis.cspBypasser.frame.contentWindow.postMessage({url, type: 'json', useCORSProxy});
goosemodScope.cspBypasser.frame.contentWindow.postMessage({url, type: 'json', useCORSProxy});
window.addEventListener('message', async (e) => {
if (e.data.verify !== url) return;
@ -73,7 +79,7 @@ export default {
text: (url, useCORSProxy = true) => {
return new Promise((res) => {
globalThis.cspBypasser.frame.contentWindow.postMessage({url, type: 'text', useCORSProxy});
goosemodScope.cspBypasser.frame.contentWindow.postMessage({url, type: 'text', useCORSProxy});
window.addEventListener('message', async (e) => {
if (e.data.verify !== url) return;
@ -85,7 +91,7 @@ export default {
blob: (url, useCORSProxy = true) => {
return new Promise((res) => {
globalThis.cspBypasser.frame.contentWindow.postMessage({url, type: 'blob', useCORSProxy});
goosemodScope.cspBypasser.frame.contentWindow.postMessage({url, type: 'blob', useCORSProxy});
window.addEventListener('message', async (e) => {
if (e.data.verify !== url) return;
@ -97,7 +103,7 @@ export default {
image: (url, useCORSProxy = true) => {
return new Promise((res) => {
globalThis.cspBypasser.frame.contentWindow.postMessage({url, type: 'img', useCORSProxy});
goosemodScope.cspBypasser.frame.contentWindow.postMessage({url, type: 'img', useCORSProxy});
window.addEventListener('message', async (e) => {
if (e.data.verify !== url) return;

Loading…
Cancel
Save