Update arRPC

This commit is contained in:
smartfridge 2022-11-20 13:48:07 +01:00
parent beaa993e39
commit ddac01ee8f
14 changed files with 246 additions and 252 deletions

View File

@ -27,8 +27,7 @@
}, },
"homepage": "https://github.com/armcord/armcord#readme", "homepage": "https://github.com/armcord/armcord#readme",
"devDependencies": { "devDependencies": {
"@types/node": "^17.0.42", "@types/node": "^17.0.45",
"@types/node-fetch": "^2.6.2",
"@types/ws": "^8.5.3", "@types/ws": "^8.5.3",
"chalk-cli": "^5.0.0", "chalk-cli": "^5.0.0",
"copyfiles": "^2.4.1", "copyfiles": "^2.4.1",
@ -36,17 +35,15 @@
"electron-builder": "^23.6.0", "electron-builder": "^23.6.0",
"husky": "^8.0.1", "husky": "^8.0.1",
"prettier": "^2.7.0", "prettier": "^2.7.0",
"typescript": "^4.7.3" "typescript": "^4.9.3"
}, },
"dependencies": { "dependencies": {
"@pyke/vibe": "github:pykeio/vibe#11984868ce9e007859ed91ff159c7f7f0a34e7ae", "@pyke/vibe": "github:pykeio/vibe#11984868ce9e007859ed91ff159c7f7f0a34e7ae",
"arrpc": "file:./src/arrpc", "arrpc": "file:./src/arrpc",
"cross-fetch": "^3.1.5",
"electron-context-menu": "github:ArmCord/electron-context-menu", "electron-context-menu": "github:ArmCord/electron-context-menu",
"extract-zip": "^2.0.1", "extract-zip": "^2.0.1",
"node-fetch": "v2",
"os-locale": "^6.0.2",
"v8-compile-cache": "^2.3.0", "v8-compile-cache": "^2.3.0",
"whatwg-url": "^11.0.0",
"ws": "^8.8.0" "ws": "^8.8.0"
}, },
"build": { "build": {

View File

@ -2,47 +2,41 @@ lockfileVersion: 5.4
specifiers: specifiers:
'@pyke/vibe': github:pykeio/vibe#11984868ce9e007859ed91ff159c7f7f0a34e7ae '@pyke/vibe': github:pykeio/vibe#11984868ce9e007859ed91ff159c7f7f0a34e7ae
'@types/node': ^17.0.42 '@types/node': ^17.0.45
'@types/node-fetch': ^2.6.2
'@types/ws': ^8.5.3 '@types/ws': ^8.5.3
arrpc: file:./src/arrpc arrpc: file:./src/arrpc
chalk-cli: ^5.0.0 chalk-cli: ^5.0.0
copyfiles: ^2.4.1 copyfiles: ^2.4.1
cross-fetch: ^3.1.5
electron: ^20.1.0 electron: ^20.1.0
electron-builder: ^23.6.0 electron-builder: ^23.6.0
electron-context-menu: github:ArmCord/electron-context-menu electron-context-menu: github:ArmCord/electron-context-menu
extract-zip: ^2.0.1 extract-zip: ^2.0.1
husky: ^8.0.1 husky: ^8.0.1
node-fetch: v2
os-locale: ^6.0.2
prettier: ^2.7.0 prettier: ^2.7.0
typescript: ^4.7.3 typescript: ^4.9.3
v8-compile-cache: ^2.3.0 v8-compile-cache: ^2.3.0
whatwg-url: ^11.0.0
ws: ^8.8.0 ws: ^8.8.0
dependencies: dependencies:
'@pyke/vibe': github.com/pykeio/vibe/11984868ce9e007859ed91ff159c7f7f0a34e7ae_electron@20.3.1 '@pyke/vibe': github.com/pykeio/vibe/11984868ce9e007859ed91ff159c7f7f0a34e7ae_electron@20.3.5
arrpc: file:src/arrpc arrpc: file:src/arrpc
cross-fetch: 3.1.5
electron-context-menu: github.com/ArmCord/electron-context-menu/280c81398c02a063f46e3285a9708d8db1a7ce32 electron-context-menu: github.com/ArmCord/electron-context-menu/280c81398c02a063f46e3285a9708d8db1a7ce32
extract-zip: 2.0.1 extract-zip: 2.0.1
node-fetch: 2.6.7
os-locale: 6.0.2
v8-compile-cache: 2.3.0 v8-compile-cache: 2.3.0
whatwg-url: 11.0.0 ws: 8.11.0
ws: 8.9.0
devDependencies: devDependencies:
'@types/node': 17.0.45 '@types/node': 17.0.45
'@types/node-fetch': 2.6.2
'@types/ws': 8.5.3 '@types/ws': 8.5.3
chalk-cli: 5.0.0 chalk-cli: 5.0.0
copyfiles: 2.4.1 copyfiles: 2.4.1
electron: 20.3.1 electron: 20.3.5
electron-builder: 23.6.0 electron-builder: 23.6.0
husky: 8.0.1 husky: 8.0.2
prettier: 2.7.1 prettier: 2.7.1
typescript: 4.8.4 typescript: 4.9.3
packages: packages:
@ -184,15 +178,8 @@ packages:
resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==}
dev: true dev: true
/@types/node-fetch/2.6.2: /@types/node/16.18.3:
resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==} resolution: {integrity: sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==}
dependencies:
'@types/node': 17.0.45
form-data: 3.0.1
dev: true
/@types/node/16.11.64:
resolution: {integrity: sha512-z5hPTlVFzNwtJ2LNozTpJcD1Cu44c4LNuzaq1mwxmiHWQh2ULdR6Vjwo1UGldzRpzL0yUEdZddnfqGW2G70z6Q==}
/@types/node/17.0.45: /@types/node/17.0.45:
resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==}
@ -287,8 +274,8 @@ packages:
dependencies: dependencies:
color-convert: 2.0.1 color-convert: 2.0.1
/ansi-styles/6.1.1: /ansi-styles/6.2.1:
resolution: {integrity: sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==} resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
engines: {node: '>=12'} engines: {node: '>=12'}
dev: true dev: true
@ -324,7 +311,7 @@ packages:
read-config-file: 6.2.0 read-config-file: 6.2.0
sanitize-filename: 1.6.3 sanitize-filename: 1.6.3
semver: 7.3.8 semver: 7.3.8
tar: 6.1.11 tar: 6.1.12
temp-file: 3.4.0 temp-file: 3.4.0
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -515,8 +502,8 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dev: true dev: true
/cargo-cp-artifact/0.1.6: /cargo-cp-artifact/0.1.7:
resolution: {integrity: sha512-CQw0doK/aaF7j041666XzuilHxqMxaKkn+I5vmBsd8SAwS0cO5CqVEVp0xJwOKstyqWZ6WK4Ww3O6p26x/Goyg==} resolution: {integrity: sha512-pxEV9p1on8vu3BOKstVisF9TwMyGKCBRvzaVpQHuU2sLULCKrn3MJWx/4XlNzmG6xNCTPf78DJ7WCGgr2mOzjg==}
hasBin: true hasBin: true
dev: false dev: false
@ -525,7 +512,7 @@ packages:
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
hasBin: true hasBin: true
dependencies: dependencies:
ansi-styles: 6.1.1 ansi-styles: 6.2.1
chalk: 4.1.2 chalk: 4.1.2
dot-prop: 6.0.1 dot-prop: 6.0.1
get-stdin: 9.0.0 get-stdin: 9.0.0
@ -558,8 +545,9 @@ packages:
resolution: {integrity: sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==} resolution: {integrity: sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==}
dev: true dev: true
/ci-info/3.4.0: /ci-info/3.6.1:
resolution: {integrity: sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==} resolution: {integrity: sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==}
engines: {node: '>=8'}
dev: true dev: true
/cli-truncate/2.1.0: /cli-truncate/2.1.0:
@ -681,6 +669,14 @@ packages:
dev: true dev: true
optional: true optional: true
/cross-fetch/3.1.5:
resolution: {integrity: sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==}
dependencies:
node-fetch: 2.6.7
transitivePeerDependencies:
- encoding
dev: false
/cross-spawn/7.0.3: /cross-spawn/7.0.3:
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -712,8 +708,8 @@ packages:
dependencies: dependencies:
ms: 2.1.2 ms: 2.1.2
/decamelize-keys/1.1.0: /decamelize-keys/1.1.1:
resolution: {integrity: sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==} resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dependencies: dependencies:
decamelize: 1.2.0 decamelize: 1.2.0
@ -842,13 +838,13 @@ packages:
lazy-val: 1.0.5 lazy-val: 1.0.5
read-config-file: 6.2.0 read-config-file: 6.2.0
simple-update-notifier: 1.0.7 simple-update-notifier: 1.0.7
yargs: 17.6.0 yargs: 17.6.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
/electron-dl/3.3.1: /electron-dl/3.5.0:
resolution: {integrity: sha512-kmcSYZyHVEHHHFKlZWW58GiCmu2NSu3Rdwnl3+/fr/ftQYHJULVf1QkrCBPFE2bp/Ly113Za7c8wJZs1nBy04A==} resolution: {integrity: sha512-Oj+VSuScVx8hEKM2HEvTQswTX6G3MLh7UoAz/oZuvKyNDfudNi1zY6PK/UnFoK1nCl9DF6k+3PFwElKbtZlDig==}
dependencies: dependencies:
ext-name: 5.0.0 ext-name: 5.0.0
pupa: 2.1.1 pupa: 2.1.1
@ -869,7 +865,7 @@ packages:
compare-version: 0.1.2 compare-version: 0.1.2
debug: 2.6.9 debug: 2.6.9
isbinaryfile: 3.0.3 isbinaryfile: 3.0.3
minimist: 1.2.6 minimist: 1.2.7
plist: 3.0.6 plist: 3.0.6
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -889,14 +885,14 @@ packages:
- supports-color - supports-color
dev: true dev: true
/electron/20.3.1: /electron/20.3.5:
resolution: {integrity: sha512-mgFAa79Zj8oCegsluPAo6O1yXd7mVMZ0JZC2Rak9HQUAQ7x9xuQY7yop/+nMbi+bOMWwe5JrtOcvjotBArxioA==} resolution: {integrity: sha512-xTBjdgAZXf6txxfIhv9mZ3yloJZ+KTht7D2X10uHlFnQu4ZmvzqwhGuQPnldVKhRUDvZehIjulmmrFO6Mz6SzQ==}
engines: {node: '>= 10.17.0'} engines: {node: '>= 10.17.0'}
hasBin: true hasBin: true
requiresBuild: true requiresBuild: true
dependencies: dependencies:
'@electron/get': 1.14.1 '@electron/get': 1.14.1
'@types/node': 16.11.64 '@types/node': 16.18.3
extract-zip: 2.0.1 extract-zip: 2.0.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -1012,15 +1008,6 @@ packages:
path-exists: 4.0.0 path-exists: 4.0.0
dev: true dev: true
/form-data/3.0.1:
resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==}
engines: {node: '>= 6'}
dependencies:
asynckit: 0.4.0
combined-stream: 1.0.8
mime-types: 2.1.35
dev: true
/form-data/4.0.0: /form-data/4.0.0:
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
@ -1231,8 +1218,8 @@ packages:
- supports-color - supports-color
dev: true dev: true
/husky/8.0.1: /husky/8.0.2:
resolution: {integrity: sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==} resolution: {integrity: sha512-Tkv80jtvbnkK3mYWxPZePGFpQ/tT3HNSs/sasF9P2YfkMezDl3ON37YN6jUUI4eTg5LcyVynlb6r4eyvOmspvg==}
engines: {node: '>=14'} engines: {node: '>=14'}
hasBin: true hasBin: true
dev: true dev: true
@ -1281,11 +1268,6 @@ packages:
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
optional: true optional: true
/invert-kv/3.0.1:
resolution: {integrity: sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==}
engines: {node: '>=8'}
dev: false
/is-arrayish/0.2.1: /is-arrayish/0.2.1:
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
dev: true dev: true
@ -1294,11 +1276,11 @@ packages:
resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==}
hasBin: true hasBin: true
dependencies: dependencies:
ci-info: 3.4.0 ci-info: 3.6.1
dev: true dev: true
/is-core-module/2.10.0: /is-core-module/2.11.0:
resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==}
dependencies: dependencies:
has: 1.0.3 has: 1.0.3
dev: true dev: true
@ -1411,13 +1393,6 @@ packages:
resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==}
dev: true dev: true
/lcid/3.1.1:
resolution: {integrity: sha512-M6T051+5QCGLBQb8id3hdvIW8+zeFV2FyBGFS9IEK5H9Wt4MueD4bW1eWikpHgZp+5xR3l5c8pZUkQsIA0BFZg==}
engines: {node: '>=8'}
dependencies:
invert-kv: 3.0.1
dev: false
/lines-and-columns/1.2.4: /lines-and-columns/1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
dev: true dev: true
@ -1470,7 +1445,7 @@ packages:
'@types/minimist': 1.2.2 '@types/minimist': 1.2.2
camelcase-keys: 7.0.2 camelcase-keys: 7.0.2
decamelize: 5.0.1 decamelize: 5.0.1
decamelize-keys: 1.1.0 decamelize-keys: 1.1.1
hard-rejection: 2.1.0 hard-rejection: 2.1.0
minimist-options: 4.1.0 minimist-options: 4.1.0
normalize-package-data: 3.0.3 normalize-package-data: 3.0.3
@ -1535,8 +1510,8 @@ packages:
kind-of: 6.0.3 kind-of: 6.0.3
dev: true dev: true
/minimist/1.2.6: /minimist/1.2.7:
resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==}
dev: true dev: true
/minipass/3.3.4: /minipass/3.3.4:
@ -1602,7 +1577,7 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dependencies: dependencies:
hosted-git-info: 4.1.0 hosted-git-info: 4.1.0
is-core-module: 2.10.0 is-core-module: 2.11.0
semver: 7.3.8 semver: 7.3.8
validate-npm-package-license: 3.0.4 validate-npm-package-license: 3.0.4
dev: true dev: true
@ -1629,13 +1604,6 @@ packages:
dependencies: dependencies:
wrappy: 1.0.2 wrappy: 1.0.2
/os-locale/6.0.2:
resolution: {integrity: sha512-qIb8bzRqaN/vVqEYZ7lTAg6PonskO7xOmM7OClD28F6eFa4s5XGe4bGpHUHMoCHbNNuR0pDYFeSLiW5bnjWXIA==}
engines: {node: '>=12.20'}
dependencies:
lcid: 3.1.1
dev: false
/p-cancelable/1.1.0: /p-cancelable/1.1.0:
resolution: {integrity: sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==} resolution: {integrity: sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -1726,6 +1694,7 @@ packages:
resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==}
engines: {node: '>=6'} engines: {node: '>=6'}
requiresBuild: true requiresBuild: true
dev: true
/pupa/2.1.1: /pupa/2.1.1:
resolution: {integrity: sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==} resolution: {integrity: sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==}
@ -2016,9 +1985,9 @@ packages:
has-flag: 4.0.0 has-flag: 4.0.0
dev: true dev: true
/tar/6.1.11: /tar/6.1.12:
resolution: {integrity: sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==} resolution: {integrity: sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw==}
engines: {node: '>= 10'} engines: {node: '>=10'}
dependencies: dependencies:
chownr: 2.0.0 chownr: 2.0.0
fs-minipass: 2.1.0 fs-minipass: 2.1.0
@ -2063,13 +2032,6 @@ packages:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
dev: false dev: false
/tr46/3.0.0:
resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==}
engines: {node: '>=12'}
dependencies:
punycode: 2.1.1
dev: false
/trim-newlines/4.0.2: /trim-newlines/4.0.2:
resolution: {integrity: sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==} resolution: {integrity: sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -2096,8 +2058,8 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dev: true dev: true
/typescript/4.8.4: /typescript/4.9.3:
resolution: {integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==} resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==}
engines: {node: '>=4.2.0'} engines: {node: '>=4.2.0'}
hasBin: true hasBin: true
dev: true dev: true
@ -2171,19 +2133,6 @@ packages:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
dev: false dev: false
/webidl-conversions/7.0.0:
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
engines: {node: '>=12'}
dev: false
/whatwg-url/11.0.0:
resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==}
engines: {node: '>=12'}
dependencies:
tr46: 3.0.0
webidl-conversions: 7.0.0
dev: false
/whatwg-url/5.0.0: /whatwg-url/5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
dependencies: dependencies:
@ -2224,19 +2173,6 @@ packages:
optional: true optional: true
dev: false dev: false
/ws/8.9.0:
resolution: {integrity: sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: ^5.0.2
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
dev: false
/xmlbuilder/15.1.1: /xmlbuilder/15.1.1:
resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==}
engines: {node: '>=8.0'} engines: {node: '>=8.0'}
@ -2279,8 +2215,8 @@ packages:
yargs-parser: 20.2.9 yargs-parser: 20.2.9
dev: true dev: true
/yargs/17.6.0: /yargs/17.6.2:
resolution: {integrity: sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==} resolution: {integrity: sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==}
engines: {node: '>=12'} engines: {node: '>=12'}
dependencies: dependencies:
cliui: 8.0.1 cliui: 8.0.1
@ -2320,11 +2256,11 @@ packages:
version: 3.5.0 version: 3.5.0
dependencies: dependencies:
cli-truncate: 2.1.0 cli-truncate: 2.1.0
electron-dl: 3.3.1 electron-dl: 3.5.0
electron-is-dev: 2.0.0 electron-is-dev: 2.0.0
dev: false dev: false
github.com/pykeio/vibe/11984868ce9e007859ed91ff159c7f7f0a34e7ae_electron@20.3.1: github.com/pykeio/vibe/11984868ce9e007859ed91ff159c7f7f0a34e7ae_electron@20.3.5:
resolution: {tarball: https://codeload.github.com/pykeio/vibe/tar.gz/11984868ce9e007859ed91ff159c7f7f0a34e7ae} resolution: {tarball: https://codeload.github.com/pykeio/vibe/tar.gz/11984868ce9e007859ed91ff159c7f7f0a34e7ae}
id: github.com/pykeio/vibe/11984868ce9e007859ed91ff159c7f7f0a34e7ae id: github.com/pykeio/vibe/11984868ce9e007859ed91ff159c7f7f0a34e7ae
name: '@pyke/vibe' name: '@pyke/vibe'
@ -2333,6 +2269,6 @@ packages:
peerDependencies: peerDependencies:
electron: '>=11.0' electron: '>=11.0'
dependencies: dependencies:
cargo-cp-artifact: 0.1.6 cargo-cp-artifact: 0.1.7
electron: 20.3.1 electron: 20.3.5
dev: false dev: false

View File

@ -2,11 +2,21 @@
arRPC is an open source implementation of Discord's half-documented local RPC servers for their desktop client. This open source implementation purely in NodeJS allows it to be used in many places where it is otherwise impossible to do: Discord web and alternative clients like Armcord/etc. It opens a simple bridge WebSocket server which messages the JSON of exactly what to dispatch with in the client with no extra processing needed, allowing small and simple mods or plugins. **It is currently in alpha and is very WIP, expect bugs, etc.** arRPC is an open source implementation of Discord's half-documented local RPC servers for their desktop client. This open source implementation purely in NodeJS allows it to be used in many places where it is otherwise impossible to do: Discord web and alternative clients like Armcord/etc. It opens a simple bridge WebSocket server which messages the JSON of exactly what to dispatch with in the client with no extra processing needed, allowing small and simple mods or plugins. **It is currently in alpha and is very WIP, expect bugs, etc.**
<br>
Rich Presence (RPC) is the name for how some apps can talk to Discord desktop on your PC via localhost servers to display detailed info about the app's state. This usually works via parts of Discord desktop natively doing things + parts of Discord web interpreting that and setting it as your status. arRPC is an open source implementation of the local RPC servers on your PC, allowing apps to talk to it thinking it was just normal Discord. It can then send that info to apps which usually don't get RPC, like Discord Web, Armcord, etc. which can then set that as your status. This would otherwise not be possible, as web apps/browsers/etc can't just use Discord's already existing code and version.
- App with Discord RPC
- ~~Discord Desktop's native server~~ arRPC
- ~~Discord Web's setting~~ mod/plugin
<br>
### How to try ### How to try
1. Clone repo 1. Clone repo
2. Run server with `node src` (use new Node) 2. Run server with `node src` (use new Node)
3. Open Discord in browser with CSP disabled (using an extension) 3. Open Discord in browser
4. Run content of [`simple_mod.js`](simple_mod.js) in console 4. Run content of [`simple_mod.js`](simple_mod.js) in console
5. Use an app/thing with RPC 5. Use an app/thing with RPC
6. Hope it works, if not report bugs :) 6. Hope it works, if not report bugs :)
@ -24,21 +34,5 @@ arRPC is an open source implementation of Discord's half-documented local RPC se
### Commands ### Commands
- [x] DISPATCH - [x] DISPATCH
- [ ] AUTHORIZE
- [ ] AUTHENTICATE
- [ ] GET_GUILD
- [ ] GET_GUILDS
- [ ] GET_CHANNEL
- [ ] GET_CHANNELS
- [ ] SUBSCRIBE
- [ ] UNSUBSCRIBE
- [ ] SET_USER_VOICE_SETTINGS
- [ ] SELECT_VOICE_CHANNEL
- [ ] GET_SELECTED_VOICE_CHANNEL
- [ ] SELECT_TEXT_CHANNEL
- [ ] GET_VOICE_SETTINGS
- [ ] SET_VOICE_SETTINGS
- [ ] SET_CERTIFIED_DEVICES
- [x] SET_ACTIVITY - [x] SET_ACTIVITY
- [ ] SEND_ACTIVITY_JOIN_INVITE - [x] INVITE_BROWSER
- [ ] CLOSE_ACTIVITY_REQUEST

