diff --git a/dist/build.js b/dist/build.js index 69418b6..1974808 100644 --- a/dist/build.js +++ b/dist/build.js @@ -1 +1 @@ -!function(){"use strict";function t(e,n,d){var o=Symbol();const r=d.before,a=d.instead,i=d.after,t=new Proxy(n[e],{apply:(e,n,[o,t])=>(void 0!==r&&r.apply(o,t),res=void 0!==d.instead?a.apply(o,[e.bind(o),...t]):e.apply(o,t),void 0===i?res:i.apply(o,[res].concat(t)))}),c=n[e];n[e]=function(){return t(this,arguments)};var s=()=>{n[e]=c};return n[o]={name:e,orig:c,unpatch:s},s}var n={monkeyPatch:t,before:function(e,n,o){return t(e,n,{before:o})},instead:function(e,n,o){return t(e,n,{instead:o})},after:function(e,n,o){return t(e,n,{after:o})}};let o={modules:function(){let n={};return window.webpackChunkdiscord_app.push([[Math.random().toString(36)],{},e=>{n=e}]),n.c}(),filter:function(e,n){let o=[];for(const d in n){var t=n[d].exports;t&&(t.default&&t.__esModule&&e(t.default)?o.push(t.default):e(t)&&o.push(t))}return o},find:e=>o.filter(e,o.modules)[0],findAll:e=>o.filter(e,o.modules),findByProps:(...e)=>o.find(n=>e.every(e=>void 0!==n[e])),findByPropsAll:(...e)=>o.findAll(n=>e.every(e=>void 0!==n[e]))};const d={React:o.findByProps("__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","createElement"),ReactDOM:o.findByProps("__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","hydrate")};var r={add:function(e){let n=Symbol(e.name);return window.demon.__commands[n]=e,()=>{delete window.demon.__commands[n]}},init:function(d){d.demon.__commands={},d.demon.patcher.after("sendMessage",d.demon.webpack.findByProps("sendMessage"),(e,n)=>{let o;for(const t of Reflect.ownKeys(d.demon.__commands)){let e=d.demon.__commands[t];if(n[1].content.split(" ")[0]===">"+e.name){o=e.callback(n);break}}return void 0!==o&&(n[1].content=o),n})}};window.demon&&delete window.demon,async function(e){e.demon={patcher:n,webpack:o,common:d,commands:{add:r.add}},r.init(e)}(window)}(); +!function(){"use strict";function r(n,e,a){var t=Symbol();const i=a.before,u=a.instead,c=a.after,r=new Proxy(e[n],{apply:(n,e,[t,r])=>{void 0!==i&&i.apply(t,r);const o=void 0!==a.instead?u.apply(t,[n.bind(t),...r]):n.apply(t,r);return void 0===c?o:c.apply(t,[o].concat(r))}}),o=e[n];e[n]=function(){return r(this,arguments)};var s=()=>{e[n]=o};return e[t]={name:n,orig:o,unpatch:s},s}var e={monkeyPatch:r,before:function(n,e,t){return r(n,e,{before:t})},instead:function(n,e,t){return r(n,e,{instead:t})},after:function(n,e,t){return r(n,e,{after:t})}};let t={modules:function(){let e={};return window.webpackChunkdiscord_app.push([[Math.random().toString(36)],{},n=>{e=n}]),e.c}(),filter:function(n,e){let t=[];for(const o in e){var r=e[o].exports;r&&(r.default&&r.__esModule&&n(r.default)?t.push(r.default):n(r)&&t.push(r))}return t},find:n=>t.filter(n,t.modules)[0],findAll:n=>t.filter(n,t.modules),findByProps:(...n)=>t.find(e=>n.every(n=>void 0!==e[n])),findByPropsAll:(...n)=>t.findAll(e=>n.every(n=>void 0!==e[n]))};function a(t){return new Promise((n,e)=>{t.oncomplete=t.onsuccess=()=>n(t.result),t.onabort=t.onerror=()=>e(t.error)})}function n(e,r){const n=(!navigator.userAgentData&&/Safari\//.test(navigator.userAgent)&&!/Chrom(e|ium)\//.test(navigator.userAgent)&&indexedDB.databases?new Promise(function(n){function e(){return indexedDB.databases().finally(n)}t=setInterval(e,100),e()}).finally(function(){return clearInterval(t)}):Promise.resolve()).then(()=>{const n=indexedDB.open(e);return n.onupgradeneeded=()=>n.result.createObjectStore(r),a(n)});var t;return(e,t)=>n.then(n=>t(n.transaction(r,e).objectStore(r)))}let o;function i(){return o=o||n("keyval-store","keyval"),o}function u(e,n=i()){return n("readonly",n=>a(n.get(e)))}function c(e,t,n=i()){return n("readwrite",n=>(n.put(t,e),a(n.transaction)))}function s(n,e){return n("readonly",n=>(n.openCursor().onsuccess=function(){this.result&&(e(this.result),this.result.continue())},a(n.transaction)))}var d=Object.freeze({__proto__:null,clear:function(n=i()){return n("readwrite",n=>(n.clear(),a(n.transaction)))},createStore:n,del:function(e,n=i()){return n("readwrite",n=>(n.delete(e),a(n.transaction)))},delMany:function(n,e=i()){return e("readwrite",e=>(n.forEach(n=>e.delete(n)),a(e.transaction)))},entries:function(n=i()){const e=[];return s(n,n=>e.push([n.key,n.value])).then(()=>e)},get:u,getMany:function(n,e=i()){return e("readonly",e=>Promise.all(n.map(n=>a(e.get(n)))))},keys:function(n=i()){const e=[];return s(n,n=>e.push(n.key)).then(()=>e)},promisifyRequest:a,set:c,setMany:function(n,e=i()){return e("readwrite",e=>(n.forEach(n=>e.put(n[1],n[0])),a(e.transaction)))},update:function(r,o,n=i()){return n("readwrite",t=>new Promise((n,e)=>{t.get(r).onsuccess=function(){try{t.put(o(this.result),r),n(a(t.transaction))}catch(n){e(n)}}}))},values:function(n=i()){const e=[];return s(n,n=>e.push(n.value)).then(()=>e)}});const l={React:t.findByProps("__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","createElement"),ReactDOM:t.findByProps("__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","hydrate"),"idb-keyval":d};var f={add:function(n){let e=Symbol(n.name);return window.demon.__commands[e]=n,()=>{delete window.demon.__commands[e]}},init:function(o){o.demon.__commands={},o.demon.patcher.after("sendMessage",o.demon.webpack.findByProps("sendMessage"),(n,e)=>{let t;for(const r of Reflect.ownKeys(o.demon.__commands)){let n=o.demon.__commands[r];if(e[1].content.split(" ")[0]===">"+n.name){t=n.callback(e);break}}return void 0!==t&&(e[1].content=t),e})}};var m={addPlugin:async function(n,e,t){e={metadata:t,code:{start:n.toString(),stop:e.toString()},enabled:!1};const r=await u("demoncord");return r.plugin[t.name]=e,await c("demoncord",r),!0},delPlugin:async function(n){const e=await u("demoncord");return void 0===e.plugin[n]?(console.error("[Demoncord] Cannot remove non-existant plugin!"),!1):(e.plugin[n]=void 0,delete e.plugin[n],await c("demoncord",e),!0)}};window.demon&&delete window.demon,async function(n){n.demon={patcher:e,webpack:t,common:l,commands:{add:f.add},__DO_NOT_USE_OR_YOU_WILL_BE_FIRED_UNTO_THE_DEPTHS_OF_HELL:{plugins:m}},f.init(n)}(window)}(); diff --git a/src/api/common.js b/src/api/common.js index 2ca7ef0..22021bf 100644 --- a/src/api/common.js +++ b/src/api/common.js @@ -1,6 +1,8 @@ // @flow import webpack from "./webpack.js" +import * as idb from "idb-keyval"; + const common: {React: Object, ReactDOM: Object} = { React: webpack.findByProps( "__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED", @@ -9,7 +11,8 @@ const common: {React: Object, ReactDOM: Object} = { ReactDOM: webpack.findByProps( "__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED", "hydrate" - ) + ), + "idb-keyval": idb } export default common; diff --git a/src/api/plugins.js b/src/api/plugins.js index 787aaee..178fa57 100644 --- a/src/api/plugins.js +++ b/src/api/plugins.js @@ -1,20 +1,77 @@ +// @flow import { get, set } from 'idb-keyval'; -async function addPlugin(onStart, onStop, getMeta, metadata=null) { - if (metadata === null) metadata = getMeta(); // expected output: {name: "name", desc: "description", author: "author"} - const obj = { // 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 +async function addPlugin(onStart: (ctx: Object)=>void, onStop: (ctx: Object)=>void, 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, code: { - start: onStart, - stop: onStop + start: onStart.toString(), + stop: onStop.toString() // the hackiest of the hacks }, enabled: false // should plugins be enabled by default? not sure } - const globalSettings = await get("demoncord"); - if (globalSettings[metadata.name] !== undefined) { - console.log("[Demoncord] Cannot add plugin that already exists!") + 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) { + console.error("[Demoncord] Cannot remove non-existant plugin!") + 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) { + console.error("[Demoncord] Cannot start non-existant plugin!") return false } else { - + console.log(`[Demoncord] Starting ${name}...`) + const plug = globalSettings["plugin"][name] + const onStartStr: string = plug.code.start + const onStart = new Function('ctx', 'eeeeeeee', onStartStr) + 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, {}) + console.log(`[Demoncord] Started ${name}!`) + window.demon.__plugins[name] = {status: 1, ctx: ctx} + return true } } + +async function stopPlugin(name: string): Promise { + const globalSettings = await get("demoncord") + if (globalSettings["plugin"][name] === undefined ) { + console.error("[Demoncord] Cannot stop non-existant or non-running plugin!") + return false + } else { + console.log(`[Demoncord] Stopping ${name}...`) + const plug = globalSettings["plugin"][name] + const onStartStr: string = plug.code.stop + const onStart = new Function('ctx', onStartStr) + onStart() + console.log(`[Demoncord] Stopped ${name}!`) + return true + } +} + +export default { + addPlugin, + delPlugin +} diff --git a/src/init.js b/src/init.js index 8092b03..7274e20 100644 --- a/src/init.js +++ b/src/init.js @@ -3,6 +3,7 @@ import demonpatcher from "demonpatcher" import webpack from "./api/webpack.js" import common from "./api/common.js" import commands from "./api/commands.js" +import plugins from "./api/plugins.js" async function init(obj: Object): Promise { obj.demon = { @@ -11,6 +12,9 @@ async function init(obj: Object): Promise { common, commands: { add: commands.add + }, + __DO_NOT_USE_OR_YOU_WILL_BE_FIRED_UNTO_THE_DEPTHS_OF_HELL: { + plugins } } commands.init(obj)