diff --git a/package-lock.json b/package-lock.json index aad9e8d..b42ab05 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,514 +8,26 @@ "name": "play-dl", "version": "0.9.1", "license": "MIT", - "dependencies": { - "got": "^11.8.2" + "devDependencies": { + "@types/node": "^16.9.1" }, "engines": { "node": ">=16.0.0" } }, - "node_modules/@sindresorhus/is": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", - "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/cacheable-request": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", - "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "*", - "@types/node": "*", - "@types/responselike": "*" - } - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" - }, - "node_modules/@types/keyv": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.2.tgz", - "integrity": "sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/node": { - "version": "16.7.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.1.tgz", - "integrity": "sha512-ncRdc45SoYJ2H4eWU9ReDfp3vtFqDYhjOsKlFFUDEn8V1Bgr2RjYal8YT5byfadWIRluhPFU6JiDOl0H6Sl87A==" - }, - "node_modules/@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dependencies": { - "mimic-response": "^1.0.0" - } - }, - "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==", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/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==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "engines": { - "node": ">=10" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.1", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" - }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "node_modules/keyv": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", - "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.0.tgz", - "integrity": "sha512-e4FNQs+9cINYMO5NMFc6kOUCdohjqFPSgMuwuZAOUWqrfWsen+Yjy5qZFkV5K7VO7tFSLKcUL97olkED7sCBHA==" - }, - "node_modules/responselike": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", - "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", - "dependencies": { - "lowercase-keys": "^2.0.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==", + "dev": true } }, "dependencies": { - "@sindresorhus/is": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", - "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==" - }, - "@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "requires": { - "defer-to-connect": "^2.0.0" - } - }, - "@types/cacheable-request": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", - "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", - "requires": { - "@types/http-cache-semantics": "*", - "@types/keyv": "*", - "@types/node": "*", - "@types/responselike": "*" - } - }, - "@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" - }, - "@types/keyv": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.2.tgz", - "integrity": "sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==", - "requires": { - "@types/node": "*" - } - }, "@types/node": { - "version": "16.7.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.1.tgz", - "integrity": "sha512-ncRdc45SoYJ2H4eWU9ReDfp3vtFqDYhjOsKlFFUDEn8V1Bgr2RjYal8YT5byfadWIRluhPFU6JiDOl0H6Sl87A==" - }, - "@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "requires": { - "@types/node": "*" - } - }, - "cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==" - }, - "cacheable-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - } - }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "requires": { - "mimic-response": "^1.0.0" - } - }, - "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==", - "requires": { - "mimic-response": "^3.1.0" - }, - "dependencies": { - "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==" - } - } - }, - "defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { - "once": "^1.4.0" - } - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "requires": { - "pump": "^3.0.0" - } - }, - "got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", - "requires": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.1", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - } - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" - }, - "http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "requires": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - } - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "keyv": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", - "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", - "requires": { - "json-buffer": "3.0.1" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" - }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" - }, - "normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" - }, - "resolve-alpn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.0.tgz", - "integrity": "sha512-e4FNQs+9cINYMO5NMFc6kOUCdohjqFPSgMuwuZAOUWqrfWsen+Yjy5qZFkV5K7VO7tFSLKcUL97olkED7sCBHA==" - }, - "responselike": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", - "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", - "requires": { - "lowercase-keys": "^2.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==", + "dev": true } } } diff --git a/package.json b/package.json index a3a3105..a0f9b40 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "files": [ "dist/*" ], - "dependencies": { - "got": "^11.8.2" + "devDependencies": { + "@types/node": "^16.9.1" } } diff --git a/play-dl/Spotify/classes.ts b/play-dl/Spotify/classes.ts index e107490..b939756 100644 --- a/play-dl/Spotify/classes.ts +++ b/play-dl/Spotify/classes.ts @@ -1,4 +1,4 @@ -import got, { Response } from "got/dist/source"; +import { request } from "../YouTube/utils/request"; import { SpotifyDataOptions } from "."; @@ -126,14 +126,14 @@ export class SpotifyPlaylist{ let work = [] for(let i = 2; i <= Math.ceil(fetching/100); i++){ work.push(new Promise(async (resolve, reject) => { - let response = await got(`https://api.spotify.com/v1/playlists/${this.id}/tracks?offset=${(i-1)*100}&limit=100&market=${this.spotifyData.market}`, { + let response = await request(`https://api.spotify.com/v1/playlists/${this.id}/tracks?offset=${(i-1)*100}&limit=100&market=${this.spotifyData.market}`, { headers : { "Authorization" : `${this.spotifyData.token_type} ${this.spotifyData.access_token}` } }).catch((err) => reject(`Response Error : \n${err}`)) let videos: SpotifyVideo[] = [] - let res = response as Response - let json_data = JSON.parse(res.body) + if(typeof response !== 'string') return + let json_data = JSON.parse(response) json_data.items.forEach((v : any) => { videos.push(new SpotifyVideo(v.track)) }) @@ -223,14 +223,14 @@ export class SpotifyAlbum{ let work = [] for(let i = 2; i <= Math.ceil(fetching/50); i++){ work.push(new Promise(async (resolve, reject) => { - let response = await got(`https://api.spotify.com/v1/albums/${this.id}/tracks?offset=${(i-1)*50}&limit=50&market=${this.spotifyData.market}`, { + let response = await request(`https://api.spotify.com/v1/albums/${this.id}/tracks?offset=${(i-1)*50}&limit=50&market=${this.spotifyData.market}`, { headers : { "Authorization" : `${this.spotifyData.token_type} ${this.spotifyData.access_token}` } }).catch((err) => reject(`Response Error : \n${err}`)) let videos: SpotifyTracks[] = [] - let res = response as Response - let json_data = JSON.parse(res.body) + if(typeof response !== 'string') return + let json_data = JSON.parse(response) json_data.items.forEach((v : any) => { videos.push(new SpotifyTracks(v)) }) diff --git a/play-dl/Spotify/index.ts b/play-dl/Spotify/index.ts index f7bec3a..aa11869 100644 --- a/play-dl/Spotify/index.ts +++ b/play-dl/Spotify/index.ts @@ -1,4 +1,4 @@ -import got from "got/dist/source" +import { request } from "../YouTube/utils/request"; import { SpotifyAlbum, SpotifyPlaylist, SpotifyVideo } from "./classes" import readline from 'readline' import fs from 'fs' @@ -28,32 +28,32 @@ export async function spotify(url : string): Promise {return 0}) - if(typeof response !== 'number') return new SpotifyVideo(JSON.parse(response.body)) + if(typeof response !== 'number') return new SpotifyVideo(JSON.parse(response)) else throw new Error('Failed to get spotify Track Data') } else if(url.indexOf('album/') !== -1){ let albumID = url.split('album/')[1].split('&')[0].split('?')[0] - let response = await got(`https://api.spotify.com/v1/albums/${albumID}?market=${spotifyData.market}`, { + let response = await request(`https://api.spotify.com/v1/albums/${albumID}?market=${spotifyData.market}`, { headers : { "Authorization" : `${spotifyData.token_type} ${spotifyData.access_token}` } }).catch((err) => {return 0}) - if(typeof response !== 'number') return new SpotifyAlbum(JSON.parse(response.body), spotifyData) + if(typeof response !== 'number') return new SpotifyAlbum(JSON.parse(response), spotifyData) else throw new Error('Failed to get spotify Album Data') } else if(url.indexOf('playlist/') !== -1){ let playlistID = url.split('playlist/')[1].split('&')[0].split('?')[0] - let response = await got(`https://api.spotify.com/v1/playlists/${playlistID}?market=${spotifyData.market}`, { + let response = await request(`https://api.spotify.com/v1/playlists/${playlistID}?market=${spotifyData.market}`, { headers : { "Authorization" : `${spotifyData.token_type} ${spotifyData.access_token}` } }).catch((err) => {return 0}) - if(typeof response !== 'number') return new SpotifyPlaylist(JSON.parse(response.body), spotifyData) + if(typeof response !== 'number') return new SpotifyPlaylist(JSON.parse(response), spotifyData) else throw new Error('Failed to get spotify Playlist Data') } else throw new Error('URL is out of scope for play-dl.') @@ -115,17 +115,19 @@ export function Authorization(){ } async function SpotifyAuthorize(data : SpotifyDataOptions): Promise{ - let response = await got.post(`https://accounts.spotify.com/api/token?grant_type=authorization_code&code=${data.authorization_code}&redirect_uri=${encodeURI(data.redirect_url)}`, { + let response = await request(`https://accounts.spotify.com/api/token`, { headers : { "Authorization" : `Basic ${Buffer.from(`${data.client_id}:${data.client_secret}`).toString('base64')}`, "Content-Type" : "application/x-www-form-urlencoded" - } + }, + body : `grant_type=authorization_code&code=${data.authorization_code}&redirect_uri=${encodeURI(data.redirect_url)}`, + method : "POST" }).catch(() => { return 0 }) if(typeof response === 'number') return false - let resp_json = JSON.parse(response.body) + let resp_json = JSON.parse(response) spotifyData = { client_id : data.client_id, client_secret : data.client_secret, @@ -133,7 +135,7 @@ async function SpotifyAuthorize(data : SpotifyDataOptions): Promise{ access_token : resp_json.access_token, refresh_token : resp_json.refresh_token, expires_in : Number(resp_json.expires_in), - expiry : Date.now() + (Number(resp_json.expires_in) * 1000), + expiry : Date.now() + ((resp_json.expires_in - 1) * 1000), token_type : resp_json.token_type, market : data.market } @@ -147,20 +149,22 @@ export function is_expired(){ } export async function RefreshToken(): Promise{ - let response = await got.post(`https://accounts.spotify.com/api/token?grant_type=refresh_token&refresh_token=${spotifyData.refresh_token}`, { + let response = await request(`https://accounts.spotify.com/api/token`, { headers : { "Authorization" : `Basic ${Buffer.from(`${spotifyData.client_id}:${spotifyData.client_secret}`).toString('base64')}`, "Content-Type" : "application/x-www-form-urlencoded" - } + }, + body : `grant_type=refresh_token&refresh_token=${spotifyData.refresh_token}`, + method : "POST" }).catch(() => { return 0 }) if(typeof response === 'number') return false - let resp_json = JSON.parse(response.body) + let resp_json = JSON.parse(response) spotifyData.access_token = resp_json.access_token spotifyData.expires_in = Number(resp_json.expires_in) - spotifyData.expiry = Date.now() + (Number(resp_json.expires_in) * 1000) + spotifyData.expiry = Date.now() + ((resp_json.expires_in - 1) * 1000) spotifyData.token_type = resp_json.token_type fs.writeFileSync('.data/spotify.data', JSON.stringify(spotifyData, undefined, 4)) return true diff --git a/play-dl/YouTube/classes/LiveStream.ts b/play-dl/YouTube/classes/LiveStream.ts index ead0c5f..597a3f8 100644 --- a/play-dl/YouTube/classes/LiveStream.ts +++ b/play-dl/YouTube/classes/LiveStream.ts @@ -1,7 +1,7 @@ import { PassThrough } from 'stream' -import got from 'got' +import { IncomingMessage } from 'http'; import { StreamType } from '../stream'; -import Request from 'got/dist/source/core'; +import { request, request_stream } from '../utils/request'; import { video_info } from '..'; export interface FormatInterface{ @@ -21,7 +21,7 @@ export class LiveStreaming{ private video_url : string private dash_timer : NodeJS.Timer | null private segments_urls : string[] - private request : Request | null + private request : IncomingMessage | null constructor(dash_url : string, target_interval : number, video_url : string){ this.type = StreamType.Arbitrary this.url = dash_url @@ -53,8 +53,8 @@ export class LiveStreaming{ } private async dash_getter(){ - let response = await got(this.url) - let audioFormat = response.body.split('')[0].split('') + let response = await request(this.url) + let audioFormat = response.split('')[0].split('') if(audioFormat[audioFormat.length - 1] === '') audioFormat.pop() this.base_url = audioFormat[audioFormat.length - 1].split('')[1].split('')[0] let list = audioFormat[audioFormat.length - 1].split('')[1].split('')[0] @@ -90,8 +90,8 @@ export class LiveStreaming{ if(Number(segment.split('sq/')[1].split('/')[0]) !== this.packet_count){ continue } - await new Promise((resolve, reject) => { - let stream = got.stream(this.base_url + segment) + await new Promise(async(resolve, reject) => { + let stream = await request_stream(this.base_url + segment) this.request = stream stream.pipe(this.stream, { end : false }) stream.on('end', () => { @@ -116,14 +116,22 @@ export class Stream { private bytes_count : number; private per_sec_bytes : number; private content_length : number; + private video_url : string; + private timer : NodeJS.Timer; + private cookie : string; private data_ended : boolean; private playing_count : number; - private request : Request | null - constructor(url : string, type : StreamType, duration : number, contentLength : number){ + private request : IncomingMessage | null + constructor(url : string, type : StreamType, duration : number, contentLength : number, video_url : string, cookie : string){ this.url = url this.type = type this.stream = new PassThrough({ highWaterMark : 10 * 1000 * 1000 }) this.bytes_count = 0 + this.video_url = video_url + this.cookie = cookie + this.timer = setInterval(() => { + this.retry() + }, 7200 * 1000) this.per_sec_bytes = Math.ceil(contentLength / duration) this.content_length = contentLength this.request = null @@ -146,7 +154,13 @@ export class Stream { this.loop() } + private async retry(){ + let info = await video_info(this.video_url, this.cookie) + this.url = info.format[info.format.length - 1].url + } + private cleanup(){ + clearInterval(this.timer) this.request?.unpipe(this.stream) this.request?.destroy() this.request = null @@ -155,17 +169,22 @@ export class Stream { this.per_sec_bytes = 0 } - private loop(){ + private async loop(){ if(this.stream.destroyed){ this.cleanup() return } let end : number = this.bytes_count + this.per_sec_bytes * 300; - let stream = got.stream(this.url, { + let stream = await request_stream(this.url, { headers : { "range" : `bytes=${this.bytes_count}-${end >= this.content_length ? '' : end}` } }) + if(Number(stream.statusCode) >= 400){ + this.cleanup() + await this.retry() + this.loop() + } this.request = stream stream.pipe(this.stream, { end : false }) diff --git a/play-dl/YouTube/classes/Playlist.ts b/play-dl/YouTube/classes/Playlist.ts index dfead2b..becd02e 100644 --- a/play-dl/YouTube/classes/Playlist.ts +++ b/play-dl/YouTube/classes/Playlist.ts @@ -1,5 +1,5 @@ import { getPlaylistVideos, getContinuationToken } from "../utils/extractor"; -import { url_get } from "../utils/request"; +import { request } from "../utils/request"; import { Thumbnail } from "./Thumbnail"; import { Channel } from "./Channel"; import { Video } from "./Video"; @@ -62,7 +62,7 @@ export class PlayList{ async next(limit: number = Infinity): Promise { if (!this._continuation || !this._continuation.token) return []; - let nextPage = await url_get(`${BASE_API}${this._continuation.api}`, { + let nextPage = await request(`${BASE_API}${this._continuation.api}`, { method: "POST", body: JSON.stringify({ continuation: this._continuation.token, diff --git a/play-dl/YouTube/search.ts b/play-dl/YouTube/search.ts index b20c696..251d955 100644 --- a/play-dl/YouTube/search.ts +++ b/play-dl/YouTube/search.ts @@ -1,4 +1,4 @@ -import { url_get } from "./utils/request"; +import { request } from "./utils/request"; import { ParseSearchInterface, ParseSearchResult } from "./utils/parser"; import { Video } from "./classes/Video"; import { Channel } from "./classes/Channel"; @@ -29,7 +29,7 @@ export async function search(search :string, options? : ParseSearchInterface): P break } } - let body = await url_get(url, { + let body = await request(url, { headers : {'accept-language' : 'en-US,en-IN;q=0.9,en;q=0.8,hi;q=0.7'} }) let data = ParseSearchResult(body, options) diff --git a/play-dl/YouTube/stream.ts b/play-dl/YouTube/stream.ts index 7de9d70..3626f5b 100644 --- a/play-dl/YouTube/stream.ts +++ b/play-dl/YouTube/stream.ts @@ -1,6 +1,6 @@ -import got from "got/dist/source" import { video_info } from "." import { LiveStreaming, Stream } from "./classes/LiveStream" +import { request } from "./utils/request" export enum StreamType{ Arbitrary = 'arbitrary', @@ -41,18 +41,6 @@ export async function stream(url : string, cookie? : string): Promise { - return 0 - }) - if(resp === 0){ - return await stream(info.video_details.url, cookie) - } - else if(typeof resp !== "number") resp.destroy() let audioFormat = parseAudioFormats(info.format) let opusFormats = filterFormat(audioFormat, "opus") @@ -71,7 +59,7 @@ export async function stream(url : string, cookie? : string): Promise{ @@ -81,19 +69,6 @@ export async function stream_from_info(info : InfoData, cookie? : string): Promi return new LiveStreaming(info.LiveStreamData.dashManifestUrl, info.format[info.format.length - 1].targetDurationSec, info.video_details.url) } - let resp = await got(info.format[info.format.length - 1].url, { - headers : { - "range" : `bytes=0-1` - }, - retry : 0 - }).catch(() => { - return 0 - }) - if(resp === 0){ - return await stream(info.video_details.url, cookie) - } - else if(typeof resp !== "number") resp.destroy() - let audioFormat = parseAudioFormats(info.format) let opusFormats = filterFormat(audioFormat, "opus") @@ -111,7 +86,7 @@ export async function stream_from_info(info : InfoData, cookie? : string): Promi final.push(info.format[info.format.length - 1]) } - return new Stream(final[0].url, type, info.video_details.durationInSec, Number(final[0].contentLength)) + return new Stream(final[0].url, type, info.video_details.durationInSec, Number(final[0].contentLength), info.video_details.url, cookie as string) } function filterFormat(formats : any[], codec : string){ diff --git a/play-dl/YouTube/utils/cipher.ts b/play-dl/YouTube/utils/cipher.ts index 214b692..964b61f 100644 --- a/play-dl/YouTube/utils/cipher.ts +++ b/play-dl/YouTube/utils/cipher.ts @@ -1,5 +1,5 @@ import { URL } from 'url' -import { url_get } from './request' +import { request } from './request' import querystring from 'querystring' interface formatOptions { @@ -131,7 +131,6 @@ function deciper_signature(tokens : string[], signature :string){ function swappositions(array : string[], position : number){ let first = array[0] - let pos_args = array[position] array[0] = array[position] array[position] = first return array @@ -154,7 +153,7 @@ function download_url(format: formatOptions, sig : string){ } export async function format_decipher(formats: formatOptions[], html5player : string){ - let body = await url_get(html5player) + let body = await request(html5player) let tokens = js_tokens(body) formats.forEach((format) => { let cipher = format.signatureCipher || format.cipher; diff --git a/play-dl/YouTube/utils/extractor.ts b/play-dl/YouTube/utils/extractor.ts index b7774c2..f613794 100644 --- a/play-dl/YouTube/utils/extractor.ts +++ b/play-dl/YouTube/utils/extractor.ts @@ -1,4 +1,4 @@ -import { url_get } from './request' +import { request } from './request' import { format_decipher, js_tokens } from './cipher' import { Video } from '../classes/Video' import { PlayList } from '../classes/Playlist' @@ -46,7 +46,7 @@ export async function video_basic_info(url : string, cookie? : string){ } else video_id = url let new_url = `https://www.youtube.com/watch?v=${video_id}` - let body = await url_get(new_url, { + let body = await request(new_url, { headers : (cookie) ? { 'cookie' : cookie, 'accept-language' : 'en-US,en-IN;q=0.9,en;q=0.8,hi;q=0.7' } : {'accept-language' : 'en-US,en-IN;q=0.9,en;q=0.8,hi;q=0.7'} }) let player_response = JSON.parse(body.split("var ytInitialPlayerResponse = ")[1].split("}};")[0] + '}}') @@ -129,7 +129,7 @@ export async function playlist_info(url : string, parseIncomplete : boolean = fa else Playlist_id = url let new_url = `https://www.youtube.com/playlist?list=${Playlist_id}` - let body = await url_get(new_url, { + let body = await request(new_url, { headers : {'accept-language' : 'en-US,en-IN;q=0.9,en;q=0.8,hi;q=0.7'} }) let response = JSON.parse(body.split("var ytInitialData = ")[1].split(";")[0]) diff --git a/play-dl/YouTube/utils/request.ts b/play-dl/YouTube/utils/request.ts index 8783a70..39693a4 100644 --- a/play-dl/YouTube/utils/request.ts +++ b/play-dl/YouTube/utils/request.ts @@ -1,9 +1,54 @@ -import got, { OptionsOfTextResponseBody } from 'got/dist/source' +import https, { RequestOptions } from 'https' +import {IncomingMessage } from 'http' +import { URL } from 'url' -export async function url_get (url : string, options? : OptionsOfTextResponseBody) : Promise{ - let response = await got(url, options) - if(response.statusCode === 200) { - return response.body - } - else throw new Error(`Got ${response.statusCode} from ${url}`) +interface RequestOpts extends RequestOptions{ + body? : string; + method? : "GET" | "POST" } + +async function https_getter(req_url : string, options : RequestOpts = {}): Promise{ + return new Promise((resolve, reject) => { + let s = new URL(req_url) + if(!options.method) options.method = "GET" + let req_options : RequestOptions = { + host : s.hostname, + path : s.pathname + s.search, + headers : (options.headers) ? options.headers : {}, + method : options.method + } + + let req = https.request(req_options, (response) => { + resolve(response) + }) + if(options.method === "POST") req.write(options.body) + req.end() + }) +} + +export async function request(url : string, options? : RequestOpts): Promise{ + return new Promise(async (resolve, reject) => { + let data = '' + let res = await https_getter(url, options) + if(Number(res.statusCode) >= 300 && Number(res.statusCode) < 400){ + res = await https_getter(res.headers.location as string , options) + } + else if(Number(res.statusCode) > 400){ + reject(`Got ${res.statusCode} from the request`) + } + res.setEncoding('utf-8') + res.on('data', (c) => data+=c) + res.on('end', () => resolve(data)) + }) +} + +export async function request_stream(url : string, options? : RequestOpts): Promise{ + return new Promise(async (resolve, reject) => { + let data = '' + let res = await https_getter(url, options) + if(Number(res.statusCode) >= 300 && Number(res.statusCode) < 400){ + res = await https_getter(res.headers.location as string, options) + } + resolve(res) + }) +} \ No newline at end of file