mirror of
https://github.com/anidl/multi-downloader-nx.git
synced 2026-03-11 17:45:30 +00:00
added support for new crunchyroll endpoint (cloudflare bypass)
This commit is contained in:
parent
ff6fc9d993
commit
bc7b58f141
2 changed files with 72 additions and 22 deletions
67
crunchy.ts
67
crunchy.ts
|
|
@ -212,7 +212,11 @@ export default class Crunchy implements ServiceClass {
|
|||
console.info('');
|
||||
}
|
||||
const fontUrl = fontsData.root + f;
|
||||
const getFont = await this.req.getData(fontUrl);
|
||||
const getFont = await this.req.getData(fontUrl, {
|
||||
headers: {
|
||||
'User-Agent': api.defaultUserAgent
|
||||
}
|
||||
});
|
||||
if(getFont.ok && getFont.res){
|
||||
fs.writeFileSync(fontLoc, Buffer.from(await getFont.res.arrayBuffer()));
|
||||
console.info(`Downloaded: ${f}`);
|
||||
|
|
@ -233,7 +237,8 @@ export default class Crunchy implements ServiceClass {
|
|||
'grant_type': 'password',
|
||||
'scope': 'offline_access',
|
||||
'device_id': uuid,
|
||||
'device_type': 'Chrome on Windows'
|
||||
'device_name': 'iPhone',
|
||||
'device_type': 'iPhone 13'
|
||||
}).toString();
|
||||
const authReqOpts: reqModule.Params = {
|
||||
method: 'POST',
|
||||
|
|
@ -260,7 +265,8 @@ export default class Crunchy implements ServiceClass {
|
|||
'grant_type': 'client_id',
|
||||
'scope': 'offline_access',
|
||||
'device_id': uuid,
|
||||
'device_type': 'Chrome on Windows'
|
||||
'device_name': 'iPhone',
|
||||
'device_type': 'iPhone 13'
|
||||
}).toString();
|
||||
const authReqOpts: reqModule.Params = {
|
||||
method: 'POST',
|
||||
|
|
@ -286,6 +292,7 @@ export default class Crunchy implements ServiceClass {
|
|||
const profileReqOptions = {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token.access_token}`,
|
||||
'User-Agent': api.defaultUserAgent
|
||||
},
|
||||
useProxy: true
|
||||
};
|
||||
|
|
@ -315,7 +322,8 @@ export default class Crunchy implements ServiceClass {
|
|||
//'grant_type': 'etp_rt_cookie',
|
||||
'scope': 'offline_access',
|
||||
'device_id': uuid,
|
||||
'device_type': 'Chrome on Windows'
|
||||
'device_name': 'iPhone',
|
||||
'device_type': 'iPhone 13'
|
||||
}).toString();
|
||||
const authReqOpts: reqModule.Params = {
|
||||
method: 'POST',
|
||||
|
|
@ -400,6 +408,7 @@ export default class Crunchy implements ServiceClass {
|
|||
const cmsTokenReqOpts = {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token.access_token}`,
|
||||
'User-Agent': api.defaultUserAgent
|
||||
},
|
||||
useProxy: true
|
||||
};
|
||||
|
|
@ -432,7 +441,11 @@ export default class Crunchy implements ServiceClass {
|
|||
'Key-Pair-Id': this.cmsToken.cms.key_pair_id,
|
||||
}),
|
||||
].join('');
|
||||
const indexReq = await this.req.getData(indexReqOpts);
|
||||
const indexReq = await this.req.getData(indexReqOpts, {
|
||||
headers: {
|
||||
'User-Agent': api.defaultUserAgent
|
||||
}
|
||||
});
|
||||
if(!indexReq.ok || ! indexReq.res){
|
||||
console.error('Get CMS index FAILED!');
|
||||
return;
|
||||
|
|
@ -448,6 +461,7 @@ export default class Crunchy implements ServiceClass {
|
|||
const searchReqOpts = {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token.access_token}`,
|
||||
'User-Agent': api.defaultUserAgent
|
||||
},
|
||||
useProxy: true
|
||||
};
|
||||
|
|
@ -715,6 +729,7 @@ export default class Crunchy implements ServiceClass {
|
|||
const AuthHeaders = {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token.access_token}`,
|
||||
'User-Agent': api.defaultUserAgent
|
||||
},
|
||||
useProxy: true
|
||||
};
|
||||
|
|
@ -756,6 +771,7 @@ export default class Crunchy implements ServiceClass {
|
|||
const AuthHeaders = {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token.access_token}`,
|
||||
'User-Agent': api.defaultUserAgent
|
||||
},
|
||||
useProxy: true
|
||||
};
|
||||
|
|
@ -795,6 +811,7 @@ export default class Crunchy implements ServiceClass {
|
|||
const newlyAddedReqOpts = {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token.access_token}`,
|
||||
'User-Agent': api.defaultUserAgent
|
||||
},
|
||||
useProxy: true
|
||||
};
|
||||
|
|
@ -829,6 +846,7 @@ export default class Crunchy implements ServiceClass {
|
|||
const AuthHeaders = {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token.access_token}`,
|
||||
'User-Agent': api.defaultUserAgent
|
||||
},
|
||||
useProxy: true
|
||||
};
|
||||
|
|
@ -1031,7 +1049,11 @@ export default class Crunchy implements ServiceClass {
|
|||
}),
|
||||
].join('');
|
||||
|
||||
const extIdReq = await this.req.getData(extIdReqOpts);
|
||||
const extIdReq = await this.req.getData(extIdReqOpts, {
|
||||
headers: {
|
||||
'User-Agent': api.defaultUserAgent
|
||||
}
|
||||
});
|
||||
if (!extIdReq.ok || !extIdReq.res) {
|
||||
console.error('Objects Request FAILED!');
|
||||
if (extIdReq.error && extIdReq.error.res && extIdReq.error.res.body) {
|
||||
|
|
@ -1061,6 +1083,7 @@ export default class Crunchy implements ServiceClass {
|
|||
const AuthHeaders = {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token.access_token}`,
|
||||
'User-Agent': api.defaultUserAgent
|
||||
},
|
||||
useProxy: true
|
||||
};
|
||||
|
|
@ -1240,6 +1263,7 @@ export default class Crunchy implements ServiceClass {
|
|||
'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'
|
||||
}
|
||||
|
|
@ -1271,11 +1295,19 @@ export default class Crunchy implements ServiceClass {
|
|||
const compiledChapters: string[] = [];
|
||||
if (options.chapters) {
|
||||
//Make Chapter Request
|
||||
const chapterRequest = await this.req.getData(`https://static.crunchyroll.com/skip-events/production/${currentMediaId}.json`);
|
||||
const chapterRequest = await this.req.getData(`https://static.crunchyroll.com/skip-events/production/${currentMediaId}.json`, {
|
||||
headers: {
|
||||
'User-Agent': api.defaultUserAgent
|
||||
}
|
||||
});
|
||||
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`);
|
||||
const oldChapterRequest = await this.req.getData(`https://static.crunchyroll.com/datalab-intro-v2/${currentMediaId}.json`, {
|
||||
headers: {
|
||||
'User-Agent': api.defaultUserAgent
|
||||
}
|
||||
});
|
||||
if(!oldChapterRequest.ok || !oldChapterRequest.res) {
|
||||
console.warn('Old Chapter API request failed');
|
||||
} else {
|
||||
|
|
@ -1734,7 +1766,10 @@ export default class Crunchy implements ServiceClass {
|
|||
'asset_id': assetId,
|
||||
'session_id': sessionId,
|
||||
'user_id': this.token.account_id
|
||||
})
|
||||
}),
|
||||
headers: {
|
||||
'User-Agent': api.defaultUserAgent
|
||||
}
|
||||
});
|
||||
if(!decReq.ok || !decReq.res){
|
||||
console.error('Request to DRM Authentication failed:', decReq.error?.res.status, decReq.error?.message);
|
||||
|
|
@ -1947,7 +1982,11 @@ export default class Crunchy implements ServiceClass {
|
|||
fileName = parseFileName(options.fileName, variables, options.numbers, options.override).join(path.sep);
|
||||
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);
|
||||
const chunkPage = await this.req.getData(selPlUrl, {
|
||||
headers: {
|
||||
'User-Agent': api.defaultUserAgent
|
||||
}
|
||||
});
|
||||
if(!chunkPage.ok || !chunkPage.res){
|
||||
console.error('CAN\'T FETCH VIDEO PLAYLIST!');
|
||||
dlFailed = true;
|
||||
|
|
@ -2097,7 +2136,11 @@ export default class Crunchy implements ServiceClass {
|
|||
if (files.some(a => a.type === 'Subtitle' && (a.language.cr_locale == langItem.cr_locale || a.language.locale == langItem.locale) && a.cc === isCC && a.signs === isSigns))
|
||||
continue;
|
||||
if(options.dlsubs.includes('all') || options.dlsubs.includes(langItem.locale)){
|
||||
const subsAssReq = await this.req.getData(subsItem.url);
|
||||
const subsAssReq = await this.req.getData(subsItem.url, {
|
||||
headers: {
|
||||
'User-Agent': api.defaultUserAgent
|
||||
}
|
||||
});
|
||||
if(subsAssReq.ok && subsAssReq.res){
|
||||
let sBody = await subsAssReq.res.text();
|
||||
if (subsItem.format == 'vtt') {
|
||||
|
|
@ -2469,6 +2512,7 @@ export default class Crunchy implements ServiceClass {
|
|||
const AuthHeaders = {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token.access_token}`,
|
||||
'User-Agent': api.defaultUserAgent
|
||||
},
|
||||
useProxy: true
|
||||
};
|
||||
|
|
@ -2497,6 +2541,7 @@ export default class Crunchy implements ServiceClass {
|
|||
const AuthHeaders = {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token.access_token}`,
|
||||
'User-Agent': api.defaultUserAgent
|
||||
},
|
||||
useProxy: true
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export type APIType = {
|
|||
collections: string
|
||||
// beta api
|
||||
beta_auth: string
|
||||
defaultUserAgent: string,
|
||||
authBasic: string
|
||||
authBasicMob: string
|
||||
authBasicSwitch: string,
|
||||
|
|
@ -72,17 +73,20 @@ const api: APIType = {
|
|||
search3: `${domain.api}/autocomplete.0.json`,
|
||||
session: `${domain.api}/start_session.0.json`,
|
||||
collections: `${domain.api}/list_collections.0.json`,
|
||||
// beta api
|
||||
beta_auth: `${domain.api_beta}/auth/v1/token`,
|
||||
// new api
|
||||
beta_auth: `${domain.www}/auth/v1/token`,
|
||||
// This User-Agent bypasses Cloudflare security by the newer Endpoint
|
||||
defaultUserAgent: 'Crunchyroll/4.68.2 (bundle_identifier:com.crunchyroll.iphone; build_number:4007128.533694055) iOS/18.2.0 Gravity/4.68.2',
|
||||
authBasic: 'Basic bm9haWhkZXZtXzZpeWcwYThsMHE6',
|
||||
authBasicMob: 'Basic dXU4aG0wb2g4dHFpOWV0eXl2aGo6SDA2VnVjRnZUaDJ1dEYxM0FBS3lLNE85UTRhX3BlX1o=',
|
||||
authBasicMob: 'Basic eHVuaWh2ZWRidDNtYmlzdWhldnQ6MWtJUzVkeVR2akUwX3JxYUEzWWVBaDBiVVhVbXhXMTE=',
|
||||
authBasicSwitch: 'Basic dC1rZGdwMmg4YzNqdWI4Zm4wZnE6eWZMRGZNZnJZdktYaDRKWFMxTEVJMmNDcXUxdjVXYW4=',
|
||||
beta_profile: `${domain.api_beta}/accounts/v1/me/profile`,
|
||||
beta_cmsToken: `${domain.api_beta}/index/v2`,
|
||||
search: `${domain.api_beta}/content/v2/discover/search`,
|
||||
cms: `${domain.api_beta}/content/v2/cms`,
|
||||
beta_browse: `${domain.api_beta}/content/v1/browse`,
|
||||
beta_cms: `${domain.api_beta}/cms/v2`,
|
||||
beta_profile: `${domain.www}/accounts/v1/me/profile`,
|
||||
beta_cmsToken: `${domain.www}/index/v2`,
|
||||
search: `${domain.www}/content/v2/discover/search`,
|
||||
cms: `${domain.www}/content/v2/cms`,
|
||||
beta_browse: `${domain.www}/content/v1/browse`,
|
||||
beta_cms: `${domain.www}/cms/v2`,
|
||||
// beta api
|
||||
drm: `${domain.api_beta}/drm/v1/auth`,
|
||||
crunchyAuthHeader: {},
|
||||
crunchyAuthHeaderMob: {},
|
||||
|
|
@ -106,8 +110,9 @@ api.crunchyAuthHeader = {
|
|||
};
|
||||
|
||||
api.crunchyAuthHeaderMob = {
|
||||
Authorization: api.authBasicSwitch,
|
||||
'user-agent': 'Crunchyroll/3.60.0 Android/9 okhttp/4.12.0'
|
||||
Authorization: api.authBasicMob,
|
||||
'User-Agent': api.defaultUserAgent,
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
|
||||
};
|
||||
|
||||
api.crunchyAuthHeaderSwitch = {
|
||||
|
|
|
|||
Loading…
Reference in a new issue