View File

@ -1,6 +1,6 @@
{ {
"name": "arrpc", "name": "arrpc",
"version": "0.1.0", "version": "1.1.0",
"description": "Open Discord RPC server for atypical setups", "description": "Open Discord RPC server for atypical setups",
"main": "src/index.js", "main": "src/index.js",
"scripts": { "scripts": {

View File

@ -1,31 +1,24 @@
const dispatch = (() => { let Dispatcher;
let Dispatcher;
return function (event) { const ws = new WebSocket("ws://127.0.0.1:1337"); // connect to arRPC bridge
Dispatcher ??= window.Vencord?.Webpack.Common.FluxDispatcher;
if (!Dispatcher) {
const cache = webpackChunkdiscord_app.push([[Symbol()], {}, (w) => w]).c;
webpackChunkdiscord_app.pop();
outer: for (const id in cache) {
const mod = cache[id].exports;
for (const exp in mod) {
if (mod[exp]?.isDispatching) {
Dispatcher = mod[exp];
break outer;
}
}
}
}
if (!Dispatcher) return; // failed to find, your choice if and how u wanna handle this
return Dispatcher.dispatch(event);
};
})();
const ws = new WebSocket("ws://localhost:1337"); // connect to arRPC bridge
ws.onmessage = (x) => { ws.onmessage = (x) => {
msg = JSON.parse(x.data); msg = JSON.parse(x.data);
console.log(msg); console.log(msg);
dispatch({type: "LOCAL_ACTIVITY_UPDATE", ...msg}); // set RPC status if (!Dispatcher) {
const cache = window.webpackChunkdiscord_app.push([[Symbol()], {}, (x) => x]).c;
window.webpackChunkdiscord_app.pop();
for (const id in cache) {
let mod = cache[id].exports;
mod = mod && (mod.Z ?? mod.ZP);
if (mod && mod.register && mod.wait) {
Dispatcher = mod;
break;
}
}
}
Dispatcher.dispatch({type: "LOCAL_ACTIVITY_UPDATE", ...msg}); // set RPC status
}; };

View File

@ -1,8 +1,22 @@
const ws = require("ws"); const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`;
const log = (...args) => console.log(`[${rgb(88, 101, 242, "arRPC")} > ${rgb(87, 242, 135, "bridge")}]`, ...args);
const {WebSocketServer} = require("ws");
// basic bridge to pass info onto webapp
const send = (msg) => { const send = (msg) => {
wss.clients.forEach((x) => x.send(JSON.stringify(msg))); wss.clients.forEach((x) => x.send(JSON.stringify(msg)));
}; };
const wss = new ws.WebSocketServer({port: 1337}); const port = 1337;
const wss = new WebSocketServer({port});
wss.on("connection", (socket) => {
log("web connected");
socket.on("close", () => {
log("web disconnected");
});
});
wss.on("listening", () => log("listening on", port));
module.exports = {send}; module.exports = {send};

View File

@ -1,11 +1,27 @@
var __importDefault = const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`;
(this && this.__importDefault) || const log = (...args) => console.log(`[${rgb(88, 101, 242, "arRPC")}]`, ...args);
function (mod) {
return mod && mod.__esModule ? mod : {default: mod}; log("arRPC v1.1.0-beta ArmCord");
};
const server = require("./server.js"); const Bridge = require("./bridge.js");
global.fetch = __importDefault(require("node-fetch")); const {RPCServer} = require("./server.js");
async function start() { const fetch = require("cross-fetch");
const x = await new server.RPCServer(); const {mainWindow} = require("../../../ts-out/window.js");
const {sleep} = require("../../../ts-out/utils.js");
async function run() {
const server = await new RPCServer();
server.on("activity", (data) => mainWindow.webContents.send("rpc", data));
server.on("invite", (code) => {
console.log(code);
const {createInviteWindow, inviteWindow} = require("../../../ts-out/window.js");
const {exportPort} = require("./transports/websocket.js");
createInviteWindow();
const win = inviteWindow;
//doesnt work
win.loadURL("https://discord.com/invite/" + code);
win.show();
});
} }
start(); run();
//server.on('activity', data => Bridge.send(data));

View File

@ -1,22 +1,25 @@
const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`; const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`;
const log = (...args) => console.log(`[${rgb(88, 101, 242, "arRPC")} > ${rgb(87, 242, 135, "bridge")}]`, ...args); const log = (...args) => console.log(`[${rgb(88, 101, 242, "arRPC")} > ${rgb(87, 242, 135, "bridge")}]`, ...args);
const IPCServer = require("./transports/ipc.js"); const {IPCServer} = require("./transports/ipc.js");
const {EventEmitter} = require("events");
const WSServer = require("./transports/websocket.js"); const {WSServer} = require("./transports/websocket.js");
const Bridge = require("./bridge.js"); const Bridge = require("./bridge.js");
const fetch = require("cross-fetch");
const lookupAsset = (name, assets) => { const lookupAsset = (name, assets) => {
return assets.find((x) => x.name === name)?.id; return assets.find((x) => x.name === name)?.id;
}; };
class RPCServer { class RPCServer extends EventEmitter {
constructor() { constructor() {
super();
return (async () => { return (async () => {
this.onConnection = this.onConnection.bind(this); this.onConnection = this.onConnection.bind(this);
this.onMessage = this.onMessage.bind(this); this.onMessage = this.onMessage.bind(this);
this.ipc = await new IPCServer.IPCServer(this.onMessage, this.onConnection); this.ipc = await new IPCServer(this.onMessage, this.onConnection);
this.ws = await new WSServer.WSServer(this.onMessage, this.onConnection); this.ws = await new WSServer(this.onMessage, this.onConnection);
return this;
})(); })();
} }
@ -24,14 +27,22 @@ class RPCServer {
socket.send({ socket.send({
cmd: "DISPATCH", cmd: "DISPATCH",
evt: "READY", evt: "READY",
data: {}
data: {
v: 1
}
}); });
this.emit("connection", socket);
} }
async onMessage(socket, {cmd, args}) { async onMessage(socket, {cmd, args, nonce}) {
this.emit("message", {socket, cmd, args, nonce});
switch (cmd) { switch (cmd) {
case "SET_ACTIVITY": case "SET_ACTIVITY":
if (!socket.application) { if (!socket.application) {
// fetch info about application
socket.application = await ( socket.application = await (
await fetch(`https://discord.com/api/v9/oauth2/applications/${socket.clientId}/rpc`) await fetch(`https://discord.com/api/v9/oauth2/applications/${socket.clientId}/rpc`)
).json(); ).json();
@ -41,28 +52,31 @@ class RPCServer {
log("fetched app info for", socket.clientId, socket.application); log("fetched app info for", socket.clientId, socket.application);
} }
const {activity, pid} = args; const {activity, pid} = args; // translate given parameters into what discord dispatch expects
const {buttons, timestamps, instance} = activity; const {buttons, timestamps, instance} = activity;
const metadata = {}; const metadata = {};
const extra = {}; const extra = {};
if (buttons) { if (buttons) {
// map buttons into expected metadata
metadata.button_urls = buttons.map((x) => x.url); metadata.button_urls = buttons.map((x) => x.url);
extra.buttons = buttons.map((x) => x.label); extra.buttons = buttons.map((x) => x.label);
} }
if (timestamps) if (timestamps)
for (const x in timestamps) { for (const x in timestamps) {
// translate s -> ms timestamps
if (Date.now().toString().length - timestamps[x].toString().length > 2) if (Date.now().toString().length - timestamps[x].toString().length > 2)
timestamps[x] = Math.floor(1e3 * timestamps[x]); timestamps[x] = Math.floor(1000 * timestamps[x]);
} }
// lookup assets to ids
if (activity.assets?.large_image) if (activity.assets?.large_image)
activity.assets.large_image = lookupAsset(activity.assets.large_image, socket.application.assets); activity.assets.large_image = lookupAsset(activity.assets.large_image, socket.application.assets);
if (activity.assets?.small_image) if (activity.assets?.small_image)
activity.assets.small_image = lookupAsset(activity.assets.small_image, socket.application.assets); activity.assets.small_image = lookupAsset(activity.assets.small_image, socket.application.assets);
Bridge.send({ this.emit("activity", {
activity: { activity: {
name: socket.application.name, name: socket.application.name,
application_id: socket.application.id, application_id: socket.application.id,
@ -76,6 +90,19 @@ class RPCServer {
}); });
break; break;
case "INVITE_BROWSER":
const {code} = args;
socket.send({
cmd,
data: {
code
},
nonce
});
this.emit("invite", code);
break;
} }
} }
} }

View File

@ -1,16 +1,20 @@
const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`; const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`;
const log = (...args) => console.log(`[${rgb(88, 101, 242, "arRPC")} > ${rgb(254, 231, 92, "ipc")}]`, ...args); const log = (...args) => console.log(`[${rgb(88, 101, 242, "arRPC")} > ${rgb(254, 231, 92, "ipc")}]`, ...args);
const path = require("path");
const {join} = require("path");
const {platform, env} = require("process"); const {platform, env} = require("process");
const {unlinkSync} = require("fs"); const {unlinkSync} = require("fs");
const {createServer, createConnection} = require("net"); const {createServer, createConnection} = require("net");
const SOCKET_PATH = const SOCKET_PATH =
platform === "win32" platform === "win32"
? "\\\\?\\pipe\\discord-ipc" ? "\\\\?\\pipe\\discord-ipc"
: path.join(env.XDG_RUNTIME_DIR || env.TMPDIR || env.TMP || env.TEMP || "/tmp", "discord-ipc"); : join(env.XDG_RUNTIME_DIR || env.TMPDIR || env.TMP || env.TEMP || "/tmp", "discord-ipc");
// enums for various constants
const Types = { const Types = {
// types of packets
HANDSHAKE: 0, HANDSHAKE: 0,
FRAME: 1, FRAME: 1,
CLOSE: 2, CLOSE: 2,
@ -19,12 +23,14 @@ const Types = {
}; };
const CloseCodes = { const CloseCodes = {
// codes for closures
CLOSE_NORMAL: 1000, CLOSE_NORMAL: 1000,
CLOSE_UNSUPPORTED: 1003, CLOSE_UNSUPPORTED: 1003,
CLOSE_ABNORMAL: 1006 CLOSE_ABNORMAL: 1006
}; };
const ErrorCodes = { const ErrorCodes = {
// codes for errors
INVALID_CLIENTID: 4000, INVALID_CLIENTID: 4000,
INVALID_ORIGIN: 4001, INVALID_ORIGIN: 4001,
RATELIMITED: 4002, RATELIMITED: 4002,
@ -120,7 +126,7 @@ const socketIsAvailable = async (socket) => {
}; };
const possibleOutcomes = Promise.race([ const possibleOutcomes = Promise.race([
new Promise((res) => socket.on("error", res)), // errore new Promise((res) => socket.on("error", res)), // errored
new Promise((res, rej) => socket.on("pong", () => rej("socket ponged"))), // ponged new Promise((res, rej) => socket.on("pong", () => rej("socket ponged"))), // ponged
new Promise((res, rej) => setTimeout(() => rej("timed out"), 1000)) // timed out new Promise((res, rej) => setTimeout(() => rej("timed out"), 1000)) // timed out
]).then( ]).then(
@ -209,6 +215,7 @@ class IPCServer {
const ver = params.v ?? 1; const ver = params.v ?? 1;
const clientId = params.client_id ?? ""; const clientId = params.client_id ?? "";
// encoding is always json for ipc
if (ver !== 1) { if (ver !== 1) {
log("unsupported version requested", ver); log("unsupported version requested", ver);
@ -251,5 +258,4 @@ class IPCServer {
this.messageHandler(socket, msg); this.messageHandler(socket, msg);
} }
} }
module.exports = {IPCServer}; module.exports = {IPCServer};

View File

@ -1,14 +1,15 @@
const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`; const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`;
const log = (...args) => console.log(`[${rgb(88, 101, 242, "arRPC")} > ${rgb(235, 69, 158, "websocket")}]`, ...args); const log = (...args) => console.log(`[${rgb(88, 101, 242, "arRPC")} > ${rgb(235, 69, 158, "websocket")}]`, ...args);
const ws = require("ws");
const {createServer} = require("http");
const querystring = require("querystring");
const portRange = [6463, 6472]; const {WebSocketServer} = require("ws");
const {createServer} = require("http");
const {parse} = require("querystring");
var exportPort = 0000;
const portRange = [6463, 6472]; // ports available/possible: 6463-6472
class WSServer { class WSServer {
constructor(messageHandler, connectionHandler) { constructor(messageHandler, connectionHandler) {
return new Promise(async (res) => { return (async () => {
this.messageHandler = messageHandler; this.messageHandler = messageHandler;
this.connectionHandler = connectionHandler; this.connectionHandler = connectionHandler;
@ -19,54 +20,60 @@ class WSServer {
let http, wss; let http, wss;
while (port <= portRange[1]) { while (port <= portRange[1]) {
try { log("trying port", port);
log("trying port", port);
http = createServer(); if (
http.on("error", (e) => { await new Promise((res) => {
log("http error", e); http = createServer();
http.on("error", (e) => {
// log('http error', e);
if (e.code === "EADDRINUSE") { if (e.code === "EADDRINUSE") {
log(port, "in use!"); log(port, "in use!");
} res(false);
}); }
});
wss = new ws.WebSocketServer({server: http}); wss = new WebSocketServer({server: http});
wss.on("error", (e) => { wss.on("error", (e) => {
log("wss error", e); // log('wss error', e);
}); });
wss.on("connection", this.onConnection); wss.on("connection", this.onConnection);
http.listen(port, "127.0.0.1", () => { http.listen(port, "127.0.0.1", () => {
log("listening on", port); log("listening on", port);
exportPort = port;
this.http = http;
this.wss = wss;
this.http = http; res(true);
this.wss = wss; });
})
res(this); )
}); break;
} catch (e) { port++;
log("failed to start", e);
}
break;
} }
});
return this;
})();
} }
onConnection(socket, req) { onConnection(socket, req) {
const params = querystring.parse(req.url.split("?")[1]); const params = parse(req.url.split("?")[1]);
const ver = parseInt(params.v ?? 1); const ver = parseInt(params.v ?? 1);
const encoding = params.encoding ?? "json"; const encoding = params.encoding ?? "json"; // json | etf (erlpack)
const clientId = params.client_id ?? ""; const clientId = params.client_id ?? "";
const origin = req.headers.origin ?? ""; const origin = req.headers.origin ?? "";
log(`new connection! origin:`, origin, JSON.parse(JSON.stringify(params))); log(`new connection! origin:`, origin, JSON.parse(JSON.stringify(params)));
if (origin !== "") { if (
log("origin is defined, denying", origin); origin !== "" &&
!["https://discord.com", "https://ptb.discord.com", "https://canary.discord.com/"].includes(origin)
) {
log("disallowed origin", origin);
socket.close(); socket.close();
return; return;
@ -86,12 +93,12 @@ class WSServer {
return; return;
} }
if (clientId === "") { /* if (clientId === '') {
log("client id required"); log('client id required');
socket.close(); socket.close();
return; return;
} } */
socket.clientId = clientId; socket.clientId = clientId;
socket.encoding = encoding; socket.encoding = encoding;
@ -120,5 +127,4 @@ class WSServer {
this.messageHandler(socket, JSON.parse(msg)); this.messageHandler(socket, JSON.parse(msg));
} }
} }
module.exports = {WSServer, exportPort};
module.exports = {WSServer};

View File

@ -28,6 +28,13 @@ contextBridge.exposeInMainWorld("armcord", {
splashEnd: () => ipcRenderer.send("splashEnd"), splashEnd: () => ipcRenderer.send("splashEnd"),
openSettingsWindow: () => ipcRenderer.send("openSettingsWindow") openSettingsWindow: () => ipcRenderer.send("openSettingsWindow")
}); });
let windowCallback: (arg0: object) => void;
contextBridge.exposeInMainWorld("ArmCordRPC", {
listen: (callback: any) => (windowCallback = callback)
});
ipcRenderer.on("rpc", (event, data: object) => {
windowCallback(data);
});
//to be only used inside armcord internal setup/splash etc //to be only used inside armcord internal setup/splash etc
if (window.location.href.indexOf("splash.html") > -1 || window.location.href.indexOf("setup.html") > -1) { if (window.location.href.indexOf("splash.html") > -1 || window.location.href.indexOf("setup.html") > -1) {
contextBridge.exposeInMainWorld("armcordinternal", { contextBridge.exposeInMainWorld("armcordinternal", {

View File

@ -69,13 +69,10 @@ if (window.location.href.indexOf("splash.html") > -1) {
return Dispatcher.dispatch(event); return Dispatcher.dispatch(event);
}; };
})(); })();
const ws = new WebSocket('ws://localhost:1337'); // connect to arRPC bridge ArmCordRPC.listen((data) => {
ws.onmessage = x => { console.log(data)
msg = JSON.parse(x.data); dispatch({ type: "LOCAL_ACTIVITY_UPDATE", ...data });
console.log(msg); })
dispatch({ type: "LOCAL_ACTIVITY_UPDATE", ...msg }); // set RPC status
};
`); `);
const cssPath = path.join(__dirname, "../", "/content/css/discord.css"); const cssPath = path.join(__dirname, "../", "/content/css/discord.css");
addStyle(fs.readFileSync(cssPath, "utf8")); addStyle(fs.readFileSync(cssPath, "utf8"));

View File

@ -66,7 +66,8 @@
<input class="tgl tgl-light left" id="websocket" type="checkbox" /> <input class="tgl tgl-light left" id="websocket" type="checkbox" />
<label class="tgl-btn left" for="websocket"></label> <label class="tgl-btn left" for="websocket"></label>
<p class="description"> <p class="description">
Uses <a target="_blank" href="https://github.com/OpenAsar/arrpc">arRPC</a> to support Discord RPC (Rich Presence) with local programs on your machine. Work in progress. Uses <a target="_blank" href="https://github.com/OpenAsar/arrpc">arRPC</a> to support Discord RPC (Rich
Presence) with local programs on your machine. Work in progress.
</p> </p>
</div> </div>
<br /> <br />

View File

@ -1,7 +1,7 @@
import * as fs from "fs"; import * as fs from "fs";
import {app, dialog, session} from "electron"; import {app, dialog, session} from "electron";
import path from "path"; import path from "path";
import fetch from "node-fetch" import fetch from "cross-fetch"
import extract from "extract-zip" import extract from "extract-zip"
import util from "util" import util from "util"
const streamPipeline = util.promisify(require('stream').pipeline) const streamPipeline = util.promisify(require('stream').pipeline)