diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index f20158d..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Build and Zip -on: [push, workflow_dispatch] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - uses: pnpm/action-setup@v2 - with: - version: latest - - - name: Install dependencies - run: pnpm install - - - name: Build app - run: pnpm run build - - - name: Create Zip File - uses: vimtor/action-zip@v1 - with: - files: ./dist ./patches - dest: goofmod.zip - - - name: Upload Zip - uses: svenstaro/upload-release-action@2.7.0 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: ${{ github.workspace }}/goofmod.zip - asset_name: goofmod.zip - tag: "Build" - overwrite: true diff --git a/.github/workflows/zip&publish.yml b/.github/workflows/zip&publish.yml new file mode 100644 index 0000000..7b5ef4d --- /dev/null +++ b/.github/workflows/zip&publish.yml @@ -0,0 +1,24 @@ +name: Zip and Publish +on: [workflow_dispatch] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Create Zip File + uses: vimtor/action-zip@v1 + with: + files: ./patches + dest: patches.zip + + - name: Upload Zip + uses: svenstaro/upload-release-action@2.7.0 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ${{ github.workspace }}/patches.zip + asset_name: patches.zip + tag: "Build" + overwrite: true diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..d23208f --- /dev/null +++ b/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 5980d91..7728843 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,2 @@ -# GoofMod -A helper mod for GoofCord. - -Based on https://github.com/ArmCord/Mod and https://github.com/Vendicated/Vencord +# GoofCord Scripts +A collection of default GoofCord helper scripts \ No newline at end of file diff --git a/fix.bat b/fix.bat index 6486a7d..9b4edab 100644 --- a/fix.bat +++ b/fix.bat @@ -1,15 +1,9 @@ @echo off -:: Windows script to copy built goofmod into the scripts folder -:: Also, copy all files from the "./patches" folder to the destination +:: Windows script to copy patches into the scripts folder -set "source_goofmod=.\dist\0_goofmod.js" set "source_patches=.\patches" set "destination_goofmod=C:\Users\Administrator\AppData\Roaming\GoofCord\scripts" - -:: Copy goofmod.js -copy "%source_goofmod%" "%destination_goofmod%" - :: Copy all files from the "patches" folder xcopy "%source_patches%" "%destination_goofmod%" /E /Y \ No newline at end of file diff --git a/package.json b/package.json deleted file mode 100644 index d380d84..0000000 --- a/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "GoofMod", - "version": "1.0.0", - "description": "GoofCord helper mod", - "main": "dist/BL0_goofmod.js", - "type": "module", - "scripts": { - "build": "rollup -c", - "dev": "rollup -cw" - }, - "author": "smartfrigde", - "license": "OSL-3.0", - "dependencies": { - "rollup": "^3.29.2", - "rollup-plugin-serve": "^2.0.2" - }, - "packageManager": "pnpm@8.5.0", - "devDependencies": { - "@rollup/plugin-node-resolve": "^15.2.1" - } -} diff --git a/patches/AL10_screenshareQuality.js b/patches/AL10_screenshareQuality.js index 356f3cf..58f8858 100644 --- a/patches/AL10_screenshareQuality.js +++ b/patches/AL10_screenshareQuality.js @@ -5,8 +5,8 @@ */ function patchScreenshareQuality(responseParams) { - window.goofmod.log("[ScreenshareQualityPatch] Loading screenshare quality patch..."); - const StreamQuality = window.goofmod.find(m => m.prototype?.getVideoQuality); + console.log("[ScreenshareQualityPatch] Loading screenshare quality patch..."); + const StreamQuality = Vencord.Webpack.find(m => m.prototype?.getVideoQuality); const ASPECT_RATIO = screen.width / screen.height; const width = Math.round(responseParams.height * ASPECT_RATIO); @@ -57,8 +57,9 @@ function patchScreenshareQuality(responseParams) { // Setting default settings patchScreenshareQuality({ - framerate: 60, + framerate: 30, height: 1080 }); -window.patchScreenshareQuality = patchScreenshareQuality; \ No newline at end of file +window.ScreenshareQuality = {}; +window.ScreenshareQuality.patchScreenshareQuality = patchScreenshareQuality; \ No newline at end of file diff --git a/patches/AL11_messageEncryption.js b/patches/AL11_messageEncryption.js new file mode 100644 index 0000000..19bc7dc --- /dev/null +++ b/patches/AL11_messageEncryption.js @@ -0,0 +1,5 @@ +/** + * @name MessageEncryption + * @description Encrypts messages + * @version 1.0.0 + */ \ No newline at end of file diff --git a/patches/BL10_consoleSupressor.js b/patches/BL10_consoleSupressor.js index 5d5ac88..6270beb 100644 --- a/patches/BL10_consoleSupressor.js +++ b/patches/BL10_consoleSupressor.js @@ -1,34 +1,18 @@ /** * @name ConsoleSupressor - * @description Suppresses messages in the console that are not necessary - * @version 1.0.0 + * @description Suppresses Discord logger + * @version 2.0.0 */ -// All the messages here are useless and just spam the console -// Some filters are not included to keep the list small -const messagesToFilter = [ - "[Gate", // [GatewaySocket] - "[RTC", // [RTCConnection] - "[Anal", // [Analytics] - "[Unif", // [UnifiedConnection] - "[Str" // [StreamTile] -]; - -function filterConsoleMessages() { - const originalConsoleMethods = {}; - - // Iterate through all console methods and filter messages - Object.keys(console).forEach(method => { - originalConsoleMethods[method] = console[method]; - - console[method] = function () { - const message = arguments[0]; - if (message && messagesToFilter.some(msg => message.includes(msg))) { - return; +const patches = [ + { + find: "=console)[", + replacement: [ + { + match: /\(.=console.{53}/, + replace: "" } - originalConsoleMethods[method].apply(console, arguments); - }; - }); -} - -filterConsoleMessages(); \ No newline at end of file + ], + plugin: 'ConsoleSupressor' + } +]; \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index 91de5f7..0000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,158 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -dependencies: - rollup: - specifier: ^3.29.2 - version: 3.29.2 - rollup-plugin-serve: - specifier: ^2.0.2 - version: 2.0.2 - -devDependencies: - '@rollup/plugin-node-resolve': - specifier: ^15.2.1 - version: 15.2.1(rollup@3.29.2) - -packages: - - /@rollup/plugin-node-resolve@15.2.1(rollup@3.29.2): - resolution: {integrity: sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.4(rollup@3.29.2) - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-builtin-module: 3.2.1 - is-module: 1.0.0 - resolve: 1.22.6 - rollup: 3.29.2 - dev: true - - /@rollup/pluginutils@5.0.4(rollup@3.29.2): - resolution: {integrity: sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.1 - estree-walker: 2.0.2 - picomatch: 2.3.1 - rollup: 3.29.2 - dev: true - - /@types/estree@1.0.1: - resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} - dev: true - - /@types/resolve@1.20.2: - resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - dev: true - - /builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - dev: true - - /deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - dev: true - - /estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: true - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - optional: true - - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true - - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - dependencies: - function-bind: 1.1.1 - dev: true - - /is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - dependencies: - builtin-modules: 3.3.0 - dev: true - - /is-core-module@2.13.0: - resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} - dependencies: - has: 1.0.3 - dev: true - - /is-module@1.0.0: - resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - dev: true - - /mime@3.0.0: - resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} - engines: {node: '>=10.0.0'} - hasBin: true - dev: false - - /opener@1.5.2: - resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} - hasBin: true - dev: false - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /resolve@1.22.6: - resolution: {integrity: sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==} - hasBin: true - dependencies: - is-core-module: 2.13.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /rollup-plugin-serve@2.0.2: - resolution: {integrity: sha512-ALqyTbPhlf7FZ5RzlbDvMYvbKuCHWginJkTo6dMsbgji/a78IbsXox+pC83HENdkTRz8OXrTj+aShp3+3ratpg==} - dependencies: - mime: 3.0.0 - opener: 1.5.2 - dev: false - - /rollup@3.29.2: - resolution: {integrity: sha512-CJouHoZ27v6siztc21eEQGo0kIcE5D1gVPA571ez0mMYb25LGYGKnVNXpEj5MGlepmDWGXNjDB5q7uNiPHC11A==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} - hasBin: true - optionalDependencies: - fsevents: 2.3.3 - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index 84a1943..0000000 --- a/rollup.config.js +++ /dev/null @@ -1,24 +0,0 @@ -import serve from 'rollup-plugin-serve'; -import { nodeResolve } from '@rollup/plugin-node-resolve'; -const prod = !process.env.ROLLUP_WATCH; -export default [{ - input: './src/lib.js', - output: { - file: './dist/BL0_goofmod.js', - format: 'iife', - name: 'goofmod', - freeze: false, - sourcemap: false, - compact: true, - }, - plugins: [ - !prod && serve({ - contentBase: 'dist', - port: 1234, - headers: { - 'Access-Control-Allow-Origin': '*', - } - }), nodeResolve() - ] - }]; - \ No newline at end of file diff --git a/src/lib.js b/src/lib.js deleted file mode 100644 index fe465b4..0000000 --- a/src/lib.js +++ /dev/null @@ -1,195 +0,0 @@ -import {cache, subscriptions} from "./webpack" -import "./spitroast/index.js"; - -export let SelectedGuildStore; -export let FluxDispatcher; -export let SettingsRouter; - -window.goofmod = {}; - -export function log(data) { - console.log("%c[GoofMod]", "color: #5865f2;", data); -} -window.goofmod.log = log; - -log("Loading...") - -export const filters = { - byProps: (...props) => - props.length === 1 - ? m => m[props[0]] !== void 0 - : m => props.every(p => m[p] !== void 0), - - byCode: (...code) => m => { - if (typeof m !== "function") return false; - const s = Function.prototype.toString.call(m); - for (const c of code) { - if (!s.includes(c)) return false; - } - return true; - }, - byStoreName: (name) => m => - m.constructor?.displayName === name -}; - -/** - * Find the first module that matches the filter - */ -export function find(filter, getDefault = true, isWaitFor = false) { - if (typeof filter !== "function") - throw new Error("Invalid filter. Expected a function got " + typeof filter); - - for (const key in cache) { - const mod = cache[key]; - if (!mod?.exports) continue; - - if (filter(mod.exports)) { - return isWaitFor ? [mod.exports, Number(key)] : mod.exports; - } - - if (typeof mod.exports !== "object") continue; - - if (mod.exports.default && filter(mod.exports.default)) { - const found = getDefault ? mod.exports.default : mod.exports; - return isWaitFor ? [found, Number(key)] : found; - } - - // the length check makes search about 20% faster - for (const nestedMod in mod.exports) if (nestedMod.length <= 3) { - const nested = mod.exports[nestedMod]; - if (nested && filter(nested)) { - return isWaitFor ? [nested, Number(key)] : nested; - } - } - } - - if (!isWaitFor) { - const err = new Error("Didn't find module matching this filter"); - console.warn(err); - } - - return isWaitFor ? [null, null] : null; -} -window.goofmod.find = find; - -/** - * Find the first module that has the specified properties - */ -export function findByProps(...props) { - return find(filters.byProps(...props)); -} -window.goofmod.findByProps = findByProps; - -const GET_KEY = Symbol.for("GoofMod_Helper.lazy.get"); -const CACHED_KEY = Symbol.for("GoofMod_Helper.lazy.cached"); -const handler = {}; - -/** - * Wraps the result of {@see makeLazy} in a Proxy you can consume as if it wasn't lazy. - * On first property access, the lazy is evaluated - * @param factory lazy factory - * @returns Proxy - * - * Note that the example below exists already as an api, see {@link findByPropsLazy} - * @example const mod = proxyLazy(() => findByProps("blah")); console.log(mod.blah); - */ -export function proxyLazy(factory) { - const proxyDummy = Object.assign(function () { - }, { - [CACHED_KEY]: void 0, - [GET_KEY]: () => proxyDummy[CACHED_KEY] ??= factory(), - }); - - return new Proxy(proxyDummy, handler); -} - -/** - * find but lazy - */ -export function findLazy(filter, getDefault = true) { - return proxyLazy(() => find(filter, getDefault)); -} -window.goofmod.findLazy = findLazy; - -/** - * Finds a mangled module by the provided code "code" (must be unique and can be anywhere in the module) - * then maps it into an easily usable module via the specified mappers - * @param code Code snippet - * @param mappers Mappers to create the non mangled exports - * @returns Unmangled exports as specified in mappers - * - * @example mapMangledModule("headerIdIsManaged:", { - * openModal: filters.byCode("headerIdIsManaged:"), - * closeModal: filters.byCode("key==") - * }) - */ -export function mapMangledModule(code, mappers) { - const exports = {}; - - const id = findModuleId(code); - if (id === null) - return exports; - - const mod = wreq(id); - outer: - for (const key in mod) { - const member = mod[key]; - for (const newName in mappers) { - // if the current mapper matches this module - if (mappers[newName](member)) { - exports[newName] = member; - continue outer; - } - } - } - return exports; -} - -/** - * Same as {@link mapMangledModule} but lazy - */ -export function mapMangledModuleLazy(code, mappers) { - return proxyLazy(() => mapMangledModule(code, mappers)); -} - -/** - * Wait for a module that matches the provided filter to be registered, - * then call the callback with the module as the first argument - */ -export function waitFor(filter, callback) { - if (typeof filter === "string") - filter = filters.byProps(filter); - else if (Array.isArray(filter)) - filter = filters.byProps(...filter); - else if (typeof filter !== "function") - throw new Error("filter must be a string, string[] or function, got " + typeof filter); - - const [existing, id] = find(filter, true, true); - if (existing) return void callback(existing, id); - - subscriptions.set(filter, callback); -} - -export function waitForStore(name, cb) { - waitFor(filters.byStoreName(name), cb); -} - -export const NavigationRouter = mapMangledModuleLazy("transitionToGuild - ", { - transitionTo: filters.byCode("transitionTo -"), - transitionToGuild: filters.byCode("transitionToGuild -"), - goBack: filters.byCode("goBack()"), - goForward: filters.byCode("goForward()"), -}); - -waitFor(["dispatch", "subscribe"], m => { - FluxDispatcher = m; - const cb = () => { - m.unsubscribe("CONNECTION_OPEN", cb); - _resolveReady(); - }; - m.subscribe("CONNECTION_OPEN", cb); -}); - -waitForStore("SelectedGuildStore", m => SelectedGuildStore = m); -waitFor(["open", "saveAccountChanges"], m => SettingsRouter = m); -waitFor(["open", "saveAccountChanges"], m => SettingsRouter = m); \ No newline at end of file diff --git a/src/spitroast/LICENSE b/src/spitroast/LICENSE deleted file mode 100644 index 670154e..0000000 --- a/src/spitroast/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/spitroast/getPatchFunc.js b/src/spitroast/getPatchFunc.js deleted file mode 100644 index aff3216..0000000 --- a/src/spitroast/getPatchFunc.js +++ /dev/null @@ -1,50 +0,0 @@ -// curried - getPatchFunc("before")(...) -// allows us to apply an argument while leaving the rest open much cleaner. -// functional programming strikes again! -- sink -import hook from "./hook.js"; -import { patchedObjects } from "./shared.js"; -import { unpatch } from "./unpatch.js"; -// creates a hook if needed, else just adds one to the patches array -export default (patchType) => (funcName, funcParent, callback, oneTime = false) => { - if (typeof funcParent[funcName] !== "function") - throw new Error(`${funcName} is not a function in ${funcParent.constructor.name}`); - if (!patchedObjects.has(funcParent)) - patchedObjects.set(funcParent, {}); - const parentInjections = patchedObjects.get(funcParent); - if (!parentInjections[funcName]) { - const origFunc = funcParent[funcName]; - // note to future me optimising for size: extracting new Map() to a func increases size --sink - parentInjections[funcName] = { - o: origFunc, - b: new Map(), - i: new Map(), - a: new Map(), - }; - const runHook = (ctxt, args, construct) => { - const ret = hook(funcName, funcParent, args, ctxt, construct); - if (oneTime) - unpatchThisPatch(); - return ret; - }; - const replaceProxy = new Proxy(origFunc, { - apply: (_, ctxt, args) => runHook(ctxt, args, false), - construct: (_, args) => runHook(origFunc, args, true), - get: (target, prop, receiver) => prop == "toString" - ? origFunc.toString.bind(origFunc) - : Reflect.get(target, prop, receiver), - }); - // this works around breaking some async find implementation which listens for assigns via proxy - // see comment in unpatch.ts - const success = Reflect.defineProperty(funcParent, funcName, { - value: replaceProxy, - configurable: true, - writable: true, - }); - if (!success) - funcParent[funcName] = replaceProxy; - } - const hookId = Symbol(); - const unpatchThisPatch = () => unpatch(funcParent, funcName, hookId, patchType); - parentInjections[funcName][patchType].set(hookId, callback); - return unpatchThisPatch; -}; diff --git a/src/spitroast/hook.js b/src/spitroast/hook.js deleted file mode 100644 index c4308dc..0000000 --- a/src/spitroast/hook.js +++ /dev/null @@ -1,30 +0,0 @@ -// calls relevant patches and returns the final result -import { patchedObjects } from "./shared.js"; -export default function (funcName, funcParent, funcArgs, -// the value of `this` to apply -ctxt, -// if true, the function is actually constructor -isConstruct) { - const patch = patchedObjects.get(funcParent)?.[funcName]; - // This is in the event that this function is being called after all patches are removed. - if (!patch) - return isConstruct - ? Reflect.construct(funcParent[funcName], funcArgs, ctxt) - : funcParent[funcName].apply(ctxt, funcArgs); - // Before patches - for (const hook of patch.b.values()) { - const maybefuncArgs = hook.call(ctxt, funcArgs); - if (Array.isArray(maybefuncArgs)) - funcArgs = maybefuncArgs; - } - // Instead patches - let workingRetVal = [...patch.i.values()].reduce((prev, current) => (...args) => current.call(ctxt, args, prev), - // This calls the original function - (...args) => isConstruct - ? Reflect.construct(patch.o, args, ctxt) - : patch.o.apply(ctxt, args))(...funcArgs); - // After patches - for (const hook of patch.a.values()) - workingRetVal = hook.call(ctxt, funcArgs, workingRetVal) ?? workingRetVal; - return workingRetVal; -} diff --git a/src/spitroast/index.js b/src/spitroast/index.js deleted file mode 100644 index 6a1c5d9..0000000 --- a/src/spitroast/index.js +++ /dev/null @@ -1,9 +0,0 @@ -import getPatchFunc from "./getPatchFunc.js"; -import { unpatchAll } from "./unpatch.js"; - -window.spitroast = {}; - -window.spitroast.before = getPatchFunc("b"); -window.spitroast.instead = getPatchFunc("i"); -window.spitroast.after = getPatchFunc("a"); -window.spitroast.unpatchAll = unpatchAll; diff --git a/src/spitroast/shared.js b/src/spitroast/shared.js deleted file mode 100644 index 615ef53..0000000 --- a/src/spitroast/shared.js +++ /dev/null @@ -1,3 +0,0 @@ -// we use this array multiple times -export const patchTypes = ["a", "b", "i"]; -export const patchedObjects = new Map(); diff --git a/src/spitroast/unpatch.js b/src/spitroast/unpatch.js deleted file mode 100644 index 0530906..0000000 --- a/src/spitroast/unpatch.js +++ /dev/null @@ -1,32 +0,0 @@ -import { patchedObjects, patchTypes } from "./shared.js"; -export function unpatch(funcParent, funcName, hookId, type) { - const patchedObject = patchedObjects.get(funcParent); - const patch = patchedObject?.[funcName]; - if (!patch?.[type].has(hookId)) - return false; - patch[type].delete(hookId); - // If there are no more hooks for every type, remove the patch - if (patchTypes.every((t) => patch[t].size === 0)) { - // reflect defineproperty is like object defineproperty - // but instead of erroring it returns if it worked or not. - // this is more easily minifiable, hence its use. -- sink - const success = Reflect.defineProperty(funcParent, funcName, { - value: patch.o, - writable: true, - configurable: true, - }); - if (!success) - funcParent[funcName] = patch.o; - delete patchedObject[funcName]; - } - if (Object.keys(patchedObject).length == 0) - patchedObjects.delete(funcParent); - return true; -} -export function unpatchAll() { - for (const [parentObject, patchedObject] of patchedObjects.entries()) - for (const funcName in patchedObject) - for (const hookType of patchTypes) - for (const hookId of patchedObject[funcName]?.[hookType].keys() ?? []) - unpatch(parentObject, funcName, hookId, hookType); -} diff --git a/src/webpack.js b/src/webpack.js deleted file mode 100644 index 859cde9..0000000 --- a/src/webpack.js +++ /dev/null @@ -1,161 +0,0 @@ -/** - * @name GoofMod - * @description Helper mod for GoofCord - * @version 1.0.0 - */ - -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2023 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ -export const subscriptions = new Map(); -export const listeners = new Set(); -export let cache, wreq; -let webpackChunk; -const WEBPACK_CHUNK = "webpackChunkdiscord_app"; - -function _initWebpack(instance) { - if (cache !== void 0) throw "no."; - - wreq = instance.push([[Symbol("GoofMod_Helper")], {}, r => r]); - cache = wreq.c; - instance.pop(); -} - -function patchPush() { - function handlePush(chunk) { - try { - const modules = chunk[1]; - for (const id in modules) { - let mod = modules[id]; - // Discords Webpack chunks for some ungodly reason contain random - // newlines. Cyn recommended this workaround and it seems to work fine, - // however this could potentially break code, so if anything goes weird, - // this is probably why. - // Additionally, `[actual newline]` is one less char than "\n", so if Discord - // ever targets newer browsers, the minifier could potentially use this trick and - // cause issues. - let code = mod.toString().replaceAll("\n", ""); - // a very small minority of modules use function() instead of arrow functions, - // but, unnamed toplevel functions aren't valid. However 0, function() makes it a statement - if (code.startsWith("function(")) { - code = "0," + code; - } - const originalMod = mod; - - const factory = modules[id] = function (module, exports, require) { - try { - mod(module, exports, require); - } catch (err) { - // Just rethrow discord errors - if (mod === originalMod) throw err; - - console.error("Error in patched chunk", err); - return void originalMod(module, exports, require); - } - - // There are (at the time of writing) 11 modules exporting the window - // Make these non enumerable to improve webpack search performance - if (module.exports === window) { - Object.defineProperty(require.c, id, { - value: require.c[id], - enumerable: false, - configurable: true, - writable: true - }); - return; - } - - const numberId = Number(id); - - for (const callback of listeners) { - try { - callback(exports, numberId); - } catch (err) { - console.error("Error in webpack listener", err); - } - } - - for (const [filter, callback] of subscriptions) { - try { - if (filter(exports)) { - subscriptions.delete(filter); - callback(exports, numberId); - } else if (typeof exports === "object") { - if (exports.default && filter(exports.default)) { - subscriptions.delete(filter); - callback(exports.default, numberId); - } - - for (const nested in exports) if (nested.length <= 3) { - if (exports[nested] && filter(exports[nested])) { - subscriptions.delete(filter); - callback(exports[nested], numberId); - } - } - } - } catch (err) { - console.error("Error while firing callback for webpack chunk", err); - } - } - } - - // for some reason throws some error on which calling .toString() leads to infinite recursion - // when you force load all chunks??? - try { - factory.toString = () => mod.toString(); - factory.original = originalMod; - } catch { - } - - - } - } catch (err) { - console.error("Error in handlePush", err); - } - - return handlePush.original.call(window[WEBPACK_CHUNK], chunk); - } - - handlePush.original = window[WEBPACK_CHUNK].push; - Object.defineProperty(window[WEBPACK_CHUNK], "push", { - get: () => handlePush, - set: v => (handlePush.original = v), - configurable: true - }); -} - -if (window[WEBPACK_CHUNK]) { - console.info(`Patching ${WEBPACK_CHUNK}.push (was already existant, likely from cache!)`); - _initWebpack(window[WEBPACK_CHUNK]); - patchPush(); -} else { - Object.defineProperty(window, WEBPACK_CHUNK, { - get: () => webpackChunk, - set: v => { - if (v?.push !== Array.prototype.push) { - console.info(`Patching ${WEBPACK_CHUNK}.push`); - _initWebpack(v); - patchPush(); - delete window[WEBPACK_CHUNK]; - window[WEBPACK_CHUNK] = v; - } - webpackChunk = v; - }, - configurable: true - }); -} -