From 1368c25824f3a0ef43457a5473085184a52f1523 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Thu, 23 Mar 2023 04:37:32 +0100 Subject: ci: Auto generate plugin json --- .github/workflows/build.yml | 3 + .github/workflows/reportBrokenPlugins.yml | 2 +- package.json | 2 + pnpm-lock.yaml | 290 ++++++++++++++++++++++++++++++ scripts/generatePluginList.ts | 191 ++++++++++++++++++++ scripts/generateReport.ts | 285 +++++++++++++++++++++++++++++ src/plugins/richerCider.desktop.tsx | 67 ------- src/plugins/viewIcons.tsx | 20 +-- test/generateReport.ts | 285 ----------------------------- 9 files changed, 782 insertions(+), 363 deletions(-) create mode 100644 scripts/generatePluginList.ts create mode 100644 scripts/generateReport.ts delete mode 100644 src/plugins/richerCider.desktop.tsx delete mode 100644 test/generateReport.ts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c264821..b7a95cf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,6 +37,9 @@ jobs: - name: Build run: pnpm build --standalone + - name: Generate plugin list + run: pnpm generatePluginJson dist/plugins.json + - name: Clean up obsolete files run: | rm -rf dist/extension* Vencord.user.css diff --git a/.github/workflows/reportBrokenPlugins.yml b/.github/workflows/reportBrokenPlugins.yml index 719eca7..2e927bb 100644 --- a/.github/workflows/reportBrokenPlugins.yml +++ b/.github/workflows/reportBrokenPlugins.yml @@ -36,7 +36,7 @@ jobs: export PATH="$PWD/node_modules/.bin:$PATH" export CHROMIUM_BIN=$(which chromium-browser) - esbuild test/generateReport.ts > dist/report.mjs + esbuild scripts/generateReport.ts > dist/report.mjs node dist/report.mjs >> $GITHUB_STEP_SUMMARY env: DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }} diff --git a/package.json b/package.json index 763189e..c6975a4 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "scripts": { "build": "node scripts/build/build.mjs", "buildWeb": "node --require=./scripts/suppressExperimentalWarnings.js scripts/build/buildWeb.mjs", + "generatePluginJson": "tsx scripts/generatePluginList.ts", "inject": "node scripts/runInstaller.mjs", "lint": "eslint . --ext .js,.jsx,.ts,.tsx", "lint-styles": "stylelint \"src/**/*.css\"", @@ -59,6 +60,7 @@ "standalone-electron-types": "^1.0.0", "stylelint": "^14.16.1", "stylelint-config-standard": "^29.0.0", + "tsx": "^3.12.6", "type-fest": "^3.5.3", "typescript": "^4.9.4" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac7aca7..30ce7bb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,7 @@ specifiers: standalone-electron-types: ^1.0.0 stylelint: ^14.16.1 stylelint-config-standard: ^29.0.0 + tsx: ^3.12.6 type-fest: ^3.5.3 typescript: ^4.9.4 @@ -67,6 +68,7 @@ devDependencies: standalone-electron-types: 1.0.0 stylelint: 14.16.1 stylelint-config-standard: 29.0.0_stylelint@14.16.1 + tsx: 3.12.6 type-fest: 3.5.3 typescript: 4.9.4 @@ -104,6 +106,27 @@ packages: postcss-selector-parser: 6.0.11 dev: true + /@esbuild-kit/cjs-loader/2.4.2: + resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==} + dependencies: + '@esbuild-kit/core-utils': 3.1.0 + get-tsconfig: 4.4.0 + dev: true + + /@esbuild-kit/core-utils/3.1.0: + resolution: {integrity: sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw==} + dependencies: + esbuild: 0.17.12 + source-map-support: 0.5.21 + dev: true + + /@esbuild-kit/esm-loader/2.5.5: + resolution: {integrity: sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==} + dependencies: + '@esbuild-kit/core-utils': 3.1.0 + get-tsconfig: 4.4.0 + dev: true + /@esbuild/android-arm/0.15.18: resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==} engines: {node: '>=12'} @@ -113,6 +136,96 @@ packages: dev: true optional: true + /@esbuild/android-arm/0.17.12: + resolution: {integrity: sha512-E/sgkvwoIfj4aMAPL2e35VnUJspzVYl7+M1B2cqeubdBhADV4uPon0KCc8p2G+LqSJ6i8ocYPCqY3A4GGq0zkQ==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64/0.17.12: + resolution: {integrity: sha512-WQ9p5oiXXYJ33F2EkE3r0FRDFVpEdcDiwNX3u7Xaibxfx6vQE0Sb8ytrfQsA5WO6kDn6mDfKLh6KrPBjvkk7xA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64/0.17.12: + resolution: {integrity: sha512-m4OsaCr5gT+se25rFPHKQXARMyAehHTQAz4XX1Vk3d27VtqiX0ALMBPoXZsGaB6JYryCLfgGwUslMqTfqeLU0w==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64/0.17.12: + resolution: {integrity: sha512-O3GCZghRIx+RAN0NDPhyyhRgwa19MoKlzGonIb5hgTj78krqp9XZbYCvFr9N1eUxg0ZQEpiiZ4QvsOQwBpP+lg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64/0.17.12: + resolution: {integrity: sha512-5D48jM3tW27h1qjaD9UNRuN+4v0zvksqZSPZqeSWggfMlsVdAhH3pwSfQIFJwcs9QJ9BRibPS4ViZgs3d2wsCA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64/0.17.12: + resolution: {integrity: sha512-OWvHzmLNTdF1erSvrfoEBGlN94IE6vCEaGEkEH29uo/VoONqPnoDFfShi41Ew+yKimx4vrmmAJEGNoyyP+OgOQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64/0.17.12: + resolution: {integrity: sha512-A0Xg5CZv8MU9xh4a+7NUpi5VHBKh1RaGJKqjxe4KG87X+mTjDE6ZvlJqpWoeJxgfXHT7IMP9tDFu7IZ03OtJAw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm/0.17.12: + resolution: {integrity: sha512-WsHyJ7b7vzHdJ1fv67Yf++2dz3D726oO3QCu8iNYik4fb5YuuReOI9OtA+n7Mk0xyQivNTPbl181s+5oZ38gyA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64/0.17.12: + resolution: {integrity: sha512-cK3AjkEc+8v8YG02hYLQIQlOznW+v9N+OI9BAFuyqkfQFR+DnDLhEM5N8QRxAUz99cJTo1rLNXqRrvY15gbQUg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32/0.17.12: + resolution: {integrity: sha512-jdOBXJqcgHlah/nYHnj3Hrnl9l63RjtQ4vn9+bohjQPI2QafASB5MtHAoEv0JQHVb/xYQTFOeuHnNYE1zF7tYw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-loong64/0.15.18: resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==} engines: {node: '>=12'} @@ -122,6 +235,114 @@ packages: dev: true optional: true + /@esbuild/linux-loong64/0.17.12: + resolution: {integrity: sha512-GTOEtj8h9qPKXCyiBBnHconSCV9LwFyx/gv3Phw0pa25qPYjVuuGZ4Dk14bGCfGX3qKF0+ceeQvwmtI+aYBbVA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el/0.17.12: + resolution: {integrity: sha512-o8CIhfBwKcxmEENOH9RwmUejs5jFiNoDw7YgS0EJTF6kgPgcqLFjgoc5kDey5cMHRVCIWc6kK2ShUePOcc7RbA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64/0.17.12: + resolution: {integrity: sha512-biMLH6NR/GR4z+ap0oJYb877LdBpGac8KfZoEnDiBKd7MD/xt8eaw1SFfYRUeMVx519kVkAOL2GExdFmYnZx3A==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64/0.17.12: + resolution: {integrity: sha512-jkphYUiO38wZGeWlfIBMB72auOllNA2sLfiZPGDtOBb1ELN8lmqBrlMiucgL8awBw1zBXN69PmZM6g4yTX84TA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x/0.17.12: + resolution: {integrity: sha512-j3ucLdeY9HBcvODhCY4b+Ds3hWGO8t+SAidtmWu/ukfLLG/oYDMaA+dnugTVAg5fnUOGNbIYL9TOjhWgQB8W5g==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64/0.17.12: + resolution: {integrity: sha512-uo5JL3cgaEGotaqSaJdRfFNSCUJOIliKLnDGWaVCgIKkHxwhYMm95pfMbWZ9l7GeW9kDg0tSxcy9NYdEtjwwmA==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64/0.17.12: + resolution: {integrity: sha512-DNdoRg8JX+gGsbqt2gPgkgb00mqOgOO27KnrWZtdABl6yWTST30aibGJ6geBq3WM2TIeW6COs5AScnC7GwtGPg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64/0.17.12: + resolution: {integrity: sha512-aVsENlr7B64w8I1lhHShND5o8cW6sB9n9MUtLumFlPhG3elhNWtE7M1TFpj3m7lT3sKQUMkGFjTQBrvDDO1YWA==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64/0.17.12: + resolution: {integrity: sha512-qbHGVQdKSwi0JQJuZznS4SyY27tYXYF0mrgthbxXrZI3AHKuRvU+Eqbg/F0rmLDpW/jkIZBlCO1XfHUBMNJ1pg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64/0.17.12: + resolution: {integrity: sha512-zsCp8Ql+96xXTVTmm6ffvoTSZSV2B/LzzkUXAY33F/76EajNw1m+jZ9zPfNJlJ3Rh4EzOszNDHsmG/fZOhtqDg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32/0.17.12: + resolution: {integrity: sha512-FfrFjR4id7wcFYOdqbDfDET3tjxCozUgbqdkOABsSFzoZGFC92UK7mg4JKRc/B3NNEf1s2WHxJ7VfTdVDPN3ng==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64/0.17.12: + resolution: {integrity: sha512-JOOxw49BVZx2/5tW3FqkdjSD/5gXYeVGPDcB0lvap0gLQshkh1Nyel1QazC+wNxus3xPlsYAgqU1BUmrmCvWtw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@eslint/eslintrc/1.3.3: resolution: {integrity: sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -563,6 +784,10 @@ packages: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} dev: true + /buffer-from/1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + /buffer/5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} dependencies: @@ -1047,6 +1272,36 @@ packages: esbuild-windows-arm64: 0.15.18 dev: true + /esbuild/0.17.12: + resolution: {integrity: sha512-bX/zHl7Gn2CpQwcMtRogTTBf9l1nl+H6R8nUbjk+RuKqAE3+8FDulLA+pHvX7aA7Xe07Iwa+CWvy9I8Y2qqPKQ==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.17.12 + '@esbuild/android-arm64': 0.17.12 + '@esbuild/android-x64': 0.17.12 + '@esbuild/darwin-arm64': 0.17.12 + '@esbuild/darwin-x64': 0.17.12 + '@esbuild/freebsd-arm64': 0.17.12 + '@esbuild/freebsd-x64': 0.17.12 + '@esbuild/linux-arm': 0.17.12 + '@esbuild/linux-arm64': 0.17.12 + '@esbuild/linux-ia32': 0.17.12 + '@esbuild/linux-loong64': 0.17.12 + '@esbuild/linux-mips64el': 0.17.12 + '@esbuild/linux-ppc64': 0.17.12 + '@esbuild/linux-riscv64': 0.17.12 + '@esbuild/linux-s390x': 0.17.12 + '@esbuild/linux-x64': 0.17.12 + '@esbuild/netbsd-x64': 0.17.12 + '@esbuild/openbsd-x64': 0.17.12 + '@esbuild/sunos-x64': 0.17.12 + '@esbuild/win32-arm64': 0.17.12 + '@esbuild/win32-ia32': 0.17.12 + '@esbuild/win32-x64': 0.17.12 + dev: true + /escape-string-regexp/1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} @@ -1400,6 +1655,14 @@ packages: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: true @@ -1411,6 +1674,10 @@ packages: pump: 3.0.0 dev: true + /get-tsconfig/4.4.0: + resolution: {integrity: sha512-0Gdjo/9+FzsYhXCEFueo2aY1z1tpXrxWZzP7k8ul9qt1U5o8rYJwTJYmaeHdrVosYIVYkOy2iwCJ9FdpocJhPQ==} + dev: true + /get-value/2.0.6: resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} engines: {node: '>=0.10.0'} @@ -2467,6 +2734,13 @@ packages: urix: 0.1.0 dev: true + /source-map-support/0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + /source-map-url/0.4.1: resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} deprecated: See https://github.com/lydell/source-map-url#deprecated @@ -2477,6 +2751,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + /spdx-correct/3.1.1: resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} dependencies: @@ -2739,6 +3018,17 @@ packages: typescript: 4.9.4 dev: true + /tsx/3.12.6: + resolution: {integrity: sha512-q93WgS3lBdHlPgS0h1i+87Pt6n9K/qULIMNYZo07nSeu2z5QE2CellcAZfofVXBo2tQg9av2ZcRMQ2S2i5oadQ==} + hasBin: true + dependencies: + '@esbuild-kit/cjs-loader': 2.4.2 + '@esbuild-kit/core-utils': 3.1.0 + '@esbuild-kit/esm-loader': 2.5.5 + optionalDependencies: + fsevents: 2.3.2 + dev: true + /type-check/0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} diff --git a/scripts/generatePluginList.ts b/scripts/generatePluginList.ts new file mode 100644 index 0000000..1f66c3d --- /dev/null +++ b/scripts/generatePluginList.ts @@ -0,0 +1,191 @@ +/* + * 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 . +*/ + +import { Dirent, readdirSync, readFileSync, writeFileSync } from "fs"; +import { access, readFile } from "fs/promises"; +import { join } from "path"; +import { BigIntLiteral, createSourceFile, Identifier, isArrayLiteralExpression, isCallExpression, isExportAssignment, isIdentifier, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isStringLiteral, isVariableStatement, NamedDeclaration, NodeArray, ObjectLiteralExpression, ScriptTarget, StringLiteral, SyntaxKind } from "typescript"; + +interface Dev { + name: string; + id: string; +} + +interface PluginData { + name: string; + description: string; + authors: Dev[]; + dependencies: string[]; + hasPatches: boolean; + hasCommands: boolean; + required: boolean; + enabledByDefault: boolean; + target: "desktop" | "web" | "dev"; +} + +const devs = {} as Record; + +function getName(node: NamedDeclaration) { + return node.name && isIdentifier(node.name) ? node.name.text : undefined; +} + +function hasName(node: NamedDeclaration, name: string) { + return getName(node) === name; +} + +function getObjectProp(node: ObjectLiteralExpression, name: string) { + const prop = node.properties.find(p => hasName(p, name)); + if (prop && isPropertyAssignment(prop)) return prop.initializer; + return prop; +} + +function parseDevs() { + const file = createSourceFile("constants.ts", readFileSync("src/utils/constants.ts", "utf8"), ScriptTarget.Latest); + + for (const child of file.getChildAt(0).getChildren()) { + if (!isVariableStatement(child)) continue; + + const devsDeclaration = child.declarationList.declarations.find(d => hasName(d, "Devs")); + if (!devsDeclaration?.initializer || !isCallExpression(devsDeclaration.initializer)) continue; + + const value = devsDeclaration.initializer.arguments[0]; + + if (!isObjectLiteralExpression(value)) return; + + for (const prop of value.properties) { + const name = (prop.name as Identifier).text; + const value = isPropertyAssignment(prop) ? prop.initializer : prop; + + if (!isObjectLiteralExpression(value)) throw new Error(`Failed to parse devs: ${name} is not an object literal`); + + devs[name] = { + name: (getObjectProp(value, "name") as StringLiteral).text, + id: (getObjectProp(value, "id") as BigIntLiteral).text.slice(0, -1) + }; + } + + return; + } + + throw new Error("Could not find Devs constant"); +} + +async function parseFile(fileName: string) { + const file = createSourceFile(fileName, await readFile(fileName, "utf8"), ScriptTarget.Latest); + + const fail = (reason: string) => { + return new Error(`Invalid plugin ${fileName}, because ${reason}`); + }; + + for (const node of file.getChildAt(0).getChildren()) { + if (!isExportAssignment(node) || !isCallExpression(node.expression)) continue; + + const call = node.expression; + if (!isIdentifier(call.expression) || call.expression.text !== "definePlugin") continue; + + const pluginObj = node.expression.arguments[0]; + if (!isObjectLiteralExpression(pluginObj)) throw fail("no object literal passed to definePlugin"); + + const data = { + hasPatches: false, + hasCommands: false, + enabledByDefault: false, + required: false, + } as PluginData; + + for (const prop of pluginObj.properties) { + const key = getName(prop); + const value = isPropertyAssignment(prop) ? prop.initializer : prop; + + switch (key) { + case "name": + case "description": + if (!isStringLiteral(value)) throw fail(`${key} is not a string literal`); + data[key] = value.text; + break; + case "patches": + data.hasPatches = true; + break; + case "commands": + data.hasCommands = true; + break; + case "authors": + if (!isArrayLiteralExpression(value)) throw fail("authors is not an array literal"); + data.authors = value.elements.map(e => { + if (!isPropertyAccessExpression(e)) throw fail("authors array contains non-property access expressions"); + return devs[getName(e)!]; + }); + break; + case "dependencies": + if (!isArrayLiteralExpression(value)) throw fail("dependencies is not an array literal"); + const { elements } = value; + if (elements.some(e => !isStringLiteral(e))) throw fail("dependencies array contains non-string elements"); + data.dependencies = (elements as NodeArray).map(e => e.text); + break; + case "required": + case "enabledByDefault": + data[key] = value.kind === SyntaxKind.TrueKeyword; + if (!data[key] && value.kind !== SyntaxKind.FalseKeyword) throw fail(`${key} is not a boolean literal`); + break; + } + } + + if (!data.name || !data.description || !data.authors) throw fail("name, description or authors are missing"); + + const fileBits = fileName.split("."); + if (fileBits.length > 2 && ["ts", "tsx"].includes(fileBits.at(-1)!)) { + const mod = fileBits.at(-2)!; + if (!["web", "desktop", "dev"].includes(mod)) throw fail(`invalid target ${fileBits.at(-2)}`); + data.target = mod as any; + } + + return data; + } + + throw fail("no default export called 'definePlugin' found"); +} + +async function getEntryPoint(dirent: Dirent) { + const base = join("./src/plugins", dirent.name); + if (!dirent.isDirectory()) return base; + + for (const name of ["index.ts", "index.tsx"]) { + const full = join(base, name); + try { + await access(full); + return full; + } catch { } + } + + throw new Error(`${dirent.name}: Couldn't find entry point`); +} + +(async () => { + parseDevs(); + const plugins = readdirSync("./src/plugins", { withFileTypes: true }).filter(d => d.name !== "index.ts"); + + const promises = plugins.map(async dirent => parseFile(await getEntryPoint(dirent))); + + const data = JSON.stringify(await Promise.all(promises)); + + if (process.argv.length > 2) { + writeFileSync(process.argv[2], data); + } else { + console.log(data); + } +})(); diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts new file mode 100644 index 0000000..d55cc8a --- /dev/null +++ b/scripts/generateReport.ts @@ -0,0 +1,285 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2022 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 . +*/ + +// eslint-disable-next-line spaced-comment +/// +// eslint-disable-next-line spaced-comment +/// + +import { readFileSync } from "fs"; +import pup, { JSHandle } from "puppeteer-core"; + +for (const variable of ["DISCORD_TOKEN", "CHROMIUM_BIN"]) { + if (!process.env[variable]) { + console.error(`Missing environment variable ${variable}`); + process.exit(1); + } +} + +const CANARY = process.env.USE_CANARY === "true"; + +const browser = await pup.launch({ + headless: true, + executablePath: process.env.CHROMIUM_BIN +}); + +const page = await browser.newPage(); +await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"); + +function maybeGetError(handle: JSHandle) { + return (handle as JSHandle)?.getProperty("message") + .then(m => m.jsonValue()); +} + +const report = { + badPatches: [] as { + plugin: string; + type: string; + id: string; + match: string; + error?: string; + }[], + badStarts: [] as { + plugin: string; + error: string; + }[], + otherErrors: [] as string[] +}; + +function toCodeBlock(s: string) { + s = s.replace(/```/g, "`\u200B`\u200B`"); + return "```" + s + " ```"; +} + +async function printReport() { + console.log("# Vencord Report" + (CANARY ? " (Canary)" : "")); + console.log(); + + console.log("## Bad Patches"); + report.badPatches.forEach(p => { + console.log(`- ${p.plugin} (${p.type})`); + console.log(` - ID: \`${p.id}\``); + console.log(` - Match: ${toCodeBlock(p.match)}`); + if (p.error) console.log(` - Error: ${toCodeBlock(p.error)}`); + }); + + console.log(); + + console.log("## Bad Starts"); + report.badStarts.forEach(p => { + console.log(`- ${p.plugin}`); + console.log(` - Error: ${toCodeBlock(p.error)}`); + }); + + console.log("## Discord Errors"); + report.otherErrors.forEach(e => { + console.log(`- ${toCodeBlock(e)}`); + }); + + if (process.env.DISCORD_WEBHOOK) { + // this code was written almost entirely by Copilot xD + await fetch(process.env.DISCORD_WEBHOOK, { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + description: "Here's the latest Vencord Report!", + username: "Vencord Reporter" + (CANARY ? " (Canary)" : ""), + avatar_url: "https://cdn.discordapp.com/icons/1015060230222131221/f0204a918c6c9c9a43195997e97d8adf.webp", + embeds: [ + { + title: "Bad Patches", + description: report.badPatches.map(p => { + const lines = [ + `**__${p.plugin} (${p.type}):__**`, + `ID: \`${p.id}\``, + `Match: ${toCodeBlock(p.match)}` + ]; + if (p.error) lines.push(`Error: ${toCodeBlock(p.error)}`); + return lines.join("\n"); + }).join("\n\n") || "None", + color: report.badPatches.length ? 0xff0000 : 0x00ff00 + }, + { + title: "Bad Starts", + description: report.badStarts.map(p => { + const lines = [ + `**__${p.plugin}:__**`, + toCodeBlock(p.error) + ]; + return lines.join("\n"); + } + ).join("\n\n") || "None", + color: report.badStarts.length ? 0xff0000 : 0x00ff00 + }, + { + title: "Discord Errors", + description: toCodeBlock(report.otherErrors.join("\n")), + color: report.otherErrors.length ? 0xff0000 : 0x00ff00 + } + ] + }) + }).then(res => { + if (!res.ok) console.error(`Webhook failed with status ${res.status}`); + else console.error("Posted to Discord Webhook successfully"); + }); + } +} + +page.on("console", async e => { + const level = e.type(); + const args = e.args(); + + const firstArg = (await args[0]?.jsonValue()); + if (firstArg === "PUPPETEER_TEST_DONE_SIGNAL") { + await browser.close(); + await printReport(); + process.exit(); + } + + const isVencord = (await args[0]?.jsonValue()) === "[Vencord]"; + const isDebug = (await args[0]?.jsonValue()) === "[PUP_DEBUG]"; + + if (isVencord) { + // make ci fail + process.exitCode = 1; + + const jsonArgs = await Promise.all(args.map(a => a.jsonValue())); + const [, tag, message] = jsonArgs; + const cause = await maybeGetError(args[3]); + + switch (tag) { + case "WebpackInterceptor:": + const [, plugin, type, id, regex] = (message as string).match(/Patch by (.+?) (had no effect|errored|found no module) \(Module id is (.+?)\): (.+)/)!; + report.badPatches.push({ + plugin, + type, + id, + match: regex, + error: cause + }); + break; + case "PluginManager:": + const [, name] = (message as string).match(/Failed to start (.+)/)!; + report.badStarts.push({ + plugin: name, + error: cause + }); + break; + } + } else if (isDebug) { + console.error(e.text()); + } else if (level === "error") { + const text = e.text(); + if (!text.startsWith("Failed to load resource: the server responded with a status of")) { + console.error("Got unexpected error", text); + report.otherErrors.push(text); + } + } +}); + +page.on("error", e => console.error("[Error]", e)); +page.on("pageerror", e => console.error("[Page Error]", e)); + +await page.setBypassCSP(true); + +function runTime(token: string) { + console.error("[PUP_DEBUG]", "Starting test..."); + + try { + // spoof languages to not be suspicious + Object.defineProperty(navigator, "languages", { + get: function () { + return ["en-US", "en"]; + }, + }); + + + // Monkey patch Logger to not log with custom css + // @ts-ignore + Vencord.Util.Logger.prototype._log = function (level, levelColor, args) { + if (level === "warn" || level === "error") + console[level]("[Vencord]", this.name + ":", ...args); + }; + + // force enable all plugins and patches + Vencord.Plugins.patches.length = 0; + Object.values(Vencord.Plugins.plugins).forEach(p => { + // Needs native server to run + if (p.name === "WebRichPresence (arRPC)") return; + + p.required = true; + p.patches?.forEach(patch => { + patch.plugin = p.name; + delete patch.predicate; + if (!Array.isArray(patch.replacement)) + patch.replacement = [patch.replacement]; + Vencord.Plugins.patches.push(patch); + }); + }); + + Vencord.Webpack.waitFor( + "loginToken", + m => { + console.error("[PUP_DEBUG]", "Logging in with token..."); + m.loginToken(token); + } + ); + + // force load all chunks + Vencord.Webpack.onceReady.then(() => setTimeout(async () => { + console.error("[PUP_DEBUG]", "Webpack is ready!"); + + const { wreq } = Vencord.Webpack; + + console.error("[PUP_DEBUG]", "Loading all chunks..."); + const ids = Function("return" + wreq.u.toString().match(/\{.+\}/s)![0])(); + for (const id in ids) { + const isWasm = await fetch(wreq.p + wreq.u(id)) + .then(r => r.text()) + .then(t => t.includes(".module.wasm")); + + if (!isWasm) + await wreq.e(id as any); + + await new Promise(r => setTimeout(r, 100)); + } + console.error("[PUP_DEBUG]", "Finished loading chunks!"); + + for (const patch of Vencord.Plugins.patches) { + if (!patch.all) { + new Vencord.Util.Logger("WebpackInterceptor").warn(`Patch by ${patch.plugin} found no module (Module id is -): ${patch.find}`); + } + } + setTimeout(() => console.log("PUPPETEER_TEST_DONE_SIGNAL"), 1000); + }, 1000)); + } catch (e) { + console.error("[PUP_DEBUG]", "A fatal error occured"); + console.error("[PUP_DEBUG]", e); + process.exit(1); + } +} + +await page.evaluateOnNewDocument(` + ${readFileSync("./dist/browser.js", "utf-8")} + + ;(${runTime.toString()})(${JSON.stringify(process.env.DISCORD_TOKEN)}); +`); + +await page.goto(CANARY ? "https://canary.discord.com/login" : "https://discord.com/login"); diff --git a/src/plugins/richerCider.desktop.tsx b/src/plugins/richerCider.desktop.tsx deleted file mode 100644 index 8b6fb5e..0000000 --- a/src/plugins/richerCider.desktop.tsx +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 OpenAsar - * - * 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 . -*/ - -import { Link } from "@components/Link"; -import definePlugin from "@utils/types"; -import { Forms } from "@webpack/common"; -const appIds = [ - "911790844204437504", - "886578863147192350", - "1020414178047041627", - "1032800329332445255" -]; -export default definePlugin({ - name: "richerCider", - description: "Enhances Cider (More details in info button) by adding the \"Listening to\" type prefix to the user's rich presence when an applicable ID is found.", - authors: [{ - id: 191621342473224192n, - name: "cryptofyre", - }], - patches: [ - { - find: '.displayName="LocalActivityStore"', - replacement: { - match: /LOCAL_ACTIVITY_UPDATE:function\((\i)\)\{/, - replace: "$&$self.patchActivity($1.activity);", - } - } - ], - settingsAboutComponent: () => ( - <> - Install Cider to use this Plugin - - Follow the link to our website to get Cider up and running, and then enable the plugin. - -

- What is Cider? - - Cider is an open-source and community oriented Apple Music client for Windows, macOS, and Linux. - -

- Recommended Optional Plugins - - I'd recommend using TimeBarAllActivities alongside this plugin to give off a much better visual to the eye (Keep in mind this only affects your client and will not show for other users) - - - ), - patchActivity(activity: any) { - if (appIds.includes(activity.application_id)) { - activity.type = 2; /* LISTENING type */ - } - }, -}); diff --git a/src/plugins/viewIcons.tsx b/src/plugins/viewIcons.tsx index 26f2902..7d56538 100644 --- a/src/plugins/viewIcons.tsx +++ b/src/plugins/viewIcons.tsx @@ -19,7 +19,7 @@ import { Devs } from "@utils/constants"; import { LazyComponent } from "@utils/misc"; import { ModalRoot, ModalSize, openModal } from "@utils/modal"; -import { PluginDef } from "@utils/types"; +import definePlugin from "@utils/types"; import { find, findByCode, findByPropsLazy } from "@webpack"; import { Menu } from "@webpack/common"; import type { Guild } from "discord-types/general"; @@ -30,12 +30,12 @@ const MaskedLink = LazyComponent(() => find(m => m.type?.toString().includes("MA const GuildBannerStore = findByPropsLazy("getGuildBannerURL"); const OPEN_URL = "Vencord.Plugins.plugins.ViewIcons.openImage("; -export default new class ViewIcons implements PluginDef { - name = "ViewIcons"; - authors = [Devs.Ven]; - description = "Makes Avatars/Banners in user profiles clickable, and adds Guild Context Menu Entries to View Banner/Icon."; +export default definePlugin({ + name: "ViewIcons", + authors: [Devs.Ven], + description: "Makes Avatars/Banners in user profiles clickable, and adds Guild Context Menu Entries to View Banner/Icon.", - dependencies = ["MenuItemDeobfuscatorAPI"]; + dependencies: ["MenuItemDeobfuscatorAPI"], openImage(url: string) { const u = new URL(url); @@ -52,9 +52,9 @@ export default new class ViewIcons implements PluginDef { /> )); - } + }, - patches = [ + patches: [ { find: "onAddFriend:", replacement: { @@ -83,7 +83,7 @@ export default new class ViewIcons implements PluginDef { } ] } - ]; + ], buildGuildContextMenuEntries(guild: Guild) { return ( @@ -107,4 +107,4 @@ export default new class ViewIcons implements PluginDef { ); } -}; +}); diff --git a/test/generateReport.ts b/test/generateReport.ts deleted file mode 100644 index d55cc8a..0000000 --- a/test/generateReport.ts +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 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 . -*/ - -// eslint-disable-next-line spaced-comment -/// -// eslint-disable-next-line spaced-comment -/// - -import { readFileSync } from "fs"; -import pup, { JSHandle } from "puppeteer-core"; - -for (const variable of ["DISCORD_TOKEN", "CHROMIUM_BIN"]) { - if (!process.env[variable]) { - console.error(`Missing environment variable ${variable}`); - process.exit(1); - } -} - -const CANARY = process.env.USE_CANARY === "true"; - -const browser = await pup.launch({ - headless: true, - executablePath: process.env.CHROMIUM_BIN -}); - -const page = await browser.newPage(); -await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"); - -function maybeGetError(handle: JSHandle) { - return (handle as JSHandle)?.getProperty("message") - .then(m => m.jsonValue()); -} - -const report = { - badPatches: [] as { - plugin: string; - type: string; - id: string; - match: string; - error?: string; - }[], - badStarts: [] as { - plugin: string; - error: string; - }[], - otherErrors: [] as string[] -}; - -function toCodeBlock(s: string) { - s = s.replace(/```/g, "`\u200B`\u200B`"); - return "```" + s + " ```"; -} - -async function printReport() { - console.log("# Vencord Report" + (CANARY ? " (Canary)" : "")); - console.log(); - - console.log("## Bad Patches"); - report.badPatches.forEach(p => { - console.log(`- ${p.plugin} (${p.type})`); - console.log(` - ID: \`${p.id}\``); - console.log(` - Match: ${toCodeBlock(p.match)}`); - if (p.error) console.log(` - Error: ${toCodeBlock(p.error)}`); - }); - - console.log(); - - console.log("## Bad Starts"); - report.badStarts.forEach(p => { - console.log(`- ${p.plugin}`); - console.log(` - Error: ${toCodeBlock(p.error)}`); - }); - - console.log("## Discord Errors"); - report.otherErrors.forEach(e => { - console.log(`- ${toCodeBlock(e)}`); - }); - - if (process.env.DISCORD_WEBHOOK) { - // this code was written almost entirely by Copilot xD - await fetch(process.env.DISCORD_WEBHOOK, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - description: "Here's the latest Vencord Report!", - username: "Vencord Reporter" + (CANARY ? " (Canary)" : ""), - avatar_url: "https://cdn.discordapp.com/icons/1015060230222131221/f0204a918c6c9c9a43195997e97d8adf.webp", - embeds: [ - { - title: "Bad Patches", - description: report.badPatches.map(p => { - const lines = [ - `**__${p.plugin} (${p.type}):__**`, - `ID: \`${p.id}\``, - `Match: ${toCodeBlock(p.match)}` - ]; - if (p.error) lines.push(`Error: ${toCodeBlock(p.error)}`); - return lines.join("\n"); - }).join("\n\n") || "None", - color: report.badPatches.length ? 0xff0000 : 0x00ff00 - }, - { - title: "Bad Starts", - description: report.badStarts.map(p => { - const lines = [ - `**__${p.plugin}:__**`, - toCodeBlock(p.error) - ]; - return lines.join("\n"); - } - ).join("\n\n") || "None", - color: report.badStarts.length ? 0xff0000 : 0x00ff00 - }, - { - title: "Discord Errors", - description: toCodeBlock(report.otherErrors.join("\n")), - color: report.otherErrors.length ? 0xff0000 : 0x00ff00 - } - ] - }) - }).then(res => { - if (!res.ok) console.error(`Webhook failed with status ${res.status}`); - else console.error("Posted to Discord Webhook successfully"); - }); - } -} - -page.on("console", async e => { - const level = e.type(); - const args = e.args(); - - const firstArg = (await args[0]?.jsonValue()); - if (firstArg === "PUPPETEER_TEST_DONE_SIGNAL") { - await browser.close(); - await printReport(); - process.exit(); - } - - const isVencord = (await args[0]?.jsonValue()) === "[Vencord]"; - const isDebug = (await args[0]?.jsonValue()) === "[PUP_DEBUG]"; - - if (isVencord) { - // make ci fail - process.exitCode = 1; - - const jsonArgs = await Promise.all(args.map(a => a.jsonValue())); - const [, tag, message] = jsonArgs; - const cause = await maybeGetError(args[3]); - - switch (tag) { - case "WebpackInterceptor:": - const [, plugin, type, id, regex] = (message as string).match(/Patch by (.+?) (had no effect|errored|found no module) \(Module id is (.+?)\): (.+)/)!; - report.badPatches.push({ - plugin, - type, - id, - match: regex, - error: cause - }); - break; - case "PluginManager:": - const [, name] = (message as string).match(/Failed to start (.+)/)!; - report.badStarts.push({ - plugin: name, - error: cause - }); - break; - } - } else if (isDebug) { - console.error(e.text()); - } else if (level === "error") { - const text = e.text(); - if (!text.startsWith("Failed to load resource: the server responded with a status of")) { - console.error("Got unexpected error", text); - report.otherErrors.push(text); - } - } -}); - -page.on("error", e => console.error("[Error]", e)); -page.on("pageerror", e => console.error("[Page Error]", e)); - -await page.setBypassCSP(true); - -function runTime(token: string) { - console.error("[PUP_DEBUG]", "Starting test..."); - - try { - // spoof languages to not be suspicious - Object.defineProperty(navigator, "languages", { - get: function () { - return ["en-US", "en"]; - }, - }); - - - // Monkey patch Logger to not log with custom css - // @ts-ignore - Vencord.Util.Logger.prototype._log = function (level, levelColor, args) { - if (level === "warn" || level === "error") - console[level]("[Vencord]", this.name + ":", ...args); - }; - - // force enable all plugins and patches - Vencord.Plugins.patches.length = 0; - Object.values(Vencord.Plugins.plugins).forEach(p => { - // Needs native server to run - if (p.name === "WebRichPresence (arRPC)") return; - - p.required = true; - p.patches?.forEach(patch => { - patch.plugin = p.name; - delete patch.predicate; - if (!Array.isArray(patch.replacement)) - patch.replacement = [patch.replacement]; - Vencord.Plugins.patches.push(patch); - }); - }); - - Vencord.Webpack.waitFor( - "loginToken", - m => { - console.error("[PUP_DEBUG]", "Logging in with token..."); - m.loginToken(token); - } - ); - - // force load all chunks - Vencord.Webpack.onceReady.then(() => setTimeout(async () => { - console.error("[PUP_DEBUG]", "Webpack is ready!"); - - const { wreq } = Vencord.Webpack; - - console.error("[PUP_DEBUG]", "Loading all chunks..."); - const ids = Function("return" + wreq.u.toString().match(/\{.+\}/s)![0])(); - for (const id in ids) { - const isWasm = await fetch(wreq.p + wreq.u(id)) - .then(r => r.text()) - .then(t => t.includes(".module.wasm")); - - if (!isWasm) - await wreq.e(id as any); - - await new Promise(r => setTimeout(r, 100)); - } - console.error("[PUP_DEBUG]", "Finished loading chunks!"); - - for (const patch of Vencord.Plugins.patches) { - if (!patch.all) { - new Vencord.Util.Logger("WebpackInterceptor").warn(`Patch by ${patch.plugin} found no module (Module id is -): ${patch.find}`); - } - } - setTimeout(() => console.log("PUPPETEER_TEST_DONE_SIGNAL"), 1000); - }, 1000)); - } catch (e) { - console.error("[PUP_DEBUG]", "A fatal error occured"); - console.error("[PUP_DEBUG]", e); - process.exit(1); - } -} - -await page.evaluateOnNewDocument(` - ${readFileSync("./dist/browser.js", "utf-8")} - - ;(${runTime.toString()})(${JSON.stringify(process.env.DISCORD_TOKEN)}); -`); - -await page.goto(CANARY ? "https://canary.discord.com/login" : "https://discord.com/login"); -- cgit