diff --git a/.github/updateUserAgents.js b/.github/updateUserAgents.js index f47d33e..bc0a0d6 100644 --- a/.github/updateUserAgents.js +++ b/.github/updateUserAgents.js @@ -9,7 +9,8 @@ for (let i = 0; i < 10; i++) { // only use Windows and Linux user agents and exclude Internet Explorer ones while (!(userAgent.data.platform.startsWith('Win') || userAgent.data.platform.startsWith('Linux')) - || userAgent.data.userAgent.includes('; MSIE') || userAgent.data.userAgent.includes('Trident/')) { + || userAgent.data.userAgent.includes('; MSIE') || userAgent.data.userAgent.includes('Trident/') + || userAgents.includes(userAgent.toString())) { userAgent = generator.random(); } diff --git a/package-lock.json b/package-lock.json index ab0efd7..3d171c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "play-dl", - "version": "1.9.3", + "version": "1.9.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "play-dl", - "version": "1.9.3", + "version": "1.9.4", "license": "GPL-3.0", "dependencies": { "play-audio": "^0.5.2" @@ -60,9 +60,9 @@ } }, "node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "version": "17.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", + "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", "dev": true }, "node_modules/any-promise": { @@ -234,9 +234,9 @@ } }, "node_modules/esbuild": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.16.tgz", - "integrity": "sha512-niiWy7nesZFGCiDr0NR9/JLEhtZPYHG/ABYTqveNWvocw/gGI5rKHOj3+5yUv3yH10/geTlZiyVaNvjJWL9Xbw==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.29.tgz", + "integrity": "sha512-SQS8cO8xFEqevYlrHt6exIhK853Me4nZ4aMW6ieysInLa0FMAL+AKs87HYNRtR2YWRcEIqoXAHh+Ytt5/66qpg==", "dev": true, "hasInstallScript": true, "bin": { @@ -246,30 +246,48 @@ "node": ">=12" }, "optionalDependencies": { - "esbuild-android-arm64": "0.14.16", - "esbuild-darwin-64": "0.14.16", - "esbuild-darwin-arm64": "0.14.16", - "esbuild-freebsd-64": "0.14.16", - "esbuild-freebsd-arm64": "0.14.16", - "esbuild-linux-32": "0.14.16", - "esbuild-linux-64": "0.14.16", - "esbuild-linux-arm": "0.14.16", - "esbuild-linux-arm64": "0.14.16", - "esbuild-linux-mips64le": "0.14.16", - "esbuild-linux-ppc64le": "0.14.16", - "esbuild-linux-s390x": "0.14.16", - "esbuild-netbsd-64": "0.14.16", - "esbuild-openbsd-64": "0.14.16", - "esbuild-sunos-64": "0.14.16", - "esbuild-windows-32": "0.14.16", - "esbuild-windows-64": "0.14.16", - "esbuild-windows-arm64": "0.14.16" + "esbuild-android-64": "0.14.29", + "esbuild-android-arm64": "0.14.29", + "esbuild-darwin-64": "0.14.29", + "esbuild-darwin-arm64": "0.14.29", + "esbuild-freebsd-64": "0.14.29", + "esbuild-freebsd-arm64": "0.14.29", + "esbuild-linux-32": "0.14.29", + "esbuild-linux-64": "0.14.29", + "esbuild-linux-arm": "0.14.29", + "esbuild-linux-arm64": "0.14.29", + "esbuild-linux-mips64le": "0.14.29", + "esbuild-linux-ppc64le": "0.14.29", + "esbuild-linux-riscv64": "0.14.29", + "esbuild-linux-s390x": "0.14.29", + "esbuild-netbsd-64": "0.14.29", + "esbuild-openbsd-64": "0.14.29", + "esbuild-sunos-64": "0.14.29", + "esbuild-windows-32": "0.14.29", + "esbuild-windows-64": "0.14.29", + "esbuild-windows-arm64": "0.14.29" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.29.tgz", + "integrity": "sha512-tJuaN33SVZyiHxRaVTo1pwW+rn3qetJX/SRuc/83rrKYtyZG0XfsQ1ao1nEudIt9w37ZSNXR236xEfm2C43sbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, "node_modules/esbuild-android-arm64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.16.tgz", - "integrity": "sha512-9qRiUXiV0qIa4Dfv+GLKsk/HHOq3U9qh8yZK9iX0awlzLPFb38NJrNTGtb/TeI6AyyZqsGgwLm/JeJ1UtEN9Aw==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.29.tgz", + "integrity": "sha512-D74dCv6yYnMTlofVy1JKiLM5JdVSQd60/rQfJSDP9qvRAI0laPXIG/IXY1RG6jobmFMUfL38PbFnCqyI/6fPXg==", "cpu": [ "arm64" ], @@ -283,9 +301,9 @@ } }, "node_modules/esbuild-darwin-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.16.tgz", - "integrity": "sha512-1Xa86DpTJFRffA7go0pqUdC0ggxxGxjsrnrvA2nHBVHNf9Ix/cgGuPfxZwf3fRZxDDAT2RdqF5SRZzLYvUCtZQ==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.29.tgz", + "integrity": "sha512-+CJaRvfTkzs9t+CjGa0Oa28WoXa7EeLutQhxus+fFcu0MHhsBhlmeWHac3Cc/Sf/xPi1b2ccDFfzGYJCfV0RrA==", "cpu": [ "x64" ], @@ -299,9 +317,9 @@ } }, "node_modules/esbuild-darwin-arm64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.16.tgz", - "integrity": "sha512-a0Tp0tec/s5hYT6OiJ2zvfH/6IfXFCH406yqFfXe5u8Nfo6l6IG33L7nqCYCEPnBLF7oYfZk6Re0VDwpgK18kQ==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.29.tgz", + "integrity": "sha512-5Wgz/+zK+8X2ZW7vIbwoZ613Vfr4A8HmIs1XdzRmdC1kG0n5EG5fvKk/jUxhNlrYPx1gSY7XadQ3l4xAManPSw==", "cpu": [ "arm64" ], @@ -315,9 +333,9 @@ } }, "node_modules/esbuild-freebsd-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.16.tgz", - "integrity": "sha512-FqEdOphRS5kJ8MFqQ21Y0yducmwcFHmpkceLkup1kpsGChr3PGO7DfzXmF5fECNnMxRpk/jgk7e6nV4zXTau/A==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.29.tgz", + "integrity": "sha512-VTfS7Bm9QA12JK1YXF8+WyYOfvD7WMpbArtDj6bGJ5Sy5xp01c/q70Arkn596aGcGj0TvQRplaaCIrfBG1Wdtg==", "cpu": [ "x64" ], @@ -331,9 +349,9 @@ } }, "node_modules/esbuild-freebsd-arm64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.16.tgz", - "integrity": "sha512-4Au4zR0//Df1v6FuWJEMZFRzaF69FvxHgSmKjikq7x6Ect+h4TbJKkblC3eDrfTA8L6l5bB1vhh0dbKq4zBy5Q==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.29.tgz", + "integrity": "sha512-WP5L4ejwLWWvd3Fo2J5mlXvG3zQHaw5N1KxFGnUc4+2ZFZknP0ST63i0IQhpJLgEJwnQpXv2uZlU1iWZjFqEIg==", "cpu": [ "arm64" ], @@ -347,9 +365,9 @@ } }, "node_modules/esbuild-linux-32": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.16.tgz", - "integrity": "sha512-HundAiQCa0ut7PXq3lmRZY7H3/OYh27wkJ97S7jjCgWmcd5To6Bs8UBVB7I4Qi9lNk/Yty0INnqq9on1WR8JUA==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.29.tgz", + "integrity": "sha512-4myeOvFmQBWdI2U1dEBe2DCSpaZyjdQtmjUY11Zu2eQg4ynqLb8Y5mNjNU9UN063aVsCYYfbs8jbken/PjyidA==", "cpu": [ "ia32" ], @@ -363,9 +381,9 @@ } }, "node_modules/esbuild-linux-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.16.tgz", - "integrity": "sha512-fG8MgVmQknIuYCHFOq+9iKLyygjPun+VkNH9ZIdRQrSzb3CFdEkNm+Suq5w8W+WjA/P0OIdrQ/mXXCoHCQTWSQ==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.29.tgz", + "integrity": "sha512-iaEuLhssReAKE7HMwxwFJFn7D/EXEs43fFy5CJeA4DGmU6JHh0qVJD2p/UP46DvUXLRKXsXw0i+kv5TdJ1w5pg==", "cpu": [ "x64" ], @@ -379,9 +397,9 @@ } }, "node_modules/esbuild-linux-arm": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.16.tgz", - "integrity": "sha512-0NDVeuvWska0d4Rd8R3+lWEyKaIbAxDuRAeeU6a2xaUXrTG2IPhGNLWc4NbVMbnkGqRqKB4PLdk/YaTUZjKFHQ==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.29.tgz", + "integrity": "sha512-OXa9D9QL1hwrAnYYAHt/cXAuSCmoSqYfTW/0CEY0LgJNyTxJKtqc5mlwjAZAvgyjmha0auS/sQ0bXfGf2wAokQ==", "cpu": [ "arm" ], @@ -395,9 +413,9 @@ } }, "node_modules/esbuild-linux-arm64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.16.tgz", - "integrity": "sha512-7WF1rHsPVXhme2B6ceZZABxFwCiZfMRIJO7yRiLahIdDkwfhSTR6M0a6OwO/NsLJH9fax5GdwBOIBoG5Hkz4gA==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.29.tgz", + "integrity": "sha512-KYf7s8wDfUy+kjKymW3twyGT14OABjGHRkm9gPJ0z4BuvqljfOOUbq9qT3JYFnZJHOgkr29atT//hcdD0Pi7Mw==", "cpu": [ "arm64" ], @@ -411,9 +429,9 @@ } }, "node_modules/esbuild-linux-mips64le": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.16.tgz", - "integrity": "sha512-RLNaTRdcQ81QckeIjbk1hCrgmrL6VoZBsYT8ak9ObNQzXEJNMlxOBixaF6rhW8UUYRpTpFuoYHeNya8xY884/A==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.29.tgz", + "integrity": "sha512-05jPtWQMsZ1aMGfHOvnR5KrTvigPbU35BtuItSSWLI2sJu5VrM8Pr9Owym4wPvA4153DFcOJ1EPN/2ujcDt54g==", "cpu": [ "mips64el" ], @@ -427,9 +445,9 @@ } }, "node_modules/esbuild-linux-ppc64le": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.16.tgz", - "integrity": "sha512-ky0Ii2Jmyc00FzGT2audU0UmnBVrVevYmKW10DXLPcHGhbhzJdFRemXLvvzhDM8WD9IMJK3uV6ifJzkKrv8IQA==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.29.tgz", + "integrity": "sha512-FYhBqn4Ir9xG+f6B5VIQVbRuM4S6qwy29dDNYFPoxLRnwTEKToIYIUESN1qHyUmIbfO0YB4phG2JDV2JDN9Kgw==", "cpu": [ "ppc64" ], @@ -442,10 +460,26 @@ "node": ">=12" } }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.29.tgz", + "integrity": "sha512-eqZMqPehkb4nZcffnuOpXJQdGURGd6GXQ4ZsDHSWyIUaA+V4FpMBe+5zMPtXRD2N4BtyzVvnBko6K8IWWr36ew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/esbuild-linux-s390x": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.16.tgz", - "integrity": "sha512-DuW9MPGJAzUUBPI/olMkMMepCasTbPN1Xr2cKZZEEDIibcdRnuFrMYVk3G3I8/Qb6SZBNTSnZMAyhvYFrwAkqw==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.29.tgz", + "integrity": "sha512-o7EYajF1rC/4ho7kpSG3gENVx0o2SsHm7cJ5fvewWB/TEczWU7teDgusGSujxCYcMottE3zqa423VTglNTYhjg==", "cpu": [ "s390x" ], @@ -459,9 +493,9 @@ } }, "node_modules/esbuild-netbsd-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.16.tgz", - "integrity": "sha512-l8+mnz8iVsV0iL5v5JCuP0UTv2LwO1ORdJ/scMkGUl8WrC6cBmUrrHhg+pwREqjbD8TxjfUJVM1Vvt5E8SaTsg==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.29.tgz", + "integrity": "sha512-/esN6tb6OBSot6+JxgeOZeBk6P8V/WdR3GKBFeFpSqhgw4wx7xWUqPrdx4XNpBVO7X4Ipw9SAqgBrWHlXfddww==", "cpu": [ "x64" ], @@ -475,9 +509,9 @@ } }, "node_modules/esbuild-openbsd-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.16.tgz", - "integrity": "sha512-8SbZNAV902FmcGnc+j86HWY8PyTD1H7T39RsPXXS5IC1psi3yzFr2d8NoOxb6cQd5XUVHmHT1naJsbtEAyKIPA==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.29.tgz", + "integrity": "sha512-jUTdDzhEKrD0pLpjmk0UxwlfNJNg/D50vdwhrVcW/D26Vg0hVbthMfb19PJMatzclbK7cmgk1Nu0eNS+abzoHw==", "cpu": [ "x64" ], @@ -491,9 +525,9 @@ } }, "node_modules/esbuild-sunos-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.16.tgz", - "integrity": "sha512-pMhe4uOaGjA/5YgeNoB0PRZi1V73D8sx876uFzuAxaZcYzLA5BsSbQeEccH182X6cBybE4Pm79kYedTSGOfwog==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.29.tgz", + "integrity": "sha512-EfhQN/XO+TBHTbkxwsxwA7EfiTHFe+MNDfxcf0nj97moCppD9JHPq48MLtOaDcuvrTYOcrMdJVeqmmeQ7doTcg==", "cpu": [ "x64" ], @@ -507,9 +541,9 @@ } }, "node_modules/esbuild-windows-32": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.16.tgz", - "integrity": "sha512-M68/EFCgji0DI+DgULx2ytUUSxwwODJDpiVc0YsiWKdyB4umKTu1GGxFfdZhXrWtPxB4aZFoIgJyDhsFxnHC4g==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.29.tgz", + "integrity": "sha512-uoyb0YAJ6uWH4PYuYjfGNjvgLlb5t6b3zIaGmpWPOjgpr1Nb3SJtQiK4YCPGhONgfg2v6DcJgSbOteuKXhwqAw==", "cpu": [ "ia32" ], @@ -523,9 +557,9 @@ } }, "node_modules/esbuild-windows-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.16.tgz", - "integrity": "sha512-rmSal1Co749CXSNyFJ62J5Fz/nZiFWhwMfYN9SwZazutKZ6s0QDRIhnupa93bJmzMzz4C2dqUV/VL1tqOI3y9g==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.29.tgz", + "integrity": "sha512-X9cW/Wl95QjsH8WUyr3NqbmfdU72jCp71cH3pwPvI4CgBM2IeOUDdbt6oIGljPu2bf5eGDIo8K3Y3vvXCCTd8A==", "cpu": [ "x64" ], @@ -539,9 +573,9 @@ } }, "node_modules/esbuild-windows-arm64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.16.tgz", - "integrity": "sha512-VMfEf+MDgO+rulAuSeu3HNebSHa1TDn0lJp+QRk7E2WVg9OCSwuXUEkSbqIbkif3ZjASy7h9sTCGyHcqgKQTrg==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.29.tgz", + "integrity": "sha512-+O/PI+68fbUZPpl3eXhqGHTGK7DjLcexNnyJqtLZXOFwoAjaXlS5UBCvVcR3o2va+AqZTj8o6URaz8D2K+yfQQ==", "cpu": [ "arm64" ], @@ -862,9 +896,9 @@ "dev": true }, "node_modules/marked": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.10.tgz", - "integrity": "sha512-+QvuFj0nGgO970fySghXGmuw+Fd0gD2x3+MqCWLIPf5oxdv1Ka6b2q+z9RP01P/IaKPMEramy+7cNy/Lw8c3hw==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", + "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -1073,15 +1107,18 @@ } }, "node_modules/prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.1.tgz", + "integrity": "sha512-8UVbTBYGwN37Bs9LERmxCPjdvPxlEowx2urIL6urHzdb3SDq4B/Z6xLFCblrSnE4iKWcS6ziJ3aOYrc1kz/E2A==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/queue-microtask": { @@ -1195,9 +1232,9 @@ } }, "node_modules/shiki": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.0.tgz", - "integrity": "sha512-iczxaIYeBFHTFrQPb9DVy2SKgYxC4Wo7Iucm7C17cCh2Ge/refnvHscUOxM85u57MfLoNOtjoEFUWt9gBexblA==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", + "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", "dev": true, "dependencies": { "jsonc-parser": "^3.0.0", @@ -1328,16 +1365,16 @@ "dev": true }, "node_modules/tsup": { - "version": "5.11.13", - "resolved": "https://registry.npmjs.org/tsup/-/tsup-5.11.13.tgz", - "integrity": "sha512-NVMK01gVmojZn7+iZwxRK1CzW2BIabaVMyEjs7Nm9lm4DrSf7IAqs2F3fg0vT7rH72x1cIBsW9U/TlWrCvHVQQ==", + "version": "5.12.2", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-5.12.2.tgz", + "integrity": "sha512-CZcM4UGYlKcdQzDIJbrwgpn4sQe8zobnHRgAF6C8RpMGvfRov9ipSQY3mjjnZRAkEZQO1+Jr3cxeaQJjY/iVTg==", "dev": true, "dependencies": { "bundle-require": "^3.0.2", "cac": "^6.7.12", "chokidar": "^3.5.1", "debug": "^4.3.1", - "esbuild": "^0.14.2", + "esbuild": "^0.14.25", "execa": "^5.0.0", "globby": "^11.0.3", "joycon": "^3.0.1", @@ -1362,16 +1399,16 @@ } }, "node_modules/typedoc": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.12.tgz", - "integrity": "sha512-FcyC+YuaOpr3rB9QwA1IHOi9KnU2m50sPJW5vcNRPCIdecp+3bFkh7Rq5hBU1Fyn29UR2h4h/H7twZHWDhL0sw==", + "version": "0.22.13", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.13.tgz", + "integrity": "sha512-NHNI7Dr6JHa/I3+c62gdRNXBIyX7P33O9TafGLd07ur3MqzcKgwTvpg18EtvCLHJyfeSthAtCLpM7WkStUmDuQ==", "dev": true, "dependencies": { "glob": "^7.2.0", "lunr": "^2.3.9", - "marked": "^4.0.10", - "minimatch": "^3.0.4", - "shiki": "^0.10.0" + "marked": "^4.0.12", + "minimatch": "^5.0.1", + "shiki": "^0.10.1" }, "bin": { "typedoc": "bin/typedoc" @@ -1380,7 +1417,7 @@ "node": ">= 12.10.0" }, "peerDependencies": { - "typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x" + "typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x || 4.6.x" } }, "node_modules/typedoc-plugin-extras": { @@ -1401,10 +1438,31 @@ "typedoc": "0.22.x" } }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/typescript": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", - "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -1415,9 +1473,9 @@ } }, "node_modules/vscode-oniguruma": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.1.tgz", - "integrity": "sha512-vc4WhSIaVpgJ0jJIejjYxPvURJavX6QG41vu0mGhqywMkQqulezEqEQ3cO3gc8GvcOpX6ycmKGqRoROEMBNXTQ==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", + "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", "dev": true }, "node_modules/vscode-textmate": { @@ -1485,9 +1543,9 @@ } }, "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "version": "17.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", + "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", "dev": true }, "any-promise": { @@ -1616,154 +1674,170 @@ } }, "esbuild": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.16.tgz", - "integrity": "sha512-niiWy7nesZFGCiDr0NR9/JLEhtZPYHG/ABYTqveNWvocw/gGI5rKHOj3+5yUv3yH10/geTlZiyVaNvjJWL9Xbw==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.29.tgz", + "integrity": "sha512-SQS8cO8xFEqevYlrHt6exIhK853Me4nZ4aMW6ieysInLa0FMAL+AKs87HYNRtR2YWRcEIqoXAHh+Ytt5/66qpg==", "dev": true, "requires": { - "esbuild-android-arm64": "0.14.16", - "esbuild-darwin-64": "0.14.16", - "esbuild-darwin-arm64": "0.14.16", - "esbuild-freebsd-64": "0.14.16", - "esbuild-freebsd-arm64": "0.14.16", - "esbuild-linux-32": "0.14.16", - "esbuild-linux-64": "0.14.16", - "esbuild-linux-arm": "0.14.16", - "esbuild-linux-arm64": "0.14.16", - "esbuild-linux-mips64le": "0.14.16", - "esbuild-linux-ppc64le": "0.14.16", - "esbuild-linux-s390x": "0.14.16", - "esbuild-netbsd-64": "0.14.16", - "esbuild-openbsd-64": "0.14.16", - "esbuild-sunos-64": "0.14.16", - "esbuild-windows-32": "0.14.16", - "esbuild-windows-64": "0.14.16", - "esbuild-windows-arm64": "0.14.16" + "esbuild-android-64": "0.14.29", + "esbuild-android-arm64": "0.14.29", + "esbuild-darwin-64": "0.14.29", + "esbuild-darwin-arm64": "0.14.29", + "esbuild-freebsd-64": "0.14.29", + "esbuild-freebsd-arm64": "0.14.29", + "esbuild-linux-32": "0.14.29", + "esbuild-linux-64": "0.14.29", + "esbuild-linux-arm": "0.14.29", + "esbuild-linux-arm64": "0.14.29", + "esbuild-linux-mips64le": "0.14.29", + "esbuild-linux-ppc64le": "0.14.29", + "esbuild-linux-riscv64": "0.14.29", + "esbuild-linux-s390x": "0.14.29", + "esbuild-netbsd-64": "0.14.29", + "esbuild-openbsd-64": "0.14.29", + "esbuild-sunos-64": "0.14.29", + "esbuild-windows-32": "0.14.29", + "esbuild-windows-64": "0.14.29", + "esbuild-windows-arm64": "0.14.29" } }, + "esbuild-android-64": { + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.29.tgz", + "integrity": "sha512-tJuaN33SVZyiHxRaVTo1pwW+rn3qetJX/SRuc/83rrKYtyZG0XfsQ1ao1nEudIt9w37ZSNXR236xEfm2C43sbw==", + "dev": true, + "optional": true + }, "esbuild-android-arm64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.16.tgz", - "integrity": "sha512-9qRiUXiV0qIa4Dfv+GLKsk/HHOq3U9qh8yZK9iX0awlzLPFb38NJrNTGtb/TeI6AyyZqsGgwLm/JeJ1UtEN9Aw==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.29.tgz", + "integrity": "sha512-D74dCv6yYnMTlofVy1JKiLM5JdVSQd60/rQfJSDP9qvRAI0laPXIG/IXY1RG6jobmFMUfL38PbFnCqyI/6fPXg==", "dev": true, "optional": true }, "esbuild-darwin-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.16.tgz", - "integrity": "sha512-1Xa86DpTJFRffA7go0pqUdC0ggxxGxjsrnrvA2nHBVHNf9Ix/cgGuPfxZwf3fRZxDDAT2RdqF5SRZzLYvUCtZQ==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.29.tgz", + "integrity": "sha512-+CJaRvfTkzs9t+CjGa0Oa28WoXa7EeLutQhxus+fFcu0MHhsBhlmeWHac3Cc/Sf/xPi1b2ccDFfzGYJCfV0RrA==", "dev": true, "optional": true }, "esbuild-darwin-arm64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.16.tgz", - "integrity": "sha512-a0Tp0tec/s5hYT6OiJ2zvfH/6IfXFCH406yqFfXe5u8Nfo6l6IG33L7nqCYCEPnBLF7oYfZk6Re0VDwpgK18kQ==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.29.tgz", + "integrity": "sha512-5Wgz/+zK+8X2ZW7vIbwoZ613Vfr4A8HmIs1XdzRmdC1kG0n5EG5fvKk/jUxhNlrYPx1gSY7XadQ3l4xAManPSw==", "dev": true, "optional": true }, "esbuild-freebsd-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.16.tgz", - "integrity": "sha512-FqEdOphRS5kJ8MFqQ21Y0yducmwcFHmpkceLkup1kpsGChr3PGO7DfzXmF5fECNnMxRpk/jgk7e6nV4zXTau/A==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.29.tgz", + "integrity": "sha512-VTfS7Bm9QA12JK1YXF8+WyYOfvD7WMpbArtDj6bGJ5Sy5xp01c/q70Arkn596aGcGj0TvQRplaaCIrfBG1Wdtg==", "dev": true, "optional": true }, "esbuild-freebsd-arm64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.16.tgz", - "integrity": "sha512-4Au4zR0//Df1v6FuWJEMZFRzaF69FvxHgSmKjikq7x6Ect+h4TbJKkblC3eDrfTA8L6l5bB1vhh0dbKq4zBy5Q==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.29.tgz", + "integrity": "sha512-WP5L4ejwLWWvd3Fo2J5mlXvG3zQHaw5N1KxFGnUc4+2ZFZknP0ST63i0IQhpJLgEJwnQpXv2uZlU1iWZjFqEIg==", "dev": true, "optional": true }, "esbuild-linux-32": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.16.tgz", - "integrity": "sha512-HundAiQCa0ut7PXq3lmRZY7H3/OYh27wkJ97S7jjCgWmcd5To6Bs8UBVB7I4Qi9lNk/Yty0INnqq9on1WR8JUA==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.29.tgz", + "integrity": "sha512-4myeOvFmQBWdI2U1dEBe2DCSpaZyjdQtmjUY11Zu2eQg4ynqLb8Y5mNjNU9UN063aVsCYYfbs8jbken/PjyidA==", "dev": true, "optional": true }, "esbuild-linux-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.16.tgz", - "integrity": "sha512-fG8MgVmQknIuYCHFOq+9iKLyygjPun+VkNH9ZIdRQrSzb3CFdEkNm+Suq5w8W+WjA/P0OIdrQ/mXXCoHCQTWSQ==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.29.tgz", + "integrity": "sha512-iaEuLhssReAKE7HMwxwFJFn7D/EXEs43fFy5CJeA4DGmU6JHh0qVJD2p/UP46DvUXLRKXsXw0i+kv5TdJ1w5pg==", "dev": true, "optional": true }, "esbuild-linux-arm": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.16.tgz", - "integrity": "sha512-0NDVeuvWska0d4Rd8R3+lWEyKaIbAxDuRAeeU6a2xaUXrTG2IPhGNLWc4NbVMbnkGqRqKB4PLdk/YaTUZjKFHQ==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.29.tgz", + "integrity": "sha512-OXa9D9QL1hwrAnYYAHt/cXAuSCmoSqYfTW/0CEY0LgJNyTxJKtqc5mlwjAZAvgyjmha0auS/sQ0bXfGf2wAokQ==", "dev": true, "optional": true }, "esbuild-linux-arm64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.16.tgz", - "integrity": "sha512-7WF1rHsPVXhme2B6ceZZABxFwCiZfMRIJO7yRiLahIdDkwfhSTR6M0a6OwO/NsLJH9fax5GdwBOIBoG5Hkz4gA==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.29.tgz", + "integrity": "sha512-KYf7s8wDfUy+kjKymW3twyGT14OABjGHRkm9gPJ0z4BuvqljfOOUbq9qT3JYFnZJHOgkr29atT//hcdD0Pi7Mw==", "dev": true, "optional": true }, "esbuild-linux-mips64le": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.16.tgz", - "integrity": "sha512-RLNaTRdcQ81QckeIjbk1hCrgmrL6VoZBsYT8ak9ObNQzXEJNMlxOBixaF6rhW8UUYRpTpFuoYHeNya8xY884/A==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.29.tgz", + "integrity": "sha512-05jPtWQMsZ1aMGfHOvnR5KrTvigPbU35BtuItSSWLI2sJu5VrM8Pr9Owym4wPvA4153DFcOJ1EPN/2ujcDt54g==", "dev": true, "optional": true }, "esbuild-linux-ppc64le": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.16.tgz", - "integrity": "sha512-ky0Ii2Jmyc00FzGT2audU0UmnBVrVevYmKW10DXLPcHGhbhzJdFRemXLvvzhDM8WD9IMJK3uV6ifJzkKrv8IQA==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.29.tgz", + "integrity": "sha512-FYhBqn4Ir9xG+f6B5VIQVbRuM4S6qwy29dDNYFPoxLRnwTEKToIYIUESN1qHyUmIbfO0YB4phG2JDV2JDN9Kgw==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.29.tgz", + "integrity": "sha512-eqZMqPehkb4nZcffnuOpXJQdGURGd6GXQ4ZsDHSWyIUaA+V4FpMBe+5zMPtXRD2N4BtyzVvnBko6K8IWWr36ew==", "dev": true, "optional": true }, "esbuild-linux-s390x": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.16.tgz", - "integrity": "sha512-DuW9MPGJAzUUBPI/olMkMMepCasTbPN1Xr2cKZZEEDIibcdRnuFrMYVk3G3I8/Qb6SZBNTSnZMAyhvYFrwAkqw==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.29.tgz", + "integrity": "sha512-o7EYajF1rC/4ho7kpSG3gENVx0o2SsHm7cJ5fvewWB/TEczWU7teDgusGSujxCYcMottE3zqa423VTglNTYhjg==", "dev": true, "optional": true }, "esbuild-netbsd-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.16.tgz", - "integrity": "sha512-l8+mnz8iVsV0iL5v5JCuP0UTv2LwO1ORdJ/scMkGUl8WrC6cBmUrrHhg+pwREqjbD8TxjfUJVM1Vvt5E8SaTsg==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.29.tgz", + "integrity": "sha512-/esN6tb6OBSot6+JxgeOZeBk6P8V/WdR3GKBFeFpSqhgw4wx7xWUqPrdx4XNpBVO7X4Ipw9SAqgBrWHlXfddww==", "dev": true, "optional": true }, "esbuild-openbsd-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.16.tgz", - "integrity": "sha512-8SbZNAV902FmcGnc+j86HWY8PyTD1H7T39RsPXXS5IC1psi3yzFr2d8NoOxb6cQd5XUVHmHT1naJsbtEAyKIPA==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.29.tgz", + "integrity": "sha512-jUTdDzhEKrD0pLpjmk0UxwlfNJNg/D50vdwhrVcW/D26Vg0hVbthMfb19PJMatzclbK7cmgk1Nu0eNS+abzoHw==", "dev": true, "optional": true }, "esbuild-sunos-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.16.tgz", - "integrity": "sha512-pMhe4uOaGjA/5YgeNoB0PRZi1V73D8sx876uFzuAxaZcYzLA5BsSbQeEccH182X6cBybE4Pm79kYedTSGOfwog==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.29.tgz", + "integrity": "sha512-EfhQN/XO+TBHTbkxwsxwA7EfiTHFe+MNDfxcf0nj97moCppD9JHPq48MLtOaDcuvrTYOcrMdJVeqmmeQ7doTcg==", "dev": true, "optional": true }, "esbuild-windows-32": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.16.tgz", - "integrity": "sha512-M68/EFCgji0DI+DgULx2ytUUSxwwODJDpiVc0YsiWKdyB4umKTu1GGxFfdZhXrWtPxB4aZFoIgJyDhsFxnHC4g==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.29.tgz", + "integrity": "sha512-uoyb0YAJ6uWH4PYuYjfGNjvgLlb5t6b3zIaGmpWPOjgpr1Nb3SJtQiK4YCPGhONgfg2v6DcJgSbOteuKXhwqAw==", "dev": true, "optional": true }, "esbuild-windows-64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.16.tgz", - "integrity": "sha512-rmSal1Co749CXSNyFJ62J5Fz/nZiFWhwMfYN9SwZazutKZ6s0QDRIhnupa93bJmzMzz4C2dqUV/VL1tqOI3y9g==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.29.tgz", + "integrity": "sha512-X9cW/Wl95QjsH8WUyr3NqbmfdU72jCp71cH3pwPvI4CgBM2IeOUDdbt6oIGljPu2bf5eGDIo8K3Y3vvXCCTd8A==", "dev": true, "optional": true }, "esbuild-windows-arm64": { - "version": "0.14.16", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.16.tgz", - "integrity": "sha512-VMfEf+MDgO+rulAuSeu3HNebSHa1TDn0lJp+QRk7E2WVg9OCSwuXUEkSbqIbkif3ZjASy7h9sTCGyHcqgKQTrg==", + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.29.tgz", + "integrity": "sha512-+O/PI+68fbUZPpl3eXhqGHTGK7DjLcexNnyJqtLZXOFwoAjaXlS5UBCvVcR3o2va+AqZTj8o6URaz8D2K+yfQQ==", "dev": true, "optional": true }, @@ -1996,9 +2070,9 @@ "dev": true }, "marked": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.10.tgz", - "integrity": "sha512-+QvuFj0nGgO970fySghXGmuw+Fd0gD2x3+MqCWLIPf5oxdv1Ka6b2q+z9RP01P/IaKPMEramy+7cNy/Lw8c3hw==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", + "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", "dev": true }, "merge-stream": { @@ -2141,9 +2215,9 @@ } }, "prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.1.tgz", + "integrity": "sha512-8UVbTBYGwN37Bs9LERmxCPjdvPxlEowx2urIL6urHzdb3SDq4B/Z6xLFCblrSnE4iKWcS6ziJ3aOYrc1kz/E2A==", "dev": true }, "queue-microtask": { @@ -2207,9 +2281,9 @@ "dev": true }, "shiki": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.0.tgz", - "integrity": "sha512-iczxaIYeBFHTFrQPb9DVy2SKgYxC4Wo7Iucm7C17cCh2Ge/refnvHscUOxM85u57MfLoNOtjoEFUWt9gBexblA==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", + "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", "dev": true, "requires": { "jsonc-parser": "^3.0.0", @@ -2311,16 +2385,16 @@ "dev": true }, "tsup": { - "version": "5.11.13", - "resolved": "https://registry.npmjs.org/tsup/-/tsup-5.11.13.tgz", - "integrity": "sha512-NVMK01gVmojZn7+iZwxRK1CzW2BIabaVMyEjs7Nm9lm4DrSf7IAqs2F3fg0vT7rH72x1cIBsW9U/TlWrCvHVQQ==", + "version": "5.12.2", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-5.12.2.tgz", + "integrity": "sha512-CZcM4UGYlKcdQzDIJbrwgpn4sQe8zobnHRgAF6C8RpMGvfRov9ipSQY3mjjnZRAkEZQO1+Jr3cxeaQJjY/iVTg==", "dev": true, "requires": { "bundle-require": "^3.0.2", "cac": "^6.7.12", "chokidar": "^3.5.1", "debug": "^4.3.1", - "esbuild": "^0.14.2", + "esbuild": "^0.14.25", "execa": "^5.0.0", "globby": "^11.0.3", "joycon": "^3.0.1", @@ -2333,16 +2407,36 @@ } }, "typedoc": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.12.tgz", - "integrity": "sha512-FcyC+YuaOpr3rB9QwA1IHOi9KnU2m50sPJW5vcNRPCIdecp+3bFkh7Rq5hBU1Fyn29UR2h4h/H7twZHWDhL0sw==", + "version": "0.22.13", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.13.tgz", + "integrity": "sha512-NHNI7Dr6JHa/I3+c62gdRNXBIyX7P33O9TafGLd07ur3MqzcKgwTvpg18EtvCLHJyfeSthAtCLpM7WkStUmDuQ==", "dev": true, "requires": { "glob": "^7.2.0", "lunr": "^2.3.9", - "marked": "^4.0.10", - "minimatch": "^3.0.4", - "shiki": "^0.10.0" + "marked": "^4.0.12", + "minimatch": "^5.0.1", + "shiki": "^0.10.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "typedoc-plugin-extras": { @@ -2360,15 +2454,15 @@ "requires": {} }, "typescript": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", - "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", "dev": true }, "vscode-oniguruma": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.1.tgz", - "integrity": "sha512-vc4WhSIaVpgJ0jJIejjYxPvURJavX6QG41vu0mGhqywMkQqulezEqEQ3cO3gc8GvcOpX6ycmKGqRoROEMBNXTQ==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", + "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", "dev": true }, "vscode-textmate": { diff --git a/package.json b/package.json index 0e2dc77..6f9fd26 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "play-dl", - "version": "1.9.3", + "version": "1.9.4", "description": "YouTube, SoundCloud, Spotify, Deezer searching and streaming for discord-js bots", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/play-dl/Request/useragents.json b/play-dl/Request/useragents.json index 0f7556a..0bbc642 100644 --- a/play-dl/Request/useragents.json +++ b/play-dl/Request/useragents.json @@ -1,12 +1,12 @@ [ - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 Edg/98.0.1108.50", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 Edg/98.0.1108.62", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.119 YaBrowser/22.3.0.2430 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.15.3 Chrome/87.0.4280.144 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36" ] \ No newline at end of file diff --git a/play-dl/YouTube/utils/extractor.ts b/play-dl/YouTube/utils/extractor.ts deleted file mode 100644 index 393269d..0000000 --- a/play-dl/YouTube/utils/extractor.ts +++ /dev/null @@ -1,855 +0,0 @@ -import { request } from './../../Request/index'; -import { format_decipher } from './cipher'; -import { VideoChapter, YouTubeVideo } from '../classes/Video'; -import { YouTubePlayList } from '../classes/Playlist'; -import { InfoData, StreamInfoData } from './constants'; -import { URL, URLSearchParams } from 'node:url'; -import { parseAudioFormats } from '../stream'; - -interface InfoOptions { - htmldata?: boolean; - language?: string; -} - -interface PlaylistOptions { - incomplete?: boolean; - language?: string; -} - -const video_id_pattern = /^[a-zA-Z\d_-]{11,12}$/; -const playlist_id_pattern = /^(PL|UU|LL|RD|OL)[a-zA-Z\d_-]{10,}$/; -const DEFAULT_API_KEY = 'AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8'; -const video_pattern = - /^((?:https?:)?\/\/)?(?:(?:www|m|music)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w\-]+\?v=|shorts\/|embed\/|v\/)?)([\w\-]+)(\S+)?$/; -const playlist_pattern = - /^((?:https?:)?\/\/)?(?:(?:www|m|music)\.)?((?:youtube\.com|youtu.be))\/(?:(playlist|watch))?(.*)?((\?|\&)list=)(PL|UU|LL|RD|OL)[a-zA-Z\d_-]{10,}(&.*)?$/; -/** - * Validate YouTube URL or ID. - * - * **CAUTION :** If your search word is 11 or 12 characters long, you might get it validated as video ID. - * - * To avoid above, add one more condition to yt_validate - * ```ts - * if (url.startsWith('https') && yt_validate(url) === 'video') { - * // YouTube Video Url. - * } - * ``` - * @param url YouTube URL OR ID - * @returns - * ``` - * 'playlist' | 'video' | 'search' | false - * ``` - */ -export function yt_validate(url: string): 'playlist' | 'video' | 'search' | false { - const url_ = url.trim(); - if (url_.indexOf('list=') === -1) { - if (url_.startsWith('https')) { - if (url_.match(video_pattern)) { - let id: string; - if (url_.includes('youtu.be/')) id = url_.split('youtu.be/')[1].split(/(\?|\/|&)/)[0]; - else if (url_.includes('youtube.com/embed/')) - id = url_.split('youtube.com/embed/')[1].split(/(\?|\/|&)/)[0]; - else if (url_.includes('youtube.com/shorts/')) - id = url_.split('youtube.com/shorts/')[1].split(/(\?|\/|&)/)[0]; - else id = url_.split('watch?v=')[1]?.split(/(\?|\/|&)/)[0]; - if (id?.match(video_id_pattern)) return 'video'; - else return false; - } else return false; - } else { - if (url_.match(video_id_pattern)) return 'video'; - else if (url_.match(playlist_id_pattern)) return 'playlist'; - else return 'search'; - } - } else { - if (!url_.match(playlist_pattern)) return yt_validate(url_.replace(/(\?|\&)list=[^&]+/, '')); - else return 'playlist'; - } -} -/** - * Extracts the video ID from a YouTube URL. - * - * Will return the value of `urlOrId` if it looks like a video ID. - * @param urlOrId A YouTube URL or video ID - * @returns the video ID or `false` if it can't find a video ID. - */ -function extractVideoId(urlOrId: string): string | false { - if (urlOrId.startsWith('https://') && urlOrId.match(video_pattern)) { - let id: string; - if (urlOrId.includes('youtu.be/')) { - id = urlOrId.split('youtu.be/')[1].split(/(\?|\/|&)/)[0]; - } else if (urlOrId.includes('youtube.com/embed/')) { - id = urlOrId.split('youtube.com/embed/')[1].split(/(\?|\/|&)/)[0]; - } else if (urlOrId.includes('youtube.com/shorts/')) { - id = urlOrId.split('youtube.com/shorts/')[1].split(/(\?|\/|&)/)[0]; - } else { - id = (urlOrId.split('watch?v=')[1] ?? urlOrId.split('&v=')[1]).split(/(\?|\/|&)/)[0]; - } - - if (id.match(video_id_pattern)) return id; - } else if (urlOrId.match(video_id_pattern)) { - return urlOrId; - } - - return false; -} -/** - * Extract ID of YouTube url. - * @param url ID or url of YouTube - * @returns ID of video or playlist. - */ -export function extractID(url: string): string { - const check = yt_validate(url); - if (!check || check === 'search') throw new Error('This is not a YouTube url or videoId or PlaylistID'); - const url_ = url.trim(); - if (url_.startsWith('https')) { - if (url_.indexOf('list=') === -1) { - const video_id = extractVideoId(url_); - if (!video_id) throw new Error('This is not a YouTube url or videoId or PlaylistID'); - return video_id; - } else { - return url_.split('list=')[1].split('&')[0]; - } - } else return url_; -} -/** - * Basic function to get data from a YouTube url or ID. - * - * Example - * ```ts - * const video = await play.video_basic_info('youtube video url') - * - * const res = ... // Any https package get function. - * - * const video = await play.video_basic_info(res.body, { htmldata : true }) - * ``` - * @param url YouTube url or ID or html body data - * @param options Video Info Options - * - `boolean` htmldata : given data is html data or not - * @returns Video Basic Info {@link InfoData}. - */ -export async function video_basic_info(url: string, options: InfoOptions = {}): Promise { - if (typeof url !== 'string') throw new Error('url parameter is not a URL string or a string of HTML'); - const url_ = url.trim(); - let body: string; - const cookieJar = {}; - if (options.htmldata) { - body = url_; - } else { - const video_id = extractVideoId(url_); - if (!video_id) throw new Error('This is not a YouTube Watch URL'); - const new_url = `https://www.youtube.com/watch?v=${video_id}&has_verified=1`; - body = await request(new_url, { - headers: { - 'accept-language': options.language || 'en-US;q=0.9' - }, - cookies: true, - cookieJar - }); - } - if (body.indexOf('Our systems have detected unusual traffic from your computer network.') !== -1) - throw new Error('Captcha page: YouTube has detected that you are a bot!'); - const player_data = body - .split('var ytInitialPlayerResponse = ')?.[1] - ?.split(';')[0] - .split(/;\s*(var|const|let)\s/)[0]; - if (!player_data) throw new Error('Initial Player Response Data is undefined.'); - const initial_data = body - .split('var ytInitialData = ')?.[1] - ?.split(';')[0] - .split(/;\s*(var|const|let)\s/)[0]; - if (!initial_data) throw new Error('Initial Response Data is undefined.'); - const player_response = JSON.parse(player_data); - const initial_response = JSON.parse(initial_data); - const vid = player_response.videoDetails; - - let discretionAdvised = false; - let upcoming = false; - if (player_response.playabilityStatus.status !== 'OK') { - if (player_response.playabilityStatus.status === 'CONTENT_CHECK_REQUIRED') { - if (options.htmldata) - throw new Error( - `Accepting the viewer discretion is not supported when using htmldata, video: ${vid.videoId}` - ); - discretionAdvised = true; - const cookies = - initial_response.topbar.desktopTopbarRenderer.interstitial?.consentBumpV2Renderer.agreeButton - .buttonRenderer.command.saveConsentAction; - if (cookies) { - Object.assign(cookieJar, { - VISITOR_INFO1_LIVE: cookies.visitorCookie, - CONSENT: cookies.consentCookie - }); - } - - const updatedValues = await acceptViewerDiscretion(vid.videoId, cookieJar, body, true); - player_response.streamingData = updatedValues.streamingData; - initial_response.contents.twoColumnWatchNextResults.secondaryResults = updatedValues.relatedVideos; - } else if (player_response.playabilityStatus.status === 'LIVE_STREAM_OFFLINE') upcoming = true; - else - throw new Error( - `While getting info from url\n${ - player_response.playabilityStatus.errorScreen.playerErrorMessageRenderer?.reason.simpleText ?? - player_response.playabilityStatus.errorScreen.playerKavRenderer?.reason.simpleText - }` - ); - } - const ownerInfo = - initial_response.contents.twoColumnWatchNextResults.results?.results?.contents[1]?.videoSecondaryInfoRenderer - ?.owner?.videoOwnerRenderer; - const badge = ownerInfo?.badges?.[0]?.metadataBadgeRenderer?.style?.toLowerCase(); - const html5player = `https://www.youtube.com${body.split('"jsUrl":"')[1].split('"')[0]}`; - const related: string[] = []; - initial_response.contents.twoColumnWatchNextResults.secondaryResults.secondaryResults.results.forEach( - (res: any) => { - if (res.compactVideoRenderer) - related.push(`https://www.youtube.com/watch?v=${res.compactVideoRenderer.videoId}`); - if (res.itemSectionRenderer?.contents) - res.itemSectionRenderer.contents.forEach((x: any) => { - if (x.compactVideoRenderer) - related.push(`https://www.youtube.com/watch?v=${x.compactVideoRenderer.videoId}`); - }); - } - ); - const microformat = player_response.microformat.playerMicroformatRenderer; - const musicInfo = - initial_response.contents.twoColumnWatchNextResults.results.results.contents?.[1]?.videoSecondaryInfoRenderer - ?.metadataRowContainer?.metadataRowContainerRenderer?.rows; - const music: any[] = []; - if (musicInfo) { - musicInfo.forEach((x: any) => { - if (!x.metadataRowRenderer) return; - const title = x.metadataRowRenderer.title.simpleText ?? x.metadataRowRenderer.title.runs[0].text; - let text = x.metadataRowRenderer.contents[0].simpleText ?? x.metadataRowRenderer.contents[0]?.runs?.[0]?.text; - let url = x.metadataRowRenderer.contents[0]?.runs?.[0]?.navigationEndpoint?.commandMetadata?.webCommandMetadata.url; - if (title.toLowerCase() === 'song') { - music.push({}); - music[music.length - 1].song = {text, url: url ? `https://www.youtube.com${url}` : undefined}; - } else if (music.length === 0) return; - else { - music[music.length - 1][title.toLowerCase()] = url ? {text, url: `https://www.youtube.com${url}`} : text; - } - }); - } - const rawChapters = - initial_response.playerOverlays.playerOverlayRenderer.decoratedPlayerBarRenderer.decoratedPlayerBarRenderer.playerBar?.multiMarkersPlayerBarRenderer.markersMap.find( - (m: any) => m.key === 'DESCRIPTION_CHAPTERS' - )?.value?.chapters; - const chapters: VideoChapter[] = []; - if (rawChapters) { - for (const { chapterRenderer } of rawChapters) { - chapters.push({ - title: chapterRenderer.title.simpleText, - timestamp: parseSeconds(chapterRenderer.timeRangeStartMillis / 1000), - seconds: chapterRenderer.timeRangeStartMillis / 1000, - thumbnails: chapterRenderer.thumbnail.thumbnails - }); - } - } - let upcomingDate; - if (upcoming) { - if (microformat.liveBroadcastDetails.startTimestamp) - upcomingDate = new Date(microformat.liveBroadcastDetails.startTimestamp); - else { - const timestamp = - player_response.playabilityStatus.liveStreamability.liveStreamabilityRenderer.offlineSlate - .liveStreamOfflineSlateRenderer.scheduledStartTime; - upcomingDate = new Date(parseInt(timestamp) * 1000); - } - } - const video_details = new YouTubeVideo({ - id: vid.videoId, - title: vid.title, - description: vid.shortDescription, - duration: Number(vid.lengthSeconds), - duration_raw: parseSeconds(vid.lengthSeconds), - uploadedAt: microformat.publishDate, - liveAt: microformat.liveBroadcastDetails?.startTimestamp, - upcoming: upcomingDate, - thumbnails: vid.thumbnail.thumbnails, - channel: { - name: vid.author, - id: vid.channelId, - url: `https://www.youtube.com/channel/${vid.channelId}`, - verified: Boolean(badge?.includes('verified')), - artist: Boolean(badge?.includes('artist')), - icons: ownerInfo?.thumbnail?.thumbnails || undefined - }, - views: vid.viewCount, - tags: vid.keywords, - likes: parseInt( - initial_response.contents.twoColumnWatchNextResults.results.results.contents - .find((content: any) => content.videoPrimaryInfoRenderer) - ?.videoPrimaryInfoRenderer.videoActions.menuRenderer.topLevelButtons?.find( - (button: any) => button.toggleButtonRenderer.defaultIcon.iconType === 'LIKE' - ) - ?.toggleButtonRenderer.defaultText.accessibility?.accessibilityData.label.replace(/\D+/g, '') ?? 0 - ), - live: vid.isLiveContent, - private: vid.isPrivate, - discretionAdvised, - music, - chapters - }); - let format = []; - if (!upcoming) { - format.push(...(player_response.streamingData.formats ?? [])); - format.push(...(player_response.streamingData.adaptiveFormats ?? [])); - - // get the formats for the android player for legacy videos - // fixes the stream being closed because not enough data - // arrived in time for ffmpeg to be able to extract audio data - if (parseAudioFormats(format).length === 0 && !options.htmldata) { - format = await getAndroidFormats(vid.videoId, cookieJar, body); - } - } - const LiveStreamData = { - isLive: video_details.live, - dashManifestUrl: player_response.streamingData?.dashManifestUrl ?? null, - hlsManifestUrl: player_response.streamingData?.hlsManifestUrl ?? null - }; - return { - LiveStreamData, - html5player, - format, - video_details, - related_videos: related - }; -} -/** - * Gets the data required for streaming from YouTube url, ID or html body data and deciphers it. - * - * Internal function used by {@link stream} instead of {@link video_info} - * because it only extracts the information required for streaming. - * - * @param url YouTube url or ID or html body data - * @param options Video Info Options - * - `boolean` htmldata : given data is html data or not - * @returns Deciphered Video Info {@link StreamInfoData}. - */ -export async function video_stream_info(url: string, options: InfoOptions = {}): Promise { - if (typeof url !== 'string') throw new Error('url parameter is not a URL string or a string of HTML'); - let body: string; - const cookieJar = {}; - if (options.htmldata) { - body = url; - } else { - const video_id = extractVideoId(url); - if (!video_id) throw new Error('This is not a YouTube Watch URL'); - const new_url = `https://www.youtube.com/watch?v=${video_id}&has_verified=1`; - body = await request(new_url, { - headers: { 'accept-language': 'en-US,en;q=0.9' }, - cookies: true, - cookieJar - }); - } - if (body.indexOf('Our systems have detected unusual traffic from your computer network.') !== -1) - throw new Error('Captcha page: YouTube has detected that you are a bot!'); - const player_data = body - .split('var ytInitialPlayerResponse = ')?.[1] - ?.split(';')[0] - .split(/;\s*(var|const|let)\s/)[0]; - if (!player_data) throw new Error('Initial Player Response Data is undefined.'); - const player_response = JSON.parse(player_data); - let upcoming = false; - if (player_response.playabilityStatus.status !== 'OK') { - if (player_response.playabilityStatus.status === 'CONTENT_CHECK_REQUIRED') { - if (options.htmldata) - throw new Error( - `Accepting the viewer discretion is not supported when using htmldata, video: ${player_response.videoDetails.videoId}` - ); - - const initial_data = body - .split('var ytInitialData = ')?.[1] - ?.split(';')[0] - .split(/;\s*(var|const|let)\s/)[0]; - if (!initial_data) throw new Error('Initial Response Data is undefined.'); - - const cookies = - JSON.parse(initial_data).topbar.desktopTopbarRenderer.interstitial?.consentBumpV2Renderer.agreeButton - .buttonRenderer.command.saveConsentAction; - if (cookies) { - Object.assign(cookieJar, { - VISITOR_INFO1_LIVE: cookies.visitorCookie, - CONSENT: cookies.consentCookie - }); - } - - const updatedValues = await acceptViewerDiscretion( - player_response.videoDetails.videoId, - cookieJar, - body, - false - ); - player_response.streamingData = updatedValues.streamingData; - } else if (player_response.playabilityStatus.status === 'LIVE_STREAM_OFFLINE') upcoming = true; - else - throw new Error( - `While getting info from url\n${ - player_response.playabilityStatus.errorScreen.playerErrorMessageRenderer?.reason.simpleText ?? - player_response.playabilityStatus.errorScreen.playerKavRenderer?.reason.simpleText - }` - ); - } - const html5player = `https://www.youtube.com${body.split('"jsUrl":"')[1].split('"')[0]}`; - const duration = Number(player_response.videoDetails.lengthSeconds); - const video_details = { - url: `https://www.youtube.com/watch?v=${player_response.videoDetails.videoId}`, - durationInSec: (duration < 0 ? 0 : duration) || 0 - }; - let format = []; - if (!upcoming) { - format.push(...(player_response.streamingData.formats ?? [])); - format.push(...(player_response.streamingData.adaptiveFormats ?? [])); - - // get the formats for the android player for legacy videos - // fixes the stream being closed because not enough data - // arrived in time for ffmpeg to be able to extract audio data - if (parseAudioFormats(format).length === 0 && !options.htmldata) { - format = await getAndroidFormats(player_response.videoDetails.videoId, cookieJar, body); - } - } - - const LiveStreamData = { - isLive: player_response.videoDetails.isLiveContent, - dashManifestUrl: player_response.streamingData?.dashManifestUrl ?? null, - hlsManifestUrl: player_response.streamingData?.hlsManifestUrl ?? null - }; - return await decipher_info( - { - LiveStreamData, - html5player, - format, - video_details - }, - true - ); -} -/** - * Function to convert seconds to [hour : minutes : seconds] format - * @param seconds seconds to convert - * @returns [hour : minutes : seconds] format - */ -function parseSeconds(seconds: number): string { - const d = Number(seconds); - const h = Math.floor(d / 3600); - const m = Math.floor((d % 3600) / 60); - const s = Math.floor((d % 3600) % 60); - - const hDisplay = h > 0 ? (h < 10 ? `0${h}` : h) + ':' : ''; - const mDisplay = m > 0 ? (m < 10 ? `0${m}` : m) + ':' : '00:'; - const sDisplay = s > 0 ? (s < 10 ? `0${s}` : s) : '00'; - return hDisplay + mDisplay + sDisplay; -} -/** - * Gets data from YouTube url or ID or html body data and deciphers it. - * ``` - * video_basic_info + decipher_info = video_info - * ``` - * - * Example - * ```ts - * const video = await play.video_info('youtube video url') - * - * const res = ... // Any https package get function. - * - * const video = await play.video_info(res.body, { htmldata : true }) - * ``` - * @param url YouTube url or ID or html body data - * @param options Video Info Options - * - `boolean` htmldata : given data is html data or not - * @returns Deciphered Video Info {@link InfoData}. - */ -export async function video_info(url: string, options: InfoOptions = {}): Promise { - const data = await video_basic_info(url.trim(), options); - return await decipher_info(data); -} -/** - * Function uses data from video_basic_info and deciphers it if it contains signatures. - * @param data Data - {@link InfoData} - * @param audio_only `boolean` - To decipher only audio formats only. - * @returns Deciphered Video Info {@link InfoData} - */ -export async function decipher_info( - data: T, - audio_only: boolean = false -): Promise { - if ( - data.LiveStreamData.isLive === true && - data.LiveStreamData.dashManifestUrl !== null && - data.video_details.durationInSec === 0 - ) { - return data; - } else if (data.format.length > 0 && (data.format[0].signatureCipher || data.format[0].cipher)) { - if (audio_only) data.format = parseAudioFormats(data.format); - data.format = await format_decipher(data.format, data.html5player); - return data; - } else return data; -} -/** - * Gets YouTube playlist info from a playlist url. - * - * Example - * ```ts - * const playlist = await play.playlist_info('youtube playlist url') - * - * const playlist = await play.playlist_info('youtube playlist url', { incomplete : true }) - * ``` - * @param url Playlist URL - * @param options Playlist Info Options - * - `boolean` incomplete : When this is set to `false` (default) this function will throw an error - * if the playlist contains hidden videos. - * If it is set to `true`, it parses the playlist skipping the hidden videos, - * only visible videos are included in the resulting {@link YouTubePlaylist}. - * - * @returns YouTube Playlist - */ -export async function playlist_info(url: string, options: PlaylistOptions = {}): Promise { - if (!url || typeof url !== 'string') throw new Error(`Expected playlist url, received ${typeof url}!`); - let url_ = url.trim(); - if (!url_.startsWith('https')) url_ = `https://www.youtube.com/playlist?list=${url_}`; - if (url_.indexOf('list=') === -1) throw new Error('This is not a Playlist URL'); - - if (url_.includes('music.youtube.com')) { - const urlObj = new URL(url_); - urlObj.hostname = 'www.youtube.com'; - url_ = urlObj.toString(); - } - - const body = await request(url_, { - headers: { - 'accept-language': options.language || 'en-US;q=0.9' - } - }); - if (body.indexOf('Our systems have detected unusual traffic from your computer network.') !== -1) - throw new Error('Captcha page: YouTube has detected that you are a bot!'); - const response = JSON.parse( - body - .split('var ytInitialData = ')[1] - .split(';')[0] - .split(/;\s*(var|const|let)\s/)[0] - ); - if (response.alerts) { - if (response.alerts[0].alertWithButtonRenderer?.type === 'INFO') { - if (!options.incomplete) - throw new Error( - `While parsing playlist url\n${response.alerts[0].alertWithButtonRenderer.text.simpleText}` - ); - } else if (response.alerts[0].alertRenderer?.type === 'ERROR') - throw new Error(`While parsing playlist url\n${response.alerts[0].alertRenderer.text.runs[0].text}`); - else throw new Error('While parsing playlist url\nUnknown Playlist Error'); - } - if (url_.indexOf('watch?v=') !== -1) { - return getWatchPlaylist(response, body, url_); - } else return getNormalPlaylist(response, body); -} -/** - * Function to parse Playlist from YouTube search - * @param data html data of that request - * @param limit No. of videos to parse - * @returns Array of YouTubeVideo. - */ -export function getPlaylistVideos(data: any, limit = Infinity): YouTubeVideo[] { - const videos = []; - - for (let i = 0; i < data.length; i++) { - if (limit === videos.length) break; - const info = data[i].playlistVideoRenderer; - if (!info || !info.shortBylineText) continue; - - videos.push( - new YouTubeVideo({ - id: info.videoId, - duration: parseInt(info.lengthSeconds) || 0, - duration_raw: info.lengthText?.simpleText ?? '0:00', - thumbnails: info.thumbnail.thumbnails, - title: info.title.runs[0].text, - upcoming: info.upcomingEventData?.startTime - ? new Date(parseInt(info.upcomingEventData.startTime) * 1000) - : undefined, - channel: { - id: info.shortBylineText.runs[0].navigationEndpoint.browseEndpoint.browseId || undefined, - name: info.shortBylineText.runs[0].text || undefined, - url: `https://www.youtube.com${ - info.shortBylineText.runs[0].navigationEndpoint.browseEndpoint.canonicalBaseUrl || - info.shortBylineText.runs[0].navigationEndpoint.commandMetadata.webCommandMetadata.url - }`, - icon: undefined - } - }) - ); - } - return videos; -} -/** - * Function to get Continuation Token - * @param data html data of playlist url - * @returns token - */ -export function getContinuationToken(data: any): string { - return data.find((x: any) => Object.keys(x)[0] === 'continuationItemRenderer')?.continuationItemRenderer - .continuationEndpoint?.continuationCommand?.token; -} - -async function acceptViewerDiscretion( - videoId: string, - cookieJar: { [key: string]: string }, - body: string, - extractRelated: boolean -): Promise<{ streamingData: any; relatedVideos?: any }> { - const apiKey = - body.split('INNERTUBE_API_KEY":"')[1]?.split('"')[0] ?? - body.split('innertubeApiKey":"')[1]?.split('"')[0] ?? - DEFAULT_API_KEY; - const sessionToken = - body.split('"XSRF_TOKEN":"')[1]?.split('"')[0].replaceAll('\\u003d', '=') ?? - body.split('"xsrf_token":"')[1]?.split('"')[0].replaceAll('\\u003d', '='); - if (!sessionToken) - throw new Error(`Unable to extract XSRF_TOKEN to accept the viewer discretion popup for video: ${videoId}.`); - - const verificationResponse = await request(`https://www.youtube.com/youtubei/v1/verify_age?key=${apiKey}`, { - method: 'POST', - body: JSON.stringify({ - context: { - client: { - utcOffsetMinutes: 0, - gl: 'US', - hl: 'en', - clientName: 'WEB', - clientVersion: - body.split('"INNERTUBE_CONTEXT_CLIENT_VERSION":"')[1]?.split('"')[0] ?? - body.split('"innertube_context_client_version":"')[1]?.split('"')[0] ?? - '' - }, - user: {}, - request: {} - }, - nextEndpoint: { - urlEndpoint: { - url: `watch?v=${videoId}` - } - }, - setControvercy: true - }), - cookies: true, - cookieJar - }); - - const endpoint = JSON.parse(verificationResponse).actions[0].navigateAction.endpoint; - - const videoPage = await request(`https://www.youtube.com/${endpoint.urlEndpoint.url}&pbj=1`, { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded' - }, - body: new URLSearchParams([ - ['command', JSON.stringify(endpoint)], - ['session_token', sessionToken] - ]).toString(), - cookies: true, - cookieJar - }); - - if (videoPage.includes('

Something went wrong

')) - throw new Error(`Unable to accept the viewer discretion popup for video: ${videoId}`); - - const videoPageData = JSON.parse(videoPage); - - if (videoPageData[2].playerResponse.playabilityStatus.status !== 'OK') - throw new Error( - `While getting info from url after trying to accept the discretion popup for video ${videoId}\n${ - videoPageData[2].playerResponse.playabilityStatus.errorScreen.playerErrorMessageRenderer?.reason - .simpleText ?? - videoPageData[2].playerResponse.playabilityStatus.errorScreen.playerKavRenderer?.reason.simpleText - }` - ); - - const streamingData = videoPageData[2].playerResponse.streamingData; - - if (extractRelated) - return { - streamingData, - relatedVideos: videoPageData[3].response.contents.twoColumnWatchNextResults.secondaryResults - }; - - return { streamingData }; -} - -async function getAndroidFormats(videoId: string, cookieJar: { [key: string]: string }, body: string): Promise { - const apiKey = - body.split('INNERTUBE_API_KEY":"')[1]?.split('"')[0] ?? - body.split('innertubeApiKey":"')[1]?.split('"')[0] ?? - DEFAULT_API_KEY; - - const response = await request(`https://www.youtube.com/youtubei/v1/player?key=${apiKey}`, { - method: 'POST', - body: JSON.stringify({ - context: { - client: { - clientName: 'ANDROID', - clientVersion: '16.49', - hl: 'en', - timeZone: 'UTC', - utcOffsetMinutes: 0 - } - }, - videoId: videoId, - playbackContext: { contentPlaybackContext: { html5Preference: 'HTML5_PREF_WANTS' } }, - contentCheckOk: true, - racyCheckOk: true - }), - cookies: true, - cookieJar - }); - - return JSON.parse(response).streamingData.formats; -} - -function getWatchPlaylist(response: any, body: any, url: string): YouTubePlayList { - const playlist_details = response.contents.twoColumnWatchNextResults.playlist.playlist; - - const videos = getWatchPlaylistVideos(playlist_details.contents); - const API_KEY = - body.split('INNERTUBE_API_KEY":"')[1]?.split('"')[0] ?? - body.split('innertubeApiKey":"')[1]?.split('"')[0] ?? - DEFAULT_API_KEY; - - const videoCount = playlist_details.totalVideos; - const channel = playlist_details.shortBylineText?.runs?.[0]; - const badge = playlist_details.badges?.[0]?.metadataBadgeRenderer?.style.toLowerCase(); - - return new YouTubePlayList({ - continuation: { - api: API_KEY, - token: getContinuationToken(playlist_details.contents), - clientVersion: - body.split('"INNERTUBE_CONTEXT_CLIENT_VERSION":"')[1]?.split('"')[0] ?? - body.split('"innertube_context_client_version":"')[1]?.split('"')[0] ?? - '' - }, - id: playlist_details.playlistId || '', - title: playlist_details.title || '', - videoCount: parseInt(videoCount) || 0, - videos: videos, - url: url, - channel: { - id: channel?.navigationEndpoint?.browseEndpoint?.browseId || null, - name: channel?.text || null, - url: `https://www.youtube.com${ - channel?.navigationEndpoint?.browseEndpoint?.canonicalBaseUrl || - channel?.navigationEndpoint?.commandMetadata?.webCommandMetadata?.url - }`, - verified: Boolean(badge?.includes('verified')), - artist: Boolean(badge?.includes('artist')) - } - }); -} - -function getNormalPlaylist(response: any, body: any): YouTubePlayList { - const json_data = - response.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content.sectionListRenderer.contents[0] - .itemSectionRenderer.contents[0].playlistVideoListRenderer.contents; - const playlist_details = response.sidebar.playlistSidebarRenderer.items; - - const API_KEY = - body.split('INNERTUBE_API_KEY":"')[1]?.split('"')[0] ?? - body.split('innertubeApiKey":"')[1]?.split('"')[0] ?? - DEFAULT_API_KEY; - const videos = getPlaylistVideos(json_data, 100); - - const data = playlist_details[0].playlistSidebarPrimaryInfoRenderer; - if (!data.title.runs || !data.title.runs.length) throw new Error('Failed to Parse Playlist info.'); - - const author = playlist_details[1]?.playlistSidebarSecondaryInfoRenderer.videoOwner; - const views = data.stats.length === 3 ? data.stats[1].simpleText.replace(/\D/g, '') : 0; - const lastUpdate = - data.stats - .find((x: any) => 'runs' in x && x['runs'].find((y: any) => y.text.toLowerCase().includes('last update'))) - ?.runs.pop()?.text ?? null; - const videosCount = data.stats[0].runs[0].text.replace(/\D/g, '') || 0; - - const res = new YouTubePlayList({ - continuation: { - api: API_KEY, - token: getContinuationToken(json_data), - clientVersion: - body.split('"INNERTUBE_CONTEXT_CLIENT_VERSION":"')[1]?.split('"')[0] ?? - body.split('"innertube_context_client_version":"')[1]?.split('"')[0] ?? - '' - }, - id: data.title.runs[0].navigationEndpoint.watchEndpoint.playlistId, - title: data.title.runs[0].text, - videoCount: parseInt(videosCount) || 0, - lastUpdate: lastUpdate, - views: parseInt(views) || 0, - videos: videos, - url: `https://www.youtube.com/playlist?list=${data.title.runs[0].navigationEndpoint.watchEndpoint.playlistId}`, - link: `https://www.youtube.com${data.title.runs[0].navigationEndpoint.commandMetadata.webCommandMetadata.url}`, - channel: author - ? { - name: author.videoOwnerRenderer.title.runs[0].text, - id: author.videoOwnerRenderer.title.runs[0].navigationEndpoint.browseEndpoint.browseId, - url: `https://www.youtube.com${ - author.videoOwnerRenderer.navigationEndpoint.commandMetadata.webCommandMetadata.url || - author.videoOwnerRenderer.navigationEndpoint.browseEndpoint.canonicalBaseUrl - }`, - icons: author.videoOwnerRenderer.thumbnail.thumbnails ?? [] - } - : {}, - thumbnail: data.thumbnailRenderer.playlistVideoThumbnailRenderer?.thumbnail.thumbnails.length - ? data.thumbnailRenderer.playlistVideoThumbnailRenderer.thumbnail.thumbnails[ - data.thumbnailRenderer.playlistVideoThumbnailRenderer.thumbnail.thumbnails.length - 1 - ] - : null - }); - return res; -} - -function getWatchPlaylistVideos(data: any, limit = Infinity): YouTubeVideo[] { - const videos: YouTubeVideo[] = []; - - for (let i = 0; i < data.length; i++) { - if (limit === videos.length) break; - const info = data[i].playlistPanelVideoRenderer; - if (!info || !info.shortBylineText) continue; - const channel_info = info.shortBylineText.runs[0]; - - videos.push( - new YouTubeVideo({ - id: info.videoId, - duration: parseDuration(info.lengthText?.simpleText) || 0, - duration_raw: info.lengthText?.simpleText ?? '0:00', - thumbnails: info.thumbnail.thumbnails, - title: info.title.simpleText, - upcoming: - info.thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer.style === 'UPCOMING' || undefined, - channel: { - id: channel_info.navigationEndpoint.browseEndpoint.browseId || undefined, - name: channel_info.text || undefined, - url: `https://www.youtube.com${ - channel_info.navigationEndpoint.browseEndpoint.canonicalBaseUrl || - channel_info.navigationEndpoint.commandMetadata.webCommandMetadata.url - }`, - icon: undefined - } - }) - ); - } - - return videos; -} - -function parseDuration(text: string): number { - if (!text) return 0; - const split = text.split(':'); - - switch (split.length) { - case 2: - return parseInt(split[0]) * 60 + parseInt(split[1]); - - case 3: - return parseInt(split[0]) * 60 * 60 + parseInt(split[1]) * 60 + parseInt(split[2]); - - default: - return 0; - } -}