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 { }