diff --git a/crunchy.ts b/crunchy.ts index 580974d..bf4303d 100644 --- a/crunchy.ts +++ b/crunchy.ts @@ -428,7 +428,7 @@ export default class Crunchy implements ServiceClass { const cmsTokenReqOpts = { headers: { Authorization: `Bearer ${this.token.access_token}`, - 'User-Agent': api.defaultUserAgent + ...api.crunchyDefHeader }, useProxy: true }; @@ -481,7 +481,7 @@ export default class Crunchy implements ServiceClass { const searchReqOpts = { headers: { Authorization: `Bearer ${this.token.access_token}`, - 'User-Agent': api.defaultUserAgent + ...api.crunchyDefHeader }, useProxy: true }; @@ -749,7 +749,7 @@ export default class Crunchy implements ServiceClass { const AuthHeaders = { headers: { Authorization: `Bearer ${this.token.access_token}`, - 'User-Agent': api.defaultUserAgent + ...api.crunchyDefHeader }, useProxy: true }; @@ -791,7 +791,7 @@ export default class Crunchy implements ServiceClass { const AuthHeaders = { headers: { Authorization: `Bearer ${this.token.access_token}`, - 'User-Agent': api.defaultUserAgent + ...api.crunchyDefHeader }, useProxy: true }; @@ -831,7 +831,7 @@ export default class Crunchy implements ServiceClass { const newlyAddedReqOpts = { headers: { Authorization: `Bearer ${this.token.access_token}`, - 'User-Agent': api.defaultUserAgent + ...api.crunchyDefHeader }, useProxy: true }; @@ -866,7 +866,7 @@ export default class Crunchy implements ServiceClass { const AuthHeaders = { headers: { Authorization: `Bearer ${this.token.access_token}`, - 'User-Agent': api.defaultUserAgent + ...api.crunchyDefHeader }, useProxy: true }; @@ -1103,7 +1103,7 @@ export default class Crunchy implements ServiceClass { const AuthHeaders = { headers: { Authorization: `Bearer ${this.token.access_token}`, - 'User-Agent': api.defaultUserAgent + ...api.crunchyDefHeader }, useProxy: true }; @@ -1280,12 +1280,7 @@ export default class Crunchy implements ServiceClass { const AuthHeaders: RequestInit = { headers: { Authorization: `Bearer ${this.token.access_token}`, - // 'X-Cr-Disable-Drm': 'true', - // 'X-Cr-Enable-Drm': 'false', - // 'X-Cr-Stream-Limits': 'false', - 'User-Agent': api.defaultUserAgent - //'X-Cr-Segment-CDN': 'all', - //'User-Agent': 'Crunchyroll/1.8.0 Nintendo Switch/12.3.12.0 UE4/4.27' + ...api.crunchyDefHeader } }; @@ -1316,17 +1311,13 @@ export default class Crunchy implements ServiceClass { if (options.chapters) { //Make Chapter Request const chapterRequest = await this.req.getData(`https://static.crunchyroll.com/skip-events/production/${currentMediaId}.json`, { - headers: { - 'User-Agent': api.defaultUserAgent - } + headers: api.crunchyDefHeader }); if(!chapterRequest.ok || !chapterRequest.res){ //Old Chapter Request Fallback console.warn('Chapter request failed, attempting old API'); const oldChapterRequest = await this.req.getData(`https://static.crunchyroll.com/datalab-intro-v2/${currentMediaId}.json`, { - headers: { - 'User-Agent': api.defaultUserAgent - } + headers: api.crunchyDefHeader }); if(!oldChapterRequest.ok || !oldChapterRequest.res) { console.warn('Old Chapter API request failed'); @@ -1809,7 +1800,7 @@ export default class Crunchy implements ServiceClass { await this.refreshToken(true, true); encryptionKeysVideo = await getKeysWVD(chosenVideoSegments.pssh_wvd, api.drm_widevine, { Authorization: `Bearer ${this.token.access_token}`, - 'User-Agent': api.defaultUserAgent, + ...api.crunchyDefHeader, Pragma: 'no-cache', 'Cache-Control': 'no-cache', 'content-type': 'application/octet-stream', @@ -1822,7 +1813,7 @@ export default class Crunchy implements ServiceClass { await this.refreshToken(true, true); encryptionKeysAudio = await getKeysWVD(chosenAudioSegments.pssh_wvd, api.drm_widevine, { Authorization: `Bearer ${this.token.access_token}`, - 'User-Agent': api.defaultUserAgent, + ...api.crunchyDefHeader, Pragma: 'no-cache', 'Cache-Control': 'no-cache', 'content-type': 'application/octet-stream', @@ -2067,9 +2058,7 @@ export default class Crunchy implements ServiceClass { const outFile = parseFileName(options.fileName + '.' + (mMeta.lang?.name || lang.name), variables, options.numbers, options.override).join(path.sep); console.info(`Output filename: ${outFile}`); const chunkPage = await this.req.getData(selPlUrl, { - headers: { - 'User-Agent': api.defaultUserAgent - } + headers: api.crunchyDefHeader, }); if(!chunkPage.ok || !chunkPage.res){ console.error('CAN\'T FETCH VIDEO PLAYLIST!'); @@ -2219,9 +2208,7 @@ export default class Crunchy implements ServiceClass { continue; if(options.dlsubs.includes('all') || options.dlsubs.includes(langItem.locale)){ const subsAssReq = await this.req.getData(subsItem.url, { - headers: { - 'User-Agent': api.defaultUserAgent - } + headers: api.crunchyDefHeader }); if(subsAssReq.ok && subsAssReq.res){ let sBody = await subsAssReq.res.text(); @@ -2594,7 +2581,7 @@ export default class Crunchy implements ServiceClass { const AuthHeaders = { headers: { Authorization: `Bearer ${this.token.access_token}`, - 'User-Agent': api.defaultUserAgent + ...api.crunchyDefHeader }, useProxy: true }; @@ -2623,7 +2610,7 @@ export default class Crunchy implements ServiceClass { const AuthHeaders = { headers: { Authorization: `Bearer ${this.token.access_token}`, - 'User-Agent': api.defaultUserAgent + ...api.crunchyDefHeader }, useProxy: true }; diff --git a/modules/cdm.ts b/modules/cdm.ts index bc0a738..f57b735 100644 --- a/modules/cdm.ts +++ b/modules/cdm.ts @@ -45,12 +45,15 @@ try { const stats = fs.statSync(file); if (stats.size < 1024 * 8 && stats.isFile()) { const fileContents = fs.readFileSync(file, { encoding: 'utf8' }); - if (fileContents.includes('-BEGIN PRIVATE KEY-') || fileContents.includes('-BEGIN RSA PRIVATE KEY-')) { + if (fileContents.startsWith('-----BEGIN RSA PRIVATE KEY-----') && fileContents.endsWith('-----END RSA PRIVATE KEY-----')) { privateKey = fs.readFileSync(file); } - if (fileContents.includes('widevine_cdm_version')) { + if (fileContents.includes('widevine_cdm_version') && fileContents.includes('oem_crypto_security_patch_level') && !fileContents.startsWith('WVD')) { identifierBlob = fs.readFileSync(file); } + if (fileContents.startsWith('WVD')) { + console.warn('Found WVD file in folder, AniDL currently only supports device_client_id_blob and device_private_key, make sure to have them in the widevine folder.'); + } } }); } catch (e) { diff --git a/modules/module.api-urls.ts b/modules/module.api-urls.ts index 6ec3e73..04761d1 100644 --- a/modules/module.api-urls.ts +++ b/modules/module.api-urls.ts @@ -36,6 +36,7 @@ export type APIType = { /** * Header */ + crunchyDefHeader: Record, crunchyAuthHeader: Record, hd_apikey: string, hd_devName: string, @@ -65,7 +66,7 @@ const api: APIType = { session: `${domain.api}/start_session.0.json`, collections: `${domain.api}/list_collections.0.json`, // This User-Agent bypasses Cloudflare security of the newer Endpoint - defaultUserAgent: 'Crunchyroll/4.77.2 (bundle_identifier:com.crunchyroll.iphone; build_number:4139672.438176041) iOS/18.3.2 Gravity/4.77.2', + defaultUserAgent: 'Crunchyroll/4.77.3 (bundle_identifier:com.crunchyroll.iphone; build_number:4148147.285670380) iOS/18.3.2 Gravity/4.77.3', beta_profile: `${domain.api_beta}/accounts/v1/me/profile`, beta_cmsToken: `${domain.api_beta}/index/v2`, search: `${domain.api_beta}/content/v2/discover/search`, @@ -79,6 +80,7 @@ const api: APIType = { drm_widevine: `${domain.www}/license/v1/license/widevine`, // playready endpoint currently broken drm_playready: `${domain.www}/license/v1/license/playReady`, + crunchyDefHeader: {}, crunchyAuthHeader: {}, //hidive API hd_apikey: '508efd7b42d546e19cc24f4d0b414e57e351ca73', @@ -93,10 +95,19 @@ const api: APIType = { hd_new_version: '6.0.1.bbf09a2' }; +api.crunchyDefHeader = { + 'User-Agent': api.defaultUserAgent, + 'Accept': '*/*', + 'Accept-Encoding': 'gzip;q=1.0, compress;q=0.5', + 'Accept-Language': 'de-IT;q=1.0, it-IT;q=0.9, en-GB;q=0.8', + 'Connection': 'keep-alive', + 'Host': 'www.crunchyroll.com' +}; + // set header api.crunchyAuthHeader = { - 'User-Agent': api.defaultUserAgent, - 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' + 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', + ...api.crunchyDefHeader }; export {