From 3c41414f4a82f13babe4eedf5d4f4b4aae4a83ee Mon Sep 17 00:00:00 2001 From: AnimeDL Date: Sat, 16 Mar 2024 11:14:21 -0700 Subject: [PATCH] Rename WV module --- crunchy.ts | 2 +- modules/cr_widevine.ts | 47 -------------------------- modules/widevine.ts | 77 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 48 deletions(-) delete mode 100644 modules/cr_widevine.ts create mode 100644 modules/widevine.ts diff --git a/crunchy.ts b/crunchy.ts index b848bff..d6ea96f 100644 --- a/crunchy.ts +++ b/crunchy.ts @@ -18,7 +18,7 @@ import * as langsData from './modules/module.langsData'; import * as yamlCfg from './modules/module.cfg-loader'; import * as yargs from './modules/module.app-args'; import Merger, { Font, MergerInput, SubtitleInput } from './modules/module.merger'; -import getKeys, { canDecrypt } from './modules/cr_widevine'; +import getKeys, { canDecrypt } from './modules/widevine'; //import vttConvert from './modules/module.vttconvert'; // args diff --git a/modules/cr_widevine.ts b/modules/cr_widevine.ts deleted file mode 100644 index 5f54f01..0000000 --- a/modules/cr_widevine.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { KeyContainer, Session } from './license'; -import fs from 'fs'; -import { console } from './log'; -import got from 'got'; -import { workingDir } from './module.cfg-loader'; -import path from 'path'; - -//read cdm files located in the same directory -let privateKey: Buffer, identifierBlob: Buffer; -export let canDecrypt: boolean; -try { - privateKey = fs.readFileSync(path.join(workingDir, 'widevine', 'device_private_key')); - identifierBlob = fs.readFileSync(path.join(workingDir, 'widevine', 'device_client_id_blob')); - canDecrypt = true; -} catch (e) { - canDecrypt = false; -} - -export default async function getKeys(pssh: string | undefined, licenseServer: string, authData: Record): Promise { - if (!pssh || !canDecrypt) return []; - //pssh found in the mpd manifest - const psshBuffer = Buffer.from( - pssh, - 'base64' - ); - - //Create a new widevine session - const session = new Session({ privateKey, identifierBlob }, psshBuffer); - - //Generate license - const response = await got(licenseServer, { - method: 'POST', - body: session.createLicenseRequest(), - headers: authData, - responseType: 'text' - }); - - if (response.statusCode === 200) { - //Parse License and return keys - const json = JSON.parse(response.body); - const keys = session.parseLicense(Buffer.from(json['license'], 'base64')); - return keys; - } else { - console.info('License request failed:', response.statusMessage); - return []; - } -} diff --git a/modules/widevine.ts b/modules/widevine.ts new file mode 100644 index 0000000..3d7c88d --- /dev/null +++ b/modules/widevine.ts @@ -0,0 +1,77 @@ +import { KeyContainer, Session } from './license'; +import fs from 'fs'; +import { console } from './log'; +import got from 'got'; +import { workingDir } from './module.cfg-loader'; +import path from 'path'; +import { ReadError, Response } from 'got'; + +//read cdm files located in the same directory +let privateKey: Buffer, identifierBlob: Buffer; +export let canDecrypt: boolean; +try { + privateKey = fs.readFileSync(path.join(workingDir, 'widevine', 'device_private_key')); + identifierBlob = fs.readFileSync(path.join(workingDir, 'widevine', 'device_client_id_blob')); + canDecrypt = true; +} catch (e) { + canDecrypt = false; +} + +export default async function getKeys(pssh: string | undefined, licenseServer: string, authData: Record): Promise { + if (!pssh || !canDecrypt) return []; + //pssh found in the mpd manifest + const psshBuffer = Buffer.from( + pssh, + 'base64' + ); + + //Create a new widevine session + const session = new Session({ privateKey, identifierBlob }, psshBuffer); + + //Generate license + let response; + try { + response = await got(licenseServer, { + method: 'POST', + body: session.createLicenseRequest(), + headers: authData, + responseType: 'text' + }); + } catch(_error){ + const error = _error as { + name: string + } & ReadError & { + res: Response + }; + if(error.response && error.response.statusCode && error.response.statusMessage){ + console.error(`${error.name} ${error.response.statusCode}: ${error.response.statusMessage}`); + } else{ + console.error(`${error.name}: ${error.code || error.message}`); + } + if(error.response && !error.res){ + error.res = error.response; + const docTitle = (error.res.body as string).match(/(.*)<\/title>/); + if(error.res.body && docTitle){ + console.error(docTitle[1]); + } + } + if(error.res && error.res.body && error.response.statusCode + && error.response.statusCode != 404 && error.response.statusCode != 403){ + console.error('Body:', error.res.body); + } + return []; + } + + if (response.statusCode === 200) { + //Parse License and return keys + try { + const json = JSON.parse(response.body); + return session.parseLicense(Buffer.from(json['license'], 'base64')); + } catch { + return session.parseLicense(response.rawBody); + } + } else { + console.info('License request failed:', response.statusMessage, response.body); + return []; + } +}