From f38dbf197e6d28e7be4874456b8850befb9fb7e7 Mon Sep 17 00:00:00 2001 From: AnimeDL Date: Tue, 18 Jun 2024 21:29:45 -0700 Subject: [PATCH] [CR] Add crunchy play streams selector --- @types/crunchyTypes.d.ts | 3 +- crunchy.ts | 62 +++++++++++++++++++++++++------------- modules/module.app-args.ts | 4 ++- modules/module.args.ts | 15 +++++++++ package.json | 2 +- 5 files changed, 62 insertions(+), 24 deletions(-) diff --git a/@types/crunchyTypes.d.ts b/@types/crunchyTypes.d.ts index 9110c90..6be23a1 100644 --- a/@types/crunchyTypes.d.ts +++ b/@types/crunchyTypes.d.ts @@ -1,11 +1,12 @@ import { HLSCallback } from 'hls-download'; -import { sxItem } from '../crunchy'; +import { CrunchyPlayStreams, sxItem } from '../crunchy'; import { LanguageItem } from '../modules/module.langsData'; import { DownloadInfo } from './messageHandler'; export type CrunchyDownloadOptions = { hslang: string, kstream: number, + cpstream: keyof typeof CrunchyPlayStreams | 'none', novids?: boolean, noaudio?: boolean, x: number, diff --git a/crunchy.ts b/crunchy.ts index 0af1aec..9a4082f 100644 --- a/crunchy.ts +++ b/crunchy.ts @@ -53,6 +53,23 @@ export type sxItem = { fonts: Font[] } +export enum CrunchyPlayStreams { + 'chrome' = 'web/chrome', + 'firefox' = 'web/firefox', + 'safari' = 'web/safari', + 'edge' = 'web/edge', + 'fallback' = 'web/fallback', + 'ps4' = 'console/ps4', + 'ps5' = 'console/ps5', + 'switch' = 'console/switch', + 'samsungtv' = 'tv/samsung', + 'lgtv' = 'tv/lg', + 'rokutv' = 'tv/roku', + 'android' = 'android/phone', + 'iphone' = 'ios/iphone', + 'ipad' = 'ios/ipad', +} + export default class Crunchy implements ServiceClass { public cfg: yamlCfg.ConfigObject; public api: 'android' | 'web'; @@ -1414,27 +1431,30 @@ export default class Crunchy implements ServiceClass { pbData = await playbackReq.res.json() as PlaybackData; } - let switchStream: CrunchyPlayStream | null = null; - const playbackReq = await this.req.getData(`https://cr-play-service.prd.crunchyrollsvc.com/v1/${currentVersion ? currentVersion.guid : currentMediaId}/console/switch/play`, AuthHeaders); - if(!playbackReq.ok || !playbackReq.res) { - console.error('Non-DRM Request Stream URLs FAILED!'); - } else { - switchStream = await playbackReq.res.json() as CrunchyPlayStream; - const derivedPlaystreams = {} as CrunchyStreams; - for (const hardsub in switchStream.hardSubs) { - const stream = switchStream.hardSubs[hardsub]; - derivedPlaystreams[hardsub] = { - url: stream.url, - 'hardsub_locale': stream.hlang + + let playStream: CrunchyPlayStream | null = null; + if (options.cpstream !== 'none') { + const playbackReq = await this.req.getData(`https://cr-play-service.prd.crunchyrollsvc.com/v1/${currentVersion ? currentVersion.guid : currentMediaId}/${CrunchyPlayStreams[options.cpstream]}/play`, AuthHeaders); + if (!playbackReq.ok || !playbackReq.res) { + console.error('Non-DRM Request Stream URLs FAILED!'); + } else { + playStream = await playbackReq.res.json() as CrunchyPlayStream; + const derivedPlaystreams = {} as CrunchyStreams; + for (const hardsub in playStream.hardSubs) { + const stream = playStream.hardSubs[hardsub]; + derivedPlaystreams[hardsub] = { + url: stream.url, + 'hardsub_locale': stream.hlang + }; + } + derivedPlaystreams[''] = { + url: playStream.url, + hardsub_locale: '' + }; + pbData.data[0][`adaptive_${options.cpstream}_${playStream.url.includes('m3u8') ? 'hls' : 'dash'}_drm`] = { + ...derivedPlaystreams }; } - derivedPlaystreams[''] = { - url: switchStream.url, - hardsub_locale: '' - }; - pbData.data[0]['adaptive_switch_dash'] = { - ...derivedPlaystreams - }; } variables.push(...([ @@ -2131,9 +2151,9 @@ export default class Crunchy implements ServiceClass { console.info('Subtitles downloading skipped!'); } - if (switchStream) { + if (playStream) { await this.refreshToken(true, true); - await this.req.getData(`https://cr-play-service.prd.crunchyrollsvc.com/v1/token/${currentVersion ? currentVersion.guid : currentMediaId}/${switchStream.token}`, {...{method: 'DELETE'}, ...AuthHeaders}); + await this.req.getData(`https://cr-play-service.prd.crunchyrollsvc.com/v1/token/${currentVersion ? currentVersion.guid : currentMediaId}/${playStream.token}`, {...{method: 'DELETE'}, ...AuthHeaders}); } await this.sleep(options.waittime); diff --git a/modules/module.app-args.ts b/modules/module.app-args.ts index afe94f8..c02e73e 100644 --- a/modules/module.app-args.ts +++ b/modules/module.app-args.ts @@ -5,6 +5,7 @@ import { DownloadInfo } from '../@types/messageHandler'; import { HLSCallback } from './hls-download'; import leven from 'leven'; import { console } from './log'; +import { CrunchyPlayStreams } from '../crunchy'; let argvC: { [x: string]: unknown; @@ -42,7 +43,8 @@ let argvC: { extid: string | undefined; q: number; x: number; - kstream: number; + kstream: number; + cpstream: keyof typeof CrunchyPlayStreams | 'none'; partsize: number; hslang: string; dlsubs: string[]; diff --git a/modules/module.args.ts b/modules/module.args.ts index 61aef8e..0e65514 100644 --- a/modules/module.args.ts +++ b/modules/module.args.ts @@ -1,4 +1,5 @@ import { aoSearchLocales, dubLanguageCodes, languages, searchLocales, subtitleLanguagesFilter } from './module.langsData'; +import { CrunchyPlayStreams } from '../crunchy'; const groups = { 'auth': 'Authentication:', @@ -283,6 +284,20 @@ const args: TAppArg[] = [ type: 'number', usage: '${stream}' }, + { + name: 'cpstream', + group: 'dl', + alias: 'cps', + service: ['crunchy'], + type: 'string', + describe: 'Select specific crunchy play stream by device, or disable stream with "none"', + choices: [...Object.keys(CrunchyPlayStreams), 'none'], + default: { + default: 'chrome' + }, + docDescribe: true, + usage: '${device}' + }, { name: 'hslang', group: 'dl', diff --git a/package.json b/package.json index 97107a3..5835f7a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "multi-downloader-nx", "short_name": "aniDL", - "version": "5.0.4b1", + "version": "5.0.4b2", "description": "Downloader for Crunchyroll, Hidive, AnimeOnegai, and AnimationDigitalNetwork with CLI and GUI", "keywords": [ "download",