cleanups, basic settings functionality

master^2
Cain Atkinson 2 years ago
parent 3e06ef0999
commit 701182ab7f

@ -1,35 +1,43 @@
// @flow // @flow
const commandsSym = Symbol("__commands");
function init(obj: Object) { function init(obj: Object) {
obj.demon.__commands = {} obj.demon[commandsSym] = {};
obj.demon.patcher.after("sendMessage", obj.demon.webpack.findByProps("sendMessage"), obj.demon.patcher.after(
(args, otherRes) => { "sendMessage",
let res; obj.demon.webpack.findByProps("sendMessage"),
for (const key of Reflect.ownKeys(obj.demon.__commands)) { (args, otherRes) => {
let command = obj.demon.__commands[key] let res;
if (args[1].content.split(" ")[0] === ">" + command.name) { for (const key of Reflect.ownKeys(obj.demon[commandsSym])) {
res = command.callback(args) let command = obj.demon[commandsSym][key];
break if (args[1].content.split(" ")[0] === ">" + command.name) {
} res = command.callback(args);
} break;
if (res !== undefined) args[1].content = res }
return args }
} if (res !== undefined) args[1].content = res;
) return args;
}
);
} }
// command = { // command = {
// name: "name", // name: "name",
// callback: (args)=>"Hello, world!" // callback: (args)=>"Hello, world!"
// } // }
function add(command: {name: string, callback: (args: Array<any>) => string}): ()=>void { function add(command: {
let sym = Symbol(command.name); name: string,
window.demon.__commands[sym] = command; callback: (args: Array<any>) => string,
return () => { }): () => void {
delete window.demon.__commands[sym]; let sym = Symbol(command.name);
} window.demon[commandsSym][sym] = command;
return () => {
delete window.demon[commandsSym][sym];
};
} }
export default { export default {
add: add, add: add,
init: init init: init,
} };

@ -2,41 +2,44 @@
import { get, set } from 'idb-keyval'; import { get, set } from 'idb-keyval';
import logger from './utils/logger.js' import logger from './utils/logger.js'
const pluginsSym = Symbol("__plugins");
async function init(obj: Object): Promise<boolean> { async function init(obj: Object): Promise<boolean> {
//TODO: check for enabled plugins in the idb, start them //TODO: check for enabled plugins in the idb, start them
let globalSettings = await get("demoncord") let globalSettings = await get("demoncord");
if (globalSettings === undefined) { if (globalSettings === undefined) {
await set("demoncord", {plugin: {}}) await set("demoncord", { plugin: {} });
globalSettings = await get("demoncord") globalSettings = await get("demoncord");
} }
obj.demon.__plugins = {} obj.demon[pluginsSym] = {};
for (let plug: Object in globalSettings.plugin) { for (let plug: Object in globalSettings.plugin) {
plug = globalSettings.plugin[plug] plug = globalSettings.plugin[plug];
if (plug.enabled) { if (plug.enabled) {
startPlugin(plug.metadata.name) startPlugin(plug.metadata.name);
} }
} }
return true return true;
} }
async function addPlugin(iife: string, metadata: Object): Promise<boolean> { async function addPlugin(iife: string, metadata: Object): Promise<boolean> {
// expected metadata: {name: "name", desc: "description", author: "author"} // expected metadata: {name: "name", desc: "description", author: "author"}
const obj: Object = { // whether the plugin is started or stopped isn't going to be stored in the iDB, so it can be accessed more easily by all components const obj: Object = {
metadata: metadata, // whether the plugin is started or stopped isn't going to be stored in the iDB, so it can be accessed more easily by all components
iife: iife, metadata: metadata,
enabled: false // should plugins be enabled by default? not sure iife: iife,
} enabled: false, // should plugins be enabled by default? not sure
const globalSettings: Object = await get("demoncord"); };
/*try { const globalSettings: Object = await get("demoncord");
/*try {
if (globalSettings["plugin"][metadata.name] !== undefined) { if (globalSettings["plugin"][metadata.name] !== undefined) {
log("Cannot add plugin that already exists!", "error", "Plugins") console.error("[Demoncord] Cannot add plugin that already exists!")
return false return false
} }
} catch (error) {*/ } catch (error) {*/
globalSettings["plugin"][metadata.name] = obj globalSettings["plugin"][metadata.name] = obj;
//} //Disabling checking for previous plugins for now as it is breaking literally fucking everything //} //Disabling checking for previous plugins for now as it is breaking literally fucking everything
await set("demoncord", globalSettings) await set("demoncord", globalSettings);
return true return true;
} }
async function delPlugin(name: string): Promise<boolean> { async function delPlugin(name: string): Promise<boolean> {
@ -65,7 +68,7 @@ async function startPlugin(name: string): Promise<boolean> {
let ctx = {} // ctx is how you're going to store things that need to be accessed in both onStart and onStop. dumb, i know let ctx = {} // ctx is how you're going to store things that need to be accessed in both onStart and onStop. dumb, i know
onStart(ctx) onStart(ctx)
logger.log(`Started ${name}!`, ["Plugins"]) logger.log(`Started ${name}!`, ["Plugins"])
window.demon.__plugins[name] = {status: 1, ctx: ctx} window.demon[pluginsSym][name] = {status: 1, ctx: ctx}
return true return true
} }
} }
@ -80,7 +83,7 @@ async function stopPlugin(name: string): Promise<boolean> {
const plug = globalSettings["plugin"][name] const plug = globalSettings["plugin"][name]
const exports: Object = (0, eval)(plug.iife) const exports: Object = (0, eval)(plug.iife)
const onStop: (ctx: Object)=>void = exports.onStop const onStop: (ctx: Object)=>void = exports.onStop
onStop(window.demon.__plugins[name].ctx) onStop(window.demon[pluginsSym][name].ctx);
logger.log(`Stopped ${name}!`, ["Plugins"]) logger.log(`Stopped ${name}!`, ["Plugins"])
return true return true
} }
@ -99,10 +102,10 @@ async function togglePlugin(name: string): Promise<boolean> {
} }
export default { export default {
init, init,
addPlugin, addPlugin,
delPlugin, delPlugin,
startPlugin, startPlugin,
stopPlugin, stopPlugin,
togglePlugin togglePlugin,
} };

@ -0,0 +1,71 @@
// @flow
import webpack from "./webpack";
const settingsSym = Symbol("__settings");
const settingsView = webpack.find(m => m.default && m.default.displayName === "SettingsView");
type getPredicateSectionsEntry =
| {
section: "HEADER",
label: string,
}
| {
section: "DIVIDER",
}
| {
section: string,
label: string,
component: Function,
};
function patch(args: mixed, ret: getPredicateSectionsEntry[]) {
const processedEntries = window.demon[settingsSym].entries.map((e) => ({
section: "DEMON_SETTINGS_LOADER_" + e.name,
label: e.name,
element: e.component,
}));
const injectionIndex =
2 + ret.findIndex((section) => section.section === "Game Activity");
ret.splice(
injectionIndex,
0,
{ section: "HEADER", label: "Demon" },
...processedEntries,
{ section: "DIVIDER" }
);
return ret;
}
function init() {
window.demon[settingsSym] = {
patch: window.demon.patcher.after(
"getPredicateSections",
settingsView.default.prototype,
patch
),
entries: [],
};
// debug
window.demonunpatch = window.demon[settingsSym].patch;
}
function unInit(obj: Object) {
window.demon[settingsSym].patch();
delete window.demon[settingsSym];
}
function unregisterSettingsEntry(name: string) {
let s = window.demon[settingsSym];
s.entries = s.entries.filter((e) => e.name !== name);
}
function registerSettingsEntry(name: string, component: Function): () => void {
window.demon[settingsSym].entries.push({ name, component });
return () => unregisterSettingsEntry(name);
}
export default { init, unInit, registerSettingsEntry, unregisterSettingsEntry };

@ -1,9 +1,9 @@
// @flow // @flow
type ModuleType = {[symbol]: any}; type ModuleType = Object/* { [symbol]: any } */;
type FilterFunc = (module: ModuleType) => boolean type FilterFunc = (module: ModuleType) => boolean;
function getModules(): any { function getModules(): any {
let modules: {c: mixed[]} = {}; let modules: { c: mixed[] } = {};
window.webpackChunkdiscord_app.push([ window.webpackChunkdiscord_app.push([
[Math.random().toString(36)], [Math.random().toString(36)],
@ -17,32 +17,44 @@ function getModules(): any {
} }
function filter(filter: FilterFunc, moduleList: any): Array<Object> { function filter(filter: FilterFunc, moduleList: any): Array<Object> {
let modules: Array<mixed[]> = []; let modules: Array<mixed[]> = [];
for (const mod in moduleList) { for (const mod in moduleList) {
const module = moduleList[mod].exports; const module = moduleList[mod].exports;
if (module) { if (module) {
if (module.default && module.__esModule && filter(module.default)) { modules.push(module.default); } if (module.default && module.__esModule && filter(module.default)) {
else if (filter(module)) { modules.push(module); } modules.push(module.default);
} } else if (filter(module)) {
} modules.push(module);
return modules; }
}
}
return modules;
} }
let webpack: Object = { type WebpackModules = {
modules: getModules(), modules: () => any,
filter: filter, filter: (filter: FilterFunc, moduleList: any) => Object[],
find: (filter: FilterFunc)=>webpack.filter(filter, webpack.modules)[0], find: (filter: FilterFunc) => Object,
findAll: (filter: FilterFunc)=>webpack.filter(filter, webpack.modules), findAll: (filter: FilterFunc) => Object[],
findByProps: (...props: Array<string>) => { findByProps: (...props: string[]) => Object,
return webpack.find((module) => { findByPropsAll: (...props: string[]) => Object[],
return props.every((prop)=>module[prop]!==undefined) };
})
}, let webpack: WebpackModules = {
findByPropsAll: (...props: Array<string>) => { modules: getModules(),
return webpack.findAll((module) => filter: filter,
props.every((prop)=>module[prop]!==undefined) find: (filter: FilterFunc) => webpack.filter(filter, webpack.modules)[0],
) findAll: (filter: FilterFunc) => webpack.filter(filter, webpack.modules),
} findByProps: (...props: Array<string>) => {
} return webpack.find((module) => {
return props.every((prop) => module[prop] !== undefined);
});
},
findByPropsAll: (...props: Array<string>) => {
return webpack.findAll((module) =>
props.every((prop) => module[prop] !== undefined)
);
},
};
export default webpack; export default webpack;

@ -1,52 +1,53 @@
// @flow // @flow
import Patcher from "simian" import Patcher from "simian";
import webpack from "./api/webpack.js" import webpack from "./api/webpack";
import common from "./api/common.js" import common from "./api/common";
import commands from "./api/commands.js" import commands from "./api/commands";
import plugins from "./api/plugins.js" import plugins from "./api/plugins";
import settingsInj from "./api/settingsInjection";
async function init(obj: Object): Promise<void> { async function init(obj: Object): Promise<void> {
const patcher = new Patcher() const patcher = new Patcher();
obj.demon = { obj.demon = {
patcher: { patcher: {
monkeyPatch: function(name: string, parentObj: Object, patches: Object): ()=>void { monkeyPatch: function (
let [upb,upi,upa] = [()=>{},()=>{},()=>{}] name: string,
if (patches.before !== undefined) upb = patcher.before( parentObj: Object,
name, patches: Object
parentObj, ): () => void {
patches.before let [upb, upi, upa] = [() => {}, () => {}, () => {}];
) if (patches.before !== undefined)
if (patches.instead !== undefined) upb = patcher.instead( upb = patcher.before(name, parentObj, patches.before);
name, if (patches.instead !== undefined)
parentObj, upb = patcher.instead(name, parentObj, patches.instead);
patches.instead if (patches.after !== undefined)
) upb = patcher.after(name, parentObj, patches.after);
if (patches.after !== undefined) upb = patcher.after( return () => {
name, upb();
parentObj, upi();
patches.after upa();
) };
return ()=>{ },
upb() before: patcher.before,
upi() instead: patcher.instead,
upa() after: patcher.after,
} },
}, webpack,
before: patcher.before, common,
instead: patcher.instead, commands: {
after: patcher.after add: commands.add,
}, },
webpack, __DO_NOT_USE_OR_YOU_WILL_BE_FIRED_UNTO_THE_DEPTHS_OF_HELL: {
common, plugins,
commands: { },
add: commands.add settings: {
}, register: settingsInj.registerSettingsEntry,
__DO_NOT_USE_OR_YOU_WILL_BE_FIRED_UNTO_THE_DEPTHS_OF_HELL: { unregister: settingsInj.unregisterSettingsEntry,
plugins },
} };
} commands.init(obj);
commands.init(obj) plugins.init(obj);
plugins.init(obj) settingsInj.init();
} }
export default init; export default init;

Loading…
Cancel
Save