├── .gitignore ├── LICENSE ├── README.md ├── bin └── cli ├── package-lock.json ├── package.json ├── src ├── main.ts ├── pixelfix.ts ├── rbxupload.ts └── roblox.ts ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules 3 | .vscode-test/ 4 | *.vsix 5 | .vscode/ 6 | 7 | build.rbxm 8 | log-to-vs-code-roblox-plugin.rbxm 9 | 10 | rbxupload-linux-x64 11 | rbxupload-macos-x64 12 | rbxupload-win-x64.exe 13 | rbxupload-win-x86.exe -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Corecii Cyr 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Install with node and `npm install -g rbxupload` or download packaged binaries from [the releases page](https://github.com/Corecii/RbxUpload/releases). 2 | 3 | # RbxUpload 4 | 5 | RbxUpload is a tool to upload assets to Roblox. 6 | 7 | ## Features 8 | 9 | * Upload multiple files at once; glob support 10 | * Log in with your Roblox Studio cookie 11 | * Upload to groups 12 | * Outputs image ids, not decal ids 13 | * Optional name and description 14 | * Retry with fallback name on text filtering errors 15 | * Pixelfix/alpha-bleed built in 16 | * Interactive mode 17 | * Skip any or all of interactive mode 18 | * Confirm user and group before upload 19 | 20 | ## Options 21 | 22 | On Windows, RbxUpload can retrieve your Roblox Studio cookie automatically so you do not have to provide login details or a cookie. Alternatively, you can set the `ROBLOX_COOKIE` environment variable. RbxUpload does not provide a mechanism for logging in and does not permit passwords or cookies in the command line arguments. 23 | 24 | ```plain 25 | -h, --help Display this help message 26 | -?, --? Display this help message 27 | --files string[] Files to upload 28 | -r, --registry Log in to Roblox using Roblox Studio's cookie from the registry 29 | --no-interactive Don't use interactive mode 30 | --skip Skip interactive prompts for specific values. Valid values: user, user- 31 | verify, group, group-verify, files, files-verify, type, id, name, 32 | description, name-retry, pixelfix, done 33 | --group number Group to upload to 34 | --type Type of asset to upload as. Valid values: auto, decal 35 | --name string Name of asset. '$file' will be replaced with the file name. Defaults to $file 36 | --description string Description of asset. Supports $file. Defaults to 37 | --name-retry string Fallback name if upload fails due to text filtering. Does not support $file. 38 | --description-retry string Fallback description if upload fails due to text filtering. Does not support 39 | $file. 40 | --pixelfix Use pixelfix to alpha bleed images before upload. Alpha-bleed is not saved to 41 | the file. 42 | ``` 43 | 44 | ## Tips 45 | 46 | On windows, you can add RbxUpload to your Send To menu: 47 | 1. Install RbxUpload 48 | 2. Copy-and-paste `%AppData%\Microsoft\Windows\SendTo` into File Explorer 49 | 3. Create a shortcut in SendTo... 50 | * If you downloaded RbxUpload from the releases page: 51 | 1. Put RbxUpload somewhere recognizable like `C:\` 52 | 2. Rename it `rbxupload` or `rbxupload.exe` 53 | 3. Copy-and-paste the following for the item location: `C:\rbxupload.exe --registry --skip name description --type decal --name-retry "Asset" --pixelfix` 54 | * If you used `npm install -g rbxupload`: 55 | 1. Copy-and-paste the following for the item location: `rbxupload --registry --skip name description --type decal --name-retry "Asset" --pixelfix` 56 | 4. Give the shortcut a good name like "Roblox Decal" 57 | 5. Use "Send To -> Roblox Decal" to easily upload decals to Roblox -------------------------------------------------------------------------------- /bin/cli: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require("../out/main"); -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rbxupload", 3 | "version": "0.2.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.5.5", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", 10 | "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.0.0" 14 | } 15 | }, 16 | "@babel/highlight": { 17 | "version": "7.5.0", 18 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", 19 | "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", 20 | "dev": true, 21 | "requires": { 22 | "chalk": "^2.0.0", 23 | "esutils": "^2.0.2", 24 | "js-tokens": "^4.0.0" 25 | } 26 | }, 27 | "@babel/runtime": { 28 | "version": "7.8.4", 29 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.4.tgz", 30 | "integrity": "sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==", 31 | "requires": { 32 | "regenerator-runtime": "^0.13.2" 33 | } 34 | }, 35 | "@iarna/toml": { 36 | "version": "git+https://github.com/Corecii/iarna-toml.git#629457e5556d6d44d5a48bcbe4ab4ed269767bcd", 37 | "from": "git+https://github.com/Corecii/iarna-toml.git" 38 | }, 39 | "@jimp/bmp": { 40 | "version": "0.9.3", 41 | "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.9.3.tgz", 42 | "integrity": "sha512-wXZYccgGQAsIK8DZX0wZE3gbSd2mL2+eheSJMts6I5hQjxhVRZd1Gwu425nUQGzfKCOgKYTW0nLv7/8OoOTTkw==", 43 | "requires": { 44 | "@babel/runtime": "^7.7.2", 45 | "@jimp/utils": "^0.9.3", 46 | "bmp-js": "^0.1.0", 47 | "core-js": "^3.4.1" 48 | } 49 | }, 50 | "@jimp/core": { 51 | "version": "0.9.3", 52 | "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.9.3.tgz", 53 | "integrity": "sha512-kB9lvst1QhgYOC963SAuPgv+DdVfxTProphrSffAAoo5eLeQab/Ca3ZUeX1E/SnLSr+NGVnNCd8c9gyuKDiENg==", 54 | "requires": { 55 | "@babel/runtime": "^7.7.2", 56 | "@jimp/utils": "^0.9.3", 57 | "any-base": "^1.1.0", 58 | "buffer": "^5.2.0", 59 | "core-js": "^3.4.1", 60 | "exif-parser": "^0.1.12", 61 | "file-type": "^9.0.0", 62 | "load-bmfont": "^1.3.1", 63 | "mkdirp": "0.5.1", 64 | "phin": "^2.9.1", 65 | "pixelmatch": "^4.0.2", 66 | "tinycolor2": "^1.4.1" 67 | } 68 | }, 69 | "@jimp/custom": { 70 | "version": "0.9.3", 71 | "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.9.3.tgz", 72 | "integrity": "sha512-2E7yabQMeqjcK8+ZFu3Ja5cWyrB0zv/pmzNSDg/BBPJ59HE0fj/qcERAz6VklcjHUYRUfmE5uODsb+4DE0o/YQ==", 73 | "requires": { 74 | "@babel/runtime": "^7.7.2", 75 | "@jimp/core": "^0.9.3", 76 | "core-js": "^3.4.1" 77 | } 78 | }, 79 | "@jimp/gif": { 80 | "version": "0.9.3", 81 | "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.9.3.tgz", 82 | "integrity": "sha512-DshKgMQ8lXorI/xTRyeRkZqZ3JqgnL2aGYAhx0SkAunyHgXji27chmrOGj/6KVDBucrDf/6mSexnSoUDnlWrfA==", 83 | "requires": { 84 | "@babel/runtime": "^7.7.2", 85 | "@jimp/utils": "^0.9.3", 86 | "core-js": "^3.4.1", 87 | "omggif": "^1.0.9" 88 | } 89 | }, 90 | "@jimp/jpeg": { 91 | "version": "0.9.3", 92 | "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.9.3.tgz", 93 | "integrity": "sha512-AJzcTJXfN9BHtpzAbICwR3+GoH0pSr6OYXbAS6yuKwz+xVn9UHrEjQb74CIzIRqrT/VWcIKg29cMQxgokzWY7w==", 94 | "requires": { 95 | "@babel/runtime": "^7.7.2", 96 | "@jimp/utils": "^0.9.3", 97 | "core-js": "^3.4.1", 98 | "jpeg-js": "^0.3.4" 99 | } 100 | }, 101 | "@jimp/plugin-blit": { 102 | "version": "0.9.3", 103 | "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.9.3.tgz", 104 | "integrity": "sha512-+UxCsJ3XkRSdpigpTBJ9WkdwUc3OtBlhVZdU6OL6M9ldume5Gj3rTyWvMCqytOK1tZ/+7HmxoWe4IWX31hz9qA==", 105 | "requires": { 106 | "@babel/runtime": "^7.7.2", 107 | "@jimp/utils": "^0.9.3", 108 | "core-js": "^3.4.1" 109 | } 110 | }, 111 | "@jimp/plugin-blur": { 112 | "version": "0.9.3", 113 | "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.9.3.tgz", 114 | "integrity": "sha512-RADcYjZ5vbk5ZrUiK7qv0G4xOpHtu19HWVVX9JTDbm4VByWTxPboVKlgiYLA6l+IxIXNtEqDclsADIM0s9FQhA==", 115 | "requires": { 116 | "@babel/runtime": "^7.7.2", 117 | "@jimp/utils": "^0.9.3", 118 | "core-js": "^3.4.1" 119 | } 120 | }, 121 | "@jimp/plugin-color": { 122 | "version": "0.9.3", 123 | "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.9.3.tgz", 124 | "integrity": "sha512-gHDA5GVx4/R4fitEACKmWH7hNy0aU48MZWYRxmATvuqY39KidJ0fjwp+brQ3Ivgb35AgFVc2jQYc3U/JXv4RxQ==", 125 | "requires": { 126 | "@babel/runtime": "^7.7.2", 127 | "@jimp/utils": "^0.9.3", 128 | "core-js": "^3.4.1", 129 | "tinycolor2": "^1.4.1" 130 | } 131 | }, 132 | "@jimp/plugin-contain": { 133 | "version": "0.9.3", 134 | "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.9.3.tgz", 135 | "integrity": "sha512-vdYAtp65LNDT/hMctow5o0a/SbD41/y7Z9AO7MGsfUIK92Woq90SNTWx7JplDl4HSZGrqaBONnfiEhRiYlDrdg==", 136 | "requires": { 137 | "@babel/runtime": "^7.7.2", 138 | "@jimp/utils": "^0.9.3", 139 | "core-js": "^3.4.1" 140 | } 141 | }, 142 | "@jimp/plugin-cover": { 143 | "version": "0.9.3", 144 | "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.9.3.tgz", 145 | "integrity": "sha512-yOwsvakgyS2/C4iZF1a1wg63QKfYvqb2d6k+rgY/0vaAe44JtEx+Gbg+7iOt4EaMm5BDlxRwmcA2Q8Pef8TvAQ==", 146 | "requires": { 147 | "@babel/runtime": "^7.7.2", 148 | "@jimp/utils": "^0.9.3", 149 | "core-js": "^3.4.1" 150 | } 151 | }, 152 | "@jimp/plugin-crop": { 153 | "version": "0.9.3", 154 | "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.9.3.tgz", 155 | "integrity": "sha512-kqMXSyY8hrfo0idr6qY2USOWPrNqpDWs+D6Vwa+kV6SGJhj3rMTIcptQDaamIETSxbjkE8rwUu3K4Q5UD69D7w==", 156 | "requires": { 157 | "@babel/runtime": "^7.7.2", 158 | "@jimp/utils": "^0.9.3", 159 | "core-js": "^3.4.1" 160 | } 161 | }, 162 | "@jimp/plugin-displace": { 163 | "version": "0.9.3", 164 | "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.9.3.tgz", 165 | "integrity": "sha512-0AdwxYRWDmJ2wIRIj2RR3sRmNjMhcy5Kwt9Jbi/RRnzxkRScZAiyzkNZhBul23EM7ClfjrUrZufuUvRMHxZRDw==", 166 | "requires": { 167 | "@babel/runtime": "^7.7.2", 168 | "@jimp/utils": "^0.9.3", 169 | "core-js": "^3.4.1" 170 | } 171 | }, 172 | "@jimp/plugin-dither": { 173 | "version": "0.9.3", 174 | "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.9.3.tgz", 175 | "integrity": "sha512-8OE+Xak9xepiCwSV+oAsb/gupTnttG3aDKxtpSZjwHebnr+k1VG8NgICbMSFATTVJqqZ18oj6LC+5726qHUJ9w==", 176 | "requires": { 177 | "@babel/runtime": "^7.7.2", 178 | "@jimp/utils": "^0.9.3", 179 | "core-js": "^3.4.1" 180 | } 181 | }, 182 | "@jimp/plugin-flip": { 183 | "version": "0.9.3", 184 | "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.9.3.tgz", 185 | "integrity": "sha512-w+lzE1ZF/UOjB8qJdeIm+dLQtOK1obZwGYdCIbgxZxw4SfkkjAftJdY8o8RNOXhHDZqGu+cYQZbMKP1zcoNkyQ==", 186 | "requires": { 187 | "@babel/runtime": "^7.7.2", 188 | "@jimp/utils": "^0.9.3", 189 | "core-js": "^3.4.1" 190 | } 191 | }, 192 | "@jimp/plugin-gaussian": { 193 | "version": "0.9.3", 194 | "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.9.3.tgz", 195 | "integrity": "sha512-RPrWwzlZsbWC2opSgeyWt30JU9Uwg1+GwBnoNpEMLKeqm0Dv6snASASa4zVtviGWAIq//p3Jrap7g57hKqL0Cg==", 196 | "requires": { 197 | "@babel/runtime": "^7.7.2", 198 | "@jimp/utils": "^0.9.3", 199 | "core-js": "^3.4.1" 200 | } 201 | }, 202 | "@jimp/plugin-invert": { 203 | "version": "0.9.3", 204 | "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.9.3.tgz", 205 | "integrity": "sha512-0lRsh7IPkzyYqExrZDT50h38xdlB/+KrdiDcuxWwWyIlKauLMR0kInjwf8sPeb3elPLeETmze7uwPAxrIAtsGQ==", 206 | "requires": { 207 | "@babel/runtime": "^7.7.2", 208 | "@jimp/utils": "^0.9.3", 209 | "core-js": "^3.4.1" 210 | } 211 | }, 212 | "@jimp/plugin-mask": { 213 | "version": "0.9.3", 214 | "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.9.3.tgz", 215 | "integrity": "sha512-nZ0J62Hly9JtMZctlSDVgnTd8Fg2XGikzAYilSTCjzIRtbXL5Be/qSAZrMfLD3CZ8exTxdlEGRkEJI3RZKXYCw==", 216 | "requires": { 217 | "@babel/runtime": "^7.7.2", 218 | "@jimp/utils": "^0.9.3", 219 | "core-js": "^3.4.1" 220 | } 221 | }, 222 | "@jimp/plugin-normalize": { 223 | "version": "0.9.3", 224 | "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.9.3.tgz", 225 | "integrity": "sha512-0IvgTt4R15QJnoCHvvqlK56zOtCsQV7Mkx757kdNah8uyPGjadTcFBuqCaOMK943X36IIv+o7Ix7yvNUJZt4aw==", 226 | "requires": { 227 | "@babel/runtime": "^7.7.2", 228 | "@jimp/utils": "^0.9.3", 229 | "core-js": "^3.4.1" 230 | } 231 | }, 232 | "@jimp/plugin-print": { 233 | "version": "0.9.3", 234 | "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.9.3.tgz", 235 | "integrity": "sha512-pV6oX5Bhe9O/dbgrotz46Bv6u1M+/n9G0kRUunDjwzXrvON5raBFEJHQDPcTXiqPT25Gc9Ba4/Akfo/Zl6+wgQ==", 236 | "requires": { 237 | "@babel/runtime": "^7.7.2", 238 | "@jimp/utils": "^0.9.3", 239 | "core-js": "^3.4.1", 240 | "load-bmfont": "^1.4.0" 241 | } 242 | }, 243 | "@jimp/plugin-resize": { 244 | "version": "0.9.3", 245 | "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.9.3.tgz", 246 | "integrity": "sha512-YzqVE8QoDIZpVuI52v+WejwEjEEiJfNFviQfprfm5af7uSSseZgDw1sJ0koqAu+liMSY+Ewp79v2SDrKoJKqtg==", 247 | "requires": { 248 | "@babel/runtime": "^7.7.2", 249 | "@jimp/utils": "^0.9.3", 250 | "core-js": "^3.4.1" 251 | } 252 | }, 253 | "@jimp/plugin-rotate": { 254 | "version": "0.9.3", 255 | "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.9.3.tgz", 256 | "integrity": "sha512-kADY2pI3/yMyHbuyvKB4nqPoKf8DPQBU1b4zz2K7SxcwKh1krFf4Fa9mmhhDLoFwuNSy0SPb1JCMUO4BtFCFLA==", 257 | "requires": { 258 | "@babel/runtime": "^7.7.2", 259 | "@jimp/utils": "^0.9.3", 260 | "core-js": "^3.4.1" 261 | } 262 | }, 263 | "@jimp/plugin-scale": { 264 | "version": "0.9.3", 265 | "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.9.3.tgz", 266 | "integrity": "sha512-vZaiL5Qc+WrgGEfUe4Y0vG+qbT6pe2TW68/mu124E1tKVcZjHKZUeFN0Wr/hP2myN6nqTYj0/sord2OS/04JpA==", 267 | "requires": { 268 | "@babel/runtime": "^7.7.2", 269 | "@jimp/utils": "^0.9.3", 270 | "core-js": "^3.4.1" 271 | } 272 | }, 273 | "@jimp/plugins": { 274 | "version": "0.9.3", 275 | "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.9.3.tgz", 276 | "integrity": "sha512-KYCSgFGoZBNC0224X5yUnMHCZnCdUVrsu2Yo67o3XZfUgDjO81J+vdzZ0twpPQ6qLLVAP+nQ8hkRV/QzEUstMw==", 277 | "requires": { 278 | "@babel/runtime": "^7.7.2", 279 | "@jimp/plugin-blit": "^0.9.3", 280 | "@jimp/plugin-blur": "^0.9.3", 281 | "@jimp/plugin-color": "^0.9.3", 282 | "@jimp/plugin-contain": "^0.9.3", 283 | "@jimp/plugin-cover": "^0.9.3", 284 | "@jimp/plugin-crop": "^0.9.3", 285 | "@jimp/plugin-displace": "^0.9.3", 286 | "@jimp/plugin-dither": "^0.9.3", 287 | "@jimp/plugin-flip": "^0.9.3", 288 | "@jimp/plugin-gaussian": "^0.9.3", 289 | "@jimp/plugin-invert": "^0.9.3", 290 | "@jimp/plugin-mask": "^0.9.3", 291 | "@jimp/plugin-normalize": "^0.9.3", 292 | "@jimp/plugin-print": "^0.9.3", 293 | "@jimp/plugin-resize": "^0.9.3", 294 | "@jimp/plugin-rotate": "^0.9.3", 295 | "@jimp/plugin-scale": "^0.9.3", 296 | "core-js": "^3.4.1", 297 | "timm": "^1.6.1" 298 | } 299 | }, 300 | "@jimp/png": { 301 | "version": "0.9.3", 302 | "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.9.3.tgz", 303 | "integrity": "sha512-LJXUemDTSbTGAGEp9hNQH0uTRSB8gYeE6FsfT3M00oZincu6/WzDzl0P8E95rMjNxZqAihdTyOP3+kcrbbqX+w==", 304 | "requires": { 305 | "@babel/runtime": "^7.7.2", 306 | "@jimp/utils": "^0.9.3", 307 | "core-js": "^3.4.1", 308 | "pngjs": "^3.3.3" 309 | } 310 | }, 311 | "@jimp/tiff": { 312 | "version": "0.9.3", 313 | "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.9.3.tgz", 314 | "integrity": "sha512-w9H6dT+GDHN//Srsv27JhRn7R2byzUahOGfFw7KpIn95jg0ogcxjKTo/RAGQC56sr4U092e4Npl7E85Lt934WQ==", 315 | "requires": { 316 | "@babel/runtime": "^7.7.2", 317 | "core-js": "^3.4.1", 318 | "utif": "^2.0.1" 319 | } 320 | }, 321 | "@jimp/types": { 322 | "version": "0.9.3", 323 | "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.9.3.tgz", 324 | "integrity": "sha512-hUJKoT2IhnbO/trxNWzN19n8g+p7aKbM1R+71n4wMZnD41PzrVtz+sBBCdB+JCjBJs/i7fJt4d9z0i3Xe8m7Zw==", 325 | "requires": { 326 | "@babel/runtime": "^7.7.2", 327 | "@jimp/bmp": "^0.9.3", 328 | "@jimp/gif": "^0.9.3", 329 | "@jimp/jpeg": "^0.9.3", 330 | "@jimp/png": "^0.9.3", 331 | "@jimp/tiff": "^0.9.3", 332 | "core-js": "^3.4.1", 333 | "timm": "^1.6.1" 334 | } 335 | }, 336 | "@jimp/utils": { 337 | "version": "0.9.3", 338 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.9.3.tgz", 339 | "integrity": "sha512-9D2Of6BcjYONtl77YfmU2y5aRMLe0/O2e2aQvfCxdNwD33jRdwNdN4i3m73dpiClNquApIjL4nYGhTixA4UstA==", 340 | "requires": { 341 | "@babel/runtime": "^7.7.2", 342 | "core-js": "^3.4.1" 343 | } 344 | }, 345 | "@types/bluebird": { 346 | "version": "3.5.29", 347 | "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.29.tgz", 348 | "integrity": "sha512-kmVtnxTuUuhCET669irqQmPAez4KFnFVKvpleVRyfC3g+SHD1hIkFZcWLim9BVcwUBLO59o8VZE4yGCmTif8Yw==" 349 | }, 350 | "@types/caseless": { 351 | "version": "0.12.2", 352 | "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", 353 | "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==" 354 | }, 355 | "@types/fs-extra": { 356 | "version": "8.0.1", 357 | "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.0.1.tgz", 358 | "integrity": "sha512-J00cVDALmi/hJOYsunyT52Hva5TnJeKP5yd1r+mH/ZU0mbYZflR0Z5kw5kITtKTRYMhm1JMClOFYdHnQszEvqw==", 359 | "dev": true, 360 | "requires": { 361 | "@types/node": "*" 362 | } 363 | }, 364 | "@types/node": { 365 | "version": "12.12.21", 366 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.21.tgz", 367 | "integrity": "sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA==" 368 | }, 369 | "@types/object-hash": { 370 | "version": "1.3.0", 371 | "resolved": "https://registry.npmjs.org/@types/object-hash/-/object-hash-1.3.0.tgz", 372 | "integrity": "sha512-il4NIe4jTx4lfhkKaksmmGHw5EsVkO8sHWkpJHM9m59r1dtsVadLSrJqdE8zU74NENDAsR3oLIOlooRAXlPLNA==", 373 | "dev": true, 374 | "requires": { 375 | "@types/node": "*" 376 | } 377 | }, 378 | "@types/request": { 379 | "version": "2.48.4", 380 | "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.4.tgz", 381 | "integrity": "sha512-W1t1MTKYR8PxICH+A4HgEIPuAC3sbljoEVfyZbeFJJDbr30guDspJri2XOaM2E+Un7ZjrihaDi7cf6fPa2tbgw==", 382 | "requires": { 383 | "@types/caseless": "*", 384 | "@types/node": "*", 385 | "@types/tough-cookie": "*", 386 | "form-data": "^2.5.0" 387 | } 388 | }, 389 | "@types/request-promise": { 390 | "version": "4.1.45", 391 | "resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.45.tgz", 392 | "integrity": "sha512-KFagTY/a7CzAj86DkhaAtqP0ViYTNam+CfEokSwtPFUIuq9Qrq+Rq2X4nuaB6OJmM2s0xWeiS085Ro7vR0tt9Q==", 393 | "requires": { 394 | "@types/bluebird": "*", 395 | "@types/request": "*" 396 | } 397 | }, 398 | "@types/tough-cookie": { 399 | "version": "2.3.6", 400 | "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.6.tgz", 401 | "integrity": "sha512-wHNBMnkoEBiRAd3s8KTKwIuO9biFtTf0LehITzBhSco+HQI0xkXZbLOD55SW3Aqw3oUkHstkm5SPv58yaAdFPQ==" 402 | }, 403 | "@types/winreg": { 404 | "version": "1.2.30", 405 | "resolved": "https://registry.npmjs.org/@types/winreg/-/winreg-1.2.30.tgz", 406 | "integrity": "sha1-kdZxDlNtNFucmwF8V0z2qNpkxRg=", 407 | "dev": true 408 | }, 409 | "ajv": { 410 | "version": "6.10.2", 411 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", 412 | "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", 413 | "requires": { 414 | "fast-deep-equal": "^2.0.1", 415 | "fast-json-stable-stringify": "^2.0.0", 416 | "json-schema-traverse": "^0.4.1", 417 | "uri-js": "^4.2.2" 418 | } 419 | }, 420 | "ansi-styles": { 421 | "version": "3.2.1", 422 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 423 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 424 | "requires": { 425 | "color-convert": "^1.9.0" 426 | } 427 | }, 428 | "any-base": { 429 | "version": "1.1.0", 430 | "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", 431 | "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" 432 | }, 433 | "argparse": { 434 | "version": "1.0.10", 435 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 436 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 437 | "dev": true, 438 | "requires": { 439 | "sprintf-js": "~1.0.2" 440 | } 441 | }, 442 | "array-back": { 443 | "version": "3.1.0", 444 | "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", 445 | "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==" 446 | }, 447 | "asn1": { 448 | "version": "0.2.4", 449 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 450 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 451 | "requires": { 452 | "safer-buffer": "~2.1.0" 453 | } 454 | }, 455 | "assert-plus": { 456 | "version": "1.0.0", 457 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 458 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 459 | }, 460 | "asynckit": { 461 | "version": "0.4.0", 462 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 463 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 464 | }, 465 | "aws-sign2": { 466 | "version": "0.7.0", 467 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 468 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 469 | }, 470 | "aws4": { 471 | "version": "1.9.0", 472 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", 473 | "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==" 474 | }, 475 | "balanced-match": { 476 | "version": "1.0.0", 477 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 478 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 479 | }, 480 | "base64-js": { 481 | "version": "1.3.1", 482 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", 483 | "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" 484 | }, 485 | "bcrypt-pbkdf": { 486 | "version": "1.0.2", 487 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 488 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 489 | "requires": { 490 | "tweetnacl": "^0.14.3" 491 | } 492 | }, 493 | "beautiful-dom": { 494 | "version": "1.0.7", 495 | "resolved": "https://registry.npmjs.org/beautiful-dom/-/beautiful-dom-1.0.7.tgz", 496 | "integrity": "sha512-qg7LB4i+WJ1fQZwnQxAfUO5PefZ+PxkIx2kN8IhfxhDVvT9PF4CIYFq0K59esERFQ+DpC8OAcg3oFNcrZI39XQ==" 497 | }, 498 | "bluebird": { 499 | "version": "3.7.2", 500 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 501 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 502 | }, 503 | "bmp-js": { 504 | "version": "0.1.0", 505 | "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", 506 | "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" 507 | }, 508 | "brace-expansion": { 509 | "version": "1.1.11", 510 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 511 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 512 | "requires": { 513 | "balanced-match": "^1.0.0", 514 | "concat-map": "0.0.1" 515 | } 516 | }, 517 | "buffer": { 518 | "version": "5.4.3", 519 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", 520 | "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", 521 | "requires": { 522 | "base64-js": "^1.0.2", 523 | "ieee754": "^1.1.4" 524 | } 525 | }, 526 | "buffer-equal": { 527 | "version": "0.0.1", 528 | "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", 529 | "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" 530 | }, 531 | "builtin-modules": { 532 | "version": "1.1.1", 533 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 534 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", 535 | "dev": true 536 | }, 537 | "caseless": { 538 | "version": "0.12.0", 539 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 540 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 541 | }, 542 | "chalk": { 543 | "version": "2.4.2", 544 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 545 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 546 | "requires": { 547 | "ansi-styles": "^3.2.1", 548 | "escape-string-regexp": "^1.0.5", 549 | "supports-color": "^5.3.0" 550 | } 551 | }, 552 | "color-convert": { 553 | "version": "1.9.3", 554 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 555 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 556 | "requires": { 557 | "color-name": "1.1.3" 558 | } 559 | }, 560 | "color-name": { 561 | "version": "1.1.3", 562 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 563 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 564 | }, 565 | "combined-stream": { 566 | "version": "1.0.8", 567 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 568 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 569 | "requires": { 570 | "delayed-stream": "~1.0.0" 571 | } 572 | }, 573 | "command-line-args": { 574 | "version": "5.1.1", 575 | "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", 576 | "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", 577 | "requires": { 578 | "array-back": "^3.0.1", 579 | "find-replace": "^3.0.0", 580 | "lodash.camelcase": "^4.3.0", 581 | "typical": "^4.0.0" 582 | } 583 | }, 584 | "command-line-usage": { 585 | "version": "6.1.0", 586 | "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.0.tgz", 587 | "integrity": "sha512-Ew1clU4pkUeo6AFVDFxCbnN7GIZfXl48HIOQeFQnkO3oOqvpI7wdqtLRwv9iOCZ/7A+z4csVZeiDdEcj8g6Wiw==", 588 | "requires": { 589 | "array-back": "^4.0.0", 590 | "chalk": "^2.4.2", 591 | "table-layout": "^1.0.0", 592 | "typical": "^5.2.0" 593 | }, 594 | "dependencies": { 595 | "array-back": { 596 | "version": "4.0.1", 597 | "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", 598 | "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==" 599 | }, 600 | "typical": { 601 | "version": "5.2.0", 602 | "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", 603 | "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==" 604 | } 605 | } 606 | }, 607 | "commander": { 608 | "version": "2.20.3", 609 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 610 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", 611 | "dev": true 612 | }, 613 | "concat-map": { 614 | "version": "0.0.1", 615 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 616 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 617 | }, 618 | "core-js": { 619 | "version": "3.6.4", 620 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", 621 | "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==" 622 | }, 623 | "core-util-is": { 624 | "version": "1.0.2", 625 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 626 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 627 | }, 628 | "d3-delaunay": { 629 | "version": "5.2.1", 630 | "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-5.2.1.tgz", 631 | "integrity": "sha512-ZZdeJl6cKRyqYVFYK+/meXvWIrAvZsZTD7WSxl4OPXCmuXNgDyACAClAJHD63zL25TA+IJGURUNO7rFseNFCYw==", 632 | "requires": { 633 | "delaunator": "4" 634 | } 635 | }, 636 | "dashdash": { 637 | "version": "1.14.1", 638 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 639 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 640 | "requires": { 641 | "assert-plus": "^1.0.0" 642 | } 643 | }, 644 | "deep-extend": { 645 | "version": "0.6.0", 646 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", 647 | "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" 648 | }, 649 | "delaunator": { 650 | "version": "4.0.1", 651 | "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-4.0.1.tgz", 652 | "integrity": "sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag==" 653 | }, 654 | "delay": { 655 | "version": "4.3.0", 656 | "resolved": "https://registry.npmjs.org/delay/-/delay-4.3.0.tgz", 657 | "integrity": "sha512-Lwaf3zVFDMBop1yDuFZ19F9WyGcZcGacsbdlZtWjQmM50tOcMntm1njF/Nb/Vjij3KaSvCF+sEYGKrrjObu2NA==" 658 | }, 659 | "delayed-stream": { 660 | "version": "1.0.0", 661 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 662 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 663 | }, 664 | "diff": { 665 | "version": "4.0.1", 666 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", 667 | "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", 668 | "dev": true 669 | }, 670 | "dom-walk": { 671 | "version": "0.1.1", 672 | "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", 673 | "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" 674 | }, 675 | "ecc-jsbn": { 676 | "version": "0.1.2", 677 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 678 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 679 | "requires": { 680 | "jsbn": "~0.1.0", 681 | "safer-buffer": "^2.1.0" 682 | } 683 | }, 684 | "escape-string-regexp": { 685 | "version": "1.0.5", 686 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 687 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 688 | }, 689 | "esprima": { 690 | "version": "4.0.1", 691 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 692 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 693 | "dev": true 694 | }, 695 | "esutils": { 696 | "version": "2.0.3", 697 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 698 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 699 | "dev": true 700 | }, 701 | "exif-parser": { 702 | "version": "0.1.12", 703 | "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", 704 | "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" 705 | }, 706 | "extend": { 707 | "version": "3.0.2", 708 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 709 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 710 | }, 711 | "extsprintf": { 712 | "version": "1.3.0", 713 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 714 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 715 | }, 716 | "fast-deep-equal": { 717 | "version": "2.0.1", 718 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", 719 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" 720 | }, 721 | "fast-json-stable-stringify": { 722 | "version": "2.1.0", 723 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 724 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" 725 | }, 726 | "file-type": { 727 | "version": "9.0.0", 728 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", 729 | "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==" 730 | }, 731 | "find-replace": { 732 | "version": "3.0.0", 733 | "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", 734 | "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", 735 | "requires": { 736 | "array-back": "^3.0.1" 737 | } 738 | }, 739 | "forever-agent": { 740 | "version": "0.6.1", 741 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 742 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 743 | }, 744 | "form-data": { 745 | "version": "2.5.1", 746 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", 747 | "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", 748 | "requires": { 749 | "asynckit": "^0.4.0", 750 | "combined-stream": "^1.0.6", 751 | "mime-types": "^2.1.12" 752 | } 753 | }, 754 | "fs-extra": { 755 | "version": "8.1.0", 756 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", 757 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", 758 | "requires": { 759 | "graceful-fs": "^4.2.0", 760 | "jsonfile": "^4.0.0", 761 | "universalify": "^0.1.0" 762 | } 763 | }, 764 | "fs.realpath": { 765 | "version": "1.0.0", 766 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 767 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 768 | }, 769 | "getpass": { 770 | "version": "0.1.7", 771 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 772 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 773 | "requires": { 774 | "assert-plus": "^1.0.0" 775 | } 776 | }, 777 | "glob": { 778 | "version": "7.1.6", 779 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 780 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 781 | "requires": { 782 | "fs.realpath": "^1.0.0", 783 | "inflight": "^1.0.4", 784 | "inherits": "2", 785 | "minimatch": "^3.0.4", 786 | "once": "^1.3.0", 787 | "path-is-absolute": "^1.0.0" 788 | } 789 | }, 790 | "global": { 791 | "version": "4.3.2", 792 | "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", 793 | "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", 794 | "requires": { 795 | "min-document": "^2.19.0", 796 | "process": "~0.5.1" 797 | } 798 | }, 799 | "graceful-fs": { 800 | "version": "4.2.3", 801 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", 802 | "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" 803 | }, 804 | "har-schema": { 805 | "version": "2.0.0", 806 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 807 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 808 | }, 809 | "har-validator": { 810 | "version": "5.1.3", 811 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", 812 | "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", 813 | "requires": { 814 | "ajv": "^6.5.5", 815 | "har-schema": "^2.0.0" 816 | } 817 | }, 818 | "has-flag": { 819 | "version": "3.0.0", 820 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 821 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 822 | }, 823 | "http-signature": { 824 | "version": "1.2.0", 825 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 826 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 827 | "requires": { 828 | "assert-plus": "^1.0.0", 829 | "jsprim": "^1.2.2", 830 | "sshpk": "^1.7.0" 831 | } 832 | }, 833 | "ieee754": { 834 | "version": "1.1.13", 835 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", 836 | "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" 837 | }, 838 | "inflight": { 839 | "version": "1.0.6", 840 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 841 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 842 | "requires": { 843 | "once": "^1.3.0", 844 | "wrappy": "1" 845 | } 846 | }, 847 | "inherits": { 848 | "version": "2.0.4", 849 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 850 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 851 | }, 852 | "is-function": { 853 | "version": "1.0.1", 854 | "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", 855 | "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" 856 | }, 857 | "is-typedarray": { 858 | "version": "1.0.0", 859 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 860 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 861 | }, 862 | "isstream": { 863 | "version": "0.1.2", 864 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 865 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 866 | }, 867 | "jimp": { 868 | "version": "0.9.3", 869 | "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.9.3.tgz", 870 | "integrity": "sha512-dIxvT1OMRkd3+B18XUhJ5WZ2Dw7Hp8mvjaTqfi945zZ7fga6LT22h3NLYDorHHAiy9z30KjfNnOgpBoxrdjDZg==", 871 | "requires": { 872 | "@babel/runtime": "^7.7.2", 873 | "@jimp/custom": "^0.9.3", 874 | "@jimp/plugins": "^0.9.3", 875 | "@jimp/types": "^0.9.3", 876 | "core-js": "^3.4.1", 877 | "regenerator-runtime": "^0.13.3" 878 | } 879 | }, 880 | "jpeg-js": { 881 | "version": "0.3.7", 882 | "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz", 883 | "integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==" 884 | }, 885 | "js-tokens": { 886 | "version": "4.0.0", 887 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 888 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 889 | "dev": true 890 | }, 891 | "js-yaml": { 892 | "version": "3.13.1", 893 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 894 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 895 | "dev": true, 896 | "requires": { 897 | "argparse": "^1.0.7", 898 | "esprima": "^4.0.0" 899 | } 900 | }, 901 | "jsbn": { 902 | "version": "0.1.1", 903 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 904 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 905 | }, 906 | "json-schema": { 907 | "version": "0.2.3", 908 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 909 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 910 | }, 911 | "json-schema-traverse": { 912 | "version": "0.4.1", 913 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 914 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 915 | }, 916 | "json-stringify-safe": { 917 | "version": "5.0.1", 918 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 919 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 920 | }, 921 | "jsonfile": { 922 | "version": "4.0.0", 923 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 924 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 925 | "requires": { 926 | "graceful-fs": "^4.1.6" 927 | } 928 | }, 929 | "jsprim": { 930 | "version": "1.4.1", 931 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 932 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 933 | "requires": { 934 | "assert-plus": "1.0.0", 935 | "extsprintf": "1.3.0", 936 | "json-schema": "0.2.3", 937 | "verror": "1.10.0" 938 | } 939 | }, 940 | "load-bmfont": { 941 | "version": "1.4.0", 942 | "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.0.tgz", 943 | "integrity": "sha512-kT63aTAlNhZARowaNYcY29Fn/QYkc52M3l6V1ifRcPewg2lvUZDAj7R6dXjOL9D0sict76op3T5+odumDSF81g==", 944 | "requires": { 945 | "buffer-equal": "0.0.1", 946 | "mime": "^1.3.4", 947 | "parse-bmfont-ascii": "^1.0.3", 948 | "parse-bmfont-binary": "^1.0.5", 949 | "parse-bmfont-xml": "^1.1.4", 950 | "phin": "^2.9.1", 951 | "xhr": "^2.0.1", 952 | "xtend": "^4.0.0" 953 | } 954 | }, 955 | "lodash": { 956 | "version": "4.17.15", 957 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 958 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" 959 | }, 960 | "lodash.camelcase": { 961 | "version": "4.3.0", 962 | "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", 963 | "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" 964 | }, 965 | "mime": { 966 | "version": "1.6.0", 967 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 968 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 969 | }, 970 | "mime-db": { 971 | "version": "1.42.0", 972 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", 973 | "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==" 974 | }, 975 | "mime-types": { 976 | "version": "2.1.25", 977 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", 978 | "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", 979 | "requires": { 980 | "mime-db": "1.42.0" 981 | } 982 | }, 983 | "min-document": { 984 | "version": "2.19.0", 985 | "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", 986 | "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", 987 | "requires": { 988 | "dom-walk": "^0.1.0" 989 | } 990 | }, 991 | "minimatch": { 992 | "version": "3.0.4", 993 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 994 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 995 | "requires": { 996 | "brace-expansion": "^1.1.7" 997 | } 998 | }, 999 | "minimist": { 1000 | "version": "0.0.8", 1001 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1002 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 1003 | }, 1004 | "mkdirp": { 1005 | "version": "0.5.1", 1006 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1007 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1008 | "requires": { 1009 | "minimist": "0.0.8" 1010 | } 1011 | }, 1012 | "oauth-sign": { 1013 | "version": "0.9.0", 1014 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 1015 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" 1016 | }, 1017 | "object-hash": { 1018 | "version": "2.0.1", 1019 | "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.1.tgz", 1020 | "integrity": "sha512-HgcGMooY4JC2PBt9sdUdJ6PMzpin+YtY3r/7wg0uTifP+HJWW8rammseSEHuyt0UeShI183UGssCJqm1bJR7QA==" 1021 | }, 1022 | "omggif": { 1023 | "version": "1.0.10", 1024 | "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", 1025 | "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" 1026 | }, 1027 | "once": { 1028 | "version": "1.4.0", 1029 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1030 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1031 | "requires": { 1032 | "wrappy": "1" 1033 | } 1034 | }, 1035 | "pako": { 1036 | "version": "1.0.11", 1037 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", 1038 | "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" 1039 | }, 1040 | "parse-bmfont-ascii": { 1041 | "version": "1.0.6", 1042 | "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", 1043 | "integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU=" 1044 | }, 1045 | "parse-bmfont-binary": { 1046 | "version": "1.0.6", 1047 | "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", 1048 | "integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY=" 1049 | }, 1050 | "parse-bmfont-xml": { 1051 | "version": "1.1.4", 1052 | "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", 1053 | "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", 1054 | "requires": { 1055 | "xml-parse-from-string": "^1.0.0", 1056 | "xml2js": "^0.4.5" 1057 | } 1058 | }, 1059 | "parse-headers": { 1060 | "version": "2.0.3", 1061 | "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", 1062 | "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==" 1063 | }, 1064 | "path-is-absolute": { 1065 | "version": "1.0.1", 1066 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1067 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 1068 | }, 1069 | "path-parse": { 1070 | "version": "1.0.6", 1071 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 1072 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", 1073 | "dev": true 1074 | }, 1075 | "performance-now": { 1076 | "version": "2.1.0", 1077 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1078 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 1079 | }, 1080 | "phin": { 1081 | "version": "2.9.3", 1082 | "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", 1083 | "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" 1084 | }, 1085 | "pixelmatch": { 1086 | "version": "4.0.2", 1087 | "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", 1088 | "integrity": "sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=", 1089 | "requires": { 1090 | "pngjs": "^3.0.0" 1091 | } 1092 | }, 1093 | "pngjs": { 1094 | "version": "3.4.0", 1095 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", 1096 | "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" 1097 | }, 1098 | "process": { 1099 | "version": "0.5.2", 1100 | "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", 1101 | "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" 1102 | }, 1103 | "psl": { 1104 | "version": "1.6.0", 1105 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.6.0.tgz", 1106 | "integrity": "sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA==" 1107 | }, 1108 | "punycode": { 1109 | "version": "2.1.1", 1110 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1111 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" 1112 | }, 1113 | "qs": { 1114 | "version": "6.5.2", 1115 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 1116 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 1117 | }, 1118 | "reduce-flatten": { 1119 | "version": "2.0.0", 1120 | "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", 1121 | "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==" 1122 | }, 1123 | "regenerator-runtime": { 1124 | "version": "0.13.3", 1125 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", 1126 | "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==" 1127 | }, 1128 | "request": { 1129 | "version": "2.88.0", 1130 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 1131 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 1132 | "requires": { 1133 | "aws-sign2": "~0.7.0", 1134 | "aws4": "^1.8.0", 1135 | "caseless": "~0.12.0", 1136 | "combined-stream": "~1.0.6", 1137 | "extend": "~3.0.2", 1138 | "forever-agent": "~0.6.1", 1139 | "form-data": "~2.3.2", 1140 | "har-validator": "~5.1.0", 1141 | "http-signature": "~1.2.0", 1142 | "is-typedarray": "~1.0.0", 1143 | "isstream": "~0.1.2", 1144 | "json-stringify-safe": "~5.0.1", 1145 | "mime-types": "~2.1.19", 1146 | "oauth-sign": "~0.9.0", 1147 | "performance-now": "^2.1.0", 1148 | "qs": "~6.5.2", 1149 | "safe-buffer": "^5.1.2", 1150 | "tough-cookie": "~2.4.3", 1151 | "tunnel-agent": "^0.6.0", 1152 | "uuid": "^3.3.2" 1153 | }, 1154 | "dependencies": { 1155 | "form-data": { 1156 | "version": "2.3.3", 1157 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 1158 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 1159 | "requires": { 1160 | "asynckit": "^0.4.0", 1161 | "combined-stream": "^1.0.6", 1162 | "mime-types": "^2.1.12" 1163 | } 1164 | } 1165 | } 1166 | }, 1167 | "request-promise": { 1168 | "version": "4.2.5", 1169 | "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.5.tgz", 1170 | "integrity": "sha512-ZgnepCykFdmpq86fKGwqntyTiUrHycALuGggpyCZwMvGaZWgxW6yagT0FHkgo5LzYvOaCNvxYwWYIjevSH1EDg==", 1171 | "requires": { 1172 | "bluebird": "^3.5.0", 1173 | "request-promise-core": "1.1.3", 1174 | "stealthy-require": "^1.1.1", 1175 | "tough-cookie": "^2.3.3" 1176 | } 1177 | }, 1178 | "request-promise-core": { 1179 | "version": "1.1.3", 1180 | "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", 1181 | "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", 1182 | "requires": { 1183 | "lodash": "^4.17.15" 1184 | } 1185 | }, 1186 | "resolve": { 1187 | "version": "1.14.1", 1188 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz", 1189 | "integrity": "sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg==", 1190 | "dev": true, 1191 | "requires": { 1192 | "path-parse": "^1.0.6" 1193 | } 1194 | }, 1195 | "safe-buffer": { 1196 | "version": "5.2.0", 1197 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", 1198 | "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" 1199 | }, 1200 | "safer-buffer": { 1201 | "version": "2.1.2", 1202 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1203 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1204 | }, 1205 | "sax": { 1206 | "version": "1.2.4", 1207 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 1208 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" 1209 | }, 1210 | "semver": { 1211 | "version": "5.7.1", 1212 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1213 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1214 | "dev": true 1215 | }, 1216 | "sprintf-js": { 1217 | "version": "1.0.3", 1218 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1219 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1220 | "dev": true 1221 | }, 1222 | "sshpk": { 1223 | "version": "1.16.1", 1224 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 1225 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 1226 | "requires": { 1227 | "asn1": "~0.2.3", 1228 | "assert-plus": "^1.0.0", 1229 | "bcrypt-pbkdf": "^1.0.0", 1230 | "dashdash": "^1.12.0", 1231 | "ecc-jsbn": "~0.1.1", 1232 | "getpass": "^0.1.1", 1233 | "jsbn": "~0.1.0", 1234 | "safer-buffer": "^2.0.2", 1235 | "tweetnacl": "~0.14.0" 1236 | } 1237 | }, 1238 | "stealthy-require": { 1239 | "version": "1.1.1", 1240 | "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", 1241 | "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" 1242 | }, 1243 | "supports-color": { 1244 | "version": "5.5.0", 1245 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1246 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1247 | "requires": { 1248 | "has-flag": "^3.0.0" 1249 | } 1250 | }, 1251 | "table-layout": { 1252 | "version": "1.0.0", 1253 | "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.0.tgz", 1254 | "integrity": "sha512-o8V8u943KXX9gLNK/Ss1n6Nn4YhpyY/RRnp3hKv/zTA+SXYiQnzJQlR8CZQf1RqYqgkiWMJ54Mv+Vq9Kfzxz1A==", 1255 | "requires": { 1256 | "array-back": "^3.1.0", 1257 | "deep-extend": "~0.6.0", 1258 | "typical": "^5.0.0", 1259 | "wordwrapjs": "^4.0.0" 1260 | }, 1261 | "dependencies": { 1262 | "typical": { 1263 | "version": "5.2.0", 1264 | "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", 1265 | "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==" 1266 | } 1267 | } 1268 | }, 1269 | "timm": { 1270 | "version": "1.6.2", 1271 | "resolved": "https://registry.npmjs.org/timm/-/timm-1.6.2.tgz", 1272 | "integrity": "sha512-IH3DYDL1wMUwmIlVmMrmesw5lZD6N+ZOAFWEyLrtpoL9Bcrs9u7M/vyOnHzDD2SMs4irLkVjqxZbHrXStS/Nmw==" 1273 | }, 1274 | "tinycolor2": { 1275 | "version": "1.4.1", 1276 | "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", 1277 | "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" 1278 | }, 1279 | "tough-cookie": { 1280 | "version": "2.4.3", 1281 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 1282 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 1283 | "requires": { 1284 | "psl": "^1.1.24", 1285 | "punycode": "^1.4.1" 1286 | }, 1287 | "dependencies": { 1288 | "punycode": { 1289 | "version": "1.4.1", 1290 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 1291 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 1292 | } 1293 | } 1294 | }, 1295 | "tslib": { 1296 | "version": "1.10.0", 1297 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", 1298 | "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", 1299 | "dev": true 1300 | }, 1301 | "tslint": { 1302 | "version": "5.20.1", 1303 | "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", 1304 | "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", 1305 | "dev": true, 1306 | "requires": { 1307 | "@babel/code-frame": "^7.0.0", 1308 | "builtin-modules": "^1.1.1", 1309 | "chalk": "^2.3.0", 1310 | "commander": "^2.12.1", 1311 | "diff": "^4.0.1", 1312 | "glob": "^7.1.1", 1313 | "js-yaml": "^3.13.1", 1314 | "minimatch": "^3.0.4", 1315 | "mkdirp": "^0.5.1", 1316 | "resolve": "^1.3.2", 1317 | "semver": "^5.3.0", 1318 | "tslib": "^1.8.0", 1319 | "tsutils": "^2.29.0" 1320 | } 1321 | }, 1322 | "tsutils": { 1323 | "version": "2.29.0", 1324 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", 1325 | "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", 1326 | "dev": true, 1327 | "requires": { 1328 | "tslib": "^1.8.1" 1329 | } 1330 | }, 1331 | "tunnel-agent": { 1332 | "version": "0.6.0", 1333 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1334 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1335 | "requires": { 1336 | "safe-buffer": "^5.0.1" 1337 | } 1338 | }, 1339 | "tweetnacl": { 1340 | "version": "0.14.5", 1341 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1342 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 1343 | }, 1344 | "typescript": { 1345 | "version": "3.7.4", 1346 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.4.tgz", 1347 | "integrity": "sha512-A25xv5XCtarLwXpcDNZzCGvW2D1S3/bACratYBx2sax8PefsFhlYmkQicKHvpYflFS8if4zne5zT5kpJ7pzuvw==", 1348 | "dev": true 1349 | }, 1350 | "typical": { 1351 | "version": "4.0.0", 1352 | "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", 1353 | "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==" 1354 | }, 1355 | "universalify": { 1356 | "version": "0.1.2", 1357 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 1358 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" 1359 | }, 1360 | "uri-js": { 1361 | "version": "4.2.2", 1362 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 1363 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 1364 | "requires": { 1365 | "punycode": "^2.1.0" 1366 | } 1367 | }, 1368 | "utif": { 1369 | "version": "2.0.1", 1370 | "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", 1371 | "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", 1372 | "requires": { 1373 | "pako": "^1.0.5" 1374 | } 1375 | }, 1376 | "uuid": { 1377 | "version": "3.3.3", 1378 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", 1379 | "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" 1380 | }, 1381 | "verror": { 1382 | "version": "1.10.0", 1383 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1384 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 1385 | "requires": { 1386 | "assert-plus": "^1.0.0", 1387 | "core-util-is": "1.0.2", 1388 | "extsprintf": "^1.2.0" 1389 | } 1390 | }, 1391 | "winreg": { 1392 | "version": "1.2.4", 1393 | "resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.4.tgz", 1394 | "integrity": "sha1-ugZWKbepJRMOFXeRCM9UCZDpjRs=" 1395 | }, 1396 | "wordwrapjs": { 1397 | "version": "4.0.0", 1398 | "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.0.tgz", 1399 | "integrity": "sha512-Svqw723a3R34KvsMgpjFBYCgNOSdcW3mQFK4wIfhGQhtaFVOJmdYoXgi63ne3dTlWgatVcUc7t4HtQ/+bUVIzQ==", 1400 | "requires": { 1401 | "reduce-flatten": "^2.0.0", 1402 | "typical": "^5.0.0" 1403 | }, 1404 | "dependencies": { 1405 | "typical": { 1406 | "version": "5.2.0", 1407 | "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", 1408 | "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==" 1409 | } 1410 | } 1411 | }, 1412 | "wrappy": { 1413 | "version": "1.0.2", 1414 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1415 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1416 | }, 1417 | "xhr": { 1418 | "version": "2.5.0", 1419 | "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", 1420 | "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", 1421 | "requires": { 1422 | "global": "~4.3.0", 1423 | "is-function": "^1.0.1", 1424 | "parse-headers": "^2.0.0", 1425 | "xtend": "^4.0.0" 1426 | } 1427 | }, 1428 | "xml-parse-from-string": { 1429 | "version": "1.0.1", 1430 | "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", 1431 | "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=" 1432 | }, 1433 | "xml2js": { 1434 | "version": "0.4.23", 1435 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", 1436 | "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", 1437 | "requires": { 1438 | "sax": ">=0.6.0", 1439 | "xmlbuilder": "~11.0.0" 1440 | } 1441 | }, 1442 | "xmlbuilder": { 1443 | "version": "11.0.1", 1444 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 1445 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" 1446 | }, 1447 | "xtend": { 1448 | "version": "4.0.2", 1449 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 1450 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 1451 | } 1452 | } 1453 | } 1454 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rbxupload", 3 | "version": "0.3.1", 4 | "description": "A tool to upload files to Roblox", 5 | "keywords": [ 6 | "roblox" 7 | ], 8 | "homepage": "https://github.com/Corecii/RbxUpload", 9 | "bugs": "https://github.com/Corecii/RbxUpload/issues", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/Corecii/RbxUpload.git" 13 | }, 14 | "main": "./out/main.js", 15 | "bin": { 16 | "rbxupload": "./bin/cli" 17 | }, 18 | "files": [ 19 | "out/**/*", 20 | "bin/**/*" 21 | ], 22 | "scripts": { 23 | "build": "tsc", 24 | "prepublishOnly": "tsc", 25 | "binpack": "tsc && pkg -o rbxupload -t node10-win-x64,node10-win-x86,node10-macos-x64,node10-linux-x64 .\\out\\main.js", 26 | "mtest": "tsc && node out/main.js" 27 | }, 28 | "author": "corecii@corecii.com", 29 | "license": "MIT", 30 | "devDependencies": { 31 | "@types/fs-extra": "^8.0.1", 32 | "@types/object-hash": "^1.3.0", 33 | "@types/winreg": "^1.2.30", 34 | "typescript": "^3.7.2", 35 | "tslint": "^5.20.1" 36 | }, 37 | "dependencies": { 38 | "@iarna/toml": "https://github.com/Corecii/iarna-toml", 39 | "@types/request": "^2.48.3", 40 | "@types/request-promise": "^4.1.45", 41 | "beautiful-dom": "^1.0.7", 42 | "command-line-args": "^5.1.1", 43 | "command-line-usage": "^6.1.0", 44 | "d3-delaunay": "^5.2.1", 45 | "delay": "^4.3.0", 46 | "fs-extra": "^8.1.0", 47 | "glob": "^7.1.6", 48 | "jimp": "^0.9.3", 49 | "object-hash": "^2.0.1", 50 | "request": "^2.88.0", 51 | "request-promise": "^4.2.5", 52 | "winreg": "^1.2.4" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import * as toml from "@iarna/toml"; 2 | import * as commandLineArgs from "command-line-args"; 3 | import * as commandLineUsage from "command-line-usage"; 4 | import * as delay from "delay"; 5 | import * as fs from "fs-extra"; 6 | import * as glob from "glob"; 7 | import * as path from "path"; 8 | import * as pixelfix from "./pixelfix"; 9 | import * as rbxupload from "./rbxupload"; 10 | import * as roblox from "./roblox"; 11 | 12 | function oneOf(arr: string[]) { 13 | return (input: string) => { 14 | if (arr.indexOf(input) === -1) { 15 | throw new Error("Expected one of " + arr.join(", ")); 16 | } 17 | return input; 18 | }; 19 | } 20 | 21 | const skipValues = ["user", "user-verify", "group", "group-verify", "files", "files-verify", "type", "id", "name", "description", "name-retry", "pixelfix", "done"]; 22 | const assetTypeValues = ["auto", "decal"]; // , "image", "shirt", "pants", "tshirt", "model", "animation", "place"]; 23 | 24 | const assetTypeExtensions: any = { }; 25 | assetTypeExtensions.decal = [".png", ".jpg", ".jpeg"]; 26 | // assetTypeExtensions.image = assetTypeExtensions.decal; 27 | // assetTypeExtensions.shirt = assetTypeExtensions.decal; 28 | // assetTypeExtensions.pants = assetTypeExtensions.decal; 29 | // assetTypeExtensions.tshirt = assetTypeExtensions.decal; 30 | // assetTypeExtensions.model = [".rbxm"]; 31 | // assetTypeExtensions.animation = assetTypeExtensions.model; 32 | // assetTypeExtensions.place = [".rbxl", ".rbxlx"]; 33 | 34 | const cmdOptionsDefinitions = [ 35 | { name: "help", alias: "h", type: Boolean, description: "Display this help message"}, 36 | { name: "?", alias: "?", type: Boolean, description: "Display this help message"}, 37 | { name: "files", type: String, multiple: true, description: "Files to upload", defaultOption: true}, 38 | { name: "registry", alias: "r", type: Boolean, description: "Log in to Roblox using Roblox Studio's cookie from the registry"}, 39 | { name: "no-interactive", type: Boolean, description: "Don't use interactive mode"}, 40 | { name: "skip", type: oneOf(skipValues), multiple: true, description: "Skip interactive prompts for specific values. Valid values: " + skipValues.join(", ")}, 41 | { name: "group", type: Number, description: "Group to upload to"}, 42 | { name: "type", type: oneOf(assetTypeValues), description: "Type of asset to upload as. Valid values: " + assetTypeValues.join(", ")}, 43 | // { name: "id", type: Number, description: "Existing asset id to upload to"}, 44 | { name: "name", type: String, description: "Name of asset. '$file' will be replaced with the file name. Defaults to $file"}, 45 | { name: "description", type: String, description: "Description of asset. Supports $file. Defaults to "}, 46 | { name: "name-retry", type: String, description: "Fallback name if upload fails due to text filtering. Does not support $file."}, 47 | { name: "description-retry", type: String, description: "Fallback description if upload fails due to text filtering. Does not support $file."}, 48 | { name: "pixelfix", type: Boolean, description: "Use pixelfix to alpha bleed images before upload. Alpha-bleed is not saved to the file."}, 49 | ]; 50 | 51 | const cmdOptionsGuide = [ 52 | { 53 | header: "RbxUpload", 54 | content: [ 55 | "A utility to upload files to Roblox.", 56 | ], 57 | }, 58 | { 59 | header: "Logging In", 60 | content: [ 61 | "This utility needs to log in to Roblox to create and update developer products.", 62 | "You have two choices:", 63 | "- Retrieve the cookie from Roblox Studio's registry on Windows using the {bold -r --registry} option", 64 | "- Set the {bold ROBLOX_COOKIE} environment variable to the ROBLOSECURITY cookie", 65 | "The {bold -r --registry} arguments will take priority over the ROBLOX_COOKIE environment variable", 66 | ], 67 | }, 68 | { 69 | header: "Options", 70 | optionList: cmdOptionsDefinitions, 71 | }, 72 | ]; 73 | 74 | (async () => { 75 | let cmdOptions; 76 | try { 77 | cmdOptions = commandLineArgs.default(cmdOptionsDefinitions); 78 | } catch (error) { 79 | console.error(error.message); 80 | console.log ("Try devprod --help"); 81 | return; 82 | } 83 | 84 | cmdOptions.files = cmdOptions.files || []; 85 | cmdOptions.skip = cmdOptions.skip || []; 86 | 87 | if (cmdOptions.help || cmdOptions["?"]) { 88 | console.log(commandLineUsage.default(cmdOptionsGuide)); 89 | return; 90 | } 91 | 92 | function shouldSkip(name) { 93 | return cmdOptions["no-interactive"] || (cmdOptions.skip as string[]).indexOf(name) !== -1; 94 | } 95 | 96 | if (!cmdOptions.registry && !process.env.ROBLOX_COOKIE) { 97 | if (shouldSkip("user")) { 98 | console.error("No user details provided and not in interactive mode. Cannot log in."); 99 | process.exit(1); 100 | } 101 | const input = (await rbxupload.askQuestion("Attempt to log in using the registry? [Y/n] ")).toLowerCase().trim(); 102 | if (input !== "" && input !== "y") { 103 | console.error("User cancelled"); 104 | process.exit(1); 105 | } 106 | cmdOptions.registry = true; 107 | } 108 | 109 | let cookie; 110 | if (cmdOptions.registry) { 111 | try { 112 | cookie = `.ROBLOSECURITY=${await roblox.getRegistryCookie()};`; 113 | } catch (error) { 114 | console.error(`Failed to get cookie from the registry: ${error.message}`); 115 | return; 116 | } 117 | } else if (process.env.ROBLOX_COOKIE) { 118 | cookie = process.env.ROBLOX_COOKIE; 119 | if (!cookie.startsWith(".ROBLOSECURITY=")) { 120 | cookie = `.ROBLOSECURITY=${cookie};`; 121 | } 122 | } else { 123 | console.error("You need to log in to do that. Try devprod --help"); 124 | return; 125 | } 126 | 127 | if (cmdOptions.files.length === 0) { 128 | if (shouldSkip("files")) { 129 | console.error("No files provided and files interactivity is skipped. Nothing to do."); 130 | } 131 | const input = await rbxupload.askQuestion(`What files do you want to upload? `); 132 | cmdOptions.files.push(input); 133 | } 134 | 135 | const filesRaw: string[] = []; 136 | const filePromises = []; 137 | for (let fileGlob of cmdOptions.files) { 138 | fileGlob = (fileGlob as string).replace(/^"/, "").replace(/"$/, ""); 139 | filePromises.push(new Promise((resolve, reject) => { 140 | glob.default(fileGlob, { mark: true}, (err, result) => { 141 | if (err) { 142 | reject(err); 143 | } 144 | for (const file of result) { 145 | if (!(file as string).endsWith("/")) { 146 | filesRaw.push(file); 147 | } 148 | } 149 | resolve(); 150 | }); 151 | })); 152 | } 153 | try { 154 | await Promise.all(filePromises); 155 | } catch (error) { 156 | console.error(`Failed to get files because: ${error.message}`); 157 | process.exit(1); 158 | } 159 | 160 | if (filesRaw.length === 0) { 161 | console.error(`No files found. Nothing to do.`); 162 | process.exit(1); 163 | } 164 | 165 | if (!cmdOptions.type) { 166 | if (!shouldSkip("type")) { 167 | let input = (await rbxupload.askQuestion("What kind asset do you want to upload? [AUTO/decal] ")).toLowerCase().trim(); 168 | if (input === "") { 169 | input = "auto"; 170 | } 171 | if (["image", "auto"].indexOf(input) === -1) { 172 | console.error("Invalid asset type"); 173 | process.exit(1); 174 | } 175 | cmdOptions.type = input; 176 | } 177 | } 178 | 179 | const files = { 180 | decal: [], 181 | unknown: [], 182 | }; 183 | 184 | for (const file of filesRaw) { 185 | let assetType = cmdOptions.type; 186 | if (assetType === "auto") { 187 | for (const assetTypeName of Object.keys(assetTypeExtensions)) { 188 | for (const extension of assetTypeExtensions[assetTypeName]) { 189 | if (file.toLowerCase().endsWith(extension)) { 190 | assetType = assetTypeName; 191 | break; 192 | } 193 | } 194 | if (assetType !== "auto") { 195 | break; 196 | } 197 | } 198 | if (assetType === "auto") { 199 | assetType = "unknown"; 200 | } 201 | } 202 | files[assetType].push(file); 203 | } 204 | 205 | let verifyCount = 0; 206 | 207 | if (!shouldSkip("files-verify")) { 208 | console.log("Files to upload:"); 209 | for (const assetType of Object.keys(files)) { 210 | const list = files[assetType]; 211 | if (list.length !== 0) { 212 | if (list.length > 10) { 213 | console.log(` ${assetType}: ${list.length} (hidden)`); 214 | } else { 215 | console.log(` ${assetType}: ${list.length}`); 216 | for (const file of list) { 217 | console.log(` ${file}`); 218 | } 219 | } 220 | if (assetType === "unknown") { 221 | console.log(" ...to be ignored because their asset type is unknown"); 222 | } 223 | } 224 | } 225 | verifyCount++; 226 | } 227 | 228 | let userInfo; 229 | try { 230 | userInfo = await roblox.myUserInfo(cookie); 231 | } catch (error) { 232 | console.error(`Failed to get logged in user info because: ${error.message}`); 233 | process.exit(1); 234 | } 235 | 236 | if (!shouldSkip("user-verify")) { 237 | console.log(`You are logged in as ${userInfo.username} (${userInfo.userId})`); 238 | verifyCount++; 239 | } 240 | 241 | if (!cmdOptions.group && !shouldSkip("group")) { 242 | const input = (await rbxupload.askQuestion("Upload to a group? [Enter a group id/name] ")).trim(); 243 | if (input !== "") { 244 | let inputGroupId = Number.parseInt(input, 10); 245 | if (inputGroupId !== inputGroupId || inputGroupId <= 0) { 246 | try { 247 | const groups = await roblox.userGroups(userInfo.userId, cookie); 248 | for (const group of groups) { 249 | if ((group.name as string).search(new RegExp(input, "i")) !== -1 || group.isPrimary && input.toLowerCase() === "primary") { 250 | console.log(`Using group id ${group.groupId} from group ${group.name}`); 251 | inputGroupId = group.groupId; 252 | break; 253 | } 254 | } 255 | } catch (error) { 256 | console.warn(`Could not fetch groups for user because: ${error.message}`); 257 | } 258 | if (inputGroupId !== inputGroupId || inputGroupId <= 0) { 259 | console.error("Invalid group id and could not match text with one of your groups"); 260 | process.exit(1); 261 | } 262 | } 263 | cmdOptions.group = inputGroupId; 264 | } 265 | } 266 | 267 | if (cmdOptions.group) { 268 | let groupInfo; 269 | try { 270 | groupInfo = await roblox.groupInfo(cmdOptions.group, cookie); 271 | } catch (error) { 272 | console.error(`Failed to get group info for ${cmdOptions.group} because: ${error.message}`); 273 | process.exit(1); 274 | } 275 | 276 | if (!shouldSkip("group-verify")) { 277 | console.log(`You are uploading to ${groupInfo.name} (${groupInfo.groupId})`); 278 | verifyCount++; 279 | } 280 | } 281 | 282 | if (verifyCount > 0) { 283 | const input = (await rbxupload.askQuestion(`Are these settings okay? [y/N] `)).toLowerCase().trim(); 284 | if (input !== "y") { 285 | console.error("User cancelled"); 286 | process.exit(1); 287 | } 288 | } 289 | 290 | if (!cmdOptions.name) { 291 | if (!shouldSkip("name")) { 292 | const input = (await rbxupload.askQuestion("What should these assets be named? '$file' will be replaced with the file name. [default: $file] ")).trim(); 293 | if (input !== "") { 294 | cmdOptions.name = input; 295 | } 296 | } 297 | if (!cmdOptions.name) { 298 | cmdOptions.name = "$file"; 299 | } 300 | } 301 | 302 | if (!cmdOptions.description) { 303 | if (!shouldSkip("description")) { 304 | const input = (await rbxupload.askQuestion("What should the description be? '$file' will be replaced with the file name. [default: ] ")).trim(); 305 | cmdOptions.description = input; 306 | } else { 307 | cmdOptions.description = ""; 308 | } 309 | } 310 | 311 | if (!cmdOptions["name-retry"] && !shouldSkip("name-retry")) { 312 | const input = (await rbxupload.askQuestion("Retry assets with a default name if they fail due to text filtering? [Y/n] ")).toLowerCase().trim(); 313 | if (input === "" || input === "y") { 314 | cmdOptions["name-retry"] = "Asset"; 315 | } 316 | } 317 | 318 | if (files.decal.length > 0 && !cmdOptions.pixelfix && !shouldSkip("pixelfix")) { 319 | const input = (await rbxupload.askQuestion("Run pixelfix to alpha-bleed images before upload? [Y/n] ")).toLowerCase().trim(); 320 | cmdOptions.pixelfix = input === "" || input === "y"; 321 | } 322 | 323 | for (const file of files.decal) { 324 | let imageBuffer: Buffer; 325 | try { 326 | imageBuffer = await fs.readFile(file); 327 | } catch (error) { 328 | console.error(`${file}: FAILED because: Cannot open file: ${error.message}`); 329 | } 330 | if (cmdOptions.pixelfix) { 331 | try { 332 | imageBuffer = await pixelfix.pixelfix(imageBuffer); 333 | } catch (error) { 334 | console.warn(`${file}: could not pixelfix because: ${error.message}`); 335 | } 336 | } 337 | if (imageBuffer) { 338 | let name = (cmdOptions.name as string).replace("$file", path.basename(file)); 339 | let description = (cmdOptions.description as string).replace("$file", path.basename(file)); 340 | let filteringRetried = !(cmdOptions["name-retry"] || cmdOptions["description-retry"]); 341 | while (true) { 342 | try { 343 | const data = await roblox.decalUpload({ 344 | groupId: cmdOptions.group, 345 | name: name, 346 | description: description, 347 | imageBuffer: imageBuffer, 348 | }, cookie); 349 | console.log(`${file}: rbxassetid://${data.imageId}`); 350 | break; 351 | } catch (error) { 352 | if (error.code === 1) { 353 | console.error(`${file}: retrying in 35 seconds because: rate limiting`); 354 | await delay.default(35); 355 | } else if (error.code === 2) { 356 | if (filteringRetried) { 357 | console.error(`${file}: FAILED because: text filtering`); 358 | break; 359 | } else { 360 | console.error(`${file}: retrying because: text filtering`); 361 | filteringRetried = true; 362 | name = cmdOptions["name-retry"] || "Asset"; 363 | description = cmdOptions["description-retry"] || ""; 364 | } 365 | } else { 366 | console.error(`${file}: FAILED because: ${error.message}`); 367 | break; 368 | } 369 | } 370 | } 371 | } 372 | } 373 | 374 | if (!shouldSkip("done")) { 375 | await rbxupload.askQuestion("Press enter to exit..."); 376 | } 377 | })(); 378 | -------------------------------------------------------------------------------- /src/pixelfix.ts: -------------------------------------------------------------------------------- 1 | import * as Delaunay from "d3-delaunay"; 2 | import Jimp from "jimp"; 3 | 4 | const neighborLocations = [ 5 | [-1, -1], 6 | [ 0, -1], 7 | [ 1, -1], 8 | [ 1, 0], 9 | [ 1, 1], 10 | [ 0, 1], 11 | [-1, 1], 12 | [-1, 0], 13 | ]; 14 | 15 | export async function pixelfix(input) { 16 | const voronoiPoints = []; 17 | const voronoiColors = []; 18 | const image = await Jimp.read(input); 19 | image.scan(0, 0, image.bitmap.width, image.bitmap.height, function(x, y, idx) { 20 | const alpha = this.bitmap.data[ idx + 3 ]; 21 | if (alpha !== 0) { 22 | const red = this.bitmap.data[ idx + 0 ]; 23 | const green = this.bitmap.data[ idx + 1 ]; 24 | const blue = this.bitmap.data[ idx + 2 ]; 25 | // Voronoi 26 | for (const offset of neighborLocations) { 27 | const neighborAlpha = this.bitmap.data[image.getPixelIndex(x + offset[0], y + offset[1]) + 3]; 28 | if (neighborAlpha === 0) { 29 | voronoiPoints.push([x, y]); 30 | voronoiColors.push([red, green, blue]); 31 | break; 32 | } 33 | } 34 | } 35 | }); 36 | if (voronoiPoints.length > 0) { 37 | const dela = Delaunay.Delaunay.from(voronoiPoints); 38 | image.scan(0, 0, image.bitmap.width, image.bitmap.height, function(x, y, idx) { 39 | const alpha = this.bitmap.data[ idx + 3 ]; 40 | if (alpha === 0) { 41 | const closestIndex = dela.find(x, y); 42 | if (closestIndex !== -1) { 43 | const color = voronoiColors[closestIndex]; 44 | 45 | this.bitmap.data[ idx + 0 ] = color[0]; 46 | this.bitmap.data[ idx + 1 ] = color[1]; 47 | this.bitmap.data[ idx + 2 ] = color[2]; 48 | } 49 | } 50 | }); 51 | return await image.getBufferAsync(Jimp.MIME_PNG); 52 | } else { 53 | return input; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/rbxupload.ts: -------------------------------------------------------------------------------- 1 | import * as readline from "readline"; 2 | 3 | export interface IOptions { 4 | file: string; 5 | type: string; 6 | group?: number; 7 | id?: number; 8 | name?: string; 9 | description?: string; 10 | } 11 | 12 | export function askQuestion(query) { 13 | const rl = readline.createInterface({ 14 | input: process.stdin, 15 | output: process.stdout, 16 | }); 17 | 18 | return new Promise((resolve) => rl.question(query, (ans) => { 19 | rl.close(); 20 | resolve(ans); 21 | })); 22 | } 23 | -------------------------------------------------------------------------------- /src/roblox.ts: -------------------------------------------------------------------------------- 1 | 2 | import * as BeautifulDom from "beautiful-dom"; 3 | import * as request from "request-promise"; 4 | 5 | interface IDecalUpdateOptions { 6 | name?: string; 7 | description?: string; 8 | imageBuffer?: any; 9 | groupId?: number; 10 | } 11 | 12 | export class RobloxError extends Error { 13 | public code: number; 14 | public raw?: any; 15 | constructor(code: number, message: string, raw?: any) { 16 | super(message); 17 | this.code = code; 18 | this.raw = raw; 19 | } 20 | } 21 | 22 | let lastToken: string | undefined; 23 | export async function robloxRequest(options: request.Options) { 24 | if (!options.headers) { 25 | options.headers = { }; 26 | } 27 | options.headers["x-csrf-token"] = lastToken; 28 | if (options.json === undefined) { 29 | options.json = true; 30 | } 31 | const resolveWithFullResponse = options.resolveWithFullResponse; 32 | options.resolveWithFullResponse = true; 33 | try { 34 | const response = await request.default(options); 35 | if (response.headers["x-csrf-token"]) { 36 | lastToken = response.headers["x-csrf-token"]; 37 | } 38 | options.resolveWithFullResponse = resolveWithFullResponse; 39 | if (resolveWithFullResponse) { 40 | return response; 41 | } else { 42 | return response.body; 43 | } 44 | } catch (error) { 45 | options.resolveWithFullResponse = resolveWithFullResponse; 46 | if (error.response?.headers["x-csrf-token"]) { 47 | lastToken = error.response?.headers["x-csrf-token"]; 48 | } 49 | const retry = error.response?.statusCode === 403 && (error.response?.statusMessage === "XSRF Token Validation Failed" || error.response?.statusMessage === "Token Validation Failed"); 50 | if (retry) { 51 | options.headers["x-csrf-token"] = lastToken; 52 | return await request.default(options); 53 | } 54 | throw error; 55 | } 56 | } 57 | 58 | export async function getRegistryCookie() { 59 | try { 60 | const Registry: WinregStatic = require("winreg"); 61 | const regKey = new Registry({ 62 | hive: Registry.HKCU, 63 | key: "\\Software\\Roblox\\RobloxStudioBrowser\\roblox.com", 64 | }); 65 | const cookieItem: Winreg.RegistryItem = await new Promise((resolve, reject) => { 66 | regKey.get(".ROBLOSECURITY", (err, item) => { 67 | if (err) { 68 | reject(err); 69 | } else { 70 | resolve(item); 71 | } 72 | }); 73 | }); 74 | const cookieMatches = cookieItem.value.match("COOK::<([^>]+)>"); 75 | return cookieMatches[1]; 76 | } catch (err) { 77 | console.log("Failed to get cookie from registry:", err); 78 | return undefined; 79 | } 80 | } 81 | 82 | export async function robloxLogin(username: string, password: string) { 83 | const jar = request.jar(); 84 | const response = await robloxRequest({ 85 | method: "POST", 86 | url: "https://auth.roblox.com/v2/login", 87 | body: { 88 | ctype: "Username", 89 | cvalue: username, 90 | password: password, 91 | }, 92 | jar: jar, 93 | }); 94 | for (const cookie of jar.getCookies("https://auth.roblox.com/v2/login")) { 95 | if (cookie.key === ".ROBLOSECURITY") { 96 | return cookie.value; 97 | } 98 | } 99 | throw new Error("No cookie returned"); 100 | } 101 | 102 | export async function decalUpload(options: IDecalUpdateOptions, cookie: string) { 103 | let result; 104 | try { 105 | result = await robloxRequest({ 106 | method: "POST", 107 | url: `http://data.roblox.com/data/upload/json?assetTypeId=13&name=${options.name || ""}&description=${options.description || ""}&groupId=${options.groupId || ""}`, 108 | headers: { 109 | "Cookie": cookie, 110 | "Host": "data.roblox.com", 111 | "Content-type": "*/*", 112 | "User-Agent": "Roblox/WinInet", 113 | }, 114 | body: options.imageBuffer, 115 | json: false, 116 | }); 117 | } catch (error) { 118 | throw new RobloxError(-1, `Unknown error: ${error}`, error); 119 | } 120 | let data; 121 | try { 122 | data = JSON.parse(result); 123 | } catch (error) { 124 | throw new RobloxError(-1, `Unknown error: ${error}`, error); 125 | } 126 | if (!data.Success) { 127 | if (data.Message && data.Message.toLowerCase().search("you are uploading too much") !== -1) { 128 | throw new RobloxError(1, `Uploading too much`, data); 129 | } else if (data.Message && data.Message.toLowerCase().search("inappropriate") !== -1) { 130 | throw new RobloxError(2, `Inappropriate Text`, data); 131 | } else { 132 | throw new RobloxError(-1, `Unknown error: ${data.Message}`, data); 133 | } 134 | } 135 | return { 136 | decalId: data.AssetId, 137 | imageId: data.BackingAssetId, 138 | }; 139 | } 140 | 141 | export async function myUserInfo(cookie: string) { 142 | let result; 143 | try { 144 | result = await robloxRequest({ 145 | method: "GET", 146 | url: "https://www.roblox.com/mobileapi/userinfo", 147 | headers: { 148 | Cookie: cookie, 149 | }, 150 | }); 151 | } catch (error) { 152 | throw new RobloxError(-1, `Unknown error: ${error}`, error); 153 | } 154 | if (!result) { 155 | throw new RobloxError(1, "Not logged in"); 156 | } 157 | return { 158 | userId: result.UserID, 159 | username: result.UserName, 160 | robux: result.RobuxBalance, 161 | isPremium: result.IsPremium, 162 | thumbnailUrl: result.ThumbnailUrl, 163 | }; 164 | } 165 | 166 | export async function groupInfo(groupId: number, cookie: string) { 167 | let result; 168 | try { 169 | result = await robloxRequest({ 170 | method: "GET", 171 | url: `https://api.roblox.com/groups/${groupId}`, 172 | headers: { 173 | Cookie: cookie, 174 | }, 175 | }); 176 | } catch (error) { 177 | throw new RobloxError(-1, `Unknown error: ${error} (group probably does not exit)`, error); 178 | } 179 | if (!result) { 180 | throw new RobloxError(-1, "Unknown error"); 181 | } 182 | const roles = []; 183 | for (const role of result.Roles) { 184 | roles.push({ 185 | name: role.Name, 186 | rank: role.Rank, 187 | }); 188 | } 189 | return { 190 | name: result.Name, 191 | groupId: result.Id, 192 | owner: { 193 | username: result.Owner.Name, 194 | userId: result.Owner.Id, 195 | }, 196 | emblemUrl: result.EmblemUrl, 197 | description: result.Description, 198 | roles: roles, 199 | }; 200 | } 201 | 202 | export async function userGroups(userId: number, cookie: string) { 203 | let result; 204 | try { 205 | result = await robloxRequest({ 206 | method: "GET", 207 | url: `https://api.roblox.com/users/${userId}/groups`, 208 | headers: { 209 | Cookie: cookie, 210 | }, 211 | }); 212 | } catch (error) { 213 | throw new RobloxError(-1, `Unknown error: ${error} (group probably does not exit)`, error); 214 | } 215 | if (!result) { 216 | throw new RobloxError(-1, "Unknown error"); 217 | } 218 | const groups = []; 219 | for (const group of result) { 220 | groups.push({ 221 | groupId: group.Id, 222 | name: group.Name, 223 | emblemId: group.EmblemId, 224 | emblemUrl: group.EmblemUrl, 225 | rank: group.Rank, 226 | role: group.Role, 227 | isPrimary: group.IsPrimary, 228 | }); 229 | } 230 | return groups; 231 | } 232 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "esModuleInterop": true, 5 | "target": "es6", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "outDir": "out", 9 | "emitDecoratorMetadata": true, 10 | "experimentalDecorators": true 11 | }, 12 | "lib": ["es2015"] 13 | } -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "tslint:recommended" 5 | ], 6 | "jsRules": {}, 7 | "rules": { 8 | "quotemark": [true, "double"], 9 | "object-literal-sort-keys": false, 10 | "no-console": false, 11 | "whitespace": [ 12 | true, 13 | "check-branch", 14 | "check-decl", 15 | "check-module", 16 | "check-separator", 17 | "check-rest-spread", 18 | "check-type", 19 | "check-typecast", 20 | "check-type-operator", 21 | "check-preblock", 22 | "check-postbrace" 23 | ], 24 | "max-classes-per-file": false, 25 | "object-literal-shorthand": false, 26 | "max-line-length": false 27 | }, 28 | "rulesDirectory": [] 29 | } --------------------------------------------------------------------------------