diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 82b17c7..c56cf5a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,9 +53,4 @@ jobs: draft: false prerelease: false files: | - dist/Vencord.user.js - dist/browser.js - dist/extension.zip - dist/renderer.js - dist/patcher.js - dist/preload.js + dist/* diff --git a/package.json b/package.json index a47fb5a..108fead 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ }, "dependencies": { "console-menu": "^0.1.0", - "electron-devtools-installer": "^3.2.0" + "fflate": "^0.7.4" }, "devDependencies": { "@types/node": "^18.7.13", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 158c08b..c1bb3fa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,10 +7,10 @@ specifiers: '@typescript-eslint/parser': ^5.39.0 console-menu: ^0.1.0 discord-types: ^1.3.26 - electron-devtools-installer: ^3.2.0 esbuild: ^0.15.5 eslint: ^8.24.0 eslint-plugin-header: ^3.1.1 + fflate: ^0.7.4 standalone-electron-types: ^1.0.0 type-fest: ^3.1.0 typescript: ^4.8.4 @@ -18,7 +18,7 @@ specifiers: dependencies: console-menu: 0.1.0 - electron-devtools-installer: 3.2.0 + fflate: 0.7.4 devDependencies: '@types/node': 18.7.13 @@ -252,12 +252,14 @@ packages: /balanced-match/1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true /brace-expansion/1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 + dev: true /braces/3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} @@ -296,6 +298,7 @@ packages: /concat-map/0.0.1: resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + dev: true /console-menu/0.1.0: resolution: {integrity: sha512-gOGvuhugXvHggnodbEop0Wzh05eondeCdpPZqcwlzJc7KoPrdsHUM8TZug1lN2jN7Qm3XrZcoP5dZDaO2CaYSw==} @@ -303,10 +306,6 @@ packages: keypress: 0.2.1 dev: false - /core-util-is/1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: false - /cross-spawn/7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -357,15 +356,6 @@ packages: esutils: 2.0.3 dev: true - /electron-devtools-installer/3.2.0: - resolution: {integrity: sha512-t3UczsYugm4OAbqvdImMCImIMVdFzJAHgbwHpkl5jmfu1izVgUcP/mnrPqJIpEeCK1uZGpt+yHgWEN+9EwoYhQ==} - dependencies: - rimraf: 3.0.2 - semver: 7.3.7 - tslib: 2.4.0 - unzip-crx-3: 0.2.0 - dev: false - /esbuild-android-64/0.15.5: resolution: {integrity: sha512-dYPPkiGNskvZqmIK29OPxolyY3tp+c47+Fsc2WYSOVjEPWNCHNyqhtFqQadcXMJDQt8eN0NMDukbyQgFcHquXg==} engines: {node: '>=12'} @@ -726,6 +716,10 @@ packages: reusify: 1.0.4 dev: true + /fflate/0.7.4: + resolution: {integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==} + dev: false + /file-entry-cache/6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -762,6 +756,7 @@ packages: /fs.realpath/1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true /glob-parent/5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -786,6 +781,7 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 + dev: true /globals/13.17.0: resolution: {integrity: sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==} @@ -820,10 +816,6 @@ packages: engines: {node: '>= 4'} dev: true - /immediate/3.0.6: - resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} - dev: false - /import-fresh/3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -842,9 +834,11 @@ packages: dependencies: once: 1.4.0 wrappy: 1.0.2 + dev: true /inherits/2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true /is-extglob/2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} @@ -863,10 +857,6 @@ packages: engines: {node: '>=0.12.0'} dev: true - /isarray/1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: false - /isexe/2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true @@ -890,15 +880,6 @@ packages: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true - /jszip/3.10.1: - resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} - dependencies: - lie: 3.3.0 - pako: 1.0.11 - readable-stream: 2.3.7 - setimmediate: 1.0.5 - dev: false - /keypress/0.2.1: resolution: {integrity: sha512-HjorDJFNhnM4SicvaUXac0X77NiskggxJdesG72+O5zBKpSqKFCrqmndKVqpu3pFqkla0St6uGk8Ju0sCurrmg==} dev: false @@ -911,12 +892,6 @@ packages: type-check: 0.4.0 dev: true - /lie/3.3.0: - resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} - dependencies: - immediate: 3.0.6 - dev: false - /locate-path/6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -933,6 +908,7 @@ packages: engines: {node: '>=10'} dependencies: yallist: 4.0.0 + dev: true /merge2/1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -951,17 +927,7 @@ packages: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 - - /minimist/1.2.6: - resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} - dev: false - - /mkdirp/0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - dependencies: - minimist: 1.2.6 - dev: false + dev: true /moment/2.29.4: resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} @@ -979,6 +945,7 @@ packages: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 + dev: true /optionator/0.9.1: resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} @@ -1006,10 +973,6 @@ packages: p-limit: 3.1.0 dev: true - /pako/1.0.11: - resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} - dev: false - /parent-module/1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -1025,6 +988,7 @@ packages: /path-is-absolute/1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} + dev: true /path-key/3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} @@ -1046,10 +1010,6 @@ packages: engines: {node: '>= 0.8.0'} dev: true - /process-nextick-args/2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: false - /punycode/2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} @@ -1059,18 +1019,6 @@ packages: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true - /readable-stream/2.3.7: - resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - dev: false - /regexpp/3.2.0: resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} engines: {node: '>=8'} @@ -1091,6 +1039,7 @@ packages: hasBin: true dependencies: glob: 7.2.3 + dev: true /run-parallel/1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -1098,20 +1047,13 @@ packages: queue-microtask: 1.2.3 dev: true - /safe-buffer/5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: false - /semver/7.3.7: resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} engines: {node: '>=10'} hasBin: true dependencies: lru-cache: 6.0.0 - - /setimmediate/1.0.5: - resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - dev: false + dev: true /shebang-command/2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} @@ -1136,12 +1078,6 @@ packages: '@types/node': 18.8.4 dev: true - /string_decoder/1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - dev: false - /strip-ansi/6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -1176,10 +1112,6 @@ packages: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} dev: true - /tslib/2.4.0: - resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} - dev: false - /tsutils/3.21.0_typescript@4.8.4: resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} @@ -1213,24 +1145,12 @@ packages: hasBin: true dev: true - /unzip-crx-3/0.2.0: - resolution: {integrity: sha512-0+JiUq/z7faJ6oifVB5nSwt589v1KCduqIJupNVDoWSXZtWDmjDGO3RAEOvwJ07w90aoXoP4enKsR7ecMrJtWQ==} - dependencies: - jszip: 3.10.1 - mkdirp: 0.5.6 - yaku: 0.16.7 - dev: false - /uri-js/4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: punycode: 2.1.1 dev: true - /util-deprecate/1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: false - /which/2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -1246,13 +1166,11 @@ packages: /wrappy/1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - /yaku/0.16.7: - resolution: {integrity: sha512-Syu3IB3rZvKvYk7yTiyl1bo/jiEFaaStrgv1V2TIJTqYPStSMQVO8EQjg/z+DRzLq/4LIIharNT3iH1hylEIRw==} - dev: false + dev: true /yallist/4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true /yazl/2.5.1: resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} diff --git a/scripts/build/build.mjs b/scripts/build/build.mjs index 1986369..163f4ce 100755 --- a/scripts/build/build.mjs +++ b/scripts/build/build.mjs @@ -29,8 +29,9 @@ const nodeCommonOpts = { platform: "node", target: ["esnext"], minify: true, + bundle: true, sourcemap: "linked", - plugins: [...commonOpts.plugins, makeAllPackagesExternalPlugin], + external: ["electron"] }; await Promise.all([ diff --git a/src/ipcMain/constants.ts b/src/ipcMain/constants.ts new file mode 100644 index 0000000..18726fc --- /dev/null +++ b/src/ipcMain/constants.ts @@ -0,0 +1,35 @@ +/* + * 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 . +*/ + +import { join } from "path"; +import { app } from "electron"; + +export const DATA_DIR = process.env.VENCORD_USER_DATA_DIR ?? ( + process.env.DISCORD_USER_DATA_DIR + ? join(process.env.DISCORD_USER_DATA_DIR, "..", "VencordData") + : join(app.getPath("userData"), "..", "Vencord") +); +export const SETTINGS_DIR = join(DATA_DIR, "settings"); +export const QUICKCSS_PATH = join(SETTINGS_DIR, "quickCss.css"); +export const SETTINGS_FILE = join(SETTINGS_DIR, "settings.json"); +export const ALLOWED_PROTOCOLS = [ + "https:", + "http:", + "steam:", + "spotify:" +]; diff --git a/src/ipcMain/crxToZip.ts b/src/ipcMain/crxToZip.ts new file mode 100644 index 0000000..ca43890 --- /dev/null +++ b/src/ipcMain/crxToZip.ts @@ -0,0 +1,57 @@ +/* eslint-disable header/header */ + +/*! + * crxToZip + * Copyright (c) 2013 Rob Wu + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +export function crxToZip(buf: Buffer) { + function calcLength(a: number, b: number, c: number, d: number) { + let length = 0; + + length += a << 0; + length += b << 8; + length += c << 16; + length += d << 24 >>> 0; + return length; + } + + // 50 4b 03 04 + // This is actually a zip file + if (buf[0] === 80 && buf[1] === 75 && buf[2] === 3 && buf[3] === 4) { + return buf; + } + + // 43 72 32 34 (Cr24) + if (buf[0] !== 67 || buf[1] !== 114 || buf[2] !== 50 || buf[3] !== 52) { + throw new Error("Invalid header: Does not start with Cr24"); + } + + // 02 00 00 00 + // or + // 03 00 00 00 + const isV3 = buf[4] === 3; + const isV2 = buf[4] === 2; + + if ((!isV2 && !isV3) || buf[5] || buf[6] || buf[7]) { + throw new Error("Unexpected crx format version number."); + } + + if (isV2) { + const publicKeyLength = calcLength(buf[8], buf[9], buf[10], buf[11]); + const signatureLength = calcLength(buf[12], buf[13], buf[14], buf[15]); + + // 16 = Magic number (4), CRX format version (4), lengths (2x4) + const zipStartOffset = 16 + publicKeyLength + signatureLength; + + return buf.subarray(zipStartOffset, buf.length); + } + // v3 format has header size and then header + const headerSize = calcLength(buf[8], buf[9], buf[10], buf[11]); + const zipStartOffset = 12 + headerSize; + + return buf.subarray(zipStartOffset, buf.length); +} diff --git a/src/ipcMain/extensions.ts b/src/ipcMain/extensions.ts new file mode 100644 index 0000000..9bebdaf --- /dev/null +++ b/src/ipcMain/extensions.ts @@ -0,0 +1,93 @@ +/* + * 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 . +*/ + +import https from "https"; +import { mkdir, rm, writeFile, access } from "fs/promises"; +import { constants as fsConstants } from "fs"; +import { join } from "path"; +import { DATA_DIR } from "./constants"; +import { unzip } from "fflate"; +import { session } from "electron"; +import { crxToZip } from "./crxToZip"; + +const extensionCacheDir = join(DATA_DIR, "ExtensionCache"); + +function download(url: string) { + return new Promise((resolve, reject) => { + https.get(url, res => { + const { statusCode, statusMessage, headers } = res; + if (statusCode! >= 400) + return void reject(`${statusCode}: ${statusMessage} - ${url}`); + if (statusCode! >= 300) + return void resolve(download(headers.location!)); + + const chunks = [] as Buffer[]; + res.on("error", reject); + + res.on("data", chunk => chunks.push(chunk)); + res.once("end", () => resolve(Buffer.concat(chunks))); + }); + }); +} + +async function extract(data: Buffer, outDir: string) { + await mkdir(outDir, { recursive: true }); + return new Promise((resolve, reject) => { + unzip(data, (err, files) => { + if (err) return void reject(err); + Promise.all(Object.keys(files).map(async f => { + // Signature stuff + // 'Cannot load extension with file or directory name + // _metadata. Filenames starting with "_" are reserved for use by the system.'; + if (f.startsWith("_metadata/")) return; + + if (f.endsWith("/")) return void mkdir(join(outDir, f), { recursive: true }); + + const pathElements = f.split("/"); + const name = pathElements.pop()!; + const directories = pathElements.join("/"); + const dir = join(outDir, directories); + + if (directories) { + await mkdir(dir, { recursive: true }); + } + + await writeFile(join(dir, name), files[f]); + })) + .then(() => resolve()) + .catch(err => { + rm(outDir, { recursive: true, force: true }); + reject(err); + }); + }); + }); +} + +export async function installExt(id: string) { + const extDir = join(extensionCacheDir, `${id}`); + + try { + await access(extDir, fsConstants.F_OK); + } catch (err) { + const url = `https://clients2.google.com/service/update2/crx?response=redirect&acceptformat=crx2,crx3&x=id%3D${id}%26uc&prodversion=32`; + const buf = await download(url); + await extract(crxToZip(buf), extDir); + } + + session.defaultSession.loadExtension(extDir); +} diff --git a/src/ipcMain/index.ts b/src/ipcMain/index.ts index dc05079..d815142 100644 --- a/src/ipcMain/index.ts +++ b/src/ipcMain/index.ts @@ -26,21 +26,9 @@ import monacoHtml from "@fileContent/../components/monacoWin.html;base64"; import "./updater"; import { Queue } from "../utils/Queue"; +import { QUICKCSS_PATH, ALLOWED_PROTOCOLS, SETTINGS_DIR, SETTINGS_FILE } from "./constants"; + -const DATA_DIR = process.env.VENCORD_USER_DATA_DIR ?? ( - process.env.DISCORD_USER_DATA_DIR - ? join(process.env.DISCORD_USER_DATA_DIR, "..", "VencordData") - : join(app.getPath("userData"), "..", "Vencord") -); -const SETTINGS_DIR = join(DATA_DIR, "settings"); -const QUICKCSS_PATH = join(SETTINGS_DIR, "quickCss.css"); -const SETTINGS_FILE = join(SETTINGS_DIR, "settings.json"); -const ALLOWED_PROTOCOLS = [ - "https:", - "http:", - "steam:", - "spotify:" -]; mkdirSync(SETTINGS_DIR, { recursive: true }); diff --git a/src/patcher.ts b/src/patcher.ts index 06f03d8..eca35f0 100644 --- a/src/patcher.ts +++ b/src/patcher.ts @@ -19,6 +19,7 @@ import electron, { app, BrowserWindowConstructorOptions } from "electron"; import { join } from "path"; import { initIpc } from "./ipcMain"; +import { installExt } from "./ipcMain/extensions"; import { readSettings } from "./ipcMain/index"; console.log("[Vencord] Starting up..."); @@ -68,11 +69,7 @@ electron.app.whenReady().then(() => { try { const settings = JSON.parse(readSettings()); if (settings.enableReactDevtools) - import("electron-devtools-installer") - .then(({ default: inst, REACT_DEVELOPER_TOOLS }) => - // @ts-ignore: cursed fake esm turns it into exports.default.default - (inst.default ?? inst)(REACT_DEVELOPER_TOOLS) - ) + installExt("fmkadmapgofadopljbjfkapdkoienihi") .then(() => console.info("[Vencord] Installed React Developer Tools")) .catch(err => console.error("[Vencord] Failed to install React Developer Tools", err)); } catch { }