diff --git a/dist/build.js b/dist/build.js index c3a135f..05f13e3 100644 --- a/dist/build.js +++ b/dist/build.js @@ -1 +1 @@ -!function(){"use strict";let getModules;if(window.webpackChunkdiscord_app){let modules1={};window.webpackChunkdiscord_app.push([[Math.random().toString(36)],{},a=>{modules1=a}]),getModules=()=>modules1.c}else{let modules=webpackJsonp([],[(a,b,c)=>{a.exports=c}]);getModules=()=>modules.c}let webpack={modules:getModules(),getModules,filter:function(a,b){let c=[];for(let d in b){let e=b[d].exports;e&&(e.default&&e.__esModule&&a(e.default)?c.push(e.default):a(e)&&c.push(e))}return c},find:a=>webpack.filter(a,webpack.modules)[0],findAll:a=>webpack.filter(a,webpack.modules),findByProps:(...a)=>webpack.find(b=>a.every(a=>void 0!==b[a])),findByPropsAll:(...a)=>webpack.findAll(b=>a.every(a=>void 0!==b[a])),findByDisplayName:a=>webpack.find(b=>b?.displayName===a),findByDisplayNameAll:a=>webpack.findAll(b=>b?.displayName===a),findByStrings:(...a)=>webpack.find(b=>a.every(a=>b.toString().contains(a))),reloadModules(){webpack.modules=getModules()}};function promisifyRequest(a){return new Promise((b,c)=>{a.oncomplete=a.onsuccess=()=>b(a.result),a.onabort=a.onerror=()=>c(a.error)})}function createStore(a,b){let c=indexedDB.open(a);c.onupgradeneeded=()=>c.result.createObjectStore(b);let d=promisifyRequest(c);return(a,c)=>d.then(d=>c(d.transaction(b,a).objectStore(b)))}let defaultGetStoreFunc;function defaultGetStore(){return defaultGetStoreFunc||(defaultGetStoreFunc=createStore("keyval-store","keyval")),defaultGetStoreFunc}function get(a,b=defaultGetStore()){return b("readonly",b=>promisifyRequest(b.get(a)))}function set(a,b,c=defaultGetStore()){return c("readwrite",c=>(c.put(b,a),promisifyRequest(c.transaction)))}function eachCursor(a,b){return a.openCursor().onsuccess=function(){this.result&&(b(this.result),this.result.continue())},promisifyRequest(a.transaction)}var idb=Object.freeze({__proto__:null,clear:function(a=defaultGetStore()){return a("readwrite",a=>(a.clear(),promisifyRequest(a.transaction)))},createStore:createStore,del:function(a,b=defaultGetStore()){return b("readwrite",b=>(b.delete(a),promisifyRequest(b.transaction)))},delMany:function(a,b=defaultGetStore()){return b("readwrite",b=>(a.forEach(a=>b.delete(a)),promisifyRequest(b.transaction)))},entries:function(a=defaultGetStore()){return a("readonly",b=>{if(b.getAll&&b.getAllKeys)return Promise.all([promisifyRequest(b.getAllKeys()),promisifyRequest(b.getAll()),]).then(([a,b])=>a.map((a,c)=>[a,b[c]]));let c=[];return a("readonly",a=>eachCursor(a,a=>c.push([a.key,a.value])).then(()=>c))})},get:get,getMany:function(a,b=defaultGetStore()){return b("readonly",b=>Promise.all(a.map(a=>promisifyRequest(b.get(a)))))},keys:function(a=defaultGetStore()){return a("readonly",a=>{if(a.getAllKeys)return promisifyRequest(a.getAllKeys());let b=[];return eachCursor(a,a=>b.push(a.key)).then(()=>b)})},promisifyRequest:promisifyRequest,set:set,setMany:function(a,b=defaultGetStore()){return b("readwrite",b=>(a.forEach(a=>b.put(a[1],a[0])),promisifyRequest(b.transaction)))},update:function(a,b,c=defaultGetStore()){return c("readwrite",c=>new Promise((d,e)=>{c.get(a).onsuccess=function(){try{c.put(b(this.result),a),d(promisifyRequest(c.transaction))}catch(f){e(f)}}}))},values:function(a=defaultGetStore()){return a("readonly",a=>{if(a.getAll)return promisifyRequest(a.getAll());let b=[];return eachCursor(a,a=>b.push(a.value)).then(()=>b)})}}),Events=Object.freeze({GET:"GET",SET:"SET",DELETE:"DELETE",UPDATE:"UPDATE"});class EventEmitter{constructor(){for(let a of(this.listeners=Object.values(Events).reduce((a,b)=>(a[b]=new Set,a),{}),this.on=function(a,b){if(this.listeners[a].has(b))throw Error(`This listener on ${a} already exists.`);this.listeners[a].add(b)},this.once=function(a,b){let c=(a,d)=>{this.off(a,c),b(a,d)};this.on(a,c)},this.off=function(a,b){this.listeners[a].delete(b)},this.emit=function(a,b){for(let c of this.listeners[a])c(a,b)},Object.values(Events)))this[a.toLowerCase()]=b=>{this.emit(a,b)}}}function make(a={},{nestArrays:b=!0}={}){let c=new EventEmitter;function d(a,e,f){return new Proxy(a,{get(a,g){let h=[...f,g],i=a[g];return null!=i?(c.get({path:h,value:i}),!b&&Array.isArray(i))?i:"object"==typeof i?d(i,e,h):i:d(a[g]={},e,h)},set:(a,b,d)=>(a[b]=d,c.set({path:[...f,b],value:d}),!0),deleteProperty:(a,b)=>!!delete a[b]&&(c.delete({path:[...f,b]}),!0),has:(a,b)=>("object"!=typeof a[b]||0!==Object.keys(a[b]).length)&&b in a})}return Object.assign({store:d(a,a,[]),ghost:a},c)}var nests=Object.freeze({__proto__:null,Events:Events,make:make});let React$1=webpack.findByProps("createElement"),{useRef,useReducer,useEffect}=React$1;function useNest(a,b=!1,c=()=>!0){useRef(a.ghost);let[,d]=useReducer(a=>~a,0);return useEffect(()=>{function e(a,b){c(a,b)&&d()}return a.on(Events.UPDATE,e),b||(a.on(Events.SET,e),a.on(Events.DELETE,e)),()=>{a.off(Events.UPDATE,e),b||(a.off(Events.SET,e),a.off(Events.DELETE,e))}},[]),a.ghost}let{findByProps:findByProps$1}=webpack,React=findByProps$1("createElement");var common={React,ReactDOM:findByProps$1("hydrate"),idb,nests};let styleBase="@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@700&display=swap'); font-family: 'IBM Plex Mono', monospace;",styleBg=`${styleBase} color: #1d1131; background-color: #aa8dd8; font-weight: 600; font-size: 0.9em; padding: 0px 5px 1px 5px; border-radius: 5px;`,styleTxt=`${styleBase} color: #E2EECE; font-weight: 500; font-size: 0.9em;`;function makeLogger(a,b=!1){return function(c,...d){d=d.join(""),void 0===c&&(c=["Default"],makeLogger("warn")("Requested hierarchy has not been passed to logger function, defaulting to default string",["Logger"])),"string"==typeof c&&(d=c,c=["Default"]);let e=["Demoncord",...c,d],f=[],g="";b&&e.splice(0,1);for(let h=0;h{console.log(...a)});var logger={log,warn,error,trace,debug,makeLogger};function _extends(){return(_extends=Object.assign||function(a){for(var b=1;b3!==a.transitionState&&React.createElement(ConfirmModal,_extends({transitionState:a.transitionState,onClose:()=>e=!1,onCancel:()=>e=!1&a.onClose(),onConfirm:()=>e=!0&a.onClose()},b),React.createElement("component",_extends({},c),d))),e}function leak(a){window.beelzejuice||(window.beelzejuice={});let b=Math.random().toString(36).slice(2);return window.beelzejuice[b]=new Uint8Array(Math.floor(1048576*a)).fill(666),()=>delete window.beelzejuice[b]}let ctxNest=make(),pluginNest,pluginEval=iife=>(0,eval)(iife);async function savePlugin(a,{path:b,value:c}){logger.debug(["Plugins"],`Got ${a} event for plugin manager's nest with path ${b} and val ${c}`),await set("demon",{plugins:pluginNest.ghost.plugins})}async function init$1(){pluginNest=demon.summon("internal/nest"),await get("demon")||await set("demon",{plugins:{}}),pluginNest.store.plugins=(await get("demon")).plugins,pluginNest.on(Events.SET,savePlugin),pluginNest.on(Events.DELETE,savePlugin),Object.keys(pluginNest.ghost.plugins).forEach(a=>{if(pluginNest.ghost.plugins[a].enabled){let b=pluginEval(pluginNest.ghost.plugins[a].iife),c=b.onStart();ctxNest.store[a]=c,pluginNest.store.plugins[a].enabled=!0}else pluginNest.store.plugins[a].enabled=!1})}function add$1(a){let b=pluginEval(a);logger.debug(["Plugins"],`Adding ${b.meta.name}`),pluginNest.store.plugins[b.meta.name]={iife:a,enabled:!1,desc:b.meta.desc}}function del(a){if(pluginNest.ghost.plugins[a])logger.debug(["Plugins"],`Removing ${a}`),delete pluginNest.store.plugins[a];else throw Error("Can't delete plugin that doesn't exist. lol")}function toggle(a){if(pluginNest.ghost.plugins[a]){if(pluginNest.ghost.plugins[a].enabled){logger.debug(["Plugins"],`Disabling ${a}`);let b=pluginEval(pluginNest.ghost.plugins[a].iife);b.onStop(ctxNest.store[a]),pluginNest.store.plugins[a].enabled=!1}else{logger.debug(["Plugins"],`Enabling ${a}`);let c=pluginEval(pluginNest.ghost.plugins[a].iife),d=c.onStart();ctxNest.store[a]=d,pluginNest.store.plugins[a].enabled=!0}}}var plugins$1={init:init$1,add:add$1,del,toggle};function wackyPatch(a,b,c){if("string"==typeof a){let d=a;a=b,b=d}let e=Symbol(),f=c.before,g=c.instead,h=c.after,i={apply(a,b,[d,e]){void 0!==f&&f.apply(d,[e]);let i=void 0!==c.instead?g.apply(d,[e,a.bind(d)]):a.apply(d,e);return void 0===h?i:h.apply(d,[e,i])}},j=new Proxy(a[b],i),k=a[b];a[b]=function(){return j(this,arguments)};let l=()=>{a[b]=k};return a[e]={name:b,orig:k,unpatch:l},l}function instead(a,b,c){return wackyPatch(a,b,{instead:c})}function after(a,b,c){return wackyPatch(a,b,{after:c})}let Header$1=webpack.findByProps("Sizes","Tags"),Card=webpack.findByDisplayName("Card");webpack.findByDisplayName("Flex");let FormText=webpack.findByDisplayName("FormText");webpack.findByProps("BorderColors","Colors"),webpack.findByDisplayName("FormDivider");let Switch=webpack.findByDisplayName("Switch");var PlugCard=a=>(useNest(a.nest),a.nest.ghost.plugins[a.name])?React.createElement(React.Fragment,null,React.createElement(Card,{type:"cardPrimary",className:"demon-settings-card-base",outline:!1,editable:!1},React.createElement(Header$1,{className:"demon-settings-card-header",size:Header$1.Sizes.SIZE_20},a.name),React.createElement("hr",{className:"demon-settings-card-divider"}),React.createElement(FormText,{className:"demon-settings-card-desc"},a.nest.ghost.plugins[a.name].desc),React.createElement("svg",{position:"top",async onClick(){del(a.name)},className:"demon-settings-card-delete",viewBox:"0 0 24 24"},React.createElement("path",{fill:"var(--text-muted)",d:"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12 1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.13-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"})),React.createElement(Switch,{className:"demon-settings-card-switch",checked:a.nest.ghost.plugins[a.name].enabled,async onChange(){toggle(a.name)}}))):null;let Header=webpack.findByProps("Sizes","Tags"),FormDivider=webpack.findByDisplayName("FormDivider"),Flex=webpack.findByDisplayName("Flex"),TextInput=webpack.findByDisplayName("TextInput");webpack.findByProps("BorderColors","Colors");var plugins=()=>{let a=demon.summon("internal/nest"),[b,c]=React.useState("");return useNest(a),React.createElement(React.Fragment,null,React.createElement(Header,{size:"demon-settings-header-size30"},"Plugins"),React.createElement(Flex,{basis:"auto",grow:1,shrink:1},React.createElement(TextInput,{className:"demon-settings-url",placeholder:"https://git.ruthenic.com/ruthenic/demoncord-noReplyMention/raw/branch/master/dist/plugin.js",type:"text",value:b,onChange:c,async onKeyDown(a){if("Enter"===a.key){let d=await (await fetch("https://cors.ruthenic.com/"+b)).text();add$1(d),c("")}}})),React.createElement(FormDivider,{className:"demon-settings-divider"}),Object.keys(a.ghost.plugins).map(b=>React.createElement(React.Fragment,null,React.createElement(PlugCard,{name:b,nest:a}))))};let Checkbox=webpack.findByDisplayName("Checkbox");class HummusUI extends React.Component{constructor(a){super(a),this.state={tg:0}}render(){let a=demon.summon("internal/nest");return React.createElement("div",{className:"control-group demon-settings-card-header"},React.createElement("label",{className:"demon-settings-header-size30"},"Plugins"),Object.keys(a.ghost.plugins).map(b=>React.createElement("div",{className:"demon-settings-card-base"},React.createElement("span",null,React.createElement(Checkbox,{className:`demon-stub-plugin-checkbox-${b}`,checked:a.ghost.plugins[b].enabled,onChange:async()=>{toggle(b);let c=document.getElementsByClassName(`demon-stub-plugin-checkbox-${b}`)[0];a.ghost.plugins[b].enabled?c.value="off":c.value="on",this.setState({tg:!this.state.tg})}},b)))))}}function injectCSS(a){let b=document.createElement("style");b.className="demon-element-css",b.innerHTML=a,document.head.appendChild(b)}var css={injectCSS,createClass:function(a,b){let c=Object.entries(b).map(([a,b])=>`${a}:${b}`).join(";");injectCSS(`.${a} {${c}}`)}};let SettingsView=webpack.findByDisplayName("SettingsView"),pluginSettings=[{section:"HEADER",label:"Demoncord"},{section:"demoncord",label:"Plugins",element:plugins},{section:"DIVIDER"}];var settings={init:function(){if(css.createClass("demon-settings-url",{"margin-top":"10px",width:"100%"}),css.createClass("demon-settings-divider",{"margin-top":"10px","margin-bottom":"10px",height:"1px"}),css.createClass("demon-settings-card-divider",{"margin-top":"5px","margin-bottom":"5px","margin-left":"10px","margin-right":"10px",height:"1px",border:"thin solid var(--background-modifier-accent)"}),css.createClass("demon-settings-card-base",{"margin-bottom":"10px"}),css.createClass("demon-settings-card-header",{"margin-left":"10px","margin-top":"10px"}),css.createClass("demon-settings-card-desc",{color:"var(--header-secondary)",display:"inline-block","font-size":"15px","line-height":"15px","margin-left":"10px","margin-top":"5px","margin-bottom":"10px"}),css.createClass("demon-settings-card-switch",{"margin-right":"10px","margin-top":"0px","margin-bottom":"10px",float:"right"}),css.createClass("demon-settings-card-delete",{"margin-right":"5px",float:"right",width:"24px",cursor:"pointer"}),css.createClass("demon-settings-header-size30",{"font-size":"30px","line-height":"34px"}),window.webpackChunkdiscord_app)after(SettingsView.prototype,"getPredicateSections",(a,b)=>(b.unshift(...pluginSettings),b));else{let a=webpack.findByProps("getUserSettingsModalSections"),b=webpack.findByProps("TabBarItem");after("render",a.default.prototype,(a,c)=>{c.props.children[0].props.children.props.children[1].push(React.createElement(b.TabBarItem,{key:"demoncord"},"Plugins")),"demoncord"===c.props.children[0].props.children.props.selectedItem&&(c.props.children[1].props.children[0].props.children=React.createElement(HummusUI,{},""))})}},add:function(a,b){let c=pluginSettings.push({section:"demoncord-plugins",label:"name",element:b})-1;return()=>{delete pluginSettings[c]}}};let sins={Lust:null,Pride:null,Greed:null,Wrath:null,Envy:null,Gluttony:null,Sloth(){setInterval(()=>{leak(6.66)},500),instead(webpack.findByProps("_actionHandlers").__proto__,"dispatch",(a,b)=>{let c;return setTimeout(()=>{c=b(...a)},500),c});let a={get(a,b){console.log("Some FOOL tried to access MY webpackChunkdiscord_app");let c;return setTimeout(()=>{c=a[b]},500),c}},b=new Proxy(window.webpackChunkdiscord_app,a);window.webpackChunkdiscord_app=b}},rulers={Asmodeus:"Lust",Lucifer:"Pride",Mammon:"Greed",Satan:"Wrath",Leviathan:"Envy",Beelzebub:"Gluttony",Belphegor:"Sloth"};function ritualFail(a){if(Math.random()>.5)throw"Illegal Invocation of a sin!";if(a in sins){if(sins[a])sins[a]();else throw"Illegal Invocation of a sin!"}else console.log("WTF did you do"),console.log(a)}Object.assign(webpack,{findByRitual:function(a){let b=a.split(" ");if("I"!==b.shift()||"call"!==b.shift()||"upon"!==b.shift()||"the"!==b.shift()){ritualFail(sins[Math.floor(Math.random()*sins.length)]);return}let c=b.shift();if(!("embodiment"===c||"king"===c&&"sin"===b.shift())){ritualFail(sins[Math.floor(Math.random()*sins.length)]);return}"of"!==b.shift()&&ritualFail(d);let d=b.shift().replace(",","");if(!(d in sins)){ritualFail(sins[Math.floor(Math.random()*sins.length)]);return}let e=b.shift().replace(",","");e in rulers||ritualFail(d),rulers[e]!==d&&ritualFail(rulers[e]),"to"!==b.shift()&&ritualFail(d),"summon"!==b.shift()&&ritualFail(d),"the"!==b.shift()&&ritualFail(d);let f=b.shift();"imposing"!==f&&"foreboding"!==f&&ritualFail(d);let g=b.shift();"object"!==g&&"element"!==g&&ritualFail(d),("with"!==b.shift()||"a"!==b.shift())&&ritualFail(d);let h=b.shift();"display"!==h&&"property"!==h&&ritualFail(d),("of"!==b.shift()||"name"!==b.shift())&&ritualFail(d);let i=b.shift().slice(0,-1);switch(h){case"display":return webpack.findByDisplayName(i);case"property":return webpack.findByProps(i);default:ritualFail(d)}}});let demon$1={modules:{webpack,common},utils:{logger,modals:{rawOpenConfirmModal,openConfirmModal:function(a,b,c){let d;if(c.color)d=c.color;else switch(b){case"danger":d=Colors.colorRed;break;case"confirm":d=Colors.colorGreen;break;default:d=Colors.colorBrandNew}return rawOpenConfirmModal(Markdown,{header:c.header??"Default Modal Header",confirmText:c.confirmText??"Confirm",cancelText:c.cancelText??"Cancel",confirmButtonColor:d},{editable:!1},a??"Default modal content")}},memory:{leak}},plugins:plugins$1,internal:{nest:common.nests.make()},css,patcher:{instead,before:function(a,b,c){return wackyPatch(a,b,{before:c})},after},stolas:{monologue(){let a=webpack.findByProps("getCurrentUser").getCurrentUser().username;return _.sample([`${a}, you know that when I'm lonely, I become hungry. And when I become hungry, I want to choke on that red **** of yours... **** your ***** and lick all of your *****, before taking out your *****, and **** with more teeth until you're screaming ********** like a FUCKING baby--!`,`Ohhh, ${a}! I'm so excited! I cannot wait to feel your slimy c**k inside of my ****. To ***** the— ...**** use while you and I and **** and jelly sandwiches all night...!`])}},settings};window.demon={summon:function(a){let b=a.split("/"),c=demon$1;return b.forEach(a=>{if(a in c)c=c[a];else throw Error("Module does not exist!")}),c}},plugins$1.init(),settings.init()}() +!function(){"use strict";let getModules;if(window.webpackChunkdiscord_app){let modules1;window.webpackChunkdiscord_app.push([[Math.random().toString(36)],{},a=>{modules1=a}]),getModules=()=>modules1.c}else{let modules=window.webpackJsonp([],[(a,b,c)=>{a.exports=c}]);getModules=()=>modules.c}let webpack={modules:getModules(),getModules,filter:function(a,b){let c=[];for(let d in b){let e=b[d].exports;e&&(e.default&&e.__esModule&&a(e.default)?c.push(e.default):a(e)&&c.push(e))}return c},find:a=>webpack.filter(a,webpack.modules)[0],findAll:a=>webpack.filter(a,webpack.modules),findByProps:(...a)=>webpack.find(b=>a.every(a=>void 0!==b[a])),findByPropsAll:(...a)=>webpack.findAll(b=>a.every(a=>void 0!==b[a])),findByDisplayName:a=>webpack.find(b=>b?.displayName===a),findByDisplayNameAll:a=>webpack.findAll(b=>b?.displayName===a),findByStrings:(...a)=>webpack.find(b=>a.every(a=>b.toString().contains(a))),reloadModules(){webpack.modules=getModules()}};function promisifyRequest(a){return new Promise((b,c)=>{a.oncomplete=a.onsuccess=()=>b(a.result),a.onabort=a.onerror=()=>c(a.error)})}function createStore(a,b){let c=indexedDB.open(a);c.onupgradeneeded=()=>c.result.createObjectStore(b);let d=promisifyRequest(c);return(a,c)=>d.then(d=>c(d.transaction(b,a).objectStore(b)))}let defaultGetStoreFunc;function defaultGetStore(){return defaultGetStoreFunc||(defaultGetStoreFunc=createStore("keyval-store","keyval")),defaultGetStoreFunc}function get(a,b=defaultGetStore()){return b("readonly",b=>promisifyRequest(b.get(a)))}function set(a,b,c=defaultGetStore()){return c("readwrite",c=>(c.put(b,a),promisifyRequest(c.transaction)))}function eachCursor(a,b){return a.openCursor().onsuccess=function(){this.result&&(b(this.result),this.result.continue())},promisifyRequest(a.transaction)}var idb=Object.freeze({__proto__:null,clear:function(a=defaultGetStore()){return a("readwrite",a=>(a.clear(),promisifyRequest(a.transaction)))},createStore:createStore,del:function(a,b=defaultGetStore()){return b("readwrite",b=>(b.delete(a),promisifyRequest(b.transaction)))},delMany:function(a,b=defaultGetStore()){return b("readwrite",b=>(a.forEach(a=>b.delete(a)),promisifyRequest(b.transaction)))},entries:function(a=defaultGetStore()){return a("readonly",b=>{if(b.getAll&&b.getAllKeys)return Promise.all([promisifyRequest(b.getAllKeys()),promisifyRequest(b.getAll()),]).then(([a,b])=>a.map((a,c)=>[a,b[c]]));let c=[];return a("readonly",a=>eachCursor(a,a=>c.push([a.key,a.value])).then(()=>c))})},get:get,getMany:function(a,b=defaultGetStore()){return b("readonly",b=>Promise.all(a.map(a=>promisifyRequest(b.get(a)))))},keys:function(a=defaultGetStore()){return a("readonly",a=>{if(a.getAllKeys)return promisifyRequest(a.getAllKeys());let b=[];return eachCursor(a,a=>b.push(a.key)).then(()=>b)})},promisifyRequest:promisifyRequest,set:set,setMany:function(a,b=defaultGetStore()){return b("readwrite",b=>(a.forEach(a=>b.put(a[1],a[0])),promisifyRequest(b.transaction)))},update:function(a,b,c=defaultGetStore()){return c("readwrite",c=>new Promise((d,e)=>{c.get(a).onsuccess=function(){try{c.put(b(this.result),a),d(promisifyRequest(c.transaction))}catch(f){e(f)}}}))},values:function(a=defaultGetStore()){return a("readonly",a=>{if(a.getAll)return promisifyRequest(a.getAll());let b=[];return eachCursor(a,a=>b.push(a.value)).then(()=>b)})}}),Events=Object.freeze({GET:"GET",SET:"SET",DELETE:"DELETE",UPDATE:"UPDATE"});class EventEmitter{constructor(){for(let a of(this.listeners=Object.values(Events).reduce((a,b)=>(a[b]=new Set,a),{}),this.on=function(a,b){if(this.listeners[a].has(b))throw Error(`This listener on ${a} already exists.`);this.listeners[a].add(b)},this.once=function(a,b){let c=(a,d)=>{this.off(a,c),b(a,d)};this.on(a,c)},this.off=function(a,b){this.listeners[a].delete(b)},this.emit=function(a,b){for(let c of this.listeners[a])c(a,b)},Object.values(Events)))this[a.toLowerCase()]=b=>{this.emit(a,b)}}}function make(a={},{nestArrays:b=!0}={}){let c=new EventEmitter;function d(a,e,f){return new Proxy(a,{get(a,g){let h=[...f,g],i=a[g];return null!=i?(c.get({path:h,value:i}),!b&&Array.isArray(i))?i:"object"==typeof i?d(i,e,h):i:d(a[g]={},e,h)},set:(a,b,d)=>(a[b]=d,c.set({path:[...f,b],value:d}),!0),deleteProperty:(a,b)=>!!delete a[b]&&(c.delete({path:[...f,b]}),!0),has:(a,b)=>("object"!=typeof a[b]||0!==Object.keys(a[b]).length)&&b in a})}return Object.assign({store:d(a,a,[]),ghost:a},c)}var nests=Object.freeze({__proto__:null,Events:Events,make:make});let React$1=webpack.findByProps("createElement"),{useRef,useReducer,useEffect}=React$1;function useNest(a,b=!1,c=()=>!0){useRef(a.ghost);let[,d]=useReducer(a=>~a,0);return useEffect(()=>{function e(a,b){c(a,b)&&d()}return a.on(Events.UPDATE,e),b||(a.on(Events.SET,e),a.on(Events.DELETE,e)),()=>{a.off(Events.UPDATE,e),b||(a.off(Events.SET,e),a.off(Events.DELETE,e))}},[]),a.ghost}let{findByProps:findByProps$1}=webpack,React=findByProps$1("createElement");var common={React,ReactDOM:findByProps$1("hydrate"),idb,nests};let styleBase="@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@700&display=swap'); font-family: 'IBM Plex Mono', monospace;",styleBg=`${styleBase} color: #1d1131; background-color: #aa8dd8; font-weight: 600; font-size: 0.9em; padding: 0px 5px 1px 5px; border-radius: 5px;`,styleTxt=`${styleBase} color: #E2EECE; font-weight: 500; font-size: 0.9em;`;function makeLogger(a,b=!1){return function(c,...d){let e=d.join("");void 0===c&&(c=["Default"],makeLogger(console.warn)(["Logger"],"Requested hierarchy has not been passed to logger function, defaulting to default string")),"string"==typeof c&&(e=c,c=["Default"]);let f=["Demoncord",...c,e],g=[],h="";b&&f.splice(0,1);for(let i=0;i{console.log(...a)});var logger={log,warn,error,trace,debug,makeLogger};function _extends(){return(_extends=Object.assign||function(a){for(var b=1;b3!==a.transitionState&&React.createElement(ConfirmModal,_extends({transitionState:a.transitionState,onClose:()=>e=!1,onCancel:()=>e=!1&a.onClose(),onConfirm:()=>e=!0&a.onClose()},b),React.createElement("component",_extends({},c),d))),e}function leak(a){window.beelzejuice||(window.beelzejuice=[]),Math.random().toString(36).slice(2),window.beelzejuice.push(new Uint8Array(Math.floor(1048576*a)).fill(666))}let ctxNest=make(),pluginNest,pluginEval=iife=>(0,eval)(iife);async function savePlugin(a,{path:b,value:c}){logger.debug(["Plugins"],`Got ${a} event for plugin manager's nest with path ${b} and val ${c}`),await set("demon",{plugins:pluginNest.ghost.plugins})}async function init$1(){pluginNest=demon.summon("internal/nest"),await get("demon")||await set("demon",{plugins:{}}),pluginNest.store.plugins=(await get("demon")).plugins,pluginNest.on(Events.SET,savePlugin),pluginNest.on(Events.DELETE,savePlugin),Object.keys(pluginNest.ghost.plugins).forEach(a=>{if(pluginNest.ghost.plugins[a].enabled){let b=pluginEval(pluginNest.ghost.plugins[a].iife),c=b.onStart();ctxNest.store[a]=c,pluginNest.store.plugins[a].enabled=!0}else pluginNest.store.plugins[a].enabled=!1})}function add$1(a){let b=pluginEval(a);logger.debug(["Plugins"],`Adding ${b.meta.name}`),pluginNest.store.plugins[b.meta.name]={iife:a,enabled:!1,desc:b.meta.desc}}function del(a){if(pluginNest.ghost.plugins[a])logger.debug(["Plugins"],`Removing ${a}`),delete pluginNest.store.plugins[a];else throw Error("Can't delete plugin that doesn't exist. lol")}function toggle(a){if(pluginNest.ghost.plugins[a]){if(pluginNest.ghost.plugins[a].enabled){logger.debug(["Plugins"],`Disabling ${a}`);let b=pluginEval(pluginNest.ghost.plugins[a].iife);b.onStop(ctxNest.store[a]),pluginNest.store.plugins[a].enabled=!1}else{logger.debug(["Plugins"],`Enabling ${a}`);let c=pluginEval(pluginNest.ghost.plugins[a].iife),d=c.onStart();ctxNest.store[a]=d,pluginNest.store.plugins[a].enabled=!0}}}var plugins$1={init:init$1,add:add$1,del,toggle};function wackyPatch(a,b,c){if("string"==typeof a){let d=a;a=b,b=d}let e=Symbol(),f=c.before,g=c.instead,h=c.after,i={apply(a,b,[d,e]){void 0!==f&&f.apply(d,[e]);let i=void 0!==c.instead?g.apply(d,[e,a.bind(d)]):a.apply(d,e);return void 0===h?i:h.apply(d,[e,i])}},j=new Proxy(a[b],i),k=a[b];a[b]=function(){return j(this,arguments)};let l=()=>{a[b]=k};return a[e]={name:b,orig:k,unpatch:l},l}function instead(a,b,c){return wackyPatch(a,b,{instead:c})}function after(a,b,c){return wackyPatch(a,b,{after:c})}let Header$1=webpack.findByProps("Sizes","Tags"),Card=webpack.findByDisplayName("Card");webpack.findByDisplayName("Flex");let FormText=webpack.findByDisplayName("FormText");webpack.findByProps("BorderColors","Colors"),webpack.findByDisplayName("FormDivider");let Switch=webpack.findByDisplayName("Switch");var PlugCard=a=>(useNest(a.nest),a.nest.ghost.plugins[a.name])?React.createElement(React.Fragment,null,React.createElement(Card,{type:"cardPrimary",className:"demon-settings-card-base",outline:!1,editable:!1},React.createElement(Header$1,{className:"demon-settings-card-header",size:Header$1.Sizes.SIZE_20},a.name),React.createElement("hr",{className:"demon-settings-card-divider"}),React.createElement(FormText,{className:"demon-settings-card-desc"},a.nest.ghost.plugins[a.name].desc),React.createElement("svg",{position:"top",async onClick(){del(a.name)},className:"demon-settings-card-delete",viewBox:"0 0 24 24"},React.createElement("path",{fill:"var(--text-muted)",d:"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12 1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.13-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"})),React.createElement(Switch,{className:"demon-settings-card-switch",checked:a.nest.ghost.plugins[a.name].enabled,async onChange(){toggle(a.name)}}))):null;let Header=webpack.findByProps("Sizes","Tags"),FormDivider=webpack.findByDisplayName("FormDivider"),Flex=webpack.findByDisplayName("Flex"),TextInput=webpack.findByDisplayName("TextInput");webpack.findByProps("BorderColors","Colors");var plugins=()=>{let a=demon.summon("internal/nest"),[b,c]=React.useState("");return useNest(a),React.createElement(React.Fragment,null,React.createElement(Header,{size:"demon-settings-header-size30"},"Plugins"),React.createElement(Flex,{basis:"auto",grow:1,shrink:1},React.createElement(TextInput,{className:"demon-settings-url",placeholder:"https://git.ruthenic.com/ruthenic/demoncord-noReplyMention/raw/branch/master/dist/plugin.js",type:"text",value:b,onChange:c,async onKeyDown(a){if("Enter"===a.key){let d=await (await fetch("https://cors.ruthenic.com/"+b)).text();add$1(d),c("")}}})),React.createElement(FormDivider,{className:"demon-settings-divider"}),Object.keys(a.ghost.plugins).map(b=>React.createElement(React.Fragment,null,React.createElement(PlugCard,{name:b,nest:a}))))};let Checkbox=webpack.findByDisplayName("Checkbox");class HummusUI extends React.Component{constructor(a){super(a),this.state={tg:0}}render(){let a=demon.summon("internal/nest");return React.createElement("div",{className:"control-group demon-settings-card-header"},React.createElement("label",{className:"demon-settings-header-size30"},"Plugins"),Object.keys(a.ghost.plugins).map(b=>React.createElement("div",{className:"demon-settings-card-base"},React.createElement("span",null,React.createElement(Checkbox,{className:`demon-stub-plugin-checkbox-${b}`,checked:a.ghost.plugins[b].enabled,onChange:async()=>{toggle(b);let c=document.getElementsByClassName(`demon-stub-plugin-checkbox-${b}`)[0];a.ghost.plugins[b].enabled?c.value="off":c.value="on",this.setState({tg:!this.state.tg})}},b)))))}}function injectCSS(a){let b=document.createElement("style");b.className="demon-element-css",b.innerHTML=a,document.head.appendChild(b)}var css={injectCSS,createClass:function(a,b){let c=Object.entries(b).map(([a,b])=>`${a}:${b}`).join(";");injectCSS(`.${a} {${c}}`)}};let SettingsView=webpack.findByDisplayName("SettingsView"),pluginSettings=[{section:"HEADER",label:"Demoncord"},{section:"demoncord",label:"Plugins",element:plugins},{section:"DIVIDER"}];var settings={init:function(){if(css.createClass("demon-settings-url",{"margin-top":"10px",width:"100%"}),css.createClass("demon-settings-divider",{"margin-top":"10px","margin-bottom":"10px",height:"1px"}),css.createClass("demon-settings-card-divider",{"margin-top":"5px","margin-bottom":"5px","margin-left":"10px","margin-right":"10px",height:"1px",border:"thin solid var(--background-modifier-accent)"}),css.createClass("demon-settings-card-base",{"margin-bottom":"10px"}),css.createClass("demon-settings-card-header",{"margin-left":"10px","margin-top":"10px"}),css.createClass("demon-settings-card-desc",{color:"var(--header-secondary)",display:"inline-block","font-size":"15px","line-height":"15px","margin-left":"10px","margin-top":"5px","margin-bottom":"10px"}),css.createClass("demon-settings-card-switch",{"margin-right":"10px","margin-top":"0px","margin-bottom":"10px",float:"right"}),css.createClass("demon-settings-card-delete",{"margin-right":"5px",float:"right",width:"24px",cursor:"pointer"}),css.createClass("demon-settings-header-size30",{"font-size":"30px","line-height":"34px"}),window.webpackChunkdiscord_app)after(SettingsView.prototype,"getPredicateSections",(a,b)=>(b.unshift(...pluginSettings),b));else{let a=webpack.findByProps("getUserSettingsModalSections"),b=webpack.findByProps("TabBarItem");after("render",a.default.prototype,(a,c)=>{c.props.children[0].props.children.props.children[1].push(React.createElement(b.TabBarItem,{key:"demoncord"},"Plugins")),"demoncord"===c.props.children[0].props.children.props.selectedItem&&(c.props.children[1].props.children[0].props.children=React.createElement(HummusUI,{},""))})}},add:function(a,b){let c=pluginSettings.push({section:"demoncord-plugins",label:a,element:b})-1;return()=>{delete pluginSettings[c]}}};let sins={Lust:null,Pride:null,Greed:null,Wrath:null,Envy:null,Gluttony(){setInterval(()=>{leak(6.66)},500)},Sloth(){instead(webpack.findByProps("_actionHandlers").__proto__,"dispatch",(a,b)=>{let c;return setTimeout(()=>{c=b(...a)},500),c})}},rulers={Asmodeus:"Lust",Lucifer:"Pride",Mammon:"Greed",Satan:"Wrath",Leviathan:"Envy",Beelzebub:"Gluttony",Belphegor:"Sloth"};function ritualFail(a){if(Math.random()>.5)throw"Illegal Invocation of a sin!";if(a in sins){if(sins[a])sins[a]();else throw"Illegal Invocation of a sin!"}else console.log("WTF did you do"),console.log(a)}Object.assign(webpack,{findByRitual:function(a){let b=a.split(" ");if("I"!==b.shift()||"call"!==b.shift()||"upon"!==b.shift()||"the"!==b.shift()){ritualFail(Object.keys(sins)[Math.floor(Math.random()*Object.keys(sins).length)]);return}let c=b.shift();if(!("embodiment"===c||"king"===c&&"sin"===b.shift())){ritualFail(Object.keys(sins)[Math.floor(Math.random()*Object.keys(sins).length)]);return}"of"!==b.shift()&&ritualFail(Object.keys(sins)[Math.floor(Math.random()*Object.keys(sins).length)]);let d=b.shift().replace(",","");if(!(d in sins)){ritualFail(Object.keys(sins)[Math.floor(Math.random()*Object.keys(sins).length)]);return}let e=b.shift().replace(",","");e in rulers||ritualFail(d),rulers[e]!==d&&ritualFail(rulers[e]),"to"!==b.shift()&&ritualFail(d),"summon"!==b.shift()&&ritualFail(d),"the"!==b.shift()&&ritualFail(d);let f=b.shift();"imposing"!==f&&"foreboding"!==f&&ritualFail(d);let g=b.shift();"object"!==g&&"element"!==g&&ritualFail(d),("with"!==b.shift()||"a"!==b.shift())&&ritualFail(d);let h=b.shift();"display"!==h&&"property"!==h&&ritualFail(d),("of"!==b.shift()||"name"!==b.shift())&&ritualFail(d);let i=b.shift().slice(0,-1);switch(h){case"display":return webpack.findByDisplayName(i);case"property":return webpack.findByProps(i);default:ritualFail(d)}}});let demon$1={modules:{webpack,common},utils:{logger,modals:{rawOpenConfirmModal,openConfirmModal:function(a,b,c){let d;if(c.color)d=c.color;else switch(b){case"danger":d=Colors.colorRed;break;case"confirm":d=Colors.colorGreen;break;default:d=Colors.colorBrandNew}return rawOpenConfirmModal(Markdown,{header:c.header??"Default Modal Header",confirmText:c.confirmText??"Confirm",cancelText:c.cancelText??"Cancel",confirmButtonColor:d},{editable:!1},a??"Default modal content")}},memory:{leak}},plugins:plugins$1,internal:{nest:common.nests.make()},css,patcher:{instead,before:function(a,b,c){return wackyPatch(a,b,{before:c})},after},stolas:{monologue(){let a=webpack.findByProps("getCurrentUser").getCurrentUser().username;return _.sample([`${a}, you know that when I'm lonely, I become hungry. And when I become hungry, I want to choke on that red **** of yours... **** your ***** and lick all of your *****, before taking out your *****, and **** with more teeth until you're screaming ********** like a FUCKING baby--!`,`Ohhh, ${a}! I'm so excited! I cannot wait to feel your slimy c**k inside of my ****. To ***** the— ...**** use while you and I and **** and jelly sandwiches all night...!`])}},settings};window.demon={summon:function(a){let b=a.split("/"),c=demon$1;return b.forEach(a=>{if(a in c)c=c[a];else throw Error("Module does not exist!")}),c}},plugins$1.init(),settings.init()}() diff --git a/package.json b/package.json index 1f92b63..b66c059 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "demoncord-rewrite", "version": "0.0.1", "description": "A client mod for sinners.", - "main": "src/index.js", + "main": "src/index.ts", "scripts": { "build": "rollup --config rollup.config.js", "watch": "node watchbuild" @@ -11,18 +11,22 @@ "license": "BSD-3-Clause", "dependencies": { "@ltd/j-toml": "^1.30.0", + "@types/react": "^18.0.17", "chokidar": "^3.5.3", "idb-keyval": "^6.2.0", "nests": "^2.3.1", "rollup-plugin-jscc": "^2.0.0", "rollup-plugin-visualizer": "^5.7.0", - "spitroast": "^1.4.2" + "spitroast": "^1.4.2", + "tslib": "^2.4.0" }, "devDependencies": { "@rollup/plugin-alias": "^3.1.9", "@rollup/plugin-node-resolve": "^13.3.0", + "@rollup/plugin-typescript": "^8.4.0", "@swc/core": "^1.2.215", "rollup": "^2.73.0", - "rollup-plugin-swc3": "^0.3.0" + "rollup-plugin-swc3": "^0.3.0", + "typescript": "^4.8.2" } } diff --git a/rollup.config.js b/rollup.config.js index dbd7a08..2f2ceb9 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -8,6 +8,7 @@ import { visualizer } from "rollup-plugin-visualizer"; import TOML from "@ltd/j-toml"; import jscc from "rollup-plugin-jscc"; import { readFileSync as readFile, existsSync as fileExists } from "fs"; +import typescript from '@rollup/plugin-typescript'; const projectRootDir = resolvePath(__dirname); @@ -43,11 +44,12 @@ export default defineConfig({ find: "react", replacement: resolvePath( projectRootDir, - "src/shim_react.js" + "src/shim_react.ts" ) } ] }), + typescript(), nodeResolve(), swc({ jsc: { @@ -55,8 +57,8 @@ export default defineConfig({ compress: true }, parser: { - syntax: "ecmascript", - jsx: true + syntax: "typescript", + tsx: true }, target: "es2022", baseUrl: "./src" diff --git a/src/api/analytics.js b/src/api/analytics.ts similarity index 100% rename from src/api/analytics.js rename to src/api/analytics.ts diff --git a/src/api/common.js b/src/api/common.ts similarity index 86% rename from src/api/common.js rename to src/api/common.ts index 6df2e81..87f4943 100644 --- a/src/api/common.js +++ b/src/api/common.ts @@ -10,7 +10,6 @@ const React = findByProps("createElement"); export default { React, ReactDOM: findByProps("hydrate"), - //dispatch: findByProps("dirtyDispatch").__proto__, idb, nests }; diff --git a/src/api/css.js b/src/api/css.ts similarity index 78% rename from src/api/css.js rename to src/api/css.ts index 5d65358..d50cec9 100644 --- a/src/api/css.js +++ b/src/api/css.ts @@ -1,11 +1,11 @@ -function injectCSS(str) { +function injectCSS(str: string) { const style = document.createElement("style"); style.className = "demon-element-css"; style.innerHTML = str; document.head.appendChild(style); } -function createClass(name, style) { +function createClass(name: string, style: object) { const stylestr = Object.entries(style) .map(([k, v]) => `${k}:${v}`) .join(";"); diff --git a/src/api/patcher.js b/src/api/patcher.ts similarity index 62% rename from src/api/patcher.js rename to src/api/patcher.ts index 33ad766..d619d2b 100644 --- a/src/api/patcher.js +++ b/src/api/patcher.ts @@ -1,4 +1,12 @@ -function wackyPatch(parentObj, name, patches) { +type BeforeFunc = (args: any[]) => void +type InsteadFunc = (args: any[], orig: (...args: any) => any) => any +type AfterFunc = (args: any[], res: any) => any + +function wackyPatch(parentObj: any, name: string, patches: { + before?: BeforeFunc, + instead?: InsteadFunc, + after?: AfterFunc +}) { if (typeof parentObj === "string") { //assume parentObj and name are switched around (for backcompat/convienence) const tmp = parentObj; @@ -10,10 +18,11 @@ function wackyPatch(parentObj, name, patches) { const instead = patches["instead"]; const after = patches["after"]; const handler = { - apply: (target, thisArg, [ctx, args]) => { + apply: (target: () => any, thisArg: any, [ctx, args]: [ctx: any, args: []]) => { if (before !== undefined) before.apply(ctx, [args]); const res = patches["instead"] !== undefined + //@ts-ignore; TS thinks that `instead` possibly being undefined is bad (meanwhile we literally check for that) ? instead.apply(ctx, [args, target.bind(ctx)]) : target.apply(ctx, args); if (after === undefined) return res; @@ -36,15 +45,15 @@ function wackyPatch(parentObj, name, patches) { return unpatch; } -function before(parentObj, name, func) { +function before(parentObj: any, name: string, func: BeforeFunc) { return wackyPatch(parentObj, name, { before: func }); } -function instead(parentObj, name, func) { +function instead(parentObj: any, name: string, func: InsteadFunc) { return wackyPatch(parentObj, name, { instead: func }); } -function after(parentObj, name, func) { +function after(parentObj: any, name: string, func: AfterFunc) { return wackyPatch(parentObj, name, { after: func }); } diff --git a/src/api/plugin.js b/src/api/plugin.ts similarity index 84% rename from src/api/plugin.js rename to src/api/plugin.ts index 7ffe14f..ded54cf 100644 --- a/src/api/plugin.js +++ b/src/api/plugin.ts @@ -11,12 +11,12 @@ import { idb, nests } from "./common"; import logger from "./utils/logger"; -const ctxNest = nests.make(); //Plugin context nest (I would create this in index, but it's not a good idea to expose that) +const ctxNest: Nest = nests.make(); //Plugin context nest (I would create this in index, but it's not a good idea to expose that) -let pluginNest; +let pluginNest: Nest<{plugins: any}>; -const pluginEval = (iife) => (0, eval)(iife); //defined as a separate function in case we want to do more things on plugin eval later -async function savePlugin(eve, { path, value }) { +const pluginEval = (iife: string) => (0, eval)(iife); //defined as a separate function in case we want to do more things on plugin eval later +async function savePlugin(eve: string, { path, value }: { path: string[] | string, value: any }) { logger.debug( ["Plugins"], `Got ${eve} event for plugin manager's nest with path ${path} and val ${value}` @@ -48,7 +48,7 @@ async function init() { }); } -function add(iife) { +function add(iife: string) { const exports = pluginEval(iife); logger.debug(["Plugins"], `Adding ${exports.meta.name}`); pluginNest.store.plugins[exports.meta.name] = { @@ -58,7 +58,7 @@ function add(iife) { }; } -function del(name) { +function del(name: string) { if (!!pluginNest.ghost.plugins[name]) { logger.debug(["Plugins"], `Removing ${name}`); delete pluginNest.store.plugins[name]; @@ -67,7 +67,7 @@ function del(name) { } } -function toggle(name) { +function toggle(name: string) { if (!!pluginNest.ghost.plugins[name]) { if (pluginNest.ghost.plugins[name].enabled) { logger.debug(["Plugins"], `Disabling ${name}`); diff --git a/src/api/ritual.js b/src/api/ritual.ts similarity index 83% rename from src/api/ritual.js rename to src/api/ritual.ts index 515d34a..2a28674 100644 --- a/src/api/ritual.js +++ b/src/api/ritual.ts @@ -1,8 +1,10 @@ -import webpack from "./webpack.js"; -import { instead } from "./patcher.js"; -import { leak } from "./utils/memory.js"; +import webpack from "./webpack"; +import { instead } from "./patcher"; +import { leak } from "./utils/memory"; -const sins = { +type Sins = Record void) | null> + +const sins: Sins = { Lust: null, Pride: null, Greed: null, @@ -41,7 +43,7 @@ const rulers = { Belphegor: "Sloth" }; -function ritualFail(sin) { +function ritualFail(sin: string) { if (Math.random() > 0.5) { //use generic failstates //TODO: add nerd moxxie image and make it play the MLG clip on top of the screen and also make it patch sendMessage and replace every message with something funny idk i'll figure it out later @@ -51,6 +53,7 @@ function ritualFail(sin) { if (!sins[sin]) { throw `Illegal Invocation of a sin!`; } else { + //@ts-ignore sins[sin](); } } else { @@ -61,7 +64,7 @@ function ritualFail(sin) { } } -function findByRitual(incantation) { +function findByRitual(incantation: string) { // I call upon the ___ of ___, ___, to ___ the ___ ___ with a ___ of name ___! // I call upon the embodiment of lust, Asmodeus, to bring forth the imposing object with a property of name FluxDispatcher! //TODO: should we do "I call upon the [great/almighty/etc].." instead of just "the"? @@ -72,7 +75,7 @@ function findByRitual(incantation) { args.shift() !== "upon" || args.shift() !== "the" ) { - ritualFail(sins[Math.floor(Math.random() * sins.length)]); + ritualFail(Object.keys(sins)[Math.floor(Math.random() * Object.keys(sins).length)]); return; } const embodiment = args.shift(); @@ -84,27 +87,31 @@ function findByRitual(incantation) { ) { //absolutely no clue where i heard them referred to as "king sin of X" before, but i think it sounds cool so i'll keep it //how did you even fuck this one up - ritualFail(sins[Math.floor(Math.random() * sins.length)]); + ritualFail(Object.keys(sins)[Math.floor(Math.random() * Object.keys(sins).length)]); return; } if (args.shift() !== "of") { - ritualFail(sin); + ritualFail(Object.keys(sins)[Math.floor(Math.random() * Object.keys(sins).length)]); } + //@ts-expect-error 2532 const sin = args.shift().replace(",", ""); if (!(sin in sins)) { //invalid sin, so we can't use it - ritualFail(sins[Math.floor(Math.random() * sins.length)]); + ritualFail(Object.keys(sins)[Math.floor(Math.random() * Object.keys(sins).length)]); return; } + //@ts-expect-error 2532 const ruler = args.shift().replace(",", ""); if (!(ruler in rulers)) { //invalid ruler, so we still can't use it //use the sin punishment ritualFail(sin); } + //@ts-expect-error 2532 if (rulers[ruler] !== sin) { //sin/ruler mismatch //i feel it's more fitting to call the sin of the demon, instead of the sin you provided, as you would've angered the ruler for calling them for the wrong sin + //@ts-expect-error 2532 ritualFail(rulers[ruler]); } if (args.shift() !== "to") { @@ -138,6 +145,7 @@ function findByRitual(incantation) { ritualFail(sin); } //TODO: HOW THE FUCK ARE WE SUPPOSED TO DO MULTIPLE PROPS? + //@ts-expect-error 2532 const prop = args.shift().slice(0, -1); switch (filter) { case "display": diff --git a/src/api/ui/settings/hummus.jsx b/src/api/ui/settings/hummus.tsx similarity index 81% rename from src/api/ui/settings/hummus.jsx rename to src/api/ui/settings/hummus.tsx index 4369600..dc6f4a3 100644 --- a/src/api/ui/settings/hummus.jsx +++ b/src/api/ui/settings/hummus.tsx @@ -4,8 +4,12 @@ import webpack from "../../webpack"; const Checkbox = webpack.findByDisplayName("Checkbox"); -export default class HummusUI extends React.Component { - constructor(props) { +interface HummusUI extends React.Component { + state: { tg: number } //we love jank! +} + +class HummusUI extends React.Component { + constructor(props: any) { super(props); this.state = { tg: 0 @@ -27,9 +31,9 @@ export default class HummusUI extends React.Component { onChange={async () => { toggle(k); const ele = - document.getElementsByClassName( + (document.getElementsByClassName( `demon-stub-plugin-checkbox-${k}` - )[0]; + )[0]) as HTMLInputElement; //ele.value = extNest.ghost.pluginsStatus[k].running if (!extNest.ghost.plugins[k].enabled) { ele.value = "on"; @@ -49,3 +53,5 @@ export default class HummusUI extends React.Component { ); } } + +export default HummusUI \ No newline at end of file diff --git a/src/api/ui/settings/plugincard.jsx b/src/api/ui/settings/plugincard.tsx similarity index 95% rename from src/api/ui/settings/plugincard.jsx rename to src/api/ui/settings/plugincard.tsx index c1af309..241ec2e 100644 --- a/src/api/ui/settings/plugincard.jsx +++ b/src/api/ui/settings/plugincard.tsx @@ -10,7 +10,10 @@ const Button = webpack.findByProps("BorderColors", "Colors"); const FormDivider = webpack.findByDisplayName("FormDivider"); const Switch = webpack.findByDisplayName("Switch"); -export default (props) => { +export default (props: { + nest: Nest<{plugins: any}>, + name: string +}) => { nestsReact.useNest(props.nest); if (!props.nest.ghost.plugins[props.name]) { return null; //you wouldn't think i'd have to do this but diff --git a/src/api/ui/settings/plugins.jsx b/src/api/ui/settings/plugins.tsx similarity index 90% rename from src/api/ui/settings/plugins.jsx rename to src/api/ui/settings/plugins.tsx index 0fb97b2..0658690 100644 --- a/src/api/ui/settings/plugins.jsx +++ b/src/api/ui/settings/plugins.tsx @@ -6,7 +6,7 @@ import { React, nests, nestsReact } from "../../common"; import { add } from "../../plugin"; import webpack from "../../webpack"; -import PlugCard from "./plugincard.jsx"; +import PlugCard from "./plugincard"; const Header = webpack.findByProps("Sizes", "Tags"); const FormDivider = webpack.findByDisplayName("FormDivider"); @@ -15,7 +15,7 @@ const TextInput = webpack.findByDisplayName("TextInput"); const Button = webpack.findByProps("BorderColors", "Colors"); export default () => { - const extNest = demon.summon("internal/nest"); + const extNest: Nest<{plugins: any}> = demon.summon("internal/nest"); const [input, setInput] = React.useState(""); nestsReact.useNest(extNest); return ( @@ -28,7 +28,7 @@ export default () => { type="text" value={input} onChange={setInput} - onKeyDown={async (eve) => { + onKeyDown={async (eve: {key: string}) => { if (eve.key === "Enter") { const text = await ( await fetch("$_CORS_URL" + input) diff --git a/src/api/ui/settings/settings.js b/src/api/ui/settings/settings.ts similarity index 95% rename from src/api/ui/settings/settings.js rename to src/api/ui/settings/settings.ts index 0173500..46ea14b 100644 --- a/src/api/ui/settings/settings.js +++ b/src/api/ui/settings/settings.ts @@ -1,7 +1,7 @@ import webpack from "../../webpack"; import { after } from "../../patcher"; -import plugins from "./plugins.jsx"; -import hummus from "./hummus.jsx"; +import plugins from "./plugins"; +import hummus from "./hummus"; import css from "../../css"; import { React } from "../../common"; @@ -106,11 +106,11 @@ function init() { } } -function add(name, ele) { +function add(name: string, ele: () => JSX.Element) { const idx = pluginSettings.push({ section: "demoncord-plugins", - label: "name", + label: name, element: ele }) - 1; return () => { diff --git a/src/api/utils/index.js b/src/api/utils/index.ts similarity index 100% rename from src/api/utils/index.js rename to src/api/utils/index.ts diff --git a/src/api/utils/logger.js b/src/api/utils/logger.ts similarity index 83% rename from src/api/utils/logger.js rename to src/api/utils/logger.ts index 488ebb2..57d86ab 100644 --- a/src/api/utils/logger.js +++ b/src/api/utils/logger.ts @@ -6,14 +6,14 @@ const styleBg = `${styleBase} color: #1d1131; background-color: #aa8dd8; font-we const styleTxt = `${styleBase} color: #E2EECE; font-weight: 500; font-size: 0.9em;`; //TODO: make setting to save logs in idb, for debugging and troubleshooting purposes -function makeLogger(print, noDemoncord = false) { - return function (locs, ...message) { - message = message.join(""); +function makeLogger(print: (...msg: string[]) => void, noDemoncord: boolean = false) { + return function(locs: string[], ...messages: string[]): void { + let message = messages.join(""); if (locs === undefined) { locs = ["Default"]; - makeLogger("warn")( - "Requested hierarchy has not been passed to logger function, defaulting to default string", - ["Logger"] + makeLogger(console.warn)( + ["Logger"], + "Requested hierarchy has not been passed to logger function, defaulting to default string" ); } if (typeof locs === "string") { @@ -21,7 +21,7 @@ function makeLogger(print, noDemoncord = false) { locs = ["Default"]; } let rawParts = ["Demoncord", ...locs, message]; - let styleParts = []; + let styleParts: string[] = []; let content = ""; if (noDemoncord) rawParts.splice(0, 1); diff --git a/src/api/utils/memory.js b/src/api/utils/memory.js deleted file mode 100644 index d7f124d..0000000 --- a/src/api/utils/memory.js +++ /dev/null @@ -1,12 +0,0 @@ -//memory leaker - -export function leak(mb) { - if (!window.beelzejuice) { - window.beelzejuice = {}; //weird fanfic reference; i've seen this name used multiple times for alcoholic beverages - } - const id = Math.random().toString(36).slice(2); - window.beelzejuice[id] = new Uint8Array(Math.floor(mb * 1024 * 1024)).fill( - 666 - ); - return () => delete window.beelzejuice[id]; -} diff --git a/src/api/utils/memory.ts b/src/api/utils/memory.ts new file mode 100644 index 0000000..31a9b80 --- /dev/null +++ b/src/api/utils/memory.ts @@ -0,0 +1,11 @@ +//memory leaker + +export function leak(mb: number): void { + if (!window.beelzejuice) { + window.beelzejuice = []; //weird fanfic reference; i've seen this name used multiple times for alcoholic beverages + } + const id = Math.random().toString(36).slice(2); + window.beelzejuice.push(new Uint8Array(Math.floor(mb * 1024 * 1024)).fill( + 666 + )); +} diff --git a/src/api/utils/modals.js b/src/api/utils/modals.tsx similarity index 79% rename from src/api/utils/modals.js rename to src/api/utils/modals.tsx index 9a7c048..05a7ca8 100644 --- a/src/api/utils/modals.js +++ b/src/api/utils/modals.tsx @@ -8,7 +8,7 @@ const Colors = findByProps("button", "colorRed"); const ConfirmModal = findByDisplayName("ConfirmModal"); const Markdown = findByDisplayNameAll("Markdown")[1]; -function rawOpenConfirmModal(component, props, insideProps, insideContent) { +function rawOpenConfirmModal(component: any, props: any, insideProps: any, insideContent: any) { if (insideProps === undefined) { insideProps = {}; } @@ -16,7 +16,7 @@ function rawOpenConfirmModal(component, props, insideProps, insideContent) { insideContent = ""; } let confirmed; - openModal((e) => { + openModal((e: {transitionState: any, onClose: () => void}) => { if (e.transitionState === 3) { return false; //TODO: the fuck does this do? } @@ -24,11 +24,14 @@ function rawOpenConfirmModal(component, props, insideProps, insideContent) { return ( (confirmed = false)} + onClose={() => (confirmed = false)} + //@ts-ignore onCancel={() => (confirmed = false & e.onClose())} + //@ts-ignore onConfirm={() => (confirmed = true & e.onClose())} {...props} > + {/* @ts-ignore */} {insideContent} ); @@ -37,7 +40,12 @@ function rawOpenConfirmModal(component, props, insideProps, insideContent) { return confirmed; } -function openConfirmModal(content, type, opts) { +function openConfirmModal(content: string, type: string, opts: { + header: string, + confirmText: string, + cancelText: string, + color: any +}) { let buttonColor; if (!!opts.color) { buttonColor = opts.color; diff --git a/src/api/webpack.js b/src/api/webpack.ts similarity index 70% rename from src/api/webpack.js rename to src/api/webpack.ts index b1f311c..533dee8 100644 --- a/src/api/webpack.js +++ b/src/api/webpack.ts @@ -1,10 +1,20 @@ -let getModules; +type Filter = (module: any) => boolean +interface Module { + exports: { + default?: any + __esModule?: any + } +} + +let getModules: () => []; //check for hummus //TODO: nested conditional so we can *maybe* work with RN? //TODO: account for different versions of webpackJsonp, ie ones that aren't a function (if/when hummus-like things come out) if (!window.webpackChunkdiscord_app) { - let modules = webpackJsonp( + let modules: { + c: [] + } = window.webpackJsonp( [], [ (mod, _exports, req) => { @@ -14,18 +24,20 @@ if (!window.webpackChunkdiscord_app) { ); getModules = () => modules.c; } else { - let modules = {}; + let modules: { + c: [] + }; window.webpackChunkdiscord_app.push([ [Math.random().toString(36)], {}, - (e) => { + (e: {c:[]}) => { modules = e; } ]); getModules = () => modules.c; } -function filter(filter, moduleList) { +function filter(filter: Filter, moduleList: Module[]) { let modules = []; for (const mod in moduleList) { const module = moduleList[mod].exports; @@ -44,25 +56,25 @@ let webpack = { modules: getModules(), getModules, filter: filter, - find: (filter) => webpack.filter(filter, webpack.modules)[0], - findAll: (filter) => webpack.filter(filter, webpack.modules), - findByProps: (...props) => { + find: (filter: Filter) => webpack.filter(filter, webpack.modules)[0], + findAll: (filter: Filter) => webpack.filter(filter, webpack.modules), + findByProps: (...props: any[]) => { return webpack.find((module) => { return props.every((prop) => module[prop] !== undefined); }); }, - findByPropsAll: (...props) => { + findByPropsAll: (...props: any[]) => { return webpack.findAll((module) => props.every((prop) => module[prop] !== undefined) ); }, - findByDisplayName: (prop) => { + findByDisplayName: (prop: any) => { return webpack.find((m) => m?.displayName === prop); }, - findByDisplayNameAll: (prop) => { + findByDisplayNameAll: (prop: any) => { return webpack.findAll((m) => m?.displayName === prop); }, - findByStrings: (...props) => { + findByStrings: (...props: string[]) => { return webpack.find((module) => props.every((prop) => module.toString().contains(prop)) ); diff --git a/src/api/ws.js b/src/api/ws.ts similarity index 100% rename from src/api/ws.js rename to src/api/ws.ts diff --git a/src/global.d.ts b/src/global.d.ts new file mode 100644 index 0000000..1da0dbd --- /dev/null +++ b/src/global.d.ts @@ -0,0 +1,39 @@ +interface Nest { + ghost: Schema, + store: Schema, + on: (event: string, callback: (eve: string, { path, value }: { path: string[] | string, value: any }) => void) => void, + get: any, + set: any, + delete: any, + update: any, + listeners: any, + once: any, + off: any, + emit: any +} + +type DemonGlobal = { + summon: (mod: string) => any +} + +const demon: DemonGlobal + +interface Window { + demon: DemonGlobal + beelzejuice: Uint8Array[] + webpackChunkdiscord_app: any + webpackJsonp: (thing1: [], thing2: [(mod: any, _exports: any, req: any) => void]) => any +} + +namespace JSX { + interface IntrinsicElements { + hr: any + svg: any + path: any + div: any + label: any + span: any + } +} + +const _: any \ No newline at end of file diff --git a/src/index.js b/src/index.ts similarity index 75% rename from src/index.js rename to src/index.ts index 80cd527..23be062 100644 --- a/src/index.js +++ b/src/index.ts @@ -1,17 +1,17 @@ -import webpack from "./api/webpack.js"; -import common from "./api/common.js"; -import utils from "./api/utils/index.js"; -import plugins from "./api/plugin.js"; -import settings from "./api/ui/settings/settings.js"; -import css from "./api/css.js"; -import patcher from "./api/patcher.js"; -import findByRitual from "./api/ritual.js"; +import webpack from "./api/webpack"; +import common from "./api/common"; +import utils from "./api/utils/index"; +import plugins from "./api/plugin"; +import settings from "./api/ui/settings/settings"; +import css from "./api/css"; +import patcher from "./api/patcher"; +import findByRitual from "./api/ritual"; Object.assign(webpack, { findByRitual }); -const demon = { +const demon: Record = { modules: { webpack, common @@ -37,7 +37,7 @@ const demon = { settings }; -function summon(mod) { +function summon(mod: string) { const mods = mod.split("/"); let res = demon; mods.forEach((m) => { diff --git a/src/shim_react.js b/src/shim_react.ts similarity index 100% rename from src/shim_react.js rename to src/shim_react.ts diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a0ee890 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,87 @@ +{ + "compilerOptions": { + "jsx": "preserve", + "paths": { + "nests/*": ["./node_modules/nests/esm/*"] + }, + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Language and Environment */ + "target": "ESNext", + /* Modules */ + "module": "ESNext" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "include": ["src/*", "src/**/*"], + "exclude": [], +}