feat: implement china region launcher api support

This commit is contained in:
daydreamer-json
2026-02-12 01:46:46 +09:00
parent 0120e6b88e
commit 4df4b612dd
44 changed files with 930 additions and 64 deletions

View File

@@ -58,22 +58,54 @@ export default {
channel: number,
subChannel: number,
version: string | null,
targetApp: 'EndField' | null,
targetApp: 'EndField' | 'Arknights' | 'Official',
region: 'os' | 'cn',
): Promise<TypesApiAkEndfield.LauncherLatestLauncher> => {
if (version !== null && !semver.valid(version)) throw new Error(`Invalid version string (${version})`);
const domain =
region === 'cn'
? appConfig.network.api.akEndfield.base.launcherCN
: appConfig.network.api.akEndfield.base.launcher;
const rsp = await ky
.get(`https://${appConfig.network.api.akEndfield.base.launcher}/launcher/get_latest`, {
.get(`https://${domain}/launcher/get_latest`, {
...defaultSettings.ky,
searchParams: {
appcode: appCode,
channel,
sub_channel: subChannel,
version: version ?? undefined,
target_app: targetApp ?? undefined,
target_app: targetApp,
},
})
.json();
return rsp as TypesApiAkEndfield.LauncherLatestLauncher;
},
latestLauncherExe: async (
appCode: string,
channel: number,
subChannel: number,
version: string | null,
targetApp: 'endfield' | 'official' | string,
region: 'os' | 'cn',
): Promise<TypesApiAkEndfield.LauncherLatestLauncherExe> => {
if (version !== null && !semver.valid(version)) throw new Error(`Invalid version string (${version})`);
const domain =
region === 'cn'
? appConfig.network.api.akEndfield.base.launcherCN
: appConfig.network.api.akEndfield.base.launcher;
const rsp = await ky
.get(`https://${domain}/launcher/get_latest_launcher`, {
...defaultSettings.ky,
searchParams: {
appcode: appCode,
channel,
sub_channel: subChannel,
version: version ?? undefined,
ta: targetApp,
},
})
.json();
return rsp as TypesApiAkEndfield.LauncherLatestLauncherExe;
},
web: launcherWeb,
};

View File

@@ -1,5 +1,7 @@
import akEndfield from './akEndfield/index.js';
import webArchiveOrg from './webArchiveOrg/index.js';
export default {
akEndfield,
webArchiveOrg,
};

View File

@@ -0,0 +1,11 @@
import appConfig from '../../config.js';
export default {
ky: {
headers: {
'User-Agent': appConfig.network.userAgent.chromeWindows,
},
timeout: appConfig.network.timeout,
retry: { limit: appConfig.network.retryCount },
},
};

View File

@@ -0,0 +1,85 @@
import cookie from 'cookie';
import ky from 'ky';
import defaultSettings from './defaultSettings.js';
export default {
login: {
getLoginToken: async (): Promise<string> => {
const rsp: any = await ky.get('https://archive.org/services/account/login/', defaultSettings.ky).json();
if (!rsp.value.token) throw new Error('Failed to get wayback machine login token');
return rsp.value.token;
},
login: async (username: string, password: string, token: string, remember: boolean = true) => {
const rsp = await ky.post('https://archive.org/services/account/login/', {
...defaultSettings.ky,
json: {
username,
password,
remember: String(remember),
t: token,
},
});
if (!((await rsp.json()) as any).success) throw new Error('Wayback Machine login error: ' + rsp);
return rsp.headers.getSetCookie().map((e) => cookie.parseSetCookie(e));
},
},
save: async (url: string, auth: { user: string; sig: string }): Promise<string> => {
const params = new URLSearchParams();
params.append('url', url);
params.append('capture_all', 'on');
const rsp = await ky
.post('https://web.archive.org/save/' + url, {
...defaultSettings.ky,
headers: {
...defaultSettings.ky.headers,
Cookie: cookie.stringifyCookie({ 'logged-in-sig': auth.sig, 'logged-in-user': auth.user }),
},
body: params,
})
.text();
const match = rsp.match(/spn\.watchJob\("([^"]+)"/);
if (match && match[1]) {
return match[1]; // spn2-xxxxxxxxxxxxxxxxxxx
}
throw new Error('Wayback Machine save job id not found');
},
saveStatus: async (
jobId: string,
auth: { user: string; sig: string },
): Promise<
| {
status: 'success';
job_id: string;
resources: [];
download_size: number;
total_size: number;
timestamp: string;
original_url: string;
duration_sec: number;
counters: {
outlinks: number;
embeds: number;
};
http_status: number;
first_archive: boolean;
}
| {
status: 'pending';
job_id: string;
resources: [];
download_size?: number;
total_size?: number;
}
> => {
const rsp = await ky
.get('https://web.archive.org/save/status/' + jobId, {
...defaultSettings.ky,
headers: {
...defaultSettings.ky.headers,
Cookie: cookie.stringifyCookie({ 'logged-in-sig': auth.sig, 'logged-in-user': auth.user }),
},
})
.json();
return rsp as any;
},
};