From eb3ef848001d5b9b50d16a044f472e94f4180c04 Mon Sep 17 00:00:00 2001 From: reidlab Date: Tue, 13 May 2025 01:33:30 -0700 Subject: [PATCH] downgrade `node-widevine`--fixes flake --- README.md | 6 +- flake.nix | 14 ++- package-lock.json | 232 +++------------------------------------ package.json | 2 +- src/config.ts | 2 +- src/downloader/keygen.ts | 6 +- src/log.ts | 12 +- 7 files changed, 44 insertions(+), 230 deletions(-) diff --git a/README.md b/README.md index 5b44355..f835712 100644 --- a/README.md +++ b/README.md @@ -16,13 +16,15 @@ a self-hostable web-ui apple music downloader widevine decryptor with questionab ### config -most of the config is talked on in [`config.example.toml`](./config.example.toml), just copy it over to `config.toml` and go wild! i tried to make the error reporting for invalid configurations pretty good and digestable +most of the config is talked on in [`config.example.toml`](./config.example.toml), just copy it over to `config.toml` and go wild! if you don't it will automatically be copied over on your first run. i tried to make the error reporting for invalid configurations pretty good and digestable + +one caveat--if using the nix package, it will NOT be automatically copied over due to not being embedded in the program itself, and rather it copying over a file from the pwd (which obviously won't work if you're not in it) ### running just as easy as running `npm run build` and running the `dist/index.js` file with your javascript engine of choice -alternatively, use the nix flake, which is currently broken due to an issue outside of my control (i can fix this by publishing a fork of `node-widevine` to the npm registry, but oh well, i'll do that eventually) +alternatively, use the nix flake, which has the proper `mainProgram` and default package attributes to make it easy. a nixos module is on its way!! don't fret ## limitations / the formats diff --git a/flake.nix b/flake.nix index 88f19fa..adcc9b7 100644 --- a/flake.nix +++ b/flake.nix @@ -23,14 +23,24 @@ # uncomment this and let the build fail, then get the current hash # very scuffed but endorsed! # npmDepsHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; - npmDepsHash = "sha256-f+RacjhkJP3RlK+yKJ8Xm0Rar4NyIxJjNQYDrpqhnD4="; + npmDepsHash = "sha256-MYrYRrPFSQHiKQMPafDmWvlcT/rpEmB4S2CXfLIk6Bg="; + + nativeBuildInputs = with pkgs; [ makeWrapper ]; installPhase = '' + runHook preInstall + mkdir -p $out - mv ./dist/* $out/ + mv node_modules dist $out/ + makeWrapper ${pkgs.nodejs-slim}/bin/node $out/bin/amdl \ + --add-flags "$out/dist/index.js" + + runHook postInstall ''; src = ./.; + + meta.mainProgram = package.name; }; }; diff --git a/package-lock.json b/package-lock.json index 6559ce5..012fac7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "express-handlebars": "^8.0.1", "format-duration": "^3.0.2", "git-rev-sync": "^3.0.2", - "node-widevine": "https://github.com/wangziyingwen/node-widevine", + "node-widevine": "^0.1.3", "parse-hls": "^1.0.7", "pssh-tools": "^1.2.0", "source-map-support": "^0.5.21", @@ -38,196 +38,6 @@ "typescript-eslint": "^7.13.0" } }, - "node_modules/@bufbuild/buf": { - "version": "1.52.1", - "resolved": "https://registry.npmjs.org/@bufbuild/buf/-/buf-1.52.1.tgz", - "integrity": "sha512-Sflcgagb/9gu3ShUF7jjJmYgMxut+YRNajPtTk20cUq5MIG8cCZeVfA6s6kDj2TG5QuAf49u5akTHPa5ZENr0A==", - "hasInstallScript": true, - "license": "Apache-2.0", - "bin": { - "buf": "bin/buf", - "protoc-gen-buf-breaking": "bin/protoc-gen-buf-breaking", - "protoc-gen-buf-lint": "bin/protoc-gen-buf-lint" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@bufbuild/buf-darwin-arm64": "1.52.1", - "@bufbuild/buf-darwin-x64": "1.52.1", - "@bufbuild/buf-linux-aarch64": "1.52.1", - "@bufbuild/buf-linux-armv7": "1.52.1", - "@bufbuild/buf-linux-x64": "1.52.1", - "@bufbuild/buf-win32-arm64": "1.52.1", - "@bufbuild/buf-win32-x64": "1.52.1" - } - }, - "node_modules/@bufbuild/buf-darwin-arm64": { - "version": "1.52.1", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-arm64/-/buf-darwin-arm64-1.52.1.tgz", - "integrity": "sha512-c2iCRSvhrQVCe91xQNKhwy4ES3AN0kWP1oXnCe+bzReOrBsLef9gVoxKbDv5Ywkv+epfqhuAVbltpN37P4s9mQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@bufbuild/buf-darwin-x64": { - "version": "1.52.1", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-x64/-/buf-darwin-x64-1.52.1.tgz", - "integrity": "sha512-2v742rgJBCe8E1H/u8ObUH4oeev5jCMP9TKPRy3iQZBFB2lXXgvKQCmSP2Du6Sc7bC3L4QxSbLfhJRobdjUR3Q==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@bufbuild/buf-linux-aarch64": { - "version": "1.52.1", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-aarch64/-/buf-linux-aarch64-1.52.1.tgz", - "integrity": "sha512-bnfDsmsnPlgNBueTzIemBuL4WxcASR7T+RIeTjur+VILN7kN6Pd8gUiNIQbZSvKwRdKGDRJXCfn404w+5Djo5A==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@bufbuild/buf-linux-armv7": { - "version": "1.52.1", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-armv7/-/buf-linux-armv7-1.52.1.tgz", - "integrity": "sha512-+BvlP9FZu83dOoy2+fIw9/CuTq3TwDUXqfMU14b0CRDlx6eJsTbFMsYyNCQYdp9yJsLy3keEHKlBQkYdfd1wpQ==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@bufbuild/buf-linux-x64": { - "version": "1.52.1", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-x64/-/buf-linux-x64-1.52.1.tgz", - "integrity": "sha512-MIf62fmcV1FbBzojPfQAuE1BRspkgc6w5SDYdgimd85a9FYOrpUTkt31ZPjEz/swOuneGcDecayYtt6jWEcMGA==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@bufbuild/buf-win32-arm64": { - "version": "1.52.1", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-arm64/-/buf-win32-arm64-1.52.1.tgz", - "integrity": "sha512-QCKsJlgiEeY8bUipVO2WDQHHrSkmWUU7DAqZrw/ndHNCwg+//jhuwLYEbpbRiA1qG4Va6WzosR5/3VgOetyLuw==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@bufbuild/buf-win32-x64": { - "version": "1.52.1", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-x64/-/buf-win32-x64-1.52.1.tgz", - "integrity": "sha512-VzoN16/MbZ/ozLjFp5JKhSAhs9iOEPrp0hbCpO56o/0HXFQ96KNgNEP9vYD/E90DNHWW5sgoFk74zdJLXG8wXw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@bufbuild/protobuf": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.2.0.tgz", - "integrity": "sha512-+imAQkHf7U/Rwvu0wk1XWgsP3WnpCWmK7B48f0XqSNzgk64+grljTKC7pnO/xBiEMUziF7vKRfbBnOQhg126qQ==", - "license": "(Apache-2.0 AND BSD-3-Clause)" - }, - "node_modules/@bufbuild/protoc-gen-es": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@bufbuild/protoc-gen-es/-/protoc-gen-es-2.2.0.tgz", - "integrity": "sha512-PmUTtbJJfgcabTsoF59W0bsAr7xO5aGcMe69G8vOq0ogYV1aWmvFKhHKHDtn295pOLhTXmfrDSUNi/OTHuDdpw==", - "license": "Apache-2.0", - "dependencies": { - "@bufbuild/protobuf": "^2.2.0", - "@bufbuild/protoplugin": "2.2.0" - }, - "bin": { - "protoc-gen-es": "bin/protoc-gen-es" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@bufbuild/protobuf": "2.2.0" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - } - }, - "node_modules/@bufbuild/protoplugin": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@bufbuild/protoplugin/-/protoplugin-2.2.0.tgz", - "integrity": "sha512-ijsCHuhtXbfTiffoBRve2uCPR7gy6cwJsMe8z5bYQtczGiZVVfiyAze55gk1J/1ruqkr40oZ9BwKAGOzz69f0g==", - "license": "Apache-2.0", - "dependencies": { - "@bufbuild/protobuf": "2.2.0", - "@typescript/vfs": "^1.5.2", - "typescript": "5.4.5" - } - }, - "node_modules/@bufbuild/protoplugin/node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", @@ -892,18 +702,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript/vfs": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.1.tgz", - "integrity": "sha512-JwoxboBh7Oz1v38tPbkrZ62ZXNHAk9bJ7c9x0eI5zBfBnBYGhURdbnh7Z4smN/MV48Y5OCcZb58n972UtbazsA==", - "license": "MIT", - "dependencies": { - "debug": "^4.1.1" - }, - "peerDependencies": { - "typescript": "*" - } - }, "node_modules/@ungap/structured-clone": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", @@ -1364,6 +1162,7 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2820,24 +2619,20 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "license": "MIT" }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } - }, "node_modules/node-widevine": { - "version": "0.3.1", - "resolved": "git+ssh://git@github.com/wangziyingwen/node-widevine.git#191b52f055f4c1822673e3a820cd2c43e7574c73", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/node-widevine/-/node-widevine-0.1.3.tgz", + "integrity": "sha512-sDltJNqvMbdlYOWIumnWY7+P9Vxn3DwRkE/lepgtLL7J3mUkdao9cIgs0ZF4xoeUUs4HY3mjga2sm4y3i1afcw==", "license": "GPL-3.0-or-later", "dependencies": { - "@bufbuild/buf": "^1.35.1", - "@bufbuild/protobuf": "2.2.0", - "@bufbuild/protoc-gen-es": "2.2.0", - "node-forge": "^1.3.1" + "long": "^5.2.1", + "protobufjs": "^7.1.2" + }, + "engines": { + "node": "*", + "npm": "^8.x.x", + "pnpm": "8.x.x", + "vscode": "^1.22.0" } }, "node_modules/object-inspect": { @@ -3778,6 +3573,7 @@ "version": "5.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", diff --git a/package.json b/package.json index fae0824..9c957a0 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "express-handlebars": "^8.0.1", "format-duration": "^3.0.2", "git-rev-sync": "^3.0.2", - "node-widevine": "https://github.com/wangziyingwen/node-widevine", + "node-widevine": "^0.1.3", "parse-hls": "^1.0.7", "pssh-tools": "^1.2.0", "source-map-support": "^0.5.21", diff --git a/src/config.ts b/src/config.ts index e8c90b7..1645e16 100644 --- a/src/config.ts +++ b/src/config.ts @@ -41,7 +41,7 @@ const envSchema = z.object({ export let defaultConfig = false; if (!fs.existsSync("config.toml")) { if (!fs.existsSync("config.example.toml")) { - log.error("config.toml AND config.example.toml not found?? stop this tomfoolery at once"); + log.error("no available config file!"); process.exit(1); } log.warn("config.toml not found, copying over config.example.toml"); diff --git a/src/downloader/keygen.ts b/src/downloader/keygen.ts index d9fb914..5756d2a 100644 --- a/src/downloader/keygen.ts +++ b/src/downloader/keygen.ts @@ -1,4 +1,4 @@ -import { LicenseType, Session } from "node-widevine"; +import { Session } from "node-widevine"; import { env } from "../config.js"; import { appleMusicApi } from "../appleMusicApi/index.js"; import { dataUriToBuffer } from "data-uri-to-buffer"; @@ -14,7 +14,7 @@ export async function getWidevineDecryptionKey(psshDataUri: string, trackId: str let challenge: Buffer; try { - challenge = session.createLicenseRequest(LicenseType.STREAMING); + challenge = session.createLicenseRequest(); } catch (err) { // for some reason, if gotten from a webplayback manifest, the pssh is in a completely different format // well, somewhat. it's just the raw data, we have to rebuild the pssh @@ -29,7 +29,7 @@ export async function getWidevineDecryptionKey(psshDataUri: string, trackId: str pssh = Buffer.from(rebuiltPssh, "base64"); session = new Session({ privateKey, identifierBlob }, pssh); - challenge = session.createLicenseRequest(LicenseType.STREAMING); + challenge = session.createLicenseRequest(); } const response = await appleMusicApi.getWidevineLicense( diff --git a/src/log.ts b/src/log.ts index 616c996..3f557db 100644 --- a/src/log.ts +++ b/src/log.ts @@ -37,7 +37,7 @@ function timePrefix(): string { } function stackPrefix(): string { // little tidbit: this does not work on *some* engines (v8 stack format) - // i think bun will work, i think deno will not + // i think bun will work, i think deno will not?? const frame = sourceMapSupport.wrapCallSite(callsites()[3] as sourceMapSupport.CallSite); const file = frame.getFileName(); @@ -46,9 +46,15 @@ function stackPrefix(): string { if (file === null || line === null || column === null) { return chalk.gray("unknown caller!"); } - const filePatched = `${path.relative(process.cwd(), fileURLToPath(file))}`; + // TODO: optimize this -- probably not very great currently + const relative = path.relative(process.cwd(), fileURLToPath(file)); + const parts = relative.split(path.sep); + const srcIndex = parts.indexOf("src"); + const formatted = srcIndex !== -1 + ? path.join(...parts.slice(srcIndex)) + : relative; - return chalk.gray(`${filePatched}:${line}:${column}`); + return chalk.gray(`${formatted}:${line}:${column}`); } function levelPrefix(level: Level): string { const highestLevelLength = Math.max(...Object.values(levelNames).map(n => n.length));