diff --git a/package-lock.json b/package-lock.json index 8fdb4700..f9995227 100644 --- a/package-lock.json +++ b/package-lock.json @@ -78,6 +78,7 @@ "@types/nedb": "^1.8.11", "@types/node": "^12.19.16", "@types/overlayscrollbars": "^1.12.0", + "@types/parse-torrent": "^5.8.3", "@types/passport": "^1.0.6", "@types/passport-jwt": "^3.0.4", "@types/react": "^17.0.1", @@ -152,6 +153,7 @@ "nedb-promises": "^4.1.1", "overlayscrollbars": "^1.13.1", "overlayscrollbars-react": "^0.2.2", + "parse-torrent": "^9.1.3", "passport": "^0.4.1", "passport-jwt": "^4.0.0", "postcss": "^8.2.6", @@ -1574,7 +1576,6 @@ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.12.16.tgz", "integrity": "sha512-IrYNrpDSuQfNHeqh7gsJsO35xTGyAyGkI1VxOpBEADFtxCqZ77a1RHbJqM3YJhroj7qMkNMkNtcw0lqeZUrzow==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.12.13", "@babel/helper-validator-option": "^7.12.16", @@ -1874,9 +1875,9 @@ } }, "node_modules/@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, "engines": { "node": ">=8" @@ -2971,6 +2972,15 @@ "integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==", "dev": true }, + "node_modules/@types/magnet-uri": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/magnet-uri/-/magnet-uri-5.1.2.tgz", + "integrity": "sha512-bXFPXskwHoEYP6t8rq4nWchOlbUzXkyhnfCVZmq+zb25R5pWkasw7BmTIqDKQ6RAQmq89jll1v23yLa/SvPfAw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -2996,9 +3006,9 @@ } }, "node_modules/@types/node": { - "version": "12.19.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.16.tgz", - "integrity": "sha512-7xHmXm/QJ7cbK2laF+YYD7gb5MggHIIQwqyjin3bpEGiSuvScMQ5JZZXPvRipi1MwckTQbJZROMns/JxdnIL1Q==", + "version": "12.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.1.tgz", + "integrity": "sha512-tCkE96/ZTO+cWbln2xfyvd6ngHLanvVlJ3e5BeirJ3BYI5GbAyubIrmV4JjjugDly5D9fHjOL5MNsqsCnqwW6g==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -3019,6 +3029,26 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "node_modules/@types/parse-torrent": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/@types/parse-torrent/-/parse-torrent-5.8.3.tgz", + "integrity": "sha512-c0xAjnpov+Xk/2HTtpaBm0tukNIAoZoxrqgTDwSaIu6IVCynY+2YD9zcQNk2P6H4atcXzD78/LI2CQzLlMmAJg==", + "dev": true, + "dependencies": { + "@types/magnet-uri": "*", + "@types/node": "*", + "@types/parse-torrent-file": "*" + } + }, + "node_modules/@types/parse-torrent-file": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-torrent-file/-/parse-torrent-file-4.0.2.tgz", + "integrity": "sha512-EzdzpcN0sStQ35sUV2SChTJErLsbotsxZ/RYeR9gf3zXKlPLKaA7aIAoS/nuLRvfxH8mbrWQmXSw76alKecSdg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/passport": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.6.tgz", @@ -3050,9 +3080,9 @@ } }, "node_modules/@types/prettier": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.2.0.tgz", - "integrity": "sha512-O3SQC6+6AySHwrspYn2UvC6tjo6jCTMMmylxZUFhE1CulVu5l3AxU6ca9lrJDTQDVllF62LIxVSx5fuYL6LiZg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-DxZZbyMAM9GWEzXL+BMZROWz9oo6A9EilwwOMET2UVu2uZTqMWS5S69KVtuVKaRjCUpcrOXRalet86/OpG4kqw==", "dev": true }, "node_modules/@types/prop-types": { @@ -3080,9 +3110,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.1.tgz", - "integrity": "sha512-w8t9f53B2ei4jeOqf/gxtc2Sswnc3LBK5s0DyJcg5xd10tMHXts2N31cKjWfH9IC/JvEPa/YF1U4YeP1t4R6HQ==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.2.tgz", + "integrity": "sha512-Xt40xQsrkdvjn1EyWe1Bc0dJLcil/9x2vAuW7ya+PuQip4UYUaXyhzWmAbwRsdMgwOFHpfp7/FFZebDU6Y8VHA==", "dev": true, "dependencies": { "@types/prop-types": "*", @@ -3138,9 +3168,9 @@ } }, "node_modules/@types/react-dom": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.0.tgz", - "integrity": "sha512-lUqY7OlkF/RbNtD5nIq7ot8NquXrdFrjSOR6+w9a9RFQevGi1oZO1dcJbXMeONAPKtZ2UrZOEJ5UOCVsxbLk/g==", + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.1.tgz", + "integrity": "sha512-yIVyopxQb8IDZ7SOHeTovurFq+fXiPICa+GV3gp0Xedsl+MwQlMLKmvrnEjFbQxjliH5YVAEWFh975eVNmKj7Q==", "dev": true, "dependencies": { "@types/react": "*" @@ -4537,6 +4567,12 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/bep53-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bep53-range/-/bep53-range-1.1.0.tgz", + "integrity": "sha512-yGQTG4NtwTciX0Bkgk1FqQL4p+NiCQKpTSFho2lrxvUkXIlzyJDwraj8aYxAxRZMnnOhRr7QlIBoMRPEnIR34Q==", + "dev": true + }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -4599,6 +4635,26 @@ "ieee754": "^1.1.13" } }, + "node_modules/blob-to-buffer": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/blob-to-buffer/-/blob-to-buffer-1.2.9.tgz", + "integrity": "sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/block-stream2": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz", @@ -5068,9 +5124,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001185", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001185.tgz", - "integrity": "sha512-Fpi4kVNtNvJ15H0F6vwmXtb3tukv3Zg3qhKkOGUq7KJ1J6b9kf4dnNgtEAFXhRsJo0gNj9W60+wBvn0JcTvdTg==", + "version": "1.0.30001187", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001187.tgz", + "integrity": "sha512-w7/EP1JRZ9552CyrThUnay2RkZ1DXxKe/Q2swTC4+LElLh9RRYrL1Z+27LlakB8kzY0fSmHw9mc7XYDUKAKWMA==", "dev": true }, "node_modules/capture-exit": { @@ -7075,6 +7131,15 @@ "node": "*" } }, + "node_modules/dateformat/node_modules/get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", @@ -7116,6 +7181,21 @@ "node": ">=0.10" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deep-equal": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", @@ -7608,9 +7688,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.3.663", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.663.tgz", - "integrity": "sha512-xkVkzHj6k3oRRGlmdgUCCLSLhtFYHDCTH7SeK+LJdJjnsLcrdbpr8EYmfMQhez3V/KPO5UScSpzQ0feYX6Qoyw==", + "version": "1.3.664", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.664.tgz", + "integrity": "sha512-yb8LrTQXQnh9yhnaIHLk6CYugF/An50T20+X0h++hjjhVfgSp1DGoMSYycF8/aD5eiqS4QwaNhiduFvK8rifRg==", "dev": true }, "node_modules/elliptic": { @@ -7892,12 +7972,12 @@ } }, "node_modules/eslint": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.19.0.tgz", - "integrity": "sha512-CGlMgJY56JZ9ZSYhJuhow61lMPPjUzWmChFya71Z/jilVos7mR/jPgaEfVGgMBY5DshbKdG8Ezb8FDCHcoMEMg==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.20.0.tgz", + "integrity": "sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.0.0", + "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.3.0", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -7909,7 +7989,7 @@ "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", "espree": "^7.3.1", - "esquery": "^1.2.0", + "esquery": "^1.4.0", "esutils": "^2.0.2", "file-entry-cache": "^6.0.0", "functional-red-black-tree": "^1.0.1", @@ -8337,9 +8417,9 @@ } }, "node_modules/eslint-webpack-plugin": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-2.5.0.tgz", - "integrity": "sha512-CCIWiQzkthgPq4P9arnPtj/FtswyO0j6obmSWurZrXW/haOOdDDucezeOxziTXjhUQeEDP4htjS81ARbesjd/A==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-2.5.1.tgz", + "integrity": "sha512-LB6baXTm62IwSu5gxj4xQ8URsMc1Wk95WLcK8pFklLvk4i66lS5v5knpVzCLG9u7NXYThfIMdvr/lYe2A3ZbWw==", "dev": true, "dependencies": { "@types/eslint": "^7.2.6", @@ -8378,6 +8458,15 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/eslint/node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, "node_modules/eslint/node_modules/globals": { "version": "12.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", @@ -9794,12 +9883,15 @@ } }, "node_modules/get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/get-stream": { @@ -10309,9 +10401,9 @@ } }, "node_modules/html-webpack-plugin": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.0.0.tgz", - "integrity": "sha512-kxTyb8cyZwEyUqXTgdHRUOF4C7uCrquzw2T+YTudehm/yspodgCkREjdmc4dXI8k2P4NEjqOVbnOOlPZg4TKJA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.1.0.tgz", + "integrity": "sha512-2axkp+2NHmvHUWrKe1dY4LyM3WatQEdFChr42OY7R/Ad7f0AQzaKscGCcqN/FtQBxo8rdfJP7M3RMFDttqok3g==", "dev": true, "dependencies": { "@types/html-minifier-terser": "^5.0.0", @@ -11211,14 +11303,14 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.4.tgz", - "integrity": "sha512-ILaRgn4zaSrVNXNGtON6iFNotXW3hAPF3+0fB1usg2jFlWqo5fEDdmJkz0zBfoi7Dgskr8Khi2xZ8cXqZEfXNA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", + "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.2", - "call-bind": "^1.0.0", - "es-abstract": "^1.18.0-next.1", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.0-next.2", "foreach": "^2.0.5", "has-symbols": "^1.0.1" }, @@ -12720,6 +12812,30 @@ "node": ">=10" } }, + "node_modules/magnet-uri": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/magnet-uri/-/magnet-uri-6.1.0.tgz", + "integrity": "sha512-731qLviHaqN/Ni96wm6gNKuvoip+QHWTznjHNz/4qDlsHh3/CWJoL8fZ18IIRhGJgnWoKJp8RVE5lZvQ60Khhw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "bep53-range": "^1.0.0", + "thirty-two": "^1.0.2" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -13127,9 +13243,9 @@ } }, "node_modules/mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", "dev": true, "engines": { "node": ">= 0.6" @@ -13147,6 +13263,15 @@ "node": ">= 0.6" } }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -13156,6 +13281,18 @@ "node": ">=6" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mini-create-react-context": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", @@ -14137,9 +14274,9 @@ } }, "node_modules/open": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.0.tgz", - "integrity": "sha512-PGoBCX/lclIWlpS/R2PQuIR4NJoXh6X5AwVzE7WXnWRGvHg7+4TBCgsujUgiPpm0K1y4qvQeWnCWVTpTKZBtvA==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.1.tgz", + "integrity": "sha512-Pxv+fKRsd/Ozflgn2Gjev1HZveJJeKR6hKKmdaImJMuEZ6htAvCTbcMABJo+qevlAelTLCrEK3YTKZ9fVTcSPw==", "dev": true, "dependencies": { "is-docker": "^2.0.0", @@ -14334,9 +14471,9 @@ } }, "node_modules/p-retry": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.3.0.tgz", - "integrity": "sha512-Pow4yaHpOiJou1QcpGcBJhGHiS4782LdDa6GhU91hlaNh3ExOOupjSJcxPQZYmUSZk3Pl2ARz/LRvW8Qu0+3mQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.4.0.tgz", + "integrity": "sha512-gVB/tBsG+3AHI1SyDHRrX6n9ZL0Bcbifps9W9/Bgu3Oyu4/OrAh8SvDzDsvpP0oxfCt3oWNT+0fQ9LyUGwBTLg==", "dev": true, "dependencies": { "@types/retry": "^0.12.0", @@ -14432,6 +14569,38 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-torrent": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/parse-torrent/-/parse-torrent-9.1.3.tgz", + "integrity": "sha512-/Yr951CvJM8S6TjMaqrsmMxeQEAjDeCX+MZ3hGXXc7DG2wqzp/rzOsHtDzIVqN6NsFRCqy6wYLF/W7Sgvq7bXw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "bencode": "^2.0.1", + "blob-to-buffer": "^1.2.9", + "get-stdin": "^8.0.0", + "magnet-uri": "^6.0.0", + "queue-microtask": "^1.2.2", + "simple-get": "^4.0.0", + "simple-sha1": "^3.0.1" + }, + "bin": { + "parse-torrent": "bin/cmd.js" + } + }, "node_modules/parse5": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", @@ -20785,6 +20954,51 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.0.tgz", + "integrity": "sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/simple-sha1": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/simple-sha1/-/simple-sha1-3.0.1.tgz", @@ -21745,6 +21959,15 @@ "node": ">=0.10.0" } }, + "node_modules/strip-indent/node_modules/get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -22379,9 +22602,9 @@ } }, "node_modules/terser-webpack-plugin/node_modules/terser": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz", - "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.6.0.tgz", + "integrity": "sha512-vyqLMoqadC1uR0vywqOZzriDYzgEkNJFK4q9GeyOBHIbiECHiWLKcWfbQWAUaPfxkjDhapSlZB9f7fkMrvkVjA==", "dev": true, "dependencies": { "commander": "^2.20.0", @@ -22439,6 +22662,15 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "node_modules/thirty-two": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", + "integrity": "sha1-TKL//AKlEpDSdEueP1V2k8prYno=", + "dev": true, + "engines": { + "node": ">=0.2.6" + } + }, "node_modules/throat": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", @@ -22503,21 +22735,21 @@ "dev": true }, "node_modules/tldts": { - "version": "5.7.5", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-5.7.5.tgz", - "integrity": "sha512-AiZgJ7e1b4I5d+oVXPZim+ImqVpv/S9OdePw0+clN2ZhzRc/2hJ1I2RqpBVVQejyY7w+ORdpIK/l/wl7ZUPG3w==", + "version": "5.7.6", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-5.7.6.tgz", + "integrity": "sha512-ayOOQ/ATxzo6q7NIYz6YQAaW9kftrWdIhAMcXOQ0N12c2/O1w+zFizNd4oQSz6HV7xRMD543zTHo/a89WrpDog==", "dev": true, "dependencies": { - "tldts-core": "^5.7.5" + "tldts-core": "^5.7.6" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "5.7.5", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-5.7.5.tgz", - "integrity": "sha512-yHGuhJzk7vTXNqWSs1qF89BegWQn+N5tcRp4NFWiP/dST+lbUVx4czuAMJXdNExcmGFDQOxFV2TNDSug+2YMPg==", + "version": "5.7.6", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-5.7.6.tgz", + "integrity": "sha512-VfRarBs7nbY9Af3In4O1A3d7T6eZh+w/IjRPpBo8VgRHAo7LJ+GrzCVo1yoOPmm3tdO1vUXtwBnchWN0dpL6lQ==", "dev": true }, "node_modules/tmp": { @@ -23544,9 +23776,9 @@ } }, "node_modules/webpack": { - "version": "5.21.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.21.2.tgz", - "integrity": "sha512-xHflCenx+AM4uWKX71SWHhxml5aMXdy2tu/vdi4lClm7PADKxlyDAFFN1rEFzNV0MAoPpHtBeJnl/+K6F4QBPg==", + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.22.0.tgz", + "integrity": "sha512-xqlb6r9RUXda/d9iA6P7YRTP1ChWeP50TEESKMMNIg0u8/Rb66zN9YJJO7oYgJTRyFyYi43NVC5feG45FSO1vQ==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.0", @@ -24093,9 +24325,9 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.5", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.5.tgz", + "integrity": "sha512-jYRGS3zWy20NtDtK2kBgo/TlAoy5YUuhD9/LZ7z7W4j1Fdw2cqD0xEEclf8fxc8xjD6X5Qr+qQQwCEsP8iRiYg==", "dev": true, "engines": { "node": ">=10" @@ -25509,9 +25741,9 @@ } }, "@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, "@jest/console": { @@ -26488,6 +26720,15 @@ "integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==", "dev": true }, + "@types/magnet-uri": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/magnet-uri/-/magnet-uri-5.1.2.tgz", + "integrity": "sha512-bXFPXskwHoEYP6t8rq4nWchOlbUzXkyhnfCVZmq+zb25R5pWkasw7BmTIqDKQ6RAQmq89jll1v23yLa/SvPfAw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -26513,9 +26754,9 @@ } }, "@types/node": { - "version": "12.19.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.16.tgz", - "integrity": "sha512-7xHmXm/QJ7cbK2laF+YYD7gb5MggHIIQwqyjin3bpEGiSuvScMQ5JZZXPvRipi1MwckTQbJZROMns/JxdnIL1Q==", + "version": "12.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.1.tgz", + "integrity": "sha512-tCkE96/ZTO+cWbln2xfyvd6ngHLanvVlJ3e5BeirJ3BYI5GbAyubIrmV4JjjugDly5D9fHjOL5MNsqsCnqwW6g==", "dev": true }, "@types/normalize-package-data": { @@ -26536,6 +26777,26 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "@types/parse-torrent": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/@types/parse-torrent/-/parse-torrent-5.8.3.tgz", + "integrity": "sha512-c0xAjnpov+Xk/2HTtpaBm0tukNIAoZoxrqgTDwSaIu6IVCynY+2YD9zcQNk2P6H4atcXzD78/LI2CQzLlMmAJg==", + "dev": true, + "requires": { + "@types/magnet-uri": "*", + "@types/node": "*", + "@types/parse-torrent-file": "*" + } + }, + "@types/parse-torrent-file": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-torrent-file/-/parse-torrent-file-4.0.2.tgz", + "integrity": "sha512-EzdzpcN0sStQ35sUV2SChTJErLsbotsxZ/RYeR9gf3zXKlPLKaA7aIAoS/nuLRvfxH8mbrWQmXSw76alKecSdg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/passport": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.6.tgz", @@ -26567,9 +26828,9 @@ } }, "@types/prettier": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.2.0.tgz", - "integrity": "sha512-O3SQC6+6AySHwrspYn2UvC6tjo6jCTMMmylxZUFhE1CulVu5l3AxU6ca9lrJDTQDVllF62LIxVSx5fuYL6LiZg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-DxZZbyMAM9GWEzXL+BMZROWz9oo6A9EilwwOMET2UVu2uZTqMWS5S69KVtuVKaRjCUpcrOXRalet86/OpG4kqw==", "dev": true }, "@types/prop-types": { @@ -26597,9 +26858,9 @@ "dev": true }, "@types/react": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.1.tgz", - "integrity": "sha512-w8t9f53B2ei4jeOqf/gxtc2Sswnc3LBK5s0DyJcg5xd10tMHXts2N31cKjWfH9IC/JvEPa/YF1U4YeP1t4R6HQ==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.2.tgz", + "integrity": "sha512-Xt40xQsrkdvjn1EyWe1Bc0dJLcil/9x2vAuW7ya+PuQip4UYUaXyhzWmAbwRsdMgwOFHpfp7/FFZebDU6Y8VHA==", "dev": true, "requires": { "@types/prop-types": "*", @@ -26653,9 +26914,9 @@ } }, "@types/react-dom": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.0.tgz", - "integrity": "sha512-lUqY7OlkF/RbNtD5nIq7ot8NquXrdFrjSOR6+w9a9RFQevGi1oZO1dcJbXMeONAPKtZ2UrZOEJ5UOCVsxbLk/g==", + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.1.tgz", + "integrity": "sha512-yIVyopxQb8IDZ7SOHeTovurFq+fXiPICa+GV3gp0Xedsl+MwQlMLKmvrnEjFbQxjliH5YVAEWFh975eVNmKj7Q==", "dev": true, "requires": { "@types/react": "*" @@ -27766,6 +28027,12 @@ "safe-buffer": "^5.1.1" } }, + "bep53-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bep53-range/-/bep53-range-1.1.0.tgz", + "integrity": "sha512-yGQTG4NtwTciX0Bkgk1FqQL4p+NiCQKpTSFho2lrxvUkXIlzyJDwraj8aYxAxRZMnnOhRr7QlIBoMRPEnIR34Q==", + "dev": true + }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -27810,6 +28077,12 @@ } } }, + "blob-to-buffer": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/blob-to-buffer/-/blob-to-buffer-1.2.9.tgz", + "integrity": "sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA==", + "dev": true + }, "block-stream2": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz", @@ -28224,9 +28497,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001185", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001185.tgz", - "integrity": "sha512-Fpi4kVNtNvJ15H0F6vwmXtb3tukv3Zg3qhKkOGUq7KJ1J6b9kf4dnNgtEAFXhRsJo0gNj9W60+wBvn0JcTvdTg==", + "version": "1.0.30001187", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001187.tgz", + "integrity": "sha512-w7/EP1JRZ9552CyrThUnay2RkZ1DXxKe/Q2swTC4+LElLh9RRYrL1Z+27LlakB8kzY0fSmHw9mc7XYDUKAKWMA==", "dev": true }, "capture-exit": { @@ -29834,6 +30107,14 @@ "requires": { "get-stdin": "^4.0.1", "meow": "^3.3.0" + }, + "dependencies": { + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + } } }, "debug": { @@ -29863,6 +30144,15 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "requires": { + "mimic-response": "^3.1.0" + } + }, "deep-equal": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", @@ -30284,9 +30574,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.663", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.663.tgz", - "integrity": "sha512-xkVkzHj6k3oRRGlmdgUCCLSLhtFYHDCTH7SeK+LJdJjnsLcrdbpr8EYmfMQhez3V/KPO5UScSpzQ0feYX6Qoyw==", + "version": "1.3.664", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.664.tgz", + "integrity": "sha512-yb8LrTQXQnh9yhnaIHLk6CYugF/An50T20+X0h++hjjhVfgSp1DGoMSYycF8/aD5eiqS4QwaNhiduFvK8rifRg==", "dev": true }, "elliptic": { @@ -30508,12 +30798,12 @@ } }, "eslint": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.19.0.tgz", - "integrity": "sha512-CGlMgJY56JZ9ZSYhJuhow61lMPPjUzWmChFya71Z/jilVos7mR/jPgaEfVGgMBY5DshbKdG8Ezb8FDCHcoMEMg==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.20.0.tgz", + "integrity": "sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", + "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.3.0", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -30525,7 +30815,7 @@ "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", "espree": "^7.3.1", - "esquery": "^1.2.0", + "esquery": "^1.4.0", "esutils": "^2.0.2", "file-entry-cache": "^6.0.0", "functional-red-black-tree": "^1.0.1", @@ -30552,6 +30842,15 @@ "v8-compile-cache": "^2.0.3" }, "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, "globals": { "version": "12.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", @@ -30873,9 +31172,9 @@ "dev": true }, "eslint-webpack-plugin": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-2.5.0.tgz", - "integrity": "sha512-CCIWiQzkthgPq4P9arnPtj/FtswyO0j6obmSWurZrXW/haOOdDDucezeOxziTXjhUQeEDP4htjS81ARbesjd/A==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-2.5.1.tgz", + "integrity": "sha512-LB6baXTm62IwSu5gxj4xQ8URsMc1Wk95WLcK8pFklLvk4i66lS5v5knpVzCLG9u7NXYThfIMdvr/lYe2A3ZbWw==", "dev": true, "requires": { "@types/eslint": "^7.2.6", @@ -32006,9 +32305,9 @@ "dev": true }, "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "dev": true }, "get-stream": { @@ -32435,9 +32734,9 @@ } }, "html-webpack-plugin": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.0.0.tgz", - "integrity": "sha512-kxTyb8cyZwEyUqXTgdHRUOF4C7uCrquzw2T+YTudehm/yspodgCkREjdmc4dXI8k2P4NEjqOVbnOOlPZg4TKJA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.1.0.tgz", + "integrity": "sha512-2axkp+2NHmvHUWrKe1dY4LyM3WatQEdFChr42OY7R/Ad7f0AQzaKscGCcqN/FtQBxo8rdfJP7M3RMFDttqok3g==", "dev": true, "requires": { "@types/html-minifier-terser": "^5.0.0", @@ -33094,14 +33393,14 @@ } }, "is-typed-array": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.4.tgz", - "integrity": "sha512-ILaRgn4zaSrVNXNGtON6iFNotXW3hAPF3+0fB1usg2jFlWqo5fEDdmJkz0zBfoi7Dgskr8Khi2xZ8cXqZEfXNA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", + "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", "dev": true, "requires": { "available-typed-arrays": "^1.0.2", - "call-bind": "^1.0.0", - "es-abstract": "^1.18.0-next.1", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.0-next.2", "foreach": "^2.0.5", "has-symbols": "^1.0.1" } @@ -34326,6 +34625,16 @@ "yallist": "^4.0.0" } }, + "magnet-uri": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/magnet-uri/-/magnet-uri-6.1.0.tgz", + "integrity": "sha512-731qLviHaqN/Ni96wm6gNKuvoip+QHWTznjHNz/4qDlsHh3/CWJoL8fZ18IIRhGJgnWoKJp8RVE5lZvQ60Khhw==", + "dev": true, + "requires": { + "bep53-range": "^1.0.0", + "thirty-two": "^1.0.2" + } + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -34654,9 +34963,9 @@ "dev": true }, "mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", "dev": true }, "mime-types": { @@ -34666,6 +34975,14 @@ "dev": true, "requires": { "mime-db": "1.45.0" + }, + "dependencies": { + "mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "dev": true + } } }, "mimic-fn": { @@ -34674,6 +34991,12 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true + }, "mini-create-react-context": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", @@ -35428,9 +35751,9 @@ } }, "open": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.0.tgz", - "integrity": "sha512-PGoBCX/lclIWlpS/R2PQuIR4NJoXh6X5AwVzE7WXnWRGvHg7+4TBCgsujUgiPpm0K1y4qvQeWnCWVTpTKZBtvA==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.1.tgz", + "integrity": "sha512-Pxv+fKRsd/Ozflgn2Gjev1HZveJJeKR6hKKmdaImJMuEZ6htAvCTbcMABJo+qevlAelTLCrEK3YTKZ9fVTcSPw==", "dev": true, "requires": { "is-docker": "^2.0.0", @@ -35567,9 +35890,9 @@ } }, "p-retry": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.3.0.tgz", - "integrity": "sha512-Pow4yaHpOiJou1QcpGcBJhGHiS4782LdDa6GhU91hlaNh3ExOOupjSJcxPQZYmUSZk3Pl2ARz/LRvW8Qu0+3mQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.4.0.tgz", + "integrity": "sha512-gVB/tBsG+3AHI1SyDHRrX6n9ZL0Bcbifps9W9/Bgu3Oyu4/OrAh8SvDzDsvpP0oxfCt3oWNT+0fQ9LyUGwBTLg==", "dev": true, "requires": { "@types/retry": "^0.12.0", @@ -35647,6 +35970,21 @@ "lines-and-columns": "^1.1.6" } }, + "parse-torrent": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/parse-torrent/-/parse-torrent-9.1.3.tgz", + "integrity": "sha512-/Yr951CvJM8S6TjMaqrsmMxeQEAjDeCX+MZ3hGXXc7DG2wqzp/rzOsHtDzIVqN6NsFRCqy6wYLF/W7Sgvq7bXw==", + "dev": true, + "requires": { + "bencode": "^2.0.1", + "blob-to-buffer": "^1.2.9", + "get-stdin": "^8.0.0", + "magnet-uri": "^6.0.0", + "queue-microtask": "^1.2.2", + "simple-get": "^4.0.0", + "simple-sha1": "^3.0.1" + } + }, "parse5": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", @@ -40650,6 +40988,23 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true + }, + "simple-get": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.0.tgz", + "integrity": "sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ==", + "dev": true, + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "simple-sha1": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/simple-sha1/-/simple-sha1-3.0.1.tgz", @@ -41476,6 +41831,14 @@ "dev": true, "requires": { "get-stdin": "^4.0.1" + }, + "dependencies": { + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + } } }, "strip-json-comments": { @@ -41972,9 +42335,9 @@ "dev": true }, "terser": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz", - "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.6.0.tgz", + "integrity": "sha512-vyqLMoqadC1uR0vywqOZzriDYzgEkNJFK4q9GeyOBHIbiECHiWLKcWfbQWAUaPfxkjDhapSlZB9f7fkMrvkVjA==", "dev": true, "requires": { "commander": "^2.20.0", @@ -42009,6 +42372,12 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "thirty-two": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", + "integrity": "sha1-TKL//AKlEpDSdEueP1V2k8prYno=", + "dev": true + }, "throat": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", @@ -42067,18 +42436,18 @@ "dev": true }, "tldts": { - "version": "5.7.5", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-5.7.5.tgz", - "integrity": "sha512-AiZgJ7e1b4I5d+oVXPZim+ImqVpv/S9OdePw0+clN2ZhzRc/2hJ1I2RqpBVVQejyY7w+ORdpIK/l/wl7ZUPG3w==", + "version": "5.7.6", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-5.7.6.tgz", + "integrity": "sha512-ayOOQ/ATxzo6q7NIYz6YQAaW9kftrWdIhAMcXOQ0N12c2/O1w+zFizNd4oQSz6HV7xRMD543zTHo/a89WrpDog==", "dev": true, "requires": { - "tldts-core": "^5.7.5" + "tldts-core": "^5.7.6" } }, "tldts-core": { - "version": "5.7.5", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-5.7.5.tgz", - "integrity": "sha512-yHGuhJzk7vTXNqWSs1qF89BegWQn+N5tcRp4NFWiP/dST+lbUVx4czuAMJXdNExcmGFDQOxFV2TNDSug+2YMPg==", + "version": "5.7.6", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-5.7.6.tgz", + "integrity": "sha512-VfRarBs7nbY9Af3In4O1A3d7T6eZh+w/IjRPpBo8VgRHAo7LJ+GrzCVo1yoOPmm3tdO1vUXtwBnchWN0dpL6lQ==", "dev": true }, "tmp": { @@ -42900,9 +43269,9 @@ "dev": true }, "webpack": { - "version": "5.21.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.21.2.tgz", - "integrity": "sha512-xHflCenx+AM4uWKX71SWHhxml5aMXdy2tu/vdi4lClm7PADKxlyDAFFN1rEFzNV0MAoPpHtBeJnl/+K6F4QBPg==", + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.22.0.tgz", + "integrity": "sha512-xqlb6r9RUXda/d9iA6P7YRTP1ChWeP50TEESKMMNIg0u8/Rb66zN9YJJO7oYgJTRyFyYi43NVC5feG45FSO1vQ==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.0", @@ -43303,9 +43672,9 @@ } }, "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.5", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.5.tgz", + "integrity": "sha512-jYRGS3zWy20NtDtK2kBgo/TlAoy5YUuhD9/LZ7z7W4j1Fdw2cqD0xEEclf8fxc8xjD6X5Qr+qQQwCEsP8iRiYg==", "dev": true }, "yauzl": { diff --git a/package.json b/package.json index f2aa544d..c1b9aeeb 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "@types/nedb": "^1.8.11", "@types/node": "^12.19.16", "@types/overlayscrollbars": "^1.12.0", + "@types/parse-torrent": "^5.8.3", "@types/passport": "^1.0.6", "@types/passport-jwt": "^3.0.4", "@types/react": "^17.0.1", @@ -175,6 +176,7 @@ "nedb-promises": "^4.1.1", "overlayscrollbars": "^1.13.1", "overlayscrollbars-react": "^0.2.2", + "parse-torrent": "^9.1.3", "passport": "^0.4.1", "passport-jwt": "^4.0.0", "postcss": "^8.2.6", diff --git a/server/routes/api/torrents.test.ts b/server/routes/api/torrents.test.ts index d67d0b4f..3611b7d4 100644 --- a/server/routes/api/torrents.test.ts +++ b/server/routes/api/torrents.test.ts @@ -101,7 +101,7 @@ describe('POST /api/torrents/add-urls', () => { }) .set('Cookie', [authToken]) .set('Accept', 'application/json') - .expect(500) + .expect(403) .expect('Content-Type', /json/) .end((err, res) => { if (err) done(err); @@ -208,7 +208,7 @@ describe('POST /api/torrents/add-files', () => { }) .set('Cookie', [authToken]) .set('Accept', 'application/json') - .expect(500) + .expect(403) .expect('Content-Type', /json/) .end((err, res) => { if (err) done(err); diff --git a/server/routes/api/torrents.ts b/server/routes/api/torrents.ts index e4472fe9..820819a3 100644 --- a/server/routes/api/torrents.ts +++ b/server/routes/api/torrents.ts @@ -111,12 +111,13 @@ router.get('/', (req, res) => { * @tags Torrents * @security User * @param {AddTorrentByURLOptions} request.body.required - options - application/json - * @return {object} 200 - success response - application/json + * @return {object} 200 - all torrents added - application/json + * @return {object} 202 - requests sent to torrent client - application/json + * @return {object} 207 - some succeed, some failed - application/json + * @return {Error} 403 - illegal destination - application/json * @return {Error} 500 - failure response - application/json */ router.post('/add-urls', async (req, res) => { - const callback = getResponseFn(res); - const parsedResult = addTorrentByURLSchema.safeParse(req.body); if (!parsedResult.success) { @@ -142,7 +143,8 @@ router.post('/add-urls', async (req, r }); if (finalDestination == null) { - callback(null, accessDeniedError()); + const {code, message} = accessDeniedError(); + res.status(403).json({code, message}); return; } @@ -158,14 +160,21 @@ router.post('/add-urls', async (req, r isInitialSeeding: isInitialSeeding ?? false, start: start ?? false, }) - .then((response) => { - req.services?.torrentService.fetchTorrentList(); - return response; - }) - .then(callback) - .catch((err) => { - callback(null, err); - }); + .then( + (response) => { + req.services?.torrentService.fetchTorrentList(); + if (response.length === 0) { + res.status(202).json(response); + } else if (response.length < urls.length) { + res.status(207).json(response); + } else { + res.status(200).json(response); + } + }, + ({code, message}) => { + res.status(500).json({code, message}); + }, + ); }); /** @@ -174,12 +183,13 @@ router.post('/add-urls', async (req, r * @tags Torrents * @security User * @param {AddTorrentByFileOptions} request.body.required - options - application/json - * @return {object} 200 - success response - application/json + * @return {object} 200 - all torrents added - application/json + * @return {object} 202 - requests sent to torrent client - application/json + * @return {object} 207 - some succeed, some failed - application/json + * @return {Error} 403 - illegal destination - application/json * @return {Error} 500 - failure response - application/json */ router.post('/add-files', async (req, res) => { - const callback = getResponseFn(res); - const parsedResult = addTorrentByFileSchema.safeParse(req.body); if (!parsedResult.success) { @@ -195,7 +205,8 @@ router.post('/add-files', async (req, }); if (finalDestination == null) { - callback(null, accessDeniedError()); + const {code, message} = accessDeniedError(); + res.status(403).json({code, message}); return; } @@ -210,14 +221,21 @@ router.post('/add-files', async (req, isInitialSeeding: isInitialSeeding ?? false, start: start ?? false, }) - .then((response) => { - req.services?.torrentService.fetchTorrentList(); - return response; - }) - .then(callback) - .catch((err) => { - callback(null, err); - }); + .then( + (response) => { + req.services?.torrentService.fetchTorrentList(); + if (response.length === 0) { + res.status(202).json(response); + } else if (response.length < files.length) { + res.status(207).json(response); + } else { + res.status(200).json(response); + } + }, + ({code, message}) => { + res.status(500).json({code, message}); + }, + ); }); /** diff --git a/server/services/Transmission/clientGatewayService.ts b/server/services/Transmission/clientGatewayService.ts index 87ed05a4..16d45755 100644 --- a/server/services/Transmission/clientGatewayService.ts +++ b/server/services/Transmission/clientGatewayService.ts @@ -43,8 +43,8 @@ class TransmissionClientGatewayService extends ClientGatewayService { tags, isCompleted, start, - }: Required): Promise { - const addedTorrents: [string, ...string[]] = await Promise.all( + }: Required): Promise { + const addedTorrents = await Promise.all( files.map(async (file) => { const {hashString} = (await this.clientRequestManager @@ -57,23 +57,22 @@ class TransmissionClientGatewayService extends ClientGatewayService { .catch(() => undefined)) || {}; return hashString; }), - ) - .then((results) => results.filter((hash) => hash != null) as string[]) - .then((hashes) => { - if (hashes.length < 1) { - throw new Error(); - } - return hashes as [string, ...string[]]; - }); + ).then((results) => results.filter((hash) => hash) as string[]); + + if (addedTorrents[0] == null) { + throw new Error(); + } if (tags.length > 0) { - await this.setTorrentsTags({hashes: addedTorrents, tags}); + await this.setTorrentsTags({hashes: addedTorrents as [string, ...string[]], tags}); } if (isCompleted) { // Transmission doesn't support skipping verification this.checkTorrents({hashes: addedTorrents}).catch(() => undefined); } + + return addedTorrents; } async addTorrentsByURL({ @@ -81,10 +80,9 @@ class TransmissionClientGatewayService extends ClientGatewayService { cookies, destination, tags, - isCompleted, start, - }: Required): Promise { - const addedTorrents: [string, ...string[]] = await Promise.all( + }: Required): Promise { + const addedTorrents = await Promise.all( urls.map(async (url) => { const domain = url.split('/')[2]; const {hashString} = @@ -99,23 +97,17 @@ class TransmissionClientGatewayService extends ClientGatewayService { .catch(() => undefined)) || {}; return hashString; }), - ) - .then((results) => results.filter((hash) => hash != null) as string[]) - .then((hashes) => { - if (hashes.length < 1) { - throw new Error(); - } - return hashes as [string, ...string[]]; - }); + ).then((results) => results.filter((hash) => hash) as string[]); + + if (addedTorrents[0] == null) { + throw new Error(); + } if (tags.length > 0) { - await this.setTorrentsTags({hashes: addedTorrents, tags}); + await this.setTorrentsTags({hashes: addedTorrents as [string, ...string[]], tags}); } - if (isCompleted) { - // Transmission doesn't support skipping verification - this.checkTorrents({hashes: addedTorrents}).catch(() => undefined); - } + return addedTorrents; } async checkTorrents({hashes}: CheckTorrentsOptions): Promise { diff --git a/server/services/interfaces/clientGatewayService.ts b/server/services/interfaces/clientGatewayService.ts index 918d82cc..a8357345 100644 --- a/server/services/interfaces/clientGatewayService.ts +++ b/server/services/interfaces/clientGatewayService.ts @@ -41,17 +41,17 @@ abstract class ClientGatewayService extends BaseService} options - An object of options... - * @return {Promise} - Rejects with error. + * @return {Promise} - Resolves with an array of hashes of added torrents or rejects with error. */ - abstract addTorrentsByFile(options: Required): Promise; + abstract addTorrentsByFile(options: Required): Promise; /** * Adds torrents by URL * * @param {Required} options - An object of options... - * @return {Promise} - Rejects with error. + * @return {Promise} - Resolves with an array of hashes of added torrents or rejects with error. */ - abstract addTorrentsByURL(options: Required): Promise; + abstract addTorrentsByURL(options: Required): Promise; /** * Checks torrents diff --git a/server/services/qBittorrent/clientGatewayService.ts b/server/services/qBittorrent/clientGatewayService.ts index 58d0060c..d0bdf868 100644 --- a/server/services/qBittorrent/clientGatewayService.ts +++ b/server/services/qBittorrent/clientGatewayService.ts @@ -1,4 +1,5 @@ import {homedir} from 'os'; +import parseTorrent from 'parse-torrent'; import path from 'path'; import type { @@ -50,16 +51,34 @@ class QBittorrentClientGatewayService extends ClientGatewayService { tags, isBasePath, isCompleted, + isInitialSeeding, isSequential, start, - }: Required): Promise { - // TODO: isInitialSeeding not implemented + }: Required): Promise { + const fileBuffers: Buffer[] = []; - const fileBuffers = files.map((file) => { - return Buffer.from(file, 'base64'); - }); + const torrentHashes: string[] = ( + await Promise.all( + files.map(async (file) => { + try { + const fileBuffer = Buffer.from(file, 'base64'); - return this.clientRequestManager + const {infoHash} = parseTorrent(fileBuffer); + fileBuffers.push(fileBuffer); + + return infoHash; + } catch { + return; + } + }), + ) + ).filter((hash) => hash) as string[]; + + if (torrentHashes[0] == null) { + throw new Error(); + } + + await this.clientRequestManager .torrentsAddFiles(fileBuffers, { savepath: destination, tags: tags.join(','), @@ -70,6 +89,10 @@ class QBittorrentClientGatewayService extends ClientGatewayService { skip_checking: isCompleted, }) .then(this.processClientRequestSuccess, this.processClientRequestError); + + await this.setTorrentsInitialSeeding({hashes: torrentHashes, isInitialSeeding}); + + return torrentHashes; } async addTorrentsByURL({ @@ -81,10 +104,10 @@ class QBittorrentClientGatewayService extends ClientGatewayService { isCompleted, isSequential, start, - }: Required): Promise { + }: Required): Promise { // TODO: isInitialSeeding not implemented - return this.clientRequestManager + await this.clientRequestManager .torrentsAddURLs(urls, { cookie: cookies != null ? Object.values(cookies)[0]?.[0] : undefined, savepath: destination, @@ -96,6 +119,8 @@ class QBittorrentClientGatewayService extends ClientGatewayService { skip_checking: isCompleted, }) .then(this.processClientRequestSuccess, this.processClientRequestError); + + return []; } async checkTorrents({hashes}: CheckTorrentsOptions): Promise { diff --git a/server/services/rTorrent/clientGatewayService.ts b/server/services/rTorrent/clientGatewayService.ts index d6ea05b4..367caf66 100644 --- a/server/services/rTorrent/clientGatewayService.ts +++ b/server/services/rTorrent/clientGatewayService.ts @@ -2,6 +2,7 @@ import fs from 'fs'; import geoip from 'geoip-country'; import {moveSync} from 'fs-extra'; import path from 'path'; +import parseTorrent from 'parse-torrent'; import sanitize from 'sanitize-filename'; import type { @@ -66,7 +67,7 @@ class RTorrentClientGatewayService extends ClientGatewayService { isSequential, isInitialSeeding, start, - }: Required): Promise { + }: Required): Promise { const torrentPaths = await Promise.all( files.map(async (file) => { return saveBufferToTempFile(Buffer.from(file, 'base64'), 'torrent', { @@ -75,21 +76,17 @@ class RTorrentClientGatewayService extends ClientGatewayService { }), ); - if (torrentPaths[0] != null) { - return this.addTorrentsByURL({ - urls: torrentPaths as [string, ...string[]], - cookies: {}, - destination, - tags, - isBasePath, - isCompleted, - isSequential, - isInitialSeeding, - start, - }); - } - - return Promise.reject(); + return this.addTorrentsByURL({ + urls: torrentPaths as [string, ...string[]], + cookies: {}, + destination, + tags, + isBasePath, + isCompleted, + isSequential, + isInitialSeeding, + start, + }); } async addTorrentsByURL({ @@ -102,7 +99,7 @@ class RTorrentClientGatewayService extends ClientGatewayService { isSequential, isInitialSeeding, start, - }: Required): Promise { + }: Required): Promise { await fs.promises.mkdir(destination, {recursive: true}); const torrentPaths: Array = ( @@ -123,23 +120,39 @@ class RTorrentClientGatewayService extends ClientGatewayService { return ''; } - // TODO: handle potential other types of downloads - return url; }), ) ).filter((torrentPath) => torrentPath !== ''); - if (isCompleted) { + const torrentHashes: string[] = ( await Promise.all( - torrentPaths.map((torrentPath) => { - if (!fs.existsSync(torrentPath)) { - return false; - } + torrentPaths.map( + async (torrentPath): Promise => { + try { + if (torrentPath.startsWith('magnet:')) { + return parseTorrent(torrentPath).infoHash; + } - return setCompleted(torrentPath, destination, isBasePath); - }), - ); + if (!fs.existsSync(torrentPath)) { + return; + } + + if (isCompleted) { + await setCompleted(torrentPath, destination, isBasePath); + } + + return parseTorrent(fs.readFileSync(torrentPath)).infoHash; + } catch { + return; + } + }, + ), + ) + ).filter((torrentHash) => torrentHash) as string[]; + + if (torrentHashes[0] == null) { + throw new Error(); } const methodCalls: MultiMethodCalls = torrentPaths.map((torrentPath) => { @@ -167,12 +180,11 @@ class RTorrentClientGatewayService extends ClientGatewayService { }; }, []); - return this.clientRequestManager + await this.clientRequestManager .methodCall('system.multicall', [methodCalls]) - .then(this.processClientRequestSuccess, this.processClientRequestError) - .then(() => { - // returns nothing. - }); + .then(this.processClientRequestSuccess, this.processClientRequestError); + + return torrentHashes; } async checkTorrents({hashes}: CheckTorrentsOptions): Promise {