Compare commits
No commits in common. "master" and "guiv3" have entirely different histories.
10 changed files with 98 additions and 69 deletions
4
.github/workflows/docker.yml
vendored
4
.github/workflows/docker.yml
vendored
|
|
@ -27,6 +27,6 @@ jobs:
|
||||||
github-token: ${{ github.token }}
|
github-token: ${{ github.token }}
|
||||||
push: ${{ github.ref == 'refs/heads/master' }}
|
push: ${{ github.ref == 'refs/heads/master' }}
|
||||||
tags: |
|
tags: |
|
||||||
"multidl/multi-downloader-nx:latest"
|
"izuco/multi-downloader-nx:latest"
|
||||||
- name: Image digest
|
- name: Image digest
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||||
2
.github/workflows/release-matrix.yml
vendored
2
.github/workflows/release-matrix.yml
vendored
|
|
@ -61,6 +61,6 @@ jobs:
|
||||||
github-token: ${{ github.token }}
|
github-token: ${{ github.token }}
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
"multidl/multi-downloader-nx:${{ github.event.release.tag_name }}"
|
"izuco/multi-downloader-nx:${{ github.event.release.tag_name }}"
|
||||||
- name: Image digest
|
- name: Image digest
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||||
|
|
|
||||||
4
@types/crunchyPlayStreams.d.ts
vendored
4
@types/crunchyPlayStreams.d.ts
vendored
|
|
@ -1,8 +1,6 @@
|
||||||
import { Locale } from './playbackData';
|
|
||||||
|
|
||||||
export interface CrunchyPlayStream {
|
export interface CrunchyPlayStream {
|
||||||
assetId: string;
|
assetId: string;
|
||||||
audioLocale: Locale;
|
audioLocale: string;
|
||||||
bifs: string;
|
bifs: string;
|
||||||
burnedInLocale: string;
|
burnedInLocale: string;
|
||||||
captions: { [key: string]: Caption };
|
captions: { [key: string]: Caption };
|
||||||
|
|
|
||||||
4
@types/playbackData.d.ts
vendored
4
@types/playbackData.d.ts
vendored
|
|
@ -59,11 +59,11 @@ export interface Meta {
|
||||||
versions: Version[];
|
versions: Version[];
|
||||||
audio_locale: Locale;
|
audio_locale: Locale;
|
||||||
closed_captions: Subtitles;
|
closed_captions: Subtitles;
|
||||||
captions: Subtitles;
|
captions: Record<unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Subtitles {
|
export interface Subtitles {
|
||||||
''?: SubtitleInfo;
|
'': SubtitleInfo;
|
||||||
'en-US'?: SubtitleInfo;
|
'en-US'?: SubtitleInfo;
|
||||||
'es-LA'?: SubtitleInfo;
|
'es-LA'?: SubtitleInfo;
|
||||||
'es-419'?: SubtitleInfo;
|
'es-419'?: SubtitleInfo;
|
||||||
|
|
|
||||||
14
adn.ts
14
adn.ts
|
|
@ -204,6 +204,8 @@ export default class AnimationDigitalNetwork implements ServiceClass {
|
||||||
return { isOk: false, reason: new Error('Authentication failed') };
|
return { isOk: false, reason: new Error('Authentication failed') };
|
||||||
}
|
}
|
||||||
this.token = await authReq.res.json();
|
this.token = await authReq.res.json();
|
||||||
|
const cookies = this.parseCookies(authReq.res.headers.get('Set-Cookie'));
|
||||||
|
this.token.refreshToken = cookies.adnrt;
|
||||||
yamlCfg.saveADNToken(this.token);
|
yamlCfg.saveADNToken(this.token);
|
||||||
console.info('Authentication Success');
|
console.info('Authentication Success');
|
||||||
return { isOk: true, value: undefined };
|
return { isOk: true, value: undefined };
|
||||||
|
|
@ -214,16 +216,19 @@ export default class AnimationDigitalNetwork implements ServiceClass {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${this.token.accessToken}`,
|
Authorization: `Bearer ${this.token.accessToken}`,
|
||||||
'X-Access-Token': this.token.accessToken,
|
'Cookie': `adnrt=${this.token.refreshToken}`,
|
||||||
'content-type': 'application/json'
|
'X-Access-Token': this.token.accessToken
|
||||||
},
|
},
|
||||||
body: JSON.stringify({refreshToken: this.token.refreshToken})
|
body: '{}'
|
||||||
});
|
});
|
||||||
if(!authReq.ok || !authReq.res){
|
if(!authReq.ok || !authReq.res){
|
||||||
console.error('Token refresh failed!');
|
console.error('Token refresh failed!');
|
||||||
return { isOk: false, reason: new Error('Token refresh failed') };
|
return { isOk: false, reason: new Error('Token refresh failed') };
|
||||||
}
|
}
|
||||||
this.token = await authReq.res.json();
|
this.token = await authReq.res.json();
|
||||||
|
const cookies = this.parseCookies(authReq.res.headers.get('Set-Cookie'));
|
||||||
|
//this.token.refreshtoken = this.token.refreshToken;
|
||||||
|
this.token.refreshToken = cookies.adnrt;
|
||||||
yamlCfg.saveADNToken(this.token);
|
yamlCfg.saveADNToken(this.token);
|
||||||
return { isOk: true, value: undefined };
|
return { isOk: true, value: undefined };
|
||||||
}
|
}
|
||||||
|
|
@ -458,8 +463,7 @@ export default class AnimationDigitalNetwork implements ServiceClass {
|
||||||
|
|
||||||
const configReq = await this.req.getData(`https://gw.api.animationdigitalnetwork.fr/player/video/${data.id}/configuration`, {
|
const configReq = await this.req.getData(`https://gw.api.animationdigitalnetwork.fr/player/video/${data.id}/configuration`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${this.token.accessToken}`,
|
Authorization: `Bearer ${this.token.accessToken}`
|
||||||
'X-Target-Distribution': this.locale
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if(!configReq.ok || !configReq.res){
|
if(!configReq.ok || !configReq.res){
|
||||||
|
|
|
||||||
130
crunchy.ts
130
crunchy.ts
|
|
@ -31,7 +31,7 @@ import { CrunchyEpisodeList, CrunchyEpisode } from './@types/crunchyEpisodeList'
|
||||||
import { CrunchyDownloadOptions, CrunchyEpMeta, CrunchyMuxOptions, CrunchyMultiDownload, DownloadedMedia, ParseItem, SeriesSearch, SeriesSearchItem } from './@types/crunchyTypes';
|
import { CrunchyDownloadOptions, CrunchyEpMeta, CrunchyMuxOptions, CrunchyMultiDownload, DownloadedMedia, ParseItem, SeriesSearch, SeriesSearchItem } from './@types/crunchyTypes';
|
||||||
import { ObjectInfo } from './@types/objectInfo';
|
import { ObjectInfo } from './@types/objectInfo';
|
||||||
import parseFileName, { Variable } from './modules/module.filename';
|
import parseFileName, { Variable } from './modules/module.filename';
|
||||||
import { CrunchyStreams, PlaybackData, Subtitles } from './@types/playbackData';
|
import { CrunchyStreams, PlaybackData } from './@types/playbackData';
|
||||||
import { downloaded } from './modules/module.downloadArchive';
|
import { downloaded } from './modules/module.downloadArchive';
|
||||||
import parseSelect from './modules/module.parseSelect';
|
import parseSelect from './modules/module.parseSelect';
|
||||||
import { AvailableFilenameVars, getDefault } from './modules/module.args';
|
import { AvailableFilenameVars, getDefault } from './modules/module.args';
|
||||||
|
|
@ -45,7 +45,6 @@ import { CrunchyChapters, CrunchyChapter, CrunchyOldChapter } from './@types/cru
|
||||||
import vtt2ass from './modules/module.vtt2ass';
|
import vtt2ass from './modules/module.vtt2ass';
|
||||||
import { CrunchyPlayStream } from './@types/crunchyPlayStreams';
|
import { CrunchyPlayStream } from './@types/crunchyPlayStreams';
|
||||||
import { CrunchyPlayStreams } from './@types/enums';
|
import { CrunchyPlayStreams } from './@types/enums';
|
||||||
import { randomUUID } from 'node:crypto';
|
|
||||||
|
|
||||||
export type sxItem = {
|
export type sxItem = {
|
||||||
language: langsData.LanguageItem,
|
language: langsData.LanguageItem,
|
||||||
|
|
@ -226,18 +225,15 @@ export default class Crunchy implements ServiceClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async doAuth(data: AuthData): Promise<AuthResponse> {
|
public async doAuth(data: AuthData): Promise<AuthResponse> {
|
||||||
const uuid = randomUUID();
|
|
||||||
const authData = new URLSearchParams({
|
const authData = new URLSearchParams({
|
||||||
'username': data.username,
|
'username': data.username,
|
||||||
'password': data.password,
|
'password': data.password,
|
||||||
'grant_type': 'password',
|
'grant_type': 'password',
|
||||||
'scope': 'offline_access',
|
'scope': 'offline_access'
|
||||||
'device_id': uuid,
|
|
||||||
'device_type': 'Chrome on Windows'
|
|
||||||
}).toString();
|
}).toString();
|
||||||
const authReqOpts: reqModule.Params = {
|
const authReqOpts: reqModule.Params = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: api.crunchyAuthHeaderMob,
|
headers: api.crunchyAuthHeader,
|
||||||
body: authData
|
body: authData
|
||||||
};
|
};
|
||||||
const authReq = await this.req.getData(api.beta_auth, authReqOpts);
|
const authReq = await this.req.getData(api.beta_auth, authReqOpts);
|
||||||
|
|
@ -246,7 +242,6 @@ export default class Crunchy implements ServiceClass {
|
||||||
return { isOk: false, reason: new Error('Authentication failed') };
|
return { isOk: false, reason: new Error('Authentication failed') };
|
||||||
}
|
}
|
||||||
this.token = await authReq.res.json();
|
this.token = await authReq.res.json();
|
||||||
this.token.device_id = uuid;
|
|
||||||
this.token.expires = new Date(Date.now() + this.token.expires_in);
|
this.token.expires = new Date(Date.now() + this.token.expires_in);
|
||||||
yamlCfg.saveCRToken(this.token);
|
yamlCfg.saveCRToken(this.token);
|
||||||
await this.getProfile();
|
await this.getProfile();
|
||||||
|
|
@ -255,16 +250,13 @@ export default class Crunchy implements ServiceClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async doAnonymousAuth(){
|
public async doAnonymousAuth(){
|
||||||
const uuid = randomUUID();
|
|
||||||
const authData = new URLSearchParams({
|
const authData = new URLSearchParams({
|
||||||
'grant_type': 'client_id',
|
'grant_type': 'client_id',
|
||||||
'scope': 'offline_access',
|
'scope': 'offline_access',
|
||||||
'device_id': uuid,
|
|
||||||
'device_type': 'Chrome on Windows'
|
|
||||||
}).toString();
|
}).toString();
|
||||||
const authReqOpts: reqModule.Params = {
|
const authReqOpts: reqModule.Params = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: api.crunchyAuthHeaderMob,
|
headers: api.crunchyAuthHeader,
|
||||||
body: authData
|
body: authData
|
||||||
};
|
};
|
||||||
const authReq = await this.req.getData(api.beta_auth, authReqOpts);
|
const authReq = await this.req.getData(api.beta_auth, authReqOpts);
|
||||||
|
|
@ -273,7 +265,6 @@ export default class Crunchy implements ServiceClass {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.token = await authReq.res.json();
|
this.token = await authReq.res.json();
|
||||||
this.token.device_id = uuid;
|
|
||||||
this.token.expires = new Date(Date.now() + this.token.expires_in);
|
this.token.expires = new Date(Date.now() + this.token.expires_in);
|
||||||
yamlCfg.saveCRToken(this.token);
|
yamlCfg.saveCRToken(this.token);
|
||||||
}
|
}
|
||||||
|
|
@ -308,18 +299,13 @@ export default class Crunchy implements ServiceClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loginWithToken(refreshToken: string) {
|
public async loginWithToken(refreshToken: string) {
|
||||||
const uuid = randomUUID();
|
|
||||||
const authData = new URLSearchParams({
|
const authData = new URLSearchParams({
|
||||||
'refresh_token': this.token.refresh_token,
|
'grant_type': 'etp_rt_cookie',
|
||||||
'grant_type': 'refresh_token',
|
'scope': 'offline_access'
|
||||||
//'grant_type': 'etp_rt_cookie',
|
|
||||||
'scope': 'offline_access',
|
|
||||||
'device_id': uuid,
|
|
||||||
'device_type': 'Chrome on Windows'
|
|
||||||
}).toString();
|
}).toString();
|
||||||
const authReqOpts: reqModule.Params = {
|
const authReqOpts: reqModule.Params = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {...api.crunchyAuthHeaderMob, Cookie: `etp_rt=${refreshToken}`},
|
headers: {...api.crunchyAuthHeader, Cookie: `etp_rt=${refreshToken}`},
|
||||||
body: authData
|
body: authData
|
||||||
};
|
};
|
||||||
const authReq = await this.req.getData(api.beta_auth, authReqOpts);
|
const authReq = await this.req.getData(api.beta_auth, authReqOpts);
|
||||||
|
|
@ -331,7 +317,6 @@ export default class Crunchy implements ServiceClass {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.token = await authReq.res.json();
|
this.token = await authReq.res.json();
|
||||||
this.token.device_id = uuid;
|
|
||||||
this.token.expires = new Date(Date.now() + this.token.expires_in);
|
this.token.expires = new Date(Date.now() + this.token.expires_in);
|
||||||
yamlCfg.saveCRToken(this.token);
|
yamlCfg.saveCRToken(this.token);
|
||||||
await this.getProfile(false);
|
await this.getProfile(false);
|
||||||
|
|
@ -350,18 +335,13 @@ export default class Crunchy implements ServiceClass {
|
||||||
} else {
|
} else {
|
||||||
//console.info('[WARN] The token has expired compleatly. I will try to refresh the token anyway, but you might have to reauth.');
|
//console.info('[WARN] The token has expired compleatly. I will try to refresh the token anyway, but you might have to reauth.');
|
||||||
}
|
}
|
||||||
const uuid = this.token.device_id || randomUUID();
|
|
||||||
const authData = new URLSearchParams({
|
const authData = new URLSearchParams({
|
||||||
'refresh_token': this.token.refresh_token,
|
'grant_type': 'etp_rt_cookie',
|
||||||
'grant_type': 'refresh_token',
|
'scope': 'offline_access'
|
||||||
//'grant_type': 'etp_rt_cookie',
|
|
||||||
'scope': 'offline_access',
|
|
||||||
'device_id': uuid,
|
|
||||||
'device_type': 'Chrome on Windows'
|
|
||||||
}).toString();
|
}).toString();
|
||||||
const authReqOpts: reqModule.Params = {
|
const authReqOpts: reqModule.Params = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {...api.crunchyAuthHeaderMob, Cookie: `etp_rt=${this.token.refresh_token}`},
|
headers: {...api.crunchyAuthHeader, Cookie: `etp_rt=${this.token.refresh_token}`},
|
||||||
body: authData
|
body: authData
|
||||||
};
|
};
|
||||||
const authReq = await this.req.getData(api.beta_auth, authReqOpts);
|
const authReq = await this.req.getData(api.beta_auth, authReqOpts);
|
||||||
|
|
@ -373,7 +353,6 @@ export default class Crunchy implements ServiceClass {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.token = await authReq.res.json();
|
this.token = await authReq.res.json();
|
||||||
this.token.device_id = uuid;
|
|
||||||
this.token.expires = new Date(Date.now() + this.token.expires_in);
|
this.token.expires = new Date(Date.now() + this.token.expires_in);
|
||||||
yamlCfg.saveCRToken(this.token);
|
yamlCfg.saveCRToken(this.token);
|
||||||
}
|
}
|
||||||
|
|
@ -1371,7 +1350,73 @@ export default class Crunchy implements ServiceClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const pbData = { total: 0, data: [{}], meta: {} } as PlaybackData;
|
let pbData = { total: 0, data: [{}], meta: {} } as PlaybackData;
|
||||||
|
if (this.api == 'android') {
|
||||||
|
const videoStreamsReq = [
|
||||||
|
api.beta_cms,
|
||||||
|
`${this.cmsToken.cms.bucket}/videos/${mediaId}/streams`,
|
||||||
|
'?',
|
||||||
|
new URLSearchParams({
|
||||||
|
'force_locale': '',
|
||||||
|
'preferred_audio_language': 'ja-JP',
|
||||||
|
'locale': this.locale,
|
||||||
|
'Policy': this.cmsToken.cms.policy,
|
||||||
|
'Signature': this.cmsToken.cms.signature,
|
||||||
|
'Key-Pair-Id': this.cmsToken.cms.key_pair_id,
|
||||||
|
}),
|
||||||
|
].join('');
|
||||||
|
|
||||||
|
let playbackReq = await this.req.getData(videoStreamsReq as string, AuthHeaders);
|
||||||
|
if(!playbackReq.ok || !playbackReq.res){
|
||||||
|
console.error('Request Stream URLs FAILED! Attempting fallback');
|
||||||
|
|
||||||
|
const videoStreamsReq = [
|
||||||
|
domain.api_beta,
|
||||||
|
mMeta.playback,
|
||||||
|
'?',
|
||||||
|
new URLSearchParams({
|
||||||
|
'force_locale': '',
|
||||||
|
'preferred_audio_language': 'ja-JP',
|
||||||
|
'locale': this.locale,
|
||||||
|
'Policy': this.cmsToken.cms.policy,
|
||||||
|
'Signature': this.cmsToken.cms.signature,
|
||||||
|
'Key-Pair-Id': this.cmsToken.cms.key_pair_id,
|
||||||
|
}),
|
||||||
|
].join('');
|
||||||
|
playbackReq = await this.req.getData(videoStreamsReq as string, AuthHeaders);
|
||||||
|
if(!playbackReq.ok || !playbackReq.res){
|
||||||
|
console.error('Fallback Request Stream URLs FAILED!');
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const pbDataAndroid = await playbackReq.res.json() as CrunchyAndroidStreams;
|
||||||
|
pbData = {
|
||||||
|
total: 0,
|
||||||
|
data: [{}/*pbDataAndroid.streams*/],
|
||||||
|
meta: {
|
||||||
|
audio_locale: pbDataAndroid.audio_locale,
|
||||||
|
bifs: pbDataAndroid.bifs,
|
||||||
|
captions: pbDataAndroid.captions,
|
||||||
|
closed_captions: pbDataAndroid.closed_captions,
|
||||||
|
media_id: pbDataAndroid.media_id,
|
||||||
|
subtitles: pbDataAndroid.subtitles,
|
||||||
|
versions: pbDataAndroid.versions
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
let playbackReq = await this.req.getData(`${api.cms}/videos/${mediaId}/streams`, AuthHeaders);
|
||||||
|
if(!playbackReq.ok || !playbackReq.res){
|
||||||
|
console.error('Request Stream URLs FAILED! Attempting fallback');
|
||||||
|
playbackReq = await this.req.getData(`${domain.api_beta}${mMeta.playback}`, AuthHeaders);
|
||||||
|
if(!playbackReq.ok || !playbackReq.res){
|
||||||
|
console.error('Fallback Request Stream URLs FAILED!');
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pbData = await playbackReq.res.json() as PlaybackData;
|
||||||
|
pbData.data = [{}];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let playStream: CrunchyPlayStream | null = null;
|
let playStream: CrunchyPlayStream | null = null;
|
||||||
if (options.cstream !== 'none') {
|
if (options.cstream !== 'none') {
|
||||||
|
|
@ -1392,15 +1437,6 @@ export default class Crunchy implements ServiceClass {
|
||||||
url: playStream.url,
|
url: playStream.url,
|
||||||
hardsub_locale: ''
|
hardsub_locale: ''
|
||||||
};
|
};
|
||||||
pbData.meta = {
|
|
||||||
audio_locale: playStream.audioLocale,
|
|
||||||
bifs: [playStream.bifs],
|
|
||||||
captions: playStream.captions,
|
|
||||||
closed_captions: playStream.captions,
|
|
||||||
media_id: playStream.assetId,
|
|
||||||
subtitles: playStream.subtitles,
|
|
||||||
versions: playStream.versions
|
|
||||||
};
|
|
||||||
pbData.data[0][`adaptive_${options.cstream}_${playStream.url.includes('m3u8') ? 'hls' : 'dash'}_drm`] = {
|
pbData.data[0][`adaptive_${options.cstream}_${playStream.url.includes('m3u8') ? 'hls' : 'dash'}_drm`] = {
|
||||||
...derivedPlaystreams
|
...derivedPlaystreams
|
||||||
};
|
};
|
||||||
|
|
@ -1527,14 +1563,6 @@ export default class Crunchy implements ServiceClass {
|
||||||
|
|
||||||
let tsFile = undefined;
|
let tsFile = undefined;
|
||||||
|
|
||||||
// Delete the stream if it's not needed
|
|
||||||
if (options.novids && options.noaudio) {
|
|
||||||
if (playStream) {
|
|
||||||
await this.refreshToken(true, true);
|
|
||||||
await this.req.getData(`https://cr-play-service.prd.crunchyrollsvc.com/v1/token/${currentVersion ? currentVersion.guid : currentMediaId}/${playStream.token}`, {...{method: 'DELETE'}, ...AuthHeaders});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!dlFailed && curStream !== undefined && !(options.novids && options.noaudio)){
|
if(!dlFailed && curStream !== undefined && !(options.novids && options.noaudio)){
|
||||||
const streamPlaylistsReq = await this.req.getData(curStream.url, AuthHeaders);
|
const streamPlaylistsReq = await this.req.getData(curStream.url, AuthHeaders);
|
||||||
if(!streamPlaylistsReq.ok || !streamPlaylistsReq.res){
|
if(!streamPlaylistsReq.ok || !streamPlaylistsReq.res){
|
||||||
|
|
@ -2041,7 +2069,7 @@ export default class Crunchy implements ServiceClass {
|
||||||
const subsData = Object.values(pbData.meta.subtitles);
|
const subsData = Object.values(pbData.meta.subtitles);
|
||||||
const capsData = Object.values(pbData.meta.closed_captions);
|
const capsData = Object.values(pbData.meta.closed_captions);
|
||||||
const subsDataMapped = subsData.map((s) => {
|
const subsDataMapped = subsData.map((s) => {
|
||||||
const subLang = langsData.fixAndFindCrLC(s.language);
|
const subLang = langsData.fixAndFindCrLC(s.locale);
|
||||||
return {
|
return {
|
||||||
...s,
|
...s,
|
||||||
isCC: false,
|
isCC: false,
|
||||||
|
|
@ -2050,7 +2078,7 @@ export default class Crunchy implements ServiceClass {
|
||||||
};
|
};
|
||||||
}).concat(
|
}).concat(
|
||||||
capsData.map((s) => {
|
capsData.map((s) => {
|
||||||
const subLang = langsData.fixAndFindCrLC(s.language);
|
const subLang = langsData.fixAndFindCrLC(s.locale);
|
||||||
return {
|
return {
|
||||||
...s,
|
...s,
|
||||||
isCC: true,
|
isCC: true,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# multi-downloader-nx (5.1.5v)
|
# multi-downloader-nx (5.1.0b5v)
|
||||||
|
|
||||||
If you find any bugs in this documentation or in the program itself please report it [over on GitHub](https://github.com/anidl/multi-downloader-nx/issues).
|
If you find any bugs in this documentation or in the program itself please report it [over on GitHub](https://github.com/anidl/multi-downloader-nx/issues).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ const api: APIType = {
|
||||||
// beta api
|
// beta api
|
||||||
beta_auth: `${domain.api_beta}/auth/v1/token`,
|
beta_auth: `${domain.api_beta}/auth/v1/token`,
|
||||||
authBasic: 'Basic bm9haWhkZXZtXzZpeWcwYThsMHE6',
|
authBasic: 'Basic bm9haWhkZXZtXzZpeWcwYThsMHE6',
|
||||||
authBasicMob: 'Basic dXU4aG0wb2g4dHFpOWV0eXl2aGo6SDA2VnVjRnZUaDJ1dEYxM0FBS3lLNE85UTRhX3BlX1o=',
|
authBasicMob: 'Basic d2piMV90YThta3Y3X2t4aHF6djc6MnlSWlg0Y0psX28yMzRqa2FNaXRTbXNLUVlGaUpQXzU=',
|
||||||
authBasicSwitch: 'Basic dC1rZGdwMmg4YzNqdWI4Zm4wZnE6eWZMRGZNZnJZdktYaDRKWFMxTEVJMmNDcXUxdjVXYW4=',
|
authBasicSwitch: 'Basic dC1rZGdwMmg4YzNqdWI4Zm4wZnE6eWZMRGZNZnJZdktYaDRKWFMxTEVJMmNDcXUxdjVXYW4=',
|
||||||
beta_profile: `${domain.api_beta}/accounts/v1/me/profile`,
|
beta_profile: `${domain.api_beta}/accounts/v1/me/profile`,
|
||||||
beta_cmsToken: `${domain.api_beta}/index/v2`,
|
beta_cmsToken: `${domain.api_beta}/index/v2`,
|
||||||
|
|
@ -107,7 +107,6 @@ api.crunchyAuthHeader = {
|
||||||
|
|
||||||
api.crunchyAuthHeaderMob = {
|
api.crunchyAuthHeaderMob = {
|
||||||
Authorization: api.authBasicMob,
|
Authorization: api.authBasicMob,
|
||||||
'user-agent': 'Crunchyroll/3.60.0 Android/9 okhttp/4.12.0'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
api.crunchyAuthHeaderSwitch = {
|
api.crunchyAuthHeaderSwitch = {
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ export class Req {
|
||||||
}
|
}
|
||||||
// debug
|
// debug
|
||||||
if(this.debug){
|
if(this.debug){
|
||||||
console.debug('[DEBUG] FETCH OPTIONS:');
|
console.debug('[DEBUG] GOT OPTIONS:');
|
||||||
console.debug(options);
|
console.debug(options);
|
||||||
}
|
}
|
||||||
// try do request
|
// try do request
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "multi-downloader-nx",
|
"name": "multi-downloader-nx",
|
||||||
"short_name": "aniDL",
|
"short_name": "aniDL",
|
||||||
"version": "5.1.5",
|
"version": "5.1.0b5",
|
||||||
"description": "Downloader for Crunchyroll, Hidive, AnimeOnegai, and AnimationDigitalNetwork with CLI and GUI",
|
"description": "Downloader for Crunchyroll, Hidive, AnimeOnegai, and AnimationDigitalNetwork with CLI and GUI",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"download",
|
"download",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue