// @flow import { get, set } from "idb-keyval"; import logger from "./utils/logger.js"; import settingsInj from "./settingsInj.js"; const pluginsSym = Symbol("__plugins"); async function init(obj: Object): Promise { //TODO: check for enabled plugins in the idb, start them let globalSettings = await get("demoncord"); if (globalSettings === undefined) { await set("demoncord", { plugin: {} }); globalSettings = await get("demoncord"); } obj.demon[pluginsSym] = {}; for (let plug: Object in globalSettings.plugin) { plug = globalSettings.plugin[plug]; if (plug.enabled) { startPlugin(plug.metadata.name); } } return true; } async function addPlugin(iife: string, metadata: Object): Promise { // 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 metadata: metadata, iife: iife, enabled: false, // should plugins be enabled by default? not sure }; const globalSettings: Object = await get("demoncord"); /*try { if (globalSettings["plugin"][metadata.name] !== undefined) { console.error("[Demoncord] Cannot add plugin that already exists!") return false } } catch (error) {*/ globalSettings["plugin"][metadata.name] = obj; //} //Disabling checking for previous plugins for now as it is breaking literally fucking everything await set("demoncord", globalSettings); return true; } async function delPlugin(name: string): Promise { const globalSettings = await get("demoncord"); if (globalSettings["plugin"][name] === undefined) { logger.error("Cannot remove non-existant plugin!", ["Plugins"]); return false; } else { globalSettings["plugin"][name] = undefined; delete globalSettings["plugin"][name]; } await set("demoncord", globalSettings); return true; } async function startPlugin(name: string): Promise { const globalSettings = await get("demoncord"); if (globalSettings["plugin"][name] === undefined) { logger.error("Cannot start non-existant plugin!", ["Plugins"]); return false; } else { logger.log(`Starting ${name}...`, ["Plugins"]); const plug = globalSettings["plugin"][name]; const exports: Object = (0, eval)(plug.iife); const onStart: (ctx: Object) => void = exports.onStart; 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); if (exports.settings) settingsInj.registerSettingsEntry( name, "DEMON_PLUGIN_SETTINGS_" + name, exports.settings ); logger.log(`Started ${name}!`, ["Plugins"]); window.demon[pluginsSym][name] = { status: 1, ctx: ctx }; return true; } } async function stopPlugin(name: string): Promise { const globalSettings = await get("demoncord"); if (globalSettings["plugin"][name] === undefined) { logger.error("Cannot stop non-existant or non-running plugin!", [ "Plugins", ]); return false; } else { logger.log(`Stopping ${name}...`, ["Plugins"]); const plug = globalSettings["plugin"][name]; const exports: Object = (0, eval)(plug.iife); const onStop: (ctx: Object) => void = exports.onStop; onStop(window.demon[pluginsSym][name].ctx); settingsInj.unregisterSettingsEntry("DEMON_PLUGIN_SETTINGS_" + name); logger.log(`Stopped ${name}!`, ["Plugins"]); return true; } } async function togglePlugin(name: string): Promise { const globalSettings = await get("demoncord"); if (globalSettings["plugin"][name] === undefined) { logger.error("Cannot toggle non-existant plugin!", ["Plugins"]); return false; } else { globalSettings["plugin"][name].enabled = !globalSettings["plugin"][name].enabled; await set("demoncord", globalSettings); return true; } } export default { init, addPlugin, delPlugin, startPlugin, stopPlugin, togglePlugin, };