├── .github └── workflows │ ├── docs.yml │ └── test.yml ├── .gitignore ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── src ├── client.ts ├── index.ts ├── ipc.ts ├── managers │ ├── achievement.ts │ ├── base.ts │ ├── lobby.ts │ ├── networking.ts │ └── overlay.ts ├── packet.ts ├── presence.ts ├── types.ts └── util.ts ├── test ├── config-example.json └── index.js └── tsconfig.json /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Generate Docs 2 | 3 | on: 4 | push: 5 | branches: main 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | 11 | strategy: 12 | matrix: 13 | node-version: [14.x] 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Use Node.js ${{ matrix.node-version }} 18 | uses: actions/setup-node@v1 19 | with: 20 | node-version: ${{ matrix.node-version }} 21 | - name: Build 22 | run: | 23 | npm i -g typescript 24 | npm i 25 | npm i -g typedoc typedoc-plugin-markdown 26 | npx typedoc --plugin typedoc-plugin-markdown src/index.ts 27 | cd docs && mv modules.md index.md 28 | - name: Deploy 29 | if: success() 30 | uses: peaceiris/actions-gh-pages@v3 31 | with: 32 | github_token: ${{ secrets.GITHUB_TOKEN }} 33 | publish_dir: ./docs 34 | commit_message: ${{ github.event.head_commit.message }} 35 | keep_files: true 36 | enable_jekyll: false 37 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: push 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | strategy: 10 | matrix: 11 | node-version: [14.x] 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Use Node.js ${{ matrix.node-version }} 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: ${{ matrix.node-version }} 19 | - run: npm i 20 | - run: npm i typescript 21 | - run: npm ci 22 | - run: npm run build --if-present 23 | - run: npm test 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /dist 3 | /.vscode 4 | /test/config.json 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2021 DjDeveloperr 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RPCord 2 | 3 | ![[NPM](https://npmjs.org/package/rpcord)](https://img.shields.io/npm/v/rpcord) 4 | 5 | Module to interact with local Discord Client using IPC. 6 | 7 | ## Features 8 | 9 | - All RPC Commands supported. 10 | - Simple interface. 11 | - Made with TypeScript. 12 | 13 | ## Docs 14 | 15 | Read the docs [here](https://github.com/DjDeveloperr/RPCord/blob/gh-pages/modules.md). 16 | 17 | ## Installation 18 | 19 | You can install from [NPM](https://npmjs.org/package/rpcord). 20 | 21 | ``` 22 | npm i rpcord 23 | ``` 24 | 25 | ## Example 26 | 27 | ```ts 28 | const { RPClient, Presence } = require("rpcord"); 29 | 30 | const rpc = new RPClient("803507787497865226"); 31 | 32 | rpc.on("ready", () => { 33 | console.log("Connected!"); 34 | }); 35 | 36 | rpc.connect().then(() => { 37 | rpc.setActivity( 38 | new Presence() 39 | .setLargeImage("discord") 40 | .setDetails("Nothing") 41 | .setState("Idling") 42 | .setStartTimestamp(Date.now()) 43 | .setPartyID("12345") 44 | .setPartySize(1, 2) 45 | .addButton({ 46 | label: "RPCord Repo", 47 | url: "https://github.com/DjDeveloperr/RPCord", 48 | }) 49 | .addButton({ 50 | label: "RPCord NPM", 51 | url: "https://npmjs.org/package/rpcord", 52 | }) 53 | ); 54 | }); 55 | ``` 56 | 57 | Or an advanced one! 58 | 59 | ```ts 60 | const { RPClient } = require("rpcord"); 61 | 62 | const rpc = new RPClient("client_id", { 63 | secret: "client_secret", 64 | scopes: ["rpc", "messages.read"], 65 | }); 66 | 67 | rpc.on("ready", () => { 68 | console.log("Connected!"); 69 | }); 70 | 71 | rpc.on("messageCreate", console.log); 72 | 73 | rpc.connect().then(() => { 74 | rpc.authorize().then(() => { 75 | rpc.subscribe("MESSAGE_CREATE", { channel_id: "channel_id" }); 76 | }); 77 | }); 78 | ``` 79 | 80 | ## Note 81 | 82 | For now, OAuth only works if you have at least one Redirect URI set in Developer Portal. 83 | 84 | ## Contributing 85 | 86 | You're always welcome to contribute! 87 | 88 | ## License 89 | 90 | Check [LICENSE](LICENSE) for more info. 91 | 92 | Copyright 2021 @ DjDeveloperr 93 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rpcord", 3 | "version": "1.0.6", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.12.11", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", 10 | "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.10.4" 14 | } 15 | }, 16 | "@babel/core": { 17 | "version": "7.12.10", 18 | "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz", 19 | "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==", 20 | "dev": true, 21 | "requires": { 22 | "@babel/code-frame": "^7.10.4", 23 | "@babel/generator": "^7.12.10", 24 | "@babel/helper-module-transforms": "^7.12.1", 25 | "@babel/helpers": "^7.12.5", 26 | "@babel/parser": "^7.12.10", 27 | "@babel/template": "^7.12.7", 28 | "@babel/traverse": "^7.12.10", 29 | "@babel/types": "^7.12.10", 30 | "convert-source-map": "^1.7.0", 31 | "debug": "^4.1.0", 32 | "gensync": "^1.0.0-beta.1", 33 | "json5": "^2.1.2", 34 | "lodash": "^4.17.19", 35 | "semver": "^5.4.1", 36 | "source-map": "^0.5.0" 37 | } 38 | }, 39 | "@babel/generator": { 40 | "version": "7.12.11", 41 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", 42 | "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", 43 | "dev": true, 44 | "requires": { 45 | "@babel/types": "^7.12.11", 46 | "jsesc": "^2.5.1", 47 | "source-map": "^0.5.0" 48 | } 49 | }, 50 | "@babel/helper-function-name": { 51 | "version": "7.12.11", 52 | "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz", 53 | "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==", 54 | "dev": true, 55 | "requires": { 56 | "@babel/helper-get-function-arity": "^7.12.10", 57 | "@babel/template": "^7.12.7", 58 | "@babel/types": "^7.12.11" 59 | } 60 | }, 61 | "@babel/helper-get-function-arity": { 62 | "version": "7.12.10", 63 | "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz", 64 | "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==", 65 | "dev": true, 66 | "requires": { 67 | "@babel/types": "^7.12.10" 68 | } 69 | }, 70 | "@babel/helper-member-expression-to-functions": { 71 | "version": "7.12.7", 72 | "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz", 73 | "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==", 74 | "dev": true, 75 | "requires": { 76 | "@babel/types": "^7.12.7" 77 | } 78 | }, 79 | "@babel/helper-module-imports": { 80 | "version": "7.12.5", 81 | "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", 82 | "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", 83 | "dev": true, 84 | "requires": { 85 | "@babel/types": "^7.12.5" 86 | } 87 | }, 88 | "@babel/helper-module-transforms": { 89 | "version": "7.12.1", 90 | "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz", 91 | "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==", 92 | "dev": true, 93 | "requires": { 94 | "@babel/helper-module-imports": "^7.12.1", 95 | "@babel/helper-replace-supers": "^7.12.1", 96 | "@babel/helper-simple-access": "^7.12.1", 97 | "@babel/helper-split-export-declaration": "^7.11.0", 98 | "@babel/helper-validator-identifier": "^7.10.4", 99 | "@babel/template": "^7.10.4", 100 | "@babel/traverse": "^7.12.1", 101 | "@babel/types": "^7.12.1", 102 | "lodash": "^4.17.19" 103 | } 104 | }, 105 | "@babel/helper-optimise-call-expression": { 106 | "version": "7.12.10", 107 | "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz", 108 | "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==", 109 | "dev": true, 110 | "requires": { 111 | "@babel/types": "^7.12.10" 112 | } 113 | }, 114 | "@babel/helper-replace-supers": { 115 | "version": "7.12.11", 116 | "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz", 117 | "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==", 118 | "dev": true, 119 | "requires": { 120 | "@babel/helper-member-expression-to-functions": "^7.12.7", 121 | "@babel/helper-optimise-call-expression": "^7.12.10", 122 | "@babel/traverse": "^7.12.10", 123 | "@babel/types": "^7.12.11" 124 | } 125 | }, 126 | "@babel/helper-simple-access": { 127 | "version": "7.12.1", 128 | "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz", 129 | "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==", 130 | "dev": true, 131 | "requires": { 132 | "@babel/types": "^7.12.1" 133 | } 134 | }, 135 | "@babel/helper-split-export-declaration": { 136 | "version": "7.12.11", 137 | "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz", 138 | "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==", 139 | "dev": true, 140 | "requires": { 141 | "@babel/types": "^7.12.11" 142 | } 143 | }, 144 | "@babel/helper-validator-identifier": { 145 | "version": "7.12.11", 146 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", 147 | "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", 148 | "dev": true 149 | }, 150 | "@babel/helpers": { 151 | "version": "7.12.5", 152 | "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz", 153 | "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==", 154 | "dev": true, 155 | "requires": { 156 | "@babel/template": "^7.10.4", 157 | "@babel/traverse": "^7.12.5", 158 | "@babel/types": "^7.12.5" 159 | } 160 | }, 161 | "@babel/highlight": { 162 | "version": "7.10.4", 163 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", 164 | "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", 165 | "dev": true, 166 | "requires": { 167 | "@babel/helper-validator-identifier": "^7.10.4", 168 | "chalk": "^2.0.0", 169 | "js-tokens": "^4.0.0" 170 | } 171 | }, 172 | "@babel/parser": { 173 | "version": "7.12.11", 174 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", 175 | "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==", 176 | "dev": true 177 | }, 178 | "@babel/template": { 179 | "version": "7.12.7", 180 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", 181 | "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==", 182 | "dev": true, 183 | "requires": { 184 | "@babel/code-frame": "^7.10.4", 185 | "@babel/parser": "^7.12.7", 186 | "@babel/types": "^7.12.7" 187 | } 188 | }, 189 | "@babel/traverse": { 190 | "version": "7.12.12", 191 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz", 192 | "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==", 193 | "dev": true, 194 | "requires": { 195 | "@babel/code-frame": "^7.12.11", 196 | "@babel/generator": "^7.12.11", 197 | "@babel/helper-function-name": "^7.12.11", 198 | "@babel/helper-split-export-declaration": "^7.12.11", 199 | "@babel/parser": "^7.12.11", 200 | "@babel/types": "^7.12.12", 201 | "debug": "^4.1.0", 202 | "globals": "^11.1.0", 203 | "lodash": "^4.17.19" 204 | } 205 | }, 206 | "@babel/types": { 207 | "version": "7.12.12", 208 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", 209 | "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", 210 | "dev": true, 211 | "requires": { 212 | "@babel/helper-validator-identifier": "^7.12.11", 213 | "lodash": "^4.17.19", 214 | "to-fast-properties": "^2.0.0" 215 | } 216 | }, 217 | "@nodelib/fs.scandir": { 218 | "version": "2.1.4", 219 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", 220 | "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", 221 | "dev": true, 222 | "requires": { 223 | "@nodelib/fs.stat": "2.0.4", 224 | "run-parallel": "^1.1.9" 225 | } 226 | }, 227 | "@nodelib/fs.stat": { 228 | "version": "2.0.4", 229 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", 230 | "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", 231 | "dev": true 232 | }, 233 | "@nodelib/fs.walk": { 234 | "version": "1.2.6", 235 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", 236 | "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", 237 | "dev": true, 238 | "requires": { 239 | "@nodelib/fs.scandir": "2.1.4", 240 | "fastq": "^1.6.0" 241 | } 242 | }, 243 | "@types/mdast": { 244 | "version": "3.0.3", 245 | "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.3.tgz", 246 | "integrity": "sha512-SXPBMnFVQg1s00dlMCc/jCdvPqdE4mXaMMCeRlxLDmTAEoegHT53xKtkDnzDTOcmMHUfcjyf36/YYZ6SxRdnsw==", 247 | "dev": true, 248 | "requires": { 249 | "@types/unist": "*" 250 | } 251 | }, 252 | "@types/node": { 253 | "version": "14.14.22", 254 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.22.tgz", 255 | "integrity": "sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw==", 256 | "dev": true 257 | }, 258 | "@types/node-fetch": { 259 | "version": "2.5.8", 260 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz", 261 | "integrity": "sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==", 262 | "dev": true, 263 | "requires": { 264 | "@types/node": "*", 265 | "form-data": "^3.0.0" 266 | } 267 | }, 268 | "@types/unist": { 269 | "version": "2.0.3", 270 | "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", 271 | "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", 272 | "dev": true 273 | }, 274 | "@types/uuid": { 275 | "version": "8.3.0", 276 | "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz", 277 | "integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==", 278 | "dev": true 279 | }, 280 | "ansi-styles": { 281 | "version": "3.2.1", 282 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 283 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 284 | "dev": true, 285 | "requires": { 286 | "color-convert": "^1.9.0" 287 | } 288 | }, 289 | "arg": { 290 | "version": "5.0.0", 291 | "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.0.tgz", 292 | "integrity": "sha512-4P8Zm2H+BRS+c/xX1LrHw0qKpEhdlZjLCgWy+d78T9vqa2Z2SiD2wMrYuWIAFy5IZUD7nnNXroRttz+0RzlrzQ==", 293 | "dev": true 294 | }, 295 | "array-union": { 296 | "version": "2.1.0", 297 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", 298 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 299 | "dev": true 300 | }, 301 | "asynckit": { 302 | "version": "0.4.0", 303 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 304 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 305 | "dev": true 306 | }, 307 | "bail": { 308 | "version": "1.0.5", 309 | "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", 310 | "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", 311 | "dev": true 312 | }, 313 | "braces": { 314 | "version": "3.0.2", 315 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 316 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 317 | "dev": true, 318 | "requires": { 319 | "fill-range": "^7.0.1" 320 | } 321 | }, 322 | "chalk": { 323 | "version": "2.4.2", 324 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 325 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 326 | "dev": true, 327 | "requires": { 328 | "ansi-styles": "^3.2.1", 329 | "escape-string-regexp": "^1.0.5", 330 | "supports-color": "^5.3.0" 331 | } 332 | }, 333 | "character-entities": { 334 | "version": "1.2.4", 335 | "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", 336 | "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", 337 | "dev": true 338 | }, 339 | "character-entities-legacy": { 340 | "version": "1.1.4", 341 | "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", 342 | "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", 343 | "dev": true 344 | }, 345 | "character-reference-invalid": { 346 | "version": "1.1.4", 347 | "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", 348 | "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", 349 | "dev": true 350 | }, 351 | "color-convert": { 352 | "version": "1.9.3", 353 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 354 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 355 | "dev": true, 356 | "requires": { 357 | "color-name": "1.1.3" 358 | } 359 | }, 360 | "color-name": { 361 | "version": "1.1.3", 362 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 363 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 364 | "dev": true 365 | }, 366 | "combined-stream": { 367 | "version": "1.0.8", 368 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 369 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 370 | "dev": true, 371 | "requires": { 372 | "delayed-stream": "~1.0.0" 373 | } 374 | }, 375 | "comment-parser": { 376 | "version": "1.1.1", 377 | "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.1.1.tgz", 378 | "integrity": "sha512-vue7cRi1ZO5/72FJ+wZ5+siTSBlUv3ZksTk8bWD2IkaA6obitzMZP3yI65azTJLckwmi8lxfPP5Sd9oGuZ8e2g==", 379 | "dev": true 380 | }, 381 | "convert-source-map": { 382 | "version": "1.7.0", 383 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", 384 | "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", 385 | "dev": true, 386 | "requires": { 387 | "safe-buffer": "~5.1.1" 388 | } 389 | }, 390 | "debug": { 391 | "version": "4.3.1", 392 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 393 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 394 | "dev": true, 395 | "requires": { 396 | "ms": "2.1.2" 397 | } 398 | }, 399 | "delayed-stream": { 400 | "version": "1.0.0", 401 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 402 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 403 | "dev": true 404 | }, 405 | "dir-glob": { 406 | "version": "3.0.1", 407 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 408 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 409 | "dev": true, 410 | "requires": { 411 | "path-type": "^4.0.0" 412 | } 413 | }, 414 | "doctrine": { 415 | "version": "3.0.0", 416 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 417 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 418 | "dev": true, 419 | "requires": { 420 | "esutils": "^2.0.2" 421 | } 422 | }, 423 | "emoji-regex": { 424 | "version": "6.1.1", 425 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", 426 | "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", 427 | "dev": true 428 | }, 429 | "escape-string-regexp": { 430 | "version": "1.0.5", 431 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 432 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 433 | "dev": true 434 | }, 435 | "esutils": { 436 | "version": "2.0.3", 437 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 438 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 439 | "dev": true 440 | }, 441 | "extend": { 442 | "version": "3.0.2", 443 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 444 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", 445 | "dev": true 446 | }, 447 | "fast-glob": { 448 | "version": "3.2.5", 449 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", 450 | "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", 451 | "dev": true, 452 | "requires": { 453 | "@nodelib/fs.stat": "^2.0.2", 454 | "@nodelib/fs.walk": "^1.2.3", 455 | "glob-parent": "^5.1.0", 456 | "merge2": "^1.3.0", 457 | "micromatch": "^4.0.2", 458 | "picomatch": "^2.2.1" 459 | } 460 | }, 461 | "fastq": { 462 | "version": "1.10.1", 463 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", 464 | "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", 465 | "dev": true, 466 | "requires": { 467 | "reusify": "^1.0.4" 468 | } 469 | }, 470 | "fill-range": { 471 | "version": "7.0.1", 472 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 473 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 474 | "dev": true, 475 | "requires": { 476 | "to-regex-range": "^5.0.1" 477 | } 478 | }, 479 | "form-data": { 480 | "version": "3.0.0", 481 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", 482 | "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", 483 | "dev": true, 484 | "requires": { 485 | "asynckit": "^0.4.0", 486 | "combined-stream": "^1.0.8", 487 | "mime-types": "^2.1.12" 488 | } 489 | }, 490 | "gensync": { 491 | "version": "1.0.0-beta.2", 492 | "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", 493 | "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", 494 | "dev": true 495 | }, 496 | "github-slugger": { 497 | "version": "1.3.0", 498 | "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.3.0.tgz", 499 | "integrity": "sha512-gwJScWVNhFYSRDvURk/8yhcFBee6aFjye2a7Lhb2bUyRulpIoek9p0I9Kt7PT67d/nUlZbFu8L9RLiA0woQN8Q==", 500 | "dev": true, 501 | "requires": { 502 | "emoji-regex": ">=6.0.0 <=6.1.1" 503 | } 504 | }, 505 | "glob-parent": { 506 | "version": "5.1.1", 507 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 508 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 509 | "dev": true, 510 | "requires": { 511 | "is-glob": "^4.0.1" 512 | } 513 | }, 514 | "globals": { 515 | "version": "11.12.0", 516 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 517 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 518 | "dev": true 519 | }, 520 | "globby": { 521 | "version": "11.0.2", 522 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", 523 | "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", 524 | "dev": true, 525 | "requires": { 526 | "array-union": "^2.1.0", 527 | "dir-glob": "^3.0.1", 528 | "fast-glob": "^3.1.1", 529 | "ignore": "^5.1.4", 530 | "merge2": "^1.3.0", 531 | "slash": "^3.0.0" 532 | } 533 | }, 534 | "has-flag": { 535 | "version": "3.0.0", 536 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 537 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 538 | "dev": true 539 | }, 540 | "ignore": { 541 | "version": "5.1.8", 542 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", 543 | "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", 544 | "dev": true 545 | }, 546 | "is-alphabetical": { 547 | "version": "1.0.4", 548 | "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", 549 | "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", 550 | "dev": true 551 | }, 552 | "is-alphanumerical": { 553 | "version": "1.0.4", 554 | "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", 555 | "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", 556 | "dev": true, 557 | "requires": { 558 | "is-alphabetical": "^1.0.0", 559 | "is-decimal": "^1.0.0" 560 | } 561 | }, 562 | "is-buffer": { 563 | "version": "2.0.5", 564 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", 565 | "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", 566 | "dev": true 567 | }, 568 | "is-decimal": { 569 | "version": "1.0.4", 570 | "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", 571 | "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", 572 | "dev": true 573 | }, 574 | "is-extglob": { 575 | "version": "2.1.1", 576 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 577 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 578 | "dev": true 579 | }, 580 | "is-glob": { 581 | "version": "4.0.1", 582 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 583 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 584 | "dev": true, 585 | "requires": { 586 | "is-extglob": "^2.1.1" 587 | } 588 | }, 589 | "is-hexadecimal": { 590 | "version": "1.0.4", 591 | "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", 592 | "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", 593 | "dev": true 594 | }, 595 | "is-number": { 596 | "version": "7.0.0", 597 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 598 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 599 | "dev": true 600 | }, 601 | "is-plain-obj": { 602 | "version": "2.1.0", 603 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 604 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 605 | "dev": true 606 | }, 607 | "js-tokens": { 608 | "version": "4.0.0", 609 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 610 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 611 | "dev": true 612 | }, 613 | "jsdoc-md": { 614 | "version": "9.1.0", 615 | "resolved": "https://registry.npmjs.org/jsdoc-md/-/jsdoc-md-9.1.0.tgz", 616 | "integrity": "sha512-+Jy6PfuO8QniDpK8oMBD9kHOIkLIJ4mt1TTR6vDspg/rZT5OjnZ2OCJ0wG17dv+Iorql/Q4GBIBYr1zI8KhyxA==", 617 | "dev": true, 618 | "requires": { 619 | "@babel/code-frame": "^7.12.11", 620 | "@babel/core": "^7.12.10", 621 | "arg": "^5.0.0", 622 | "comment-parser": "^1.1.1", 623 | "doctrine": "^3.0.0", 624 | "github-slugger": "^1.3.0", 625 | "globby": "^11.0.2", 626 | "kleur": "^4.1.4", 627 | "mdast-util-inject": "^1.1.0", 628 | "remark-behead": "^2.3.3", 629 | "remark-gfm": "^1.0.0", 630 | "remark-parse": "^9.0.0", 631 | "remark-stringify": "^9.0.1", 632 | "remark-toc": "^7.0.0", 633 | "unified": "^9.2.0", 634 | "unist-util-remove-position": "^3.0.0" 635 | } 636 | }, 637 | "jsesc": { 638 | "version": "2.5.2", 639 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", 640 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", 641 | "dev": true 642 | }, 643 | "json5": { 644 | "version": "2.1.3", 645 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", 646 | "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", 647 | "dev": true, 648 | "requires": { 649 | "minimist": "^1.2.5" 650 | } 651 | }, 652 | "kleur": { 653 | "version": "4.1.4", 654 | "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", 655 | "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==", 656 | "dev": true 657 | }, 658 | "lodash": { 659 | "version": "4.17.20", 660 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", 661 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", 662 | "dev": true 663 | }, 664 | "lodash.iteratee": { 665 | "version": "4.7.0", 666 | "resolved": "https://registry.npmjs.org/lodash.iteratee/-/lodash.iteratee-4.7.0.tgz", 667 | "integrity": "sha1-vkF32yiajMw8CZDx2ya1si/BVUw=", 668 | "dev": true 669 | }, 670 | "longest-streak": { 671 | "version": "2.0.4", 672 | "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", 673 | "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==", 674 | "dev": true 675 | }, 676 | "markdown-table": { 677 | "version": "2.0.0", 678 | "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", 679 | "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", 680 | "dev": true, 681 | "requires": { 682 | "repeat-string": "^1.0.0" 683 | } 684 | }, 685 | "mdast-util-from-markdown": { 686 | "version": "0.8.4", 687 | "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.4.tgz", 688 | "integrity": "sha512-jj891B5pV2r63n2kBTFh8cRI2uR9LQHsXG1zSDqfhXkIlDzrTcIlbB5+5aaYEkl8vOPIOPLf8VT7Ere1wWTMdw==", 689 | "dev": true, 690 | "requires": { 691 | "@types/mdast": "^3.0.0", 692 | "mdast-util-to-string": "^2.0.0", 693 | "micromark": "~2.11.0", 694 | "parse-entities": "^2.0.0", 695 | "unist-util-stringify-position": "^2.0.0" 696 | }, 697 | "dependencies": { 698 | "mdast-util-to-string": { 699 | "version": "2.0.0", 700 | "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", 701 | "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", 702 | "dev": true 703 | } 704 | } 705 | }, 706 | "mdast-util-gfm": { 707 | "version": "0.1.1", 708 | "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-0.1.1.tgz", 709 | "integrity": "sha512-oE1W1zSXU2L2LHg91V22HC3Z1fbsOZTBYUQq+kpM29f9297TbRm0C1l3bQ88RREl0WaUQaB49G7trvwy5utUKQ==", 710 | "dev": true, 711 | "requires": { 712 | "mdast-util-gfm-autolink-literal": "^0.1.0", 713 | "mdast-util-gfm-strikethrough": "^0.2.0", 714 | "mdast-util-gfm-table": "^0.1.0", 715 | "mdast-util-gfm-task-list-item": "^0.1.0", 716 | "mdast-util-to-markdown": "^0.6.1" 717 | } 718 | }, 719 | "mdast-util-gfm-autolink-literal": { 720 | "version": "0.1.2", 721 | "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-0.1.2.tgz", 722 | "integrity": "sha512-WFeIrcNNsfBety0gyWuiBIPing9UkVcl/m2iZOyW1uHEH2evjFocet2h77M24ub0WyZ4ucnQn/jWhO5Ozl6j4g==", 723 | "dev": true 724 | }, 725 | "mdast-util-gfm-strikethrough": { 726 | "version": "0.2.3", 727 | "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-0.2.3.tgz", 728 | "integrity": "sha512-5OQLXpt6qdbttcDG/UxYY7Yjj3e8P7X16LzvpX8pIQPYJ/C2Z1qFGMmcw+1PZMUM3Z8wt8NRfYTvCni93mgsgA==", 729 | "dev": true, 730 | "requires": { 731 | "mdast-util-to-markdown": "^0.6.0" 732 | } 733 | }, 734 | "mdast-util-gfm-table": { 735 | "version": "0.1.6", 736 | "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-0.1.6.tgz", 737 | "integrity": "sha512-j4yDxQ66AJSBwGkbpFEp9uG/LS1tZV3P33fN1gkyRB2LoRL+RR3f76m0HPHaby6F4Z5xr9Fv1URmATlRRUIpRQ==", 738 | "dev": true, 739 | "requires": { 740 | "markdown-table": "^2.0.0", 741 | "mdast-util-to-markdown": "~0.6.0" 742 | } 743 | }, 744 | "mdast-util-gfm-task-list-item": { 745 | "version": "0.1.6", 746 | "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-0.1.6.tgz", 747 | "integrity": "sha512-/d51FFIfPsSmCIRNp7E6pozM9z1GYPIkSy1urQ8s/o4TC22BZ7DqfHFWiqBD23bc7J3vV1Fc9O4QIHBlfuit8A==", 748 | "dev": true, 749 | "requires": { 750 | "mdast-util-to-markdown": "~0.6.0" 751 | } 752 | }, 753 | "mdast-util-inject": { 754 | "version": "1.1.0", 755 | "resolved": "https://registry.npmjs.org/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", 756 | "integrity": "sha1-2wa4tYW+lZotzS+H9HK6m3VvNnU=", 757 | "dev": true, 758 | "requires": { 759 | "mdast-util-to-string": "^1.0.0" 760 | } 761 | }, 762 | "mdast-util-to-markdown": { 763 | "version": "0.6.2", 764 | "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.2.tgz", 765 | "integrity": "sha512-iRczns6WMvu0hUw02LXsPDJshBIwtUPbvHBWo19IQeU0YqmzlA8Pd30U8V7uiI0VPkxzS7A/NXBXH6u+HS87Zg==", 766 | "dev": true, 767 | "requires": { 768 | "@types/unist": "^2.0.0", 769 | "longest-streak": "^2.0.0", 770 | "mdast-util-to-string": "^2.0.0", 771 | "parse-entities": "^2.0.0", 772 | "repeat-string": "^1.0.0", 773 | "zwitch": "^1.0.0" 774 | }, 775 | "dependencies": { 776 | "mdast-util-to-string": { 777 | "version": "2.0.0", 778 | "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", 779 | "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", 780 | "dev": true 781 | } 782 | } 783 | }, 784 | "mdast-util-to-string": { 785 | "version": "1.1.0", 786 | "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", 787 | "integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==", 788 | "dev": true 789 | }, 790 | "mdast-util-toc": { 791 | "version": "5.1.0", 792 | "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-5.1.0.tgz", 793 | "integrity": "sha512-csimbRIVkiqc+PpFeKDGQ/Ck2N4f9FYH3zzBMMJzcxoKL8m+cM0n94xXm0I9eaxHnKdY9n145SGTdyJC7i273g==", 794 | "dev": true, 795 | "requires": { 796 | "@types/mdast": "^3.0.3", 797 | "@types/unist": "^2.0.3", 798 | "extend": "^3.0.2", 799 | "github-slugger": "^1.2.1", 800 | "mdast-util-to-string": "^2.0.0", 801 | "unist-util-is": "^4.0.0", 802 | "unist-util-visit": "^2.0.0" 803 | }, 804 | "dependencies": { 805 | "mdast-util-to-string": { 806 | "version": "2.0.0", 807 | "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", 808 | "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", 809 | "dev": true 810 | }, 811 | "unist-util-is": { 812 | "version": "4.0.4", 813 | "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.4.tgz", 814 | "integrity": "sha512-3dF39j/u423v4BBQrk1AQ2Ve1FxY5W3JKwXxVFzBODQ6WEvccguhgp802qQLKSnxPODE6WuRZtV+ohlUg4meBA==", 815 | "dev": true 816 | } 817 | } 818 | }, 819 | "merge2": { 820 | "version": "1.4.1", 821 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 822 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 823 | "dev": true 824 | }, 825 | "micromark": { 826 | "version": "2.11.2", 827 | "resolved": "https://registry.npmjs.org/micromark/-/micromark-2.11.2.tgz", 828 | "integrity": "sha512-IXuP76p2uj8uMg4FQc1cRE7lPCLsfAXuEfdjtdO55VRiFO1asrCSQ5g43NmPqFtRwzEnEhafRVzn2jg0UiKArQ==", 829 | "dev": true, 830 | "requires": { 831 | "debug": "^4.0.0", 832 | "parse-entities": "^2.0.0" 833 | } 834 | }, 835 | "micromark-extension-gfm": { 836 | "version": "0.3.2", 837 | "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-0.3.2.tgz", 838 | "integrity": "sha512-ToQEpLkRgg7Tp8D3GM/SjZFPV0cCwWNxZmoEVIOQivOswRtPg7gg2WlCrtHhUWFNX+DgDjbq0iLOPGp4Y15oug==", 839 | "dev": true, 840 | "requires": { 841 | "micromark": "~2.11.0", 842 | "micromark-extension-gfm-autolink-literal": "~0.5.0", 843 | "micromark-extension-gfm-strikethrough": "~0.6.0", 844 | "micromark-extension-gfm-table": "~0.4.0", 845 | "micromark-extension-gfm-tagfilter": "~0.3.0", 846 | "micromark-extension-gfm-task-list-item": "~0.3.0" 847 | } 848 | }, 849 | "micromark-extension-gfm-autolink-literal": { 850 | "version": "0.5.5", 851 | "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.5.tgz", 852 | "integrity": "sha512-UBK5/7efGCyfNW3bGAOIB0zaMfclhXi7/f4JPJkLCBgoksPJJs2UeX/uk2FS7H/cbnGd7L7X0CbNkH6ceK82Ww==", 853 | "dev": true, 854 | "requires": { 855 | "micromark": "~2.11.0" 856 | } 857 | }, 858 | "micromark-extension-gfm-strikethrough": { 859 | "version": "0.6.3", 860 | "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-0.6.3.tgz", 861 | "integrity": "sha512-MKMoP9x2dsr1aeX46ibBwVf4Q6nJsi5aaUFTOMOID5VOLSxwl4CrqUV4OGFQd6AqhtzBJAxaV+N2trlTBtZDNQ==", 862 | "dev": true, 863 | "requires": { 864 | "micromark": "~2.11.0" 865 | } 866 | }, 867 | "micromark-extension-gfm-table": { 868 | "version": "0.4.2", 869 | "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-0.4.2.tgz", 870 | "integrity": "sha512-AAzmj85XO1ydHYX0Lz52HGhcH2sZLm2AVvkwzELXWgZF6vGdq5yZ3CTByFRsqNUPyQBSIYFKLDAtc6KlnO42aw==", 871 | "dev": true, 872 | "requires": { 873 | "micromark": "~2.11.0" 874 | } 875 | }, 876 | "micromark-extension-gfm-tagfilter": { 877 | "version": "0.3.0", 878 | "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-0.3.0.tgz", 879 | "integrity": "sha512-9GU0xBatryXifL//FJH+tAZ6i240xQuFrSL7mYi8f4oZSbc+NvXjkrHemeYP0+L4ZUT+Ptz3b95zhUZnMtoi/Q==", 880 | "dev": true 881 | }, 882 | "micromark-extension-gfm-task-list-item": { 883 | "version": "0.3.3", 884 | "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-0.3.3.tgz", 885 | "integrity": "sha512-0zvM5iSLKrc/NQl84pZSjGo66aTGd57C1idmlWmE87lkMcXrTxg1uXa/nXomxJytoje9trP0NDLvw4bZ/Z/XCQ==", 886 | "dev": true, 887 | "requires": { 888 | "micromark": "~2.11.0" 889 | } 890 | }, 891 | "micromatch": { 892 | "version": "4.0.2", 893 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", 894 | "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", 895 | "dev": true, 896 | "requires": { 897 | "braces": "^3.0.1", 898 | "picomatch": "^2.0.5" 899 | } 900 | }, 901 | "mime-db": { 902 | "version": "1.45.0", 903 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", 904 | "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", 905 | "dev": true 906 | }, 907 | "mime-types": { 908 | "version": "2.1.28", 909 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", 910 | "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", 911 | "dev": true, 912 | "requires": { 913 | "mime-db": "1.45.0" 914 | } 915 | }, 916 | "minimist": { 917 | "version": "1.2.5", 918 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 919 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 920 | "dev": true 921 | }, 922 | "ms": { 923 | "version": "2.1.2", 924 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 925 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 926 | "dev": true 927 | }, 928 | "node-fetch": { 929 | "version": "2.6.1", 930 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", 931 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" 932 | }, 933 | "parse-entities": { 934 | "version": "2.0.0", 935 | "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", 936 | "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", 937 | "dev": true, 938 | "requires": { 939 | "character-entities": "^1.0.0", 940 | "character-entities-legacy": "^1.0.0", 941 | "character-reference-invalid": "^1.0.0", 942 | "is-alphanumerical": "^1.0.0", 943 | "is-decimal": "^1.0.0", 944 | "is-hexadecimal": "^1.0.0" 945 | } 946 | }, 947 | "path-type": { 948 | "version": "4.0.0", 949 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 950 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 951 | "dev": true 952 | }, 953 | "picomatch": { 954 | "version": "2.2.2", 955 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 956 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 957 | "dev": true 958 | }, 959 | "remark-behead": { 960 | "version": "2.3.3", 961 | "resolved": "https://registry.npmjs.org/remark-behead/-/remark-behead-2.3.3.tgz", 962 | "integrity": "sha512-quY6Of8Bwj4pgrG/Qce6a/sMMzFc0XxbfeYko+mPjOScIB+TKw3T0Y2GUcIEL8+xbQgAnCylkPQNt9haCEWK9w==", 963 | "dev": true, 964 | "requires": { 965 | "unist-util-find": "^1.0.1", 966 | "unist-util-find-all-after": "^3.0.1", 967 | "unist-util-find-all-before": "^2.0.5", 968 | "unist-util-find-all-between": "^2.0.0", 969 | "unist-util-visit": "^2.0.3" 970 | } 971 | }, 972 | "remark-gfm": { 973 | "version": "1.0.0", 974 | "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-1.0.0.tgz", 975 | "integrity": "sha512-KfexHJCiqvrdBZVbQ6RopMZGwaXz6wFJEfByIuEwGf0arvITHjiKKZ1dpXujjH9KZdm1//XJQwgfnJ3lmXaDPA==", 976 | "dev": true, 977 | "requires": { 978 | "mdast-util-gfm": "^0.1.0", 979 | "micromark-extension-gfm": "^0.3.0" 980 | } 981 | }, 982 | "remark-parse": { 983 | "version": "9.0.0", 984 | "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz", 985 | "integrity": "sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==", 986 | "dev": true, 987 | "requires": { 988 | "mdast-util-from-markdown": "^0.8.0" 989 | } 990 | }, 991 | "remark-stringify": { 992 | "version": "9.0.1", 993 | "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-9.0.1.tgz", 994 | "integrity": "sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg==", 995 | "dev": true, 996 | "requires": { 997 | "mdast-util-to-markdown": "^0.6.0" 998 | } 999 | }, 1000 | "remark-toc": { 1001 | "version": "7.0.0", 1002 | "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-7.0.0.tgz", 1003 | "integrity": "sha512-NyW/W7ttlj003eFXeIgq7eV2bffTQuO48PyC9zbh/RhTA/QaHJOAgJ4qvaRwKAVMWSBIh4W/5nZFWQ4rceV3fw==", 1004 | "dev": true, 1005 | "requires": { 1006 | "@types/unist": "^2.0.3", 1007 | "mdast-util-toc": "^5.0.0" 1008 | } 1009 | }, 1010 | "repeat-string": { 1011 | "version": "1.6.1", 1012 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 1013 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", 1014 | "dev": true 1015 | }, 1016 | "reusify": { 1017 | "version": "1.0.4", 1018 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1019 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1020 | "dev": true 1021 | }, 1022 | "run-parallel": { 1023 | "version": "1.1.10", 1024 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", 1025 | "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", 1026 | "dev": true 1027 | }, 1028 | "safe-buffer": { 1029 | "version": "5.1.2", 1030 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1031 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1032 | "dev": true 1033 | }, 1034 | "semver": { 1035 | "version": "5.7.1", 1036 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1037 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1038 | "dev": true 1039 | }, 1040 | "slash": { 1041 | "version": "3.0.0", 1042 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", 1043 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 1044 | "dev": true 1045 | }, 1046 | "source-map": { 1047 | "version": "0.5.7", 1048 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1049 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 1050 | "dev": true 1051 | }, 1052 | "supports-color": { 1053 | "version": "5.5.0", 1054 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1055 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1056 | "dev": true, 1057 | "requires": { 1058 | "has-flag": "^3.0.0" 1059 | } 1060 | }, 1061 | "to-fast-properties": { 1062 | "version": "2.0.0", 1063 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", 1064 | "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", 1065 | "dev": true 1066 | }, 1067 | "to-regex-range": { 1068 | "version": "5.0.1", 1069 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1070 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1071 | "dev": true, 1072 | "requires": { 1073 | "is-number": "^7.0.0" 1074 | } 1075 | }, 1076 | "trough": { 1077 | "version": "1.0.5", 1078 | "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", 1079 | "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", 1080 | "dev": true 1081 | }, 1082 | "typescript": { 1083 | "version": "4.1.3", 1084 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", 1085 | "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", 1086 | "dev": true 1087 | }, 1088 | "unified": { 1089 | "version": "9.2.0", 1090 | "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", 1091 | "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", 1092 | "dev": true, 1093 | "requires": { 1094 | "bail": "^1.0.0", 1095 | "extend": "^3.0.0", 1096 | "is-buffer": "^2.0.0", 1097 | "is-plain-obj": "^2.0.0", 1098 | "trough": "^1.0.0", 1099 | "vfile": "^4.0.0" 1100 | } 1101 | }, 1102 | "unist-util-find": { 1103 | "version": "1.0.2", 1104 | "resolved": "https://registry.npmjs.org/unist-util-find/-/unist-util-find-1.0.2.tgz", 1105 | "integrity": "sha512-ft06UDYzqi9o9RmGP0sZWI/zvLLQiBW2/MD+rW6mDqbOWDcmknGX9orQPspfuGRYWr8eSJAmfsBcvOpfGRJseA==", 1106 | "dev": true, 1107 | "requires": { 1108 | "lodash.iteratee": "^4.5.0", 1109 | "unist-util-visit": "^1.1.0" 1110 | }, 1111 | "dependencies": { 1112 | "unist-util-visit": { 1113 | "version": "1.4.1", 1114 | "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", 1115 | "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", 1116 | "dev": true, 1117 | "requires": { 1118 | "unist-util-visit-parents": "^2.0.0" 1119 | } 1120 | } 1121 | } 1122 | }, 1123 | "unist-util-find-all-after": { 1124 | "version": "3.0.2", 1125 | "resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-3.0.2.tgz", 1126 | "integrity": "sha512-xaTC/AGZ0rIM2gM28YVRAFPIZpzbpDtU3dRmp7EXlNVA8ziQc4hY3H7BHXM1J49nEmiqc3svnqMReW+PGqbZKQ==", 1127 | "dev": true, 1128 | "requires": { 1129 | "unist-util-is": "^4.0.0" 1130 | }, 1131 | "dependencies": { 1132 | "unist-util-is": { 1133 | "version": "4.0.4", 1134 | "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.4.tgz", 1135 | "integrity": "sha512-3dF39j/u423v4BBQrk1AQ2Ve1FxY5W3JKwXxVFzBODQ6WEvccguhgp802qQLKSnxPODE6WuRZtV+ohlUg4meBA==", 1136 | "dev": true 1137 | } 1138 | } 1139 | }, 1140 | "unist-util-find-all-before": { 1141 | "version": "2.0.5", 1142 | "resolved": "https://registry.npmjs.org/unist-util-find-all-before/-/unist-util-find-all-before-2.0.5.tgz", 1143 | "integrity": "sha512-lYakZyw3trON5qbsOsmtRARZTyKcQN8pkoMKLy558Nt8WhlqGAnRSD9qLrISkMKbS+0nhj8LiebgoheUtQXOZw==", 1144 | "dev": true, 1145 | "requires": { 1146 | "unist-util-is": "^4.0.0" 1147 | }, 1148 | "dependencies": { 1149 | "unist-util-is": { 1150 | "version": "4.0.4", 1151 | "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.4.tgz", 1152 | "integrity": "sha512-3dF39j/u423v4BBQrk1AQ2Ve1FxY5W3JKwXxVFzBODQ6WEvccguhgp802qQLKSnxPODE6WuRZtV+ohlUg4meBA==", 1153 | "dev": true 1154 | } 1155 | } 1156 | }, 1157 | "unist-util-find-all-between": { 1158 | "version": "2.1.0", 1159 | "resolved": "https://registry.npmjs.org/unist-util-find-all-between/-/unist-util-find-all-between-2.1.0.tgz", 1160 | "integrity": "sha512-OCCUtDD8UHKeODw3TPXyFDxPCbpgBzbGTTaDpR68nvxkwiVcawBqMVrokfBMvUi7ij2F5q7S4s4Jq5dvkcBt+w==", 1161 | "dev": true, 1162 | "requires": { 1163 | "unist-util-find": "^1.0.1", 1164 | "unist-util-is": "^4.0.2" 1165 | }, 1166 | "dependencies": { 1167 | "unist-util-is": { 1168 | "version": "4.0.4", 1169 | "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.4.tgz", 1170 | "integrity": "sha512-3dF39j/u423v4BBQrk1AQ2Ve1FxY5W3JKwXxVFzBODQ6WEvccguhgp802qQLKSnxPODE6WuRZtV+ohlUg4meBA==", 1171 | "dev": true 1172 | } 1173 | } 1174 | }, 1175 | "unist-util-is": { 1176 | "version": "3.0.0", 1177 | "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", 1178 | "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", 1179 | "dev": true 1180 | }, 1181 | "unist-util-remove-position": { 1182 | "version": "3.0.0", 1183 | "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-3.0.0.tgz", 1184 | "integrity": "sha512-17kIOuolVuK16LMb9KyMJlqdfCtlfQY5FjY3Sdo9iC7F5wqdXhNjMq0PBvMpkVNNnAmHxXssUW+rZ9T2zbP0Rg==", 1185 | "dev": true, 1186 | "requires": { 1187 | "unist-util-visit": "^2.0.0" 1188 | } 1189 | }, 1190 | "unist-util-stringify-position": { 1191 | "version": "2.0.3", 1192 | "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", 1193 | "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", 1194 | "dev": true, 1195 | "requires": { 1196 | "@types/unist": "^2.0.2" 1197 | } 1198 | }, 1199 | "unist-util-visit": { 1200 | "version": "2.0.3", 1201 | "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", 1202 | "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", 1203 | "dev": true, 1204 | "requires": { 1205 | "@types/unist": "^2.0.0", 1206 | "unist-util-is": "^4.0.0", 1207 | "unist-util-visit-parents": "^3.0.0" 1208 | }, 1209 | "dependencies": { 1210 | "unist-util-is": { 1211 | "version": "4.0.4", 1212 | "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.4.tgz", 1213 | "integrity": "sha512-3dF39j/u423v4BBQrk1AQ2Ve1FxY5W3JKwXxVFzBODQ6WEvccguhgp802qQLKSnxPODE6WuRZtV+ohlUg4meBA==", 1214 | "dev": true 1215 | }, 1216 | "unist-util-visit-parents": { 1217 | "version": "3.1.1", 1218 | "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", 1219 | "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", 1220 | "dev": true, 1221 | "requires": { 1222 | "@types/unist": "^2.0.0", 1223 | "unist-util-is": "^4.0.0" 1224 | } 1225 | } 1226 | } 1227 | }, 1228 | "unist-util-visit-parents": { 1229 | "version": "2.1.2", 1230 | "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", 1231 | "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", 1232 | "dev": true, 1233 | "requires": { 1234 | "unist-util-is": "^3.0.0" 1235 | } 1236 | }, 1237 | "uuid": { 1238 | "version": "8.3.2", 1239 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", 1240 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" 1241 | }, 1242 | "vfile": { 1243 | "version": "4.2.1", 1244 | "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", 1245 | "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", 1246 | "dev": true, 1247 | "requires": { 1248 | "@types/unist": "^2.0.0", 1249 | "is-buffer": "^2.0.0", 1250 | "unist-util-stringify-position": "^2.0.0", 1251 | "vfile-message": "^2.0.0" 1252 | } 1253 | }, 1254 | "vfile-message": { 1255 | "version": "2.0.4", 1256 | "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", 1257 | "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", 1258 | "dev": true, 1259 | "requires": { 1260 | "@types/unist": "^2.0.0", 1261 | "unist-util-stringify-position": "^2.0.0" 1262 | } 1263 | }, 1264 | "zwitch": { 1265 | "version": "1.0.5", 1266 | "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", 1267 | "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==", 1268 | "dev": true 1269 | } 1270 | } 1271 | } 1272 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rpcord", 3 | "version": "1.0.7", 4 | "description": "Module to interact with Discord IPC.", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "repository": { 8 | "url": "https://github.com/DjDeveloperr/RPCord" 9 | }, 10 | "scripts": { 11 | "test": "node dist/index.js", 12 | "build": "tsc" 13 | }, 14 | "author": "DjDeveloperr", 15 | "license": "MIT", 16 | "devDependencies": { 17 | "@types/node": "^14.14.22", 18 | "@types/node-fetch": "^2.5.8", 19 | "@types/uuid": "^8.3.0", 20 | "typescript": "^4.1.3" 21 | }, 22 | "dependencies": { 23 | "node-fetch": "^2.6.1", 24 | "uuid": "^8.3.2" 25 | } 26 | } -------------------------------------------------------------------------------- /src/client.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from "events"; 2 | import { DiscordIPC } from "./ipc"; 3 | import { Packet } from "./packet"; 4 | import { 5 | Application, 6 | ChannelPayload, 7 | ClientConfig, 8 | Command, 9 | Device, 10 | GetImageOptions, 11 | Guild, 12 | OpCode, 13 | PartialChannel, 14 | PartialGuild, 15 | Relationship, 16 | RPCEvent, 17 | ShortcutKeyCombo, 18 | User, 19 | UserVoiceSettings, 20 | VoiceSettings, 21 | } from "./types"; 22 | import fetch from "node-fetch"; 23 | import { Presence } from "./presence"; 24 | import { v4 } from "uuid"; 25 | import { LobbyManager } from "./managers/lobby"; 26 | import { AchievementManager } from "./managers/achievement"; 27 | import { OverlayManager } from "./managers/overlay"; 28 | import { NetworkingManager } from "./managers/networking"; 29 | 30 | export const IGNORED_AUTO_EVENTS: string[] = [ 31 | "OVERLAY", 32 | "OVERLAY_UPDATE", 33 | "READY", 34 | "ERROR", 35 | "MESSAGE_CREATE", 36 | "MESSAGE_DELETE", 37 | "MESSAGE_UPDATE", 38 | "NOTIFICATION_CREATE", 39 | "CAPTURE_SHORTCUT_CHANGE", 40 | "VOICE_CONNECTION_STATUS", 41 | "VOICE_SETTINGS_UPDATE", 42 | "VOICE_STATE_DELETE", 43 | "VOICE_STATE_UPDATE", 44 | "VOICE_STATE_CREATE", 45 | "VOICE_CHANNEL_SELECT", 46 | "CHANNEL_CREATE", 47 | "GUILD_CREATE", 48 | "GUILD_STATUS", 49 | ]; 50 | 51 | /** Client options to initialize. */ 52 | export interface RPClientOptions { 53 | secret?: string; 54 | scopes?: string[]; 55 | } 56 | 57 | /** High-level wrapper over Discord IPC. */ 58 | export class RPClient extends EventEmitter { 59 | /** Client ID */ 60 | id: string; 61 | /** Discord RPC Version */ 62 | v: number = 1; 63 | /** Internal IPC */ 64 | ipc: DiscordIPC; 65 | /** Whether Client is Authorized yet or not */ 66 | authorized: boolean = false; 67 | /** Whether Client is Authenticated yet or not */ 68 | authenticated: boolean = false; 69 | /** Auth Code saved from `authorize` */ 70 | authCode?: string; 71 | /** Access Token saved from `authenticate` */ 72 | accessToken?: string; 73 | /** Scopes to use for Authorization */ 74 | scopes?: string[]; 75 | /** Client Secret (for fetching Access Token from Auth Code) */ 76 | secret?: string; 77 | /** Underlying User account of the Discord Client */ 78 | user?: User; 79 | /** RPC Client Config (Discord) */ 80 | config?: ClientConfig; 81 | /** User's cached Voice Settings */ 82 | userVoiceSettings?: UserVoiceSettings; 83 | /** Expiration of Access Token */ 84 | expires?: number; 85 | /** Application object of the Client */ 86 | application?: Application; 87 | /** Whether Client is connected or not */ 88 | connected: boolean = false; 89 | 90 | lobbyManager: LobbyManager; 91 | achievementManager: AchievementManager; 92 | overlayManager: OverlayManager; 93 | networkingManager: NetworkingManager; 94 | private _subscribed: string[] = []; 95 | 96 | constructor(id: string, options?: RPClientOptions) { 97 | super(); 98 | this.id = id; 99 | if (options) { 100 | this.secret = options.secret; 101 | this.scopes = options.scopes; 102 | } 103 | 104 | this.ipc = new DiscordIPC(); 105 | this.ipc.on("connect", () => (this.connected = true)); 106 | this.ipc.on("close", () => (this.connected = false)); 107 | this.ipc.on("packet", (packet: Packet) => this.processPacket(packet)); 108 | 109 | this.lobbyManager = new LobbyManager(this); 110 | this.achievementManager = new AchievementManager(this); 111 | this.overlayManager = new OverlayManager(this); 112 | this.networkingManager = new NetworkingManager(this); 113 | this.setMaxListeners(100); 114 | } 115 | 116 | private processPacket(packet: Packet) { 117 | if (packet.op == OpCode.Close) { 118 | throw new Error( 119 | `Discord IPC Closed (${packet.data.code}): ${packet.data.message}` 120 | ); 121 | } 122 | 123 | switch (packet.op) { 124 | case OpCode.Frame: 125 | const cmd = packet.data.cmd as Command; 126 | const data = packet.data.data; 127 | const nonce = packet.data.nonce; 128 | 129 | if (packet.data.evt && packet.data.evt == "ERROR") { 130 | this.emit("error", data, nonce); 131 | } else { 132 | const evt = cmd 133 | .split("_") 134 | .map( 135 | (e, i) => 136 | `${i == 0 ? e[0].toLowerCase() : e[0].toUpperCase()}${e 137 | .slice(1) 138 | .toLowerCase()}` 139 | ) 140 | .join(""); 141 | 142 | switch (cmd) { 143 | case Command.Dispatch: 144 | this.emit("dispatch", packet.data, nonce); 145 | this.processEvent(packet.data.evt, data); 146 | break; 147 | 148 | case Command.Authorize: 149 | this.authorized = true; 150 | this.authCode = data.code; 151 | this.emit("authorize", data.code, nonce); 152 | this.fetchAccessToken(); 153 | break; 154 | 155 | case Command.Authenticate: 156 | this.authenticated = true; 157 | this.user = data.user; 158 | this.scopes = data.scopes; 159 | this.expires = data.expires; 160 | this.application = data.application; 161 | this.emit("authenticate", data, nonce); 162 | break; 163 | 164 | default: 165 | this.emit(evt, data, nonce); 166 | break; 167 | } 168 | } 169 | break; 170 | 171 | case OpCode.Ping: 172 | this.ipc.send(new Packet(OpCode.Pong, packet.data)); 173 | break; 174 | 175 | default: 176 | break; 177 | } 178 | } 179 | 180 | private async processEvent(evt: RPCEvent, data: any) { 181 | this.emit("raw", evt, data); 182 | 183 | switch (evt) { 184 | case RPCEvent.Ready: 185 | this.user = data.user; 186 | this.config = data.config; 187 | for (const e of Object.values(RPCEvent)) { 188 | if (IGNORED_AUTO_EVENTS.includes(e)) continue; 189 | try { 190 | await this.subscribe(e); 191 | } catch (e) {} 192 | } 193 | this.emit("ready"); 194 | break; 195 | 196 | case RPCEvent.CurrentUserUpdate: 197 | this.user = data; 198 | this.emit("currentUserUpdate", data); 199 | break; 200 | 201 | default: 202 | const event = evt 203 | .split("_") 204 | .map((e, i) => 205 | i == 0 206 | ? e.toLowerCase() 207 | : `${e[0].toUpperCase()}${e.slice(1).toLowerCase()}` 208 | ) 209 | .join(""); 210 | 211 | this.emit(event, data); 212 | break; 213 | } 214 | } 215 | 216 | /** Subscribe for an RPC Event. */ 217 | async subscribe(evt: RPCEvent, args?: any) { 218 | if (this._subscribed.includes(evt) && typeof args !== "object") return this; 219 | const nonce = v4(); 220 | 221 | const wait = this.waitFor("subscribe", (_, n) => n == nonce, 10000).then( 222 | () => { 223 | if (typeof args !== "object" && !this._subscribed.includes(evt)) 224 | this._subscribed.push(evt); 225 | return this; 226 | } 227 | ); 228 | 229 | this.ipc.send( 230 | new Packet(OpCode.Frame, { 231 | cmd: Command.Subscribe, 232 | args: args ?? {}, 233 | evt, 234 | nonce, 235 | }) 236 | ); 237 | 238 | return wait; 239 | } 240 | 241 | /** Unsubscribe from an RPC Event. */ 242 | async unsubscribe(evt: RPCEvent, args?: any) { 243 | const nonce = v4(); 244 | 245 | const wait = this.waitFor("unsubscribe", (_, n) => n == nonce, 10000).then( 246 | () => { 247 | if (typeof args !== "object" && this._subscribed.includes(evt)) 248 | this._subscribed = this._subscribed.filter((e) => e !== evt); 249 | return this; 250 | } 251 | ); 252 | 253 | this.ipc.send( 254 | new Packet(OpCode.Frame, { 255 | cmd: Command.Unsubscribe, 256 | args: args ?? {}, 257 | evt, 258 | nonce, 259 | }) 260 | ); 261 | 262 | return wait; 263 | } 264 | 265 | /** Connect to Discord IPC. */ 266 | async connect() { 267 | await this.ipc.connect(); 268 | 269 | const wait = this.waitFor("ready").then(() => this); 270 | 271 | this.ipc.send( 272 | new Packet(OpCode.Handshake, { 273 | v: 1, 274 | client_id: this.id, 275 | }) 276 | ); 277 | 278 | return wait; 279 | } 280 | 281 | /** Authorize for given scopes (or scopes in Client Options). */ 282 | async authorize(scopes?: string[]) { 283 | if (this.authorized || this.authenticated) 284 | throw new Error("Already authorized"); 285 | 286 | if (scopes) this.scopes = scopes; 287 | if (!this.scopes) this.scopes = ["rpc"]; 288 | 289 | if (!this.scopes.includes("rpc")) this.scopes.push("rpc"); 290 | 291 | const wait = this.waitFor("authenticate").then(() => this); 292 | 293 | this.ipc.send( 294 | new Packet(OpCode.Frame, { 295 | cmd: Command.Authorize, 296 | args: { 297 | client_id: this.id, 298 | scopes: this.scopes.join(" "), 299 | grant_type: "authorization_code", 300 | }, 301 | }) 302 | ); 303 | 304 | return wait; 305 | } 306 | 307 | /** Authenticate using an existing Access Token */ 308 | async authenticate(token?: string) { 309 | if (this.authenticated) throw new Error("Already Authenticated"); 310 | 311 | if (token) this.accessToken = token; 312 | if (!this.accessToken) throw new Error("Access Token is required"); 313 | 314 | const wait = this.waitFor("authenticate").then(() => this); 315 | 316 | this.ipc.send( 317 | new Packet(OpCode.Frame, { 318 | cmd: Command.Authenticate, 319 | args: { 320 | access_token: this.accessToken, 321 | }, 322 | }) 323 | ); 324 | 325 | return wait; 326 | } 327 | 328 | /** Fetches Access Token from given Auth Code */ 329 | private async fetchAccessToken(code?: string) { 330 | if (code) this.authCode = code; 331 | if (this.accessToken) throw new Error("Access Token already fetched"); 332 | if (!this.authCode) throw new Error("No Auth Code given"); 333 | 334 | const form = new URLSearchParams(); 335 | form.set("client_id", this.id); 336 | form.set("client_secret", this.secret ?? ""); 337 | form.set("scopes", this.scopes?.join(" ") ?? ""); 338 | form.set("grant_type", "authorization_code"); 339 | form.set("code", this.authCode); 340 | 341 | const res = await fetch("https://discord.com/api/v8/oauth2/token", { 342 | method: "POST", 343 | headers: { 344 | "Content-Type": "application/x-www-form-urlencoded", 345 | }, 346 | body: form.toString(), 347 | }).then((r) => r.json()); 348 | 349 | this.accessToken = res.access_token; 350 | this.authenticate(); 351 | return this.accessToken; 352 | } 353 | 354 | /** Set User's Activity (Presence) */ 355 | async setActivity(activity: Presence): Promise { 356 | const nonce = v4(); 357 | 358 | const wait = this.waitFor("setActivity", (_, n) => n == nonce, 10000).then( 359 | (act) => new Presence(act[0]) 360 | ); 361 | 362 | this.ipc.send( 363 | new Packet(OpCode.Frame, { 364 | cmd: Command.SetActivity, 365 | args: { 366 | pid: process.pid, 367 | activity, 368 | }, 369 | nonce, 370 | }) 371 | ); 372 | 373 | return wait; 374 | } 375 | 376 | /** Get a Guild by ID */ 377 | async getGuild(id: string, timeout: number = 5000): Promise { 378 | const nonce = v4(); 379 | 380 | const wait = this.waitFor("getGuild", (_, n) => n === nonce, timeout).then( 381 | (guild) => guild[0] 382 | ); 383 | 384 | this.ipc.send( 385 | new Packet(OpCode.Frame, { 386 | cmd: Command.GetGuild, 387 | args: { 388 | guild_id: id, 389 | timeout: Math.floor(timeout / (1000 * 60)), 390 | }, 391 | nonce, 392 | }) 393 | ); 394 | 395 | return wait; 396 | } 397 | 398 | /** Get all Guilds of the User */ 399 | async getGuilds(timeout: number = 5000): Promise { 400 | const nonce = v4(); 401 | 402 | const wait = this.waitFor("getGuilds", (_, n) => n === nonce, timeout).then( 403 | (d) => d[0].guilds 404 | ); 405 | 406 | this.ipc.send( 407 | new Packet(OpCode.Frame, { 408 | cmd: Command.GetGuilds, 409 | args: {}, 410 | nonce, 411 | }) 412 | ); 413 | 414 | return wait; 415 | } 416 | 417 | /** Get a Channel by ID */ 418 | async getChannel( 419 | id: string, 420 | timeout: number = 5000 421 | ): Promise { 422 | const nonce = v4(); 423 | 424 | const wait = this.waitFor( 425 | "getChannel", 426 | (_, n) => n === nonce, 427 | timeout 428 | ).then((guild) => guild[0]); 429 | 430 | this.ipc.send( 431 | new Packet(OpCode.Frame, { 432 | cmd: Command.GetChannel, 433 | args: { 434 | channel_id: id, 435 | }, 436 | nonce, 437 | }) 438 | ); 439 | 440 | return wait; 441 | } 442 | 443 | /** Get all Channels or channels of a specific Guild */ 444 | async getChannels( 445 | guild?: string, 446 | timeout: number = 5000 447 | ): Promise { 448 | const nonce = v4(); 449 | 450 | const wait = this.waitFor( 451 | "getChannels", 452 | (_, n) => n === nonce, 453 | timeout 454 | ).then((d) => d[0].channels); 455 | 456 | this.ipc.send( 457 | new Packet(OpCode.Frame, { 458 | cmd: Command.GetChannels, 459 | args: { 460 | guild_id: guild, 461 | }, 462 | nonce, 463 | }) 464 | ); 465 | 466 | return wait; 467 | } 468 | 469 | /** Set User's Voice Settings (only one property at a time or Discord will error) */ 470 | async setUserVoiceSettings( 471 | settings: UserVoiceSettings, 472 | timeout = 5000 473 | ): Promise { 474 | const nonce = v4(); 475 | 476 | const wait = this.waitFor( 477 | "setUserVoiceSettings", 478 | (_, n) => n === nonce, 479 | timeout 480 | ).then((data) => data[0]); 481 | 482 | this.ipc.send( 483 | new Packet(OpCode.Frame, { 484 | cmd: Command.SetUserVoiceSettings, 485 | args: settings, 486 | nonce, 487 | }) 488 | ); 489 | 490 | return wait; 491 | } 492 | 493 | /** Select a Voice Channel by ID */ 494 | async selectVoiceChannel( 495 | id: string, 496 | force?: boolean, 497 | timeout = 5000 498 | ): Promise { 499 | const nonce = v4(); 500 | 501 | const wait = this.waitFor( 502 | "selectVoiceChannel", 503 | (_, n) => n === nonce, 504 | timeout 505 | ).then((chan) => chan[0]); 506 | 507 | this.ipc.send( 508 | new Packet(OpCode.Frame, { 509 | cmd: Command.SelectVoiceChannel, 510 | args: { 511 | channel_id: id, 512 | force, 513 | timeout: Math.floor(timeout / (1000 * 60)), 514 | }, 515 | nonce, 516 | }) 517 | ); 518 | 519 | return wait; 520 | } 521 | 522 | /** Select a Text Channel by ID */ 523 | async selectTextChannel(id: string, timeout = 5000): Promise { 524 | const nonce = v4(); 525 | 526 | const wait = this.waitFor( 527 | "selectTextChannel", 528 | (_, n) => n === nonce, 529 | timeout 530 | ).then((chan) => chan[0]); 531 | 532 | this.ipc.send( 533 | new Packet(OpCode.Frame, { 534 | cmd: Command.SelectTextChannel, 535 | args: { 536 | channel_id: id, 537 | timeout: Math.floor(timeout / (1000 * 60)), 538 | }, 539 | nonce, 540 | }) 541 | ); 542 | 543 | return wait; 544 | } 545 | 546 | /** Get selected Voice Channel */ 547 | async getSelectedVoiceChannel(timeout = 5000): Promise { 548 | const nonce = v4(); 549 | 550 | const wait = this.waitFor( 551 | "getSelectedVoiceChannel", 552 | (_, n) => n === nonce, 553 | timeout 554 | ).then((data) => data[0]); 555 | 556 | this.ipc.send( 557 | new Packet(OpCode.Frame, { 558 | cmd: Command.GetSelectedVoiceChannel, 559 | args: {}, 560 | nonce, 561 | }) 562 | ); 563 | 564 | return wait; 565 | } 566 | 567 | /** Get Voice Settins of Client */ 568 | async getVoiceSettings(timeout = 5000): Promise { 569 | const nonce = v4(); 570 | 571 | const wait = this.waitFor( 572 | "getVoiceSettings", 573 | (_, n) => n === nonce, 574 | timeout 575 | ).then((data) => data[0]); 576 | 577 | this.ipc.send( 578 | new Packet(OpCode.Frame, { 579 | cmd: Command.GetVoiceSettings, 580 | args: {}, 581 | nonce, 582 | }) 583 | ); 584 | 585 | return wait; 586 | } 587 | 588 | /** Set Voice Settings of Client. Only one property to update at once supported */ 589 | async setVoiceSettings( 590 | settings: VoiceSettings, 591 | timeout = 5000 592 | ): Promise { 593 | const nonce = v4(); 594 | 595 | const wait = this.waitFor( 596 | "setVoiceSettings", 597 | (_, n) => n === nonce, 598 | timeout 599 | ).then((data) => data[0]); 600 | 601 | this.ipc.send( 602 | new Packet(OpCode.Frame, { 603 | cmd: Command.SetVoiceSettings, 604 | args: settings, 605 | nonce, 606 | }) 607 | ); 608 | 609 | return wait; 610 | } 611 | 612 | /** START or STOP capturing shortcut */ 613 | async captureShortcut( 614 | action: "START" | "STOP", 615 | timeout = 5000 616 | ): Promise { 617 | if (action != "START" && action != "STOP") 618 | throw new Error("Invalid Action. Must be either START or STOP"); 619 | const nonce = v4(); 620 | 621 | const wait = this.waitFor( 622 | "captureShortcut", 623 | (_, n) => n === nonce, 624 | timeout 625 | ).then((data) => data[0].shortcut); 626 | 627 | this.ipc.send( 628 | new Packet(OpCode.Frame, { 629 | cmd: Command.CaptureShortcut, 630 | args: { 631 | action, 632 | }, 633 | nonce, 634 | }) 635 | ); 636 | 637 | return wait; 638 | } 639 | 640 | /** Start capturing shortcut */ 641 | async startCaptureShortcut(timeout = 5000): Promise { 642 | return this.captureShortcut("START", timeout); 643 | } 644 | 645 | /** Stop capturing shortcut */ 646 | async stopCaptureShortcut(timeout = 5000): Promise { 647 | return this.captureShortcut("STOP", timeout); 648 | } 649 | 650 | /** Set Certified Devices (Audio/Video) */ 651 | async setCertifiedDevices( 652 | devices: Device[], 653 | timeout = 5000 654 | ): Promise { 655 | const nonce = v4(); 656 | 657 | const wait = this.waitFor( 658 | "setCertifiedDevices", 659 | (_, n) => n === nonce, 660 | timeout 661 | ).then(() => this); 662 | 663 | this.ipc.send( 664 | new Packet(OpCode.Frame, { 665 | cmd: Command.SetCertifiedDevices, 666 | args: { 667 | devices, 668 | }, 669 | nonce, 670 | }) 671 | ); 672 | 673 | return wait; 674 | } 675 | 676 | /** Approve an Activity Join Request (by user ID) */ 677 | sendActivityJoinInvite(id: string) { 678 | this.ipc.send( 679 | new Packet(OpCode.Frame, { 680 | cmd: Command.SendActivityJoinInvite, 681 | args: { 682 | user_id: id, 683 | }, 684 | }) 685 | ); 686 | } 687 | 688 | /** Close (decline) an Activity Join Request */ 689 | closeActivityRequest(id: string) { 690 | this.ipc.send( 691 | new Packet(OpCode.Frame, { 692 | cmd: Command.CloseActivityRequest, 693 | args: { 694 | user_id: id, 695 | }, 696 | }) 697 | ); 698 | } 699 | 700 | /** Get array of Relationships (Presences) */ 701 | async getRelationships(timeout = 5000): Promise { 702 | const nonce = v4(); 703 | 704 | const wait = this.waitFor( 705 | "getRelationships", 706 | (_, n) => n == nonce, 707 | timeout 708 | ).then((d) => d[0].relationships); 709 | 710 | this.ipc.send( 711 | new Packet(OpCode.Frame, { 712 | cmd: Command.GetRelationships, 713 | nonce, 714 | }) 715 | ); 716 | 717 | return wait; 718 | } 719 | 720 | /** Returns an Array of SKUs */ 721 | async getSkus(timeout: number = 5000): Promise { 722 | const nonce = v4(); 723 | 724 | const wait = this.waitFor("getSkus", (_, n) => n === nonce, timeout).then( 725 | (d) => d[0] 726 | ); 727 | 728 | this.ipc.send( 729 | new Packet(OpCode.Frame, { 730 | cmd: Command.GetSkus, 731 | nonce, 732 | }) 733 | ); 734 | 735 | return wait; 736 | } 737 | 738 | /** Returns an Array of Entitlements */ 739 | async getEntitlements(timeout: number = 5000): Promise { 740 | const nonce = v4(); 741 | 742 | const wait = this.waitFor( 743 | "getEntitlements", 744 | (_, n) => n === nonce, 745 | timeout 746 | ).then((d) => d[0]); 747 | 748 | this.ipc.send( 749 | new Packet(OpCode.Frame, { 750 | cmd: Command.GetEntitlements, 751 | nonce, 752 | }) 753 | ); 754 | 755 | return wait; 756 | } 757 | 758 | /** Gets an Image's Data (base64 URI). Supports only type: "user" ATM which is User Avatar */ 759 | async getImage(options: GetImageOptions, timeout = 5000): Promise { 760 | const nonce = v4(); 761 | 762 | const wait = this.waitFor("getImage", (_, n) => n == nonce, timeout).then( 763 | (d) => d[0] 764 | ); 765 | 766 | this.ipc.send( 767 | new Packet(OpCode.Frame, { 768 | cmd: Command.GetImage, 769 | args: options, 770 | nonce, 771 | }) 772 | ); 773 | 774 | return wait; 775 | } 776 | 777 | /** Wait for an event to fire */ 778 | async waitFor( 779 | event: string, 780 | checkFunction: (...args: any[]) => boolean = () => true, 781 | timeout?: number 782 | ): Promise { 783 | return await new Promise((resolve, reject) => { 784 | let timeoutID: any | undefined; 785 | if (timeout !== undefined) { 786 | timeoutID = setTimeout(() => { 787 | this.off(event, eventFunc); 788 | this.off("error", errorFunc); 789 | reject(new Error("Timed out: " + event)); 790 | }, timeout); 791 | } 792 | const eventFunc = (...args: any[]): void => { 793 | if (checkFunction(...args)) { 794 | this.off(event, eventFunc); 795 | this.off("error", errorFunc); 796 | if (timeoutID !== undefined) clearTimeout(timeoutID); 797 | resolve(args); 798 | } 799 | }; 800 | const errorFunc = (...args: any[]): void => { 801 | if (checkFunction(...args)) { 802 | this.off(event, eventFunc); 803 | this.off("error", errorFunc); 804 | if (timeoutID !== undefined) clearTimeout(timeoutID); 805 | reject(args[0]); 806 | } 807 | }; 808 | this.on("error", errorFunc); 809 | this.on(event, eventFunc); 810 | }); 811 | } 812 | 813 | /** Disconnect from Discord IPC */ 814 | disconnect(): void { 815 | this.ipc.close(); 816 | this.connected = false; 817 | } 818 | } 819 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ipc"; 2 | export * from "./packet"; 3 | export * from "./types"; 4 | export * from "./util"; 5 | export * from "./presence"; 6 | export * from "./client"; 7 | -------------------------------------------------------------------------------- /src/ipc.ts: -------------------------------------------------------------------------------- 1 | import { Socket, connect } from "net"; 2 | import { getIPCPath } from "./util"; 3 | import { EventEmitter } from "events"; 4 | import { Packet } from "./packet"; 5 | import { v4 } from "uuid"; 6 | 7 | export async function findIPC(id = 0): Promise { 8 | return new Promise((res, rej) => { 9 | let socket: Socket; 10 | if (id > 9) return rej(new Error("Failed to find Discord IPC")); 11 | socket = connect(getIPCPath(id)); 12 | 13 | socket.once("connect", () => { 14 | socket.removeAllListeners("connect"); 15 | socket.removeAllListeners("error"); 16 | res(socket); 17 | }); 18 | 19 | socket.once("error", () => { 20 | res(findIPC(id + 1)); 21 | }); 22 | }); 23 | } 24 | 25 | export class DiscordIPC extends EventEmitter { 26 | socket?: Socket; 27 | 28 | async connect() { 29 | this.socket = await findIPC(); 30 | this.emit("connect"); 31 | 32 | this.socket.on("data", (buffer) => { 33 | const packet = Packet.tryParse(buffer); 34 | if (packet) { 35 | this.emit("packet", packet); 36 | } 37 | }); 38 | 39 | this.socket.on("close", () => this.emit("close")); 40 | } 41 | 42 | send(packet: Packet): string { 43 | if (!packet.data.nonce) packet.data.nonce = v4(); 44 | this.socket?.write(packet.encode()); 45 | return packet.data.nonce; 46 | } 47 | 48 | close() { 49 | this.socket?.end(); 50 | this.socket = undefined; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/managers/achievement.ts: -------------------------------------------------------------------------------- 1 | import { v4 } from "uuid"; 2 | import { Packet } from "../packet"; 3 | import { Command, OpCode } from "../types"; 4 | import { BaseManager } from "./base"; 5 | 6 | export class AchievementManager extends BaseManager { 7 | /** Returns an array of User's Achievements */ 8 | async getAll(timeout: number = 5000): Promise { 9 | const nonce = v4(); 10 | 11 | const wait = this.client 12 | .waitFor("getUserAchievements", (_, n) => n === nonce, timeout) 13 | .then((d) => d[0]); 14 | 15 | this.ipc.send( 16 | new Packet(OpCode.Frame, { 17 | cmd: Command.GetUserAchievements, 18 | nonce, 19 | }) 20 | ); 21 | 22 | return wait; 23 | } 24 | 25 | /** Sets User's Achievement progress (percent) by ID */ 26 | async set( 27 | id: string, 28 | percent: number, 29 | timeout: number = 5000 30 | ): Promise { 31 | const nonce = v4(); 32 | 33 | const wait = this.client 34 | .waitFor("setUserAchievement", (_, n) => n === nonce, timeout) 35 | .then(() => this); 36 | 37 | this.ipc.send( 38 | new Packet(OpCode.Frame, { 39 | cmd: Command.SetUserAchievement, 40 | args: { 41 | achievement_id: id, 42 | percent_complete: percent, 43 | }, 44 | nonce, 45 | }) 46 | ); 47 | 48 | return wait; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/managers/base.ts: -------------------------------------------------------------------------------- 1 | import EventEmitter from "events"; 2 | import type { RPClient } from "../client"; 3 | 4 | export class BaseManager extends EventEmitter { 5 | client: RPClient; 6 | 7 | get ipc() { 8 | return this.client.ipc; 9 | } 10 | 11 | constructor(client: RPClient) { 12 | super(); 13 | this.client = client; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/managers/lobby.ts: -------------------------------------------------------------------------------- 1 | import { v4 } from "uuid"; 2 | import { Packet } from "../packet"; 3 | import { Command, Lobby, LobbyMetadata, LobbyOptions, OpCode } from "../types"; 4 | import { BaseManager } from "./base"; 5 | 6 | export class LobbyManager extends BaseManager { 7 | /** Create a new Lobby with given options */ 8 | async create(data: LobbyOptions, timeout = 5000): Promise { 9 | const nonce = v4(); 10 | 11 | const wait = this.client 12 | .waitFor("createLobby", (_, n) => n == nonce, timeout) 13 | .then((d) => d[0]); 14 | 15 | this.ipc.send( 16 | new Packet(OpCode.Frame, { 17 | cmd: Command.CreateLobby, 18 | args: data ?? {}, 19 | nonce, 20 | }) 21 | ); 22 | 23 | return wait; 24 | } 25 | 26 | /** Search for lobbies */ 27 | async search(timeout = 5000): Promise { 28 | const nonce = v4(); 29 | 30 | const wait = this.client 31 | .waitFor("searchLobbies", (_, n) => n == nonce, timeout) 32 | .then((d) => d[0]); 33 | 34 | this.ipc.send( 35 | new Packet(OpCode.Frame, { 36 | cmd: Command.SearchLobbies, 37 | args: {}, 38 | nonce, 39 | }) 40 | ); 41 | 42 | return wait; 43 | } 44 | 45 | /** Update a Lobby with given options */ 46 | async update( 47 | id: string, 48 | options: LobbyOptions, 49 | timeout = 5000 50 | ): Promise { 51 | const nonce = v4(); 52 | 53 | const wait = this.client 54 | .waitFor("updateLobby", (_, n) => n == nonce, timeout) 55 | .then(() => this); 56 | 57 | this.ipc.send( 58 | new Packet(OpCode.Frame, { 59 | cmd: Command.UpdateLobby, 60 | args: Object.assign({ id }, options || {}), 61 | nonce, 62 | }) 63 | ); 64 | 65 | return wait; 66 | } 67 | 68 | /** Delete a Lobby */ 69 | async delete(id: string, timeout = 5000): Promise { 70 | const nonce = v4(); 71 | 72 | const wait = this.client 73 | .waitFor("deleteLobby", (_, n) => n == nonce, timeout) 74 | .then(() => this); 75 | 76 | this.ipc.send( 77 | new Packet(OpCode.Frame, { 78 | cmd: Command.DeleteLobby, 79 | args: { id }, 80 | nonce, 81 | }) 82 | ); 83 | 84 | return wait; 85 | } 86 | 87 | /** Connect to a Lobby */ 88 | async connect(id: string, secret: string, timeout = 5000): Promise { 89 | const nonce = v4(); 90 | 91 | const wait = this.client 92 | .waitFor("connectToLobby", (_, n) => n == nonce, timeout) 93 | .then((d) => d[0]); 94 | 95 | this.ipc.send( 96 | new Packet(OpCode.Frame, { 97 | cmd: Command.ConnectToLobby, 98 | args: { id, secret }, 99 | nonce, 100 | }) 101 | ); 102 | 103 | return wait; 104 | } 105 | 106 | /** Disconnect from a Lobby */ 107 | async disconnect(id: string, timeout = 5000): Promise { 108 | const nonce = v4(); 109 | 110 | const wait = this.client 111 | .waitFor("disconnectFromLobby", (_, n) => n == nonce, timeout) 112 | .then((d) => d[0]); 113 | 114 | this.ipc.send( 115 | new Packet(OpCode.Frame, { 116 | cmd: Command.DisconnectFromLobby, 117 | args: { id }, 118 | nonce, 119 | }) 120 | ); 121 | 122 | return wait; 123 | } 124 | 125 | /** Connect to a Lobby Voice */ 126 | async connectVoice(id: string, timeout = 5000): Promise { 127 | const nonce = v4(); 128 | 129 | const wait = this.client 130 | .waitFor("connectToLobbyVoice", (_, n) => n == nonce, timeout) 131 | .then(() => this); 132 | 133 | this.ipc.send( 134 | new Packet(OpCode.Frame, { 135 | cmd: Command.ConnectToLobbyVoice, 136 | args: { id }, 137 | nonce, 138 | }) 139 | ); 140 | 141 | return wait; 142 | } 143 | 144 | /** Disconnect from a Lobby Voice */ 145 | async disconnectVoice(id: string, timeout = 5000): Promise { 146 | const nonce = v4(); 147 | 148 | const wait = this.client 149 | .waitFor("disconnectFromLobbyVoice", (_, n) => n == nonce, timeout) 150 | .then(() => this); 151 | 152 | this.ipc.send( 153 | new Packet(OpCode.Frame, { 154 | cmd: Command.DisconnectFromLobbyVoice, 155 | args: { id }, 156 | nonce, 157 | }) 158 | ); 159 | 160 | return wait; 161 | } 162 | 163 | async updateMember( 164 | id: string, 165 | userID: string, 166 | metadata: LobbyMetadata, 167 | timeout = 5000 168 | ): Promise { 169 | const nonce = v4(); 170 | 171 | const wait = this.client 172 | .waitFor("updateLobbyMember", (_, n) => n == nonce, timeout) 173 | .then(() => this); 174 | 175 | this.ipc.send( 176 | new Packet(OpCode.Frame, { 177 | cmd: Command.UpdateLobbyMember, 178 | args: { 179 | lobby_id: id, 180 | user_id: userID, 181 | metadata, 182 | }, 183 | nonce, 184 | }) 185 | ); 186 | 187 | return wait; 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/managers/networking.ts: -------------------------------------------------------------------------------- 1 | import { v4 } from "uuid"; 2 | import { Packet } from "../packet"; 3 | import { Command, NetworkingConfig, OpCode } from "../types"; 4 | import { BaseManager } from "./base"; 5 | 6 | export class NetworkingManager extends BaseManager { 7 | /** Gets the Networking Config */ 8 | async getConfig(timeout: number = 5000): Promise { 9 | const nonce = v4(); 10 | 11 | const wait = this.client 12 | .waitFor("getNetworkingConfig", (_, n) => n === nonce, timeout) 13 | .then((d) => d[0]); 14 | 15 | this.ipc.send( 16 | new Packet(OpCode.Frame, { 17 | cmd: Command.GetNetworkingConfig, 18 | nonce, 19 | }) 20 | ); 21 | 22 | return wait; 23 | } 24 | 25 | /** Gets the Networking System Metrics */ 26 | async systemMetrics(timeout: number = 5000): Promise { 27 | const nonce = v4(); 28 | 29 | const wait = this.client 30 | .waitFor("networkingSystemMetrics", (_, n) => n === nonce, timeout) 31 | .then((d) => d[0]); 32 | 33 | this.ipc.send( 34 | new Packet(OpCode.Frame, { 35 | cmd: Command.NetworkingSystemMetrics, 36 | nonce, 37 | }) 38 | ); 39 | 40 | return wait; 41 | } 42 | 43 | /** Gets the Networking Peer Metrics */ 44 | async peerMetrics(timeout: number = 5000): Promise { 45 | const nonce = v4(); 46 | 47 | const wait = this.client 48 | .waitFor("networkingPeerMetrics", (_, n) => n === nonce, timeout) 49 | .then((d) => d[0]); 50 | 51 | this.ipc.send( 52 | new Packet(OpCode.Frame, { 53 | cmd: Command.NetworkingPeerMetrics, 54 | nonce, 55 | }) 56 | ); 57 | 58 | return wait; 59 | } 60 | 61 | /** Creates and returns a new Networking Token */ 62 | async createToken(timeout: number = 5000): Promise { 63 | const nonce = v4(); 64 | 65 | const wait = this.client 66 | .waitFor("networkingCreateToken", (_, n) => n === nonce, timeout) 67 | .then((d) => d[0].token); 68 | 69 | this.ipc.send( 70 | new Packet(OpCode.Frame, { 71 | cmd: Command.NetworkingCreateToken, 72 | nonce, 73 | }) 74 | ); 75 | 76 | return wait; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/managers/overlay.ts: -------------------------------------------------------------------------------- 1 | import { v4 } from "uuid"; 2 | import { Packet } from "../packet"; 3 | import { Command, OpCode } from "../types"; 4 | import { BaseManager } from "./base"; 5 | 6 | export class OverlayManager extends BaseManager { 7 | /** Opens Guild Invite modal in app of given Invite Code */ 8 | openGuildInvite(code: string) { 9 | const nonce = v4(); 10 | 11 | this.ipc.send( 12 | new Packet(OpCode.Frame, { 13 | cmd: Command.OpenOverlayGuildInvite, 14 | args: { 15 | code, 16 | pid: process.pid, 17 | }, 18 | nonce, 19 | }) 20 | ); 21 | 22 | return this; 23 | } 24 | 25 | /** Opens Voice Settings Modal in app */ 26 | openVoiceSettings() { 27 | const nonce = v4(); 28 | 29 | this.ipc.send( 30 | new Packet(OpCode.Frame, { 31 | cmd: Command.OpenOverlayVoiceSettings, 32 | args: { 33 | pid: process.pid, 34 | }, 35 | nonce, 36 | }) 37 | ); 38 | 39 | return this; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/packet.ts: -------------------------------------------------------------------------------- 1 | import { OpCode } from "./types"; 2 | 3 | export class Packet { 4 | op: OpCode; 5 | data: any; 6 | 7 | constructor(op: OpCode, data?: any) { 8 | this.op = op; 9 | this.data = data ?? {}; 10 | } 11 | 12 | encode() { 13 | const data = JSON.stringify(this.data); 14 | 15 | const len = Buffer.byteLength(data); 16 | const buf = Buffer.alloc(8 + len); 17 | 18 | buf.writeInt32LE(this.op, 0); 19 | buf.writeInt32LE(len, 4); 20 | buf.write(data, 8); 21 | 22 | return buf; 23 | } 24 | 25 | static parse(data: string | Uint8Array | Buffer) { 26 | const buf = 27 | data instanceof Uint8Array ? Buffer.from(data.buffer) : Buffer.from(data); 28 | 29 | const op = buf.readInt32LE(0); 30 | const len = buf.readInt32LE(4); 31 | const json = buf 32 | .slice(8, len + 8) 33 | .toString() 34 | .trim(); 35 | 36 | return new Packet(op, JSON.parse(json)); 37 | } 38 | 39 | static tryParse(data: string | Uint8Array | Buffer) { 40 | try { 41 | return this.parse(data); 42 | } catch (e) { 43 | return; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/presence.ts: -------------------------------------------------------------------------------- 1 | export enum ActivityType { 2 | Game, 3 | Streaming, 4 | Listening, 5 | Custom, 6 | Competing, 7 | } 8 | 9 | export interface ActivityTimestamps { 10 | start?: number; 11 | end?: number; 12 | } 13 | 14 | export interface ActivityParty { 15 | id?: string; 16 | size?: [number, number]; 17 | } 18 | 19 | export interface ActivityAssets { 20 | large_image?: string; 21 | large_text?: string; 22 | small_image?: string; 23 | small_text?: string; 24 | } 25 | 26 | export interface ActivitySecrets { 27 | join?: string; 28 | spectate?: string; 29 | match?: string; 30 | } 31 | 32 | export enum ActivityFlags { 33 | Instance = 1 << 0, 34 | Join = 1 << 1, 35 | Spectate = 1 << 2, 36 | JoinRequest = 1 << 3, 37 | Sync = 1 << 4, 38 | Play = 1 << 5, 39 | } 40 | 41 | export interface ActivityButton { 42 | label: string; 43 | url: string; 44 | } 45 | 46 | export interface ActivityPayload { 47 | name?: string; 48 | type?: ActivityType; 49 | url?: string; 50 | created_at?: string; 51 | timestamps?: ActivityTimestamps; 52 | application_id?: string; 53 | details?: string | null; 54 | state?: string | null; 55 | emoji?: any; 56 | party?: ActivityParty; 57 | assets?: ActivityAssets; 58 | secrets?: ActivitySecrets; 59 | instance?: boolean; 60 | buttons?: ActivityButton[]; 61 | flags?: number; 62 | } 63 | 64 | export class Presence implements ActivityPayload { 65 | type?: ActivityType; 66 | timestamps?: ActivityTimestamps; 67 | details?: string | null; 68 | state?: string | null; 69 | party?: ActivityParty; 70 | assets?: ActivityAssets; 71 | secrets?: ActivitySecrets; 72 | instance?: boolean; 73 | buttons?: ActivityButton[]; 74 | flags?: number; 75 | 76 | constructor(data?: ActivityPayload) { 77 | if (data) Object.assign(this, data); 78 | } 79 | 80 | setType(type: ActivityType | undefined) { 81 | this.type = type; 82 | return this; 83 | } 84 | 85 | setTimestamps(ts?: { 86 | start?: Date | number | string; 87 | end?: Date | number | string; 88 | }) { 89 | if (!ts) { 90 | this.timestamps = undefined; 91 | return this; 92 | } 93 | if (!this.timestamps) this.timestamps = {}; 94 | this.timestamps.start = ts.start ? new Date(ts.start).getTime() : undefined; 95 | this.timestamps.end = ts.end ? new Date(ts.end).getTime() : undefined; 96 | return this; 97 | } 98 | 99 | setStartTimestamp(ts?: Date | number | string) { 100 | if (!ts) { 101 | if (this.timestamps && this.timestamps.start) 102 | this.timestamps.start = undefined; 103 | return this; 104 | } 105 | 106 | if (!this.timestamps) this.timestamps = {}; 107 | this.timestamps.start = ts ? new Date(ts).getTime() : undefined; 108 | return this; 109 | } 110 | 111 | setEndTimestamp(ts?: Date | number | string) { 112 | if (!ts) { 113 | if (this.timestamps && this.timestamps.end) 114 | this.timestamps.end = undefined; 115 | return this; 116 | } 117 | 118 | if (!this.timestamps) this.timestamps = {}; 119 | this.timestamps.end = ts ? new Date(ts).getTime() : undefined; 120 | return this; 121 | } 122 | 123 | setDetails(details?: string) { 124 | this.details = details; 125 | return this; 126 | } 127 | 128 | setState(state?: string) { 129 | this.state = state; 130 | return this; 131 | } 132 | 133 | setParty(party?: ActivityParty) { 134 | this.party = party; 135 | return this; 136 | } 137 | 138 | setPartyID(id?: string) { 139 | if (!id) { 140 | if (this.party && this.party.id) this.party.id = undefined; 141 | return this; 142 | } 143 | 144 | if (!this.party) this.party = {}; 145 | this.party.id = id; 146 | return this; 147 | } 148 | 149 | setPartySize(current?: number, max?: number) { 150 | if (!max && !current) { 151 | if (this.party && this.party.size) this.party.size = undefined; 152 | return this; 153 | } 154 | 155 | if (!this.party) this.party = {}; 156 | this.party.size = [current ?? max ?? 1, max ?? current ?? 1]; 157 | return this; 158 | } 159 | 160 | setAssets(assets?: ActivityAssets) { 161 | this.assets = assets; 162 | return this; 163 | } 164 | 165 | setLargeAssets(text?: string, image?: string) { 166 | if (!this.assets) this.assets = {}; 167 | this.assets.large_text = text; 168 | this.assets.large_image = image; 169 | return this; 170 | } 171 | 172 | setSmallAssets(text?: string, image?: string) { 173 | if (!this.assets) this.assets = {}; 174 | this.assets.small_text = text; 175 | this.assets.small_image = image; 176 | return this; 177 | } 178 | 179 | setLargeText(text?: string) { 180 | if (!this.assets) this.assets = {}; 181 | this.assets.large_text = text; 182 | return this; 183 | } 184 | 185 | setLargeImage(image?: string) { 186 | if (!this.assets) this.assets = {}; 187 | this.assets.large_image = image; 188 | return this; 189 | } 190 | 191 | setSmallText(text?: string) { 192 | if (!this.assets) this.assets = {}; 193 | this.assets.small_text = text; 194 | return this; 195 | } 196 | 197 | setSmallImage(image?: string) { 198 | if (!this.assets) this.assets = {}; 199 | this.assets.small_image = image; 200 | return this; 201 | } 202 | 203 | setSecrets(secrets?: ActivitySecrets) { 204 | this.secrets = secrets; 205 | return this; 206 | } 207 | 208 | setJoinSecret(secret?: string) { 209 | if (!this.secrets) this.secrets = {}; 210 | this.secrets.join = secret; 211 | return this; 212 | } 213 | 214 | setSpectateSecret(secret?: string) { 215 | if (!this.secrets) this.secrets = {}; 216 | this.secrets.spectate = secret; 217 | return this; 218 | } 219 | 220 | setMatchSecret(secret?: string) { 221 | if (!this.secrets) this.secrets = {}; 222 | this.secrets.match = secret; 223 | return this; 224 | } 225 | 226 | setInstance(instance?: boolean) { 227 | this.instance = instance; 228 | return this; 229 | } 230 | 231 | setFlags(...flags: ActivityFlags[]) { 232 | if (!flags.length) { 233 | this.flags = undefined; 234 | return this; 235 | } 236 | 237 | this.flags = flags.reduce((p, a) => p | a, 0); 238 | return this; 239 | } 240 | 241 | setButtons( 242 | ...buttons: [ActivityButton | undefined, ActivityButton | undefined] 243 | ) { 244 | this.buttons = buttons.filter((e) => e !== undefined) as ActivityButton[]; 245 | if (this.buttons.length === 0) this.buttons = undefined; 246 | return this; 247 | } 248 | 249 | addButton(button: ActivityButton) { 250 | if (!this.buttons) this.buttons = []; 251 | this.buttons.push(button); 252 | return this; 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import type { ActivityPayload } from "./presence"; 2 | 3 | /** Op Codes sent by IPC Messages. */ 4 | export enum OpCode { 5 | Handshake, 6 | Frame, 7 | Close, 8 | Ping, 9 | Pong, 10 | } 11 | 12 | /** Commands used to communicate with IPC. */ 13 | export enum Command { 14 | Dispatch = "DISPATCH", 15 | Authorize = "AUTHORIZE", 16 | Authenticate = "AUTHENTICATE", 17 | GetGuild = "GET_GUILD", 18 | GetGuilds = "GET_GUILDS", 19 | GetChannel = "GET_CHANNEL", 20 | GetChannels = "GET_CHANNELS", 21 | Subscribe = "SUBSCRIBE", 22 | Unsubscribe = "UNSUBSCRIBE", 23 | SetUserVoiceSettings = "SET_USER_VOICE_SETTINGS", 24 | SelectVoiceChannel = "SELECT_VOICE_CHANNEL", 25 | GetSelectedVoiceChannel = "GET_SELECTED_VOICE_CHANNEL", 26 | SelectTextChannel = "SELECT_TEXT_CHANNEL", 27 | GetVoiceSettings = "GET_VOICE_SETTINGS", 28 | SetVoiceSettings = "SET_VOICE_SETTINGS", 29 | CaptureShortcut = "CAPTURE_SHORTCUT", 30 | SetCertifiedDevices = "SET_CERTIFIED_DEVICES", 31 | SetActivity = "SET_ACTIVITY", 32 | SendActivityJoinInvite = "SEND_ACTIVITY_JOIN_INVITE", 33 | CloseActivityRequest = "CLOSE_ACTIVITY_REQUEST", 34 | SetUserAchievement = "SET_USER_ACHIEVEMENT", 35 | GetUserAchievements = "GET_USER_ACHIEVEMENTS", 36 | GetActivityJoinTicket = "GET_ACTIVITY_JOIN_TICKET", 37 | SendGenericEvent = "SEND_GENERIC_EVENT", 38 | NetworkingSystemMetrics = "NETWORKING_SYSTEM_METRICS", 39 | NetworkingPeerMetrics = "NETWORKING_PEER_METRICS", 40 | NetworkingCreateToken = "NETWORKING_CREATE_TOKEN", 41 | GetSkus = "GET_SKUS", 42 | GetEntitlements = "GET_ENTITLEMENTS", 43 | GetNetworkingConfig = "GET_NETWORKING_CONFIG", 44 | StartPurchase = "START_PURCHASE", 45 | GetEntitlementTicket = "GET_ENTITLEMENT_TICKET", 46 | GetApplicationTicket = "GET_APPLICATION_TICKET", 47 | ValidateApplication = "VALIDATE_APPLICATION", 48 | OpenOverlayVoiceSettings = "OPEN_OVERLAY_VOICE_SETTINGS", 49 | OpenOverlayGuildInvite = "OPEN_OVERLAY_GUILD_INVITE", 50 | OpenOverlayActivityInvite = "OVEN_OVERLAY_ACTIVITY_INVITE", 51 | SetOverlayLocked = "SET_OVERLAY_LOCKED", 52 | DisconnectFromLobbyVoice = "DISCONNECT_FROM_LOBBY_VOICE", 53 | ConnectToLobbyVoice = "CONNECT_TO_LOBBY_VOICE", 54 | SearchLobbies = "SEARCH_LOBBIES", 55 | SendToLobby = "SEND_TO_LOBBY", 56 | DisconnectFromLobby = "DISCONNECT_FROM_LOBBY", 57 | ConnectToLobby = "CONNECT_TO_LOBBY", 58 | UpdateLobbyMember = "UPDATE_LOBBY_MEMBER", 59 | DeleteLobby = "DELETE_LOBBY", 60 | UpdateLobby = "UPDATE_LOBBY", 61 | CreateLobby = "CREATE_LOBBY", 62 | GetImage = "GET_IMAGE", 63 | BrowserHandoff = "BROWSER_HANDOFF", 64 | Overlay = "OVERLAY", 65 | GuildTemplateBrowser = "GUILD_TEMPLATE_BROWSER", 66 | GiftCodeBrowser = "GIFT_CODE_BROWSER", 67 | BraintreePopupBridgeCallback = "BRAINTREE_POPUP_BRIDGE_CALLBACK", 68 | ConnectionsCallback = "CONNECTIONS_CALLBACK", 69 | DeepLink = "DEEP_LINK", 70 | InviteBrowser = "INVITE_BROWSER", 71 | OpenInviteDialog = "OPEN_INVITE_DIALOG", 72 | AcceptActivityInvite = "ACCEPT_ACTIVITY_INVITE", 73 | ActivityInviteUser = "ACTIVITY_INVITE_USER", 74 | CloseActivityJoinRequest = "CLOSE_ACTIVITY_JOIN_REQUEST", 75 | SetVoiceSettings2 = "SET_VOICE_SETTINGS_2", 76 | SetUserVoiceSettings2 = "SET_USER_VOICE_SETTINGS_2", 77 | CreateChannelInvite = "CREATE_CHANNEL_INVITE", 78 | GetRelationships = "GET_RELATIONSHIPS", 79 | } 80 | 81 | /** Events DISPATCH'd from IPC. */ 82 | export enum RPCEvent { 83 | Ready = "READY", 84 | Error = "ERROR", 85 | GuildStatus = "GUILD_STATUS", 86 | GuildCreate = "GUILD_CREATE", 87 | ChannelCreate = "CHANNEL_CREATE", 88 | VoiceChannelSelect = "VOICE_CHANNEL_SELECT", 89 | VoiceStateCreate = "VOICE_STATE_CREATE", 90 | VoiceStateUpdate = "VOICE_STATE_UPDATE", 91 | VoiceStateDelete = "VOICE_STATE_DELETE", 92 | VoiceSettingsUpdate = "VOICE_SETTINGS_UPDATE", 93 | VoiceConnectionStatus = "VOICE_CONNECTION_STATUS", 94 | SpeakingStart = "SPEAKING_START", 95 | SpeakingStop = "SPEAKING_STOP", 96 | MessageCreate = "MESSAGE_CREATE", 97 | MessageUpdate = "MESSAGE_UPDATE", 98 | MessageDelete = "MESSAGE_DELETE", 99 | NotificationCreate = "NOTIFICATION_CREATE", 100 | CaptureShortcutChange = "CAPTURE_SHORTCUT_CHANGE", 101 | ActivityJoin = "ACTIVITY_JOIN", 102 | ActivityJoinRequest = "ACTIVITY_JOIN_REQUEST", 103 | ActivitySpectate = "ACTIVITY_SPECTATE", 104 | CurrentUserUpdate = "CURRENT_USER_UPDATE", 105 | RelationshipUpdate = "RELATIONSHIP_UPDATE", 106 | VoiceSettingsUpdate2 = "VOICE_SETTINGS_UPDATE_2", 107 | GameJoin = "GAME_JOIN", 108 | GameSpectate = "GAME_SPECTATE", 109 | LobbyDelete = "LOBBY_DELETE", 110 | LobbyUpdate = "LOBBY_UPDATE", 111 | LobbyMemberConnect = "LOBBY_MEMBER_CONNECT", 112 | LobbyMemberDisconnect = "LOBBY_MEMBER_DISCONNECT", 113 | LobbyMemberUpdate = "LOBBY_MEMBER_UPDATE", 114 | LobbyMessage = "LOBBY_MESSAGE", 115 | Overlay = "OVERLAY", 116 | OverlayUpdate = "OVERLAY_UPDATE", 117 | EntitlementCreate = "ENTITLEMENT_CREATE", 118 | EntitlementDelete = "ENTITLEMENT_DELETE", 119 | UserAchievementUpdate = "USER_ACHIEVEMENT_UPDATE", 120 | } 121 | 122 | /** Nitro type of User. */ 123 | export enum PremiumType { 124 | None, 125 | NitroClassic, 126 | Nitro, 127 | } 128 | 129 | /** Partial User object */ 130 | export interface User { 131 | id: string; 132 | username: string; 133 | discriminator: string; 134 | avatar: string; 135 | bot: boolean; 136 | flags: number; 137 | premium_type: PremiumType; 138 | } 139 | 140 | /** Client Config sent on Ready event. */ 141 | export interface ClientConfig { 142 | cdn_host: string; 143 | api_endpoint: string; 144 | environment: string; 145 | } 146 | 147 | export interface UserVoiceSettingsPan { 148 | left: number; 149 | right: number; 150 | } 151 | 152 | export interface UserVoiceSettings { 153 | user_id: string; 154 | pan?: UserVoiceSettingsPan; 155 | volume?: number; 156 | mute?: boolean; 157 | } 158 | 159 | export interface Application { 160 | id: string; 161 | description: string; 162 | icon: string; 163 | rpc_origins: string[]; 164 | name: string; 165 | } 166 | 167 | export interface VoiceSettingsInput { 168 | device_id: string; 169 | volume: number; 170 | available_devices: any[]; 171 | } 172 | 173 | export interface VoiceSettingsOutput extends VoiceSettingsInput {} 174 | 175 | export interface ShortcutKeyCombo { 176 | type: KeyType; 177 | code: number; 178 | name: string; 179 | } 180 | 181 | export interface VoiceSettingsMode { 182 | type: string; 183 | auto_threshold: boolean; 184 | threshold: number; 185 | shortcut: ShortcutKeyCombo; 186 | delay: number; 187 | } 188 | 189 | export enum KeyType { 190 | KeyboardKey, 191 | MouseButton, 192 | KeyboardModifierKey, 193 | GamepadButton, 194 | } 195 | 196 | export interface VoiceSettings { 197 | input: VoiceSettingsInput; 198 | output: VoiceSettingsOutput; 199 | mode: VoiceSettingsMode; 200 | automatic_gain_control: boolean; 201 | echo_cancellation: boolean; 202 | noise_cancellation: boolean; 203 | qos: boolean; 204 | silence_warning: boolean; 205 | deaf: boolean; 206 | mute: boolean; 207 | } 208 | 209 | export interface DeviceVendor { 210 | name: string; 211 | url: string; 212 | } 213 | 214 | export interface DeviceModel { 215 | name: string; 216 | url: string; 217 | } 218 | 219 | export enum DeviceType { 220 | AudioInput = "audioinput", 221 | AudioOutput = "audiooutput", 222 | VideoInput = "videoinput", 223 | } 224 | 225 | export interface Device { 226 | type: DeviceType; 227 | id: string; 228 | vendor: DeviceVendor; 229 | model: DeviceModel; 230 | related: string[]; 231 | echo_cancellation?: boolean; 232 | noise_cancellation?: boolean; 233 | automatic_gain_control?: boolean; 234 | hardware_mute?: boolean; 235 | } 236 | 237 | export interface VoiceStateData { 238 | mute: boolean; 239 | deaf: boolean; 240 | self_mute: boolean; 241 | self_deaf: boolean; 242 | suppress: boolean; 243 | } 244 | 245 | export interface VoiceState { 246 | voice_state: VoiceStateData; 247 | user: User; 248 | nick?: string | null; 249 | mute: boolean; 250 | volume: number; 251 | pan: UserVoiceSettingsPan; 252 | } 253 | 254 | export interface Message { 255 | id: string; 256 | [name: string]: any; 257 | } 258 | 259 | export interface ChannelPayload { 260 | id: string; 261 | name: string; 262 | type: number; 263 | topic?: string; 264 | bitrate?: number; 265 | user_limit?: number; 266 | guild_id: string; 267 | position: number; 268 | voice_states?: VoiceState[]; 269 | messages?: Message[]; 270 | } 271 | 272 | export interface PartialChannel { 273 | id: string; 274 | name: string; 275 | type: number; 276 | } 277 | 278 | export interface Guild { 279 | id: string; 280 | name: string; 281 | icon_url: string | null; 282 | } 283 | 284 | export interface PartialGuild { 285 | id: string; 286 | name: string; 287 | } 288 | 289 | export interface GetImageOptions { 290 | type: "user"; 291 | id: string; 292 | format: "png" | "apng" | "webp" | "gif" | "jpg"; 293 | size: number; 294 | } 295 | 296 | export enum LobbyType { 297 | Private = 1, 298 | Public = 2, 299 | } 300 | 301 | export interface LobbyMetadata { 302 | [name: string]: string | number; 303 | } 304 | 305 | export interface LobbyOptions { 306 | type?: LobbyType; 307 | owner_id?: string; 308 | capacity?: number; 309 | metadata?: LobbyMetadata; 310 | locked?: boolean; 311 | } 312 | 313 | export interface Lobby { 314 | application_id: string; 315 | capacity: number; 316 | id: string; 317 | locked: boolean; 318 | members: Array<{ metadata: LobbyMetadata; user: User }>; 319 | metadata: LobbyMetadata; 320 | owner_id: string; 321 | region: string; 322 | secret: string; 323 | type: LobbyType; 324 | voice_states: VoiceState[]; 325 | } 326 | 327 | export interface NetworkingConfig { 328 | address: string; 329 | /** Not the token you think of, lol. */ 330 | token: string; 331 | } 332 | 333 | export interface PresencePayload { 334 | status: "online" | "offline" | "dnd" | "invisible" | "idle"; 335 | activities?: ActivityPayload[]; 336 | } 337 | 338 | export interface Relationship { 339 | type: number; 340 | user: User; 341 | presence: PresencePayload; 342 | } 343 | -------------------------------------------------------------------------------- /src/util.ts: -------------------------------------------------------------------------------- 1 | export function getIPCPath(id: number) { 2 | if (process.platform === "win32") return `\\\\?\\pipe\\discord-ipc-${id}`; 3 | 4 | let XDG_RUNTIME_DIR, TMPDIR, TMP, TEMP; 5 | 6 | XDG_RUNTIME_DIR = process.env["XDG_RUNTIME_DIR"]; 7 | TMPDIR = process.env["TMPDIR"]; 8 | TMP = process.env["TMP"]; 9 | TEMP = process.env["TEMP"]; 10 | 11 | const prefix = XDG_RUNTIME_DIR || TMPDIR || TMP || TEMP || "/tmp"; 12 | return `${prefix.replace(/\/$/, "")}/discord-ipc-${id}`; 13 | } 14 | -------------------------------------------------------------------------------- /test/config-example.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "client_id", 3 | "secret": "client_secret" 4 | } -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | const { RPClient } = require("../dist/client"); 2 | const { Packet } = require("../dist/packet"); 3 | const { OpCode, Command, RPCEvent } = require("../dist/types"); 4 | const { id, secret } = require("./config.json"); 5 | 6 | const rpc = new RPClient("663356714376101889", { 7 | secret, 8 | scopes: ["rpc", "messages.read"], 9 | }); 10 | 11 | rpc.on("messageCreate", (msg) => { 12 | console.log(msg); 13 | }); 14 | 15 | rpc.on("error", () => { }); 16 | rpc.on("dispatch", (d) => { console.log(d); }) 17 | 18 | rpc.connect().then(async () => { 19 | console.log("Connected!", rpc.user.username + "#" + rpc.user.discriminator); 20 | 21 | // await rpc.openOverlayVoiceSettings(); 22 | // const lobby = await rpc.createLobby({}); 23 | // console.log("Lobby", lobby); 24 | // // await rpc.updateLobby(lobby.id, {}); 25 | // console.log(await rpc.searchLobbies()); 26 | 27 | // rpc.authorize().then(() => { 28 | // console.log("Auth Complete!"); 29 | 30 | // rpc.subscribe("MESSAGE_CREATE", { 31 | // // dont forget to replace this channel id with the one you want to listen messages for 32 | // channel_id: "783319033730564098", 33 | // }).then(() => { 34 | // console.log("Subscribed!"); 35 | // }); 36 | // }) 37 | }); -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Basic Options */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | "target": "es2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ 8 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 9 | // "lib": [], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 13 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | "outDir": "./dist", /* Redirect output structure to the directory. */ 18 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 21 | // "removeComments": true, /* Do not emit comments to output. */ 22 | // "noEmit": true, /* Do not emit outputs. */ 23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 26 | 27 | /* Strict Type-Checking Options */ 28 | "strict": true, /* Enable all strict type-checking options. */ 29 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 30 | // "strictNullChecks": true, /* Enable strict null checks. */ 31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 36 | 37 | /* Additional Checks */ 38 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 42 | 43 | /* Module Resolution Options */ 44 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 45 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 46 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 47 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 48 | // "typeRoots": [], /* List of folders to include type definitions from. */ 49 | // "types": [], /* Type declaration files to be included in compilation. */ 50 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 51 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 52 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 53 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 54 | 55 | /* Source Map Options */ 56 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 59 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 60 | 61 | /* Experimental Options */ 62 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 63 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 64 | 65 | /* Advanced Options */ 66 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 67 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 68 | } 69 | } 70 | --------------------------------------------------------------------------------