mirror of
https://github.com/daydreamer-json/ak-endfield-api-archive.git
synced 2026-03-22 07:12:28 +01:00
feat: add support for china bilibili channel resources
This commit is contained in:
@@ -186,7 +186,7 @@ async function generateGameListMd(target: GameTarget) {
|
||||
return (await Bun.file(localJsonPath).json()) as MirrorFileEntry[];
|
||||
})();
|
||||
|
||||
mdTexts.push(`# Game Packages (${target.name})\n`);
|
||||
mdTexts.push(`# Game Packages (${target.region === 'cn' ? 'China' : 'Global'}, ${target.name})\n`);
|
||||
|
||||
// TOC
|
||||
for (const e of gameAllJson) {
|
||||
@@ -251,7 +251,7 @@ async function generatePatchListMd(target: GameTarget) {
|
||||
return (await Bun.file(localJsonPath).json()) as MirrorFileEntry[];
|
||||
})();
|
||||
|
||||
mdTexts.push(`# Game Patch Packages (${target.name})\n`);
|
||||
mdTexts.push(`# Game Patch Packages (${target.region === 'cn' ? 'China' : 'Global'}, ${target.name})\n`);
|
||||
|
||||
// TOC
|
||||
for (const e of patchAllJson) {
|
||||
@@ -322,7 +322,11 @@ async function generatePatchListMd(target: GameTarget) {
|
||||
|
||||
async function generateResourceListMd(gameTargets: GameTarget[]) {
|
||||
const sanitizedGameTargets = [
|
||||
...new Set(gameTargets.map((e) => JSON.stringify({ region: e.region, appCode: e.appCode, channel: e.channel }))),
|
||||
...new Set(
|
||||
gameTargets
|
||||
.filter((e) => [appConfig.network.api.akEndfield.channel.cnWinRelBilibili].includes(e.channel) === false)
|
||||
.map((e) => JSON.stringify({ region: e.region, appCode: e.appCode, channel: e.channel })),
|
||||
),
|
||||
].map((e) => JSON.parse(e)) as { region: 'os' | 'cn'; appCode: string; channel: number }[];
|
||||
|
||||
const platforms = ['Windows', 'Android', 'iOS', 'PlayStation'] as const;
|
||||
@@ -612,7 +616,11 @@ async function fetchAndSaveLatestGameResources(gameTargets: GameTarget[]) {
|
||||
const platforms = ['Windows', 'Android', 'iOS', 'PlayStation'] as const;
|
||||
|
||||
const sanitizedGameTargets = [
|
||||
...new Set(gameTargets.map((e) => JSON.stringify({ region: e.region, appCode: e.appCode, channel: e.channel }))),
|
||||
...new Set(
|
||||
gameTargets
|
||||
.filter((e) => [appConfig.network.api.akEndfield.channel.cnWinRelBilibili].includes(e.channel) === false)
|
||||
.map((e) => JSON.stringify({ region: e.region, appCode: e.appCode, channel: e.channel })),
|
||||
),
|
||||
].map((e) => JSON.parse(e)) as { region: 'os' | 'cn'; appCode: string; channel: number }[];
|
||||
|
||||
const needDlRawFileBase: string[] = [];
|
||||
@@ -683,7 +691,11 @@ async function fetchAndSaveAllGameResRawData(gameTargets: GameTarget[]) {
|
||||
|
||||
const platforms = ['Windows', 'Android', 'iOS', 'PlayStation'] as const;
|
||||
const sanitizedGameTargets = [
|
||||
...new Set(gameTargets.map((e) => JSON.stringify({ region: e.region, appCode: e.appCode, channel: e.channel }))),
|
||||
...new Set(
|
||||
gameTargets
|
||||
.filter((e) => [appConfig.network.api.akEndfield.channel.cnWinRelBilibili].includes(e.channel) === false)
|
||||
.map((e) => JSON.stringify({ region: e.region, appCode: e.appCode, channel: e.channel })),
|
||||
),
|
||||
].map((e) => JSON.parse(e)) as { region: 'os' | 'cn'; appCode: string; channel: number }[];
|
||||
const queue = new PQueue({ concurrency: appConfig.threadCount.network });
|
||||
const needDlRawFileBase: string[] = [];
|
||||
@@ -822,6 +834,16 @@ async function mainCmdHandler() {
|
||||
launcherSubChannel: cfg.subChannel.cnWinRel,
|
||||
dirName: String(cfg.channel.cnWinRel),
|
||||
},
|
||||
{
|
||||
name: 'Bilibili',
|
||||
region: 'cn',
|
||||
appCode: cfg.appCode.game.cnWinRel,
|
||||
launcherAppCode: cfg.appCode.launcher.cnWinRel,
|
||||
channel: cfg.channel.cnWinRelBilibili,
|
||||
subChannel: cfg.subChannel.cnWinRelBilibili,
|
||||
launcherSubChannel: cfg.subChannel.cnWinRelBilibili,
|
||||
dirName: String(cfg.channel.cnWinRelBilibili),
|
||||
},
|
||||
];
|
||||
|
||||
const launcherTargets: LauncherTarget[] = [
|
||||
|
||||
@@ -19,14 +19,14 @@ async function mainCmdHandler() {
|
||||
if (!('token' in argvUtils.getArgv()) || !argvUtils.getArgv()['token']) {
|
||||
const tokenUserRsp: string = await (async () => {
|
||||
logger.warn('Gryphline account service token has not been specified. Requesting ...');
|
||||
const onCancelFn = () => {
|
||||
const onCancel = () => {
|
||||
logger.error('Aborted');
|
||||
exitUtils.exit(1, null, false);
|
||||
};
|
||||
return (
|
||||
await prompts(
|
||||
{ name: 'value', type: 'password', message: 'Enter Gryphline account service token' },
|
||||
{ onCancel: onCancelFn },
|
||||
{ onCancel },
|
||||
)
|
||||
).value;
|
||||
})();
|
||||
@@ -53,8 +53,8 @@ async function mainCmdHandler() {
|
||||
}
|
||||
}
|
||||
if (needRetrieveToken) {
|
||||
await (async () => {
|
||||
const onCancelFn = () => {
|
||||
{
|
||||
const onCancel = () => {
|
||||
logger.error('Aborted');
|
||||
exitUtils.exit(1, null, false);
|
||||
};
|
||||
@@ -66,7 +66,7 @@ async function mainCmdHandler() {
|
||||
...{ name: 'value', type: 'text', message: 'Enter Gryphline account email' },
|
||||
validate: (value) => (Boolean(value) ? true : 'Invalid value'),
|
||||
},
|
||||
{ onCancel: onCancelFn },
|
||||
{ onCancel },
|
||||
)
|
||||
).value;
|
||||
argvUtils.setArgv({ ...argvUtils.getArgv(), email: emailRsp });
|
||||
@@ -79,12 +79,12 @@ async function mainCmdHandler() {
|
||||
...{ name: 'value', type: 'password', message: 'Enter Gryphline account password' },
|
||||
validate: (value) => (Boolean(value) ? true : 'Invalid value'),
|
||||
},
|
||||
{ onCancel: onCancelFn },
|
||||
{ onCancel },
|
||||
)
|
||||
).value;
|
||||
argvUtils.setArgv({ ...argvUtils.getArgv(), password: pwdRsp });
|
||||
}
|
||||
})();
|
||||
}
|
||||
logger.debug('Retrieving account service token ...');
|
||||
const accSrvTokenRsp = await apiUtils.akEndfield.accountService.user.auth.v1.tokenByEmailPassword(
|
||||
argvUtils.getArgv()['email'],
|
||||
@@ -101,6 +101,11 @@ async function mainCmdHandler() {
|
||||
argvUtils.getArgv()['token'],
|
||||
)
|
||||
: oauth2TokenPreRsp;
|
||||
const oauth2TokenSkportRsp = await apiUtils.akEndfield.accountService.user.oauth2.v2.grant(
|
||||
cfg.appCode.accountService.skport,
|
||||
argvUtils.getArgv()['token'],
|
||||
0,
|
||||
);
|
||||
const oauth2TokenBindRsp = await apiUtils.akEndfield.accountService.user.oauth2.v2.grant(
|
||||
cfg.appCode.accountService.binding,
|
||||
argvUtils.getArgv()['token'],
|
||||
@@ -112,8 +117,13 @@ async function mainCmdHandler() {
|
||||
cfg.channel.osWinRel,
|
||||
oauth2TokenRsp.data.code,
|
||||
);
|
||||
logger.debug('Retrieving SKPort credential ...');
|
||||
const skPortCredRsp = await apiUtils.akEndfield.zonai.web.v1.user.auth.generateCredByCode(
|
||||
oauth2TokenSkportRsp.data.code,
|
||||
1,
|
||||
);
|
||||
// logger.debug('Retrieving u8 OAuth 2.0 code ...');
|
||||
// const u8OAuth2Rsp = await apiUtils.apiAkEndfield.u8.user.auth.v2.grant(u8TokenRsp.data.token);
|
||||
// const u8OAuth2Rsp = await apiUtils.akEndfield.u8.user.auth.v2.grant(u8TokenRsp.data.token);
|
||||
logger.info('Authentication successful!');
|
||||
|
||||
logger.info('Retrieving user information data ...');
|
||||
@@ -129,6 +139,46 @@ async function mainCmdHandler() {
|
||||
oauth2TokenBindRsp.data.token,
|
||||
);
|
||||
|
||||
logger.debug('Retrieving SKPort binding data ...');
|
||||
const skPortBindingRsp = await apiUtils.akEndfield.zonai.api.v1.game.player.binding(
|
||||
skPortCredRsp.data.cred,
|
||||
skPortCredRsp.data.token,
|
||||
);
|
||||
const skPortGameRoleStr = (() => {
|
||||
const game = skPortBindingRsp.data.list.find((e) => e.appCode === 'endfield');
|
||||
if (!game) throw new Error('SKPort game id not found for endfield');
|
||||
return `${game.bindingList[0]?.gameId}_${game.bindingList[0]?.defaultRole.roleId}_${game.bindingList[0]?.defaultRole.serverId}`;
|
||||
})();
|
||||
|
||||
logger.debug('Trying SKPort attendance ...');
|
||||
await apiUtils.akEndfield.zonai.web.v1.game.endfield.attendance.record(
|
||||
skPortCredRsp.data.cred,
|
||||
skPortCredRsp.data.token,
|
||||
skPortGameRoleStr,
|
||||
);
|
||||
const attendanceRsp = await apiUtils.akEndfield.zonai.web.v1.game.endfield.attendance.get(
|
||||
skPortCredRsp.data.cred,
|
||||
skPortCredRsp.data.token,
|
||||
skPortGameRoleStr,
|
||||
);
|
||||
logger.debug(
|
||||
'SKPort attendance status: ' + (attendanceRsp.data.hasToday ? chalk.red('Not complete') : chalk.green('Done')),
|
||||
);
|
||||
|
||||
logger.debug('Testing redeem code flow ...');
|
||||
const redeemRsp = await (async () => {
|
||||
const game = skPortBindingRsp.data.list.find((e) => e.appCode === 'endfield');
|
||||
if (!game || !game.bindingList[0]) throw new Error('SKPort game id not found for endfield');
|
||||
return await apiUtils.akEndfield.gameHub.giftcode.redeem(
|
||||
appConfig.network.api.akEndfield.channel.osWinRel,
|
||||
parseInt(game.bindingList[0].defaultRole.serverId),
|
||||
'Windows',
|
||||
'RETURNOFALL',
|
||||
u8TokenRsp.data.token,
|
||||
);
|
||||
})();
|
||||
logger.debug(`Redeem result: ${JSON.stringify(redeemRsp)}`);
|
||||
|
||||
logger.debug('Retrieving gacha record ...');
|
||||
const selectedServerId = await (async () => {
|
||||
const selectedServerAccData = userGameBindingData.data.list
|
||||
|
||||
@@ -359,6 +359,195 @@ type WebViewRecordContent = {
|
||||
msg: string;
|
||||
};
|
||||
|
||||
type ZonaiWebV1UserAuthGenCredByCode = {
|
||||
code: number; // 0 = ok
|
||||
message: string; // OK
|
||||
timestamp: string; // unixtime
|
||||
data: {
|
||||
cred: string; // base64?
|
||||
userId: string;
|
||||
token: string; // hex;
|
||||
};
|
||||
};
|
||||
|
||||
type ZonaiWebV1UserCheck = {
|
||||
code: number; // 0 = ok
|
||||
message: string; // OK
|
||||
timestamp: string; // unixtime
|
||||
data: {
|
||||
cred: string;
|
||||
userId: string;
|
||||
token: string;
|
||||
};
|
||||
};
|
||||
|
||||
type ZonaiWebV1WikiMe = {
|
||||
code: number; // 0 = ok
|
||||
message: string; // OK
|
||||
timestamp: string; // unixtime
|
||||
data: {
|
||||
user: {
|
||||
userId: string;
|
||||
nickname: string;
|
||||
avatarCode: number;
|
||||
avatar: string;
|
||||
};
|
||||
resources: any[];
|
||||
};
|
||||
};
|
||||
|
||||
type ZonaiWebV2User = {
|
||||
code: number;
|
||||
message: string;
|
||||
timestamp: string;
|
||||
data: {
|
||||
user: {
|
||||
basicUser: {
|
||||
id: string;
|
||||
nickname: string;
|
||||
profile: string;
|
||||
avatarCode: number;
|
||||
avatar: string;
|
||||
gender: number;
|
||||
status: number;
|
||||
operationStatus: number;
|
||||
identity: number;
|
||||
kind: number;
|
||||
moderatorStatus: number;
|
||||
moderatorChangeTime: number;
|
||||
createdAt: string;
|
||||
latestLoginAt: string;
|
||||
};
|
||||
pendant: {
|
||||
id: number;
|
||||
iconUrl: string;
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
background: any;
|
||||
};
|
||||
userRts: {
|
||||
follow: string;
|
||||
fans: string;
|
||||
liked: string;
|
||||
};
|
||||
userSanctionList: any[];
|
||||
userInfoApply: {};
|
||||
moderator: {
|
||||
isModerator: boolean;
|
||||
operations: any[];
|
||||
role: string;
|
||||
since: string;
|
||||
status: number;
|
||||
gameOperations: {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
type ZonaiApiV1GamePlayerBinding = {
|
||||
code: number;
|
||||
message: string;
|
||||
timestamp: string;
|
||||
data: {
|
||||
list: {
|
||||
appCode: string;
|
||||
appName: string;
|
||||
bindingList: {
|
||||
uid: string;
|
||||
isOfficial: boolean;
|
||||
isDefault: boolean;
|
||||
channelMasterId: string;
|
||||
channelName: string;
|
||||
nickName: string;
|
||||
isDelete: boolean;
|
||||
gameName: string;
|
||||
gameId: number;
|
||||
roles: {
|
||||
serverId: string;
|
||||
roleId: string;
|
||||
nickname: string;
|
||||
level: number;
|
||||
isDefault: boolean;
|
||||
isBanned: boolean;
|
||||
serverType: string;
|
||||
serverName: string;
|
||||
}[];
|
||||
defaultRole: {
|
||||
serverId: string;
|
||||
roleId: string;
|
||||
nickname: string;
|
||||
level: number;
|
||||
isDefault: boolean;
|
||||
isBanned: boolean;
|
||||
serverType: string;
|
||||
serverName: string;
|
||||
};
|
||||
}[];
|
||||
}[];
|
||||
serverDefaultBinding: {};
|
||||
};
|
||||
};
|
||||
|
||||
type ZonaiWebV1GameEndfieldAttendance = {
|
||||
code: number;
|
||||
message: string;
|
||||
timestamp: string;
|
||||
data: {
|
||||
currentTs: string;
|
||||
calendar: {
|
||||
awardId: string; // endfield_attendance_1_2
|
||||
available: boolean;
|
||||
done: boolean;
|
||||
}[];
|
||||
first: {
|
||||
awardId: string; // endfield_attendance_1_2
|
||||
available: boolean;
|
||||
done: boolean;
|
||||
}[];
|
||||
resourceInfoMap: Record<
|
||||
string,
|
||||
{
|
||||
id: string; // endfield_attendance_1_2
|
||||
count: number;
|
||||
name: string;
|
||||
icon: string;
|
||||
}
|
||||
>;
|
||||
hasToday: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
type ZonaiWebV1GameEndfieldAttendanceRecord = {
|
||||
code: number;
|
||||
message: string;
|
||||
timestamp: string;
|
||||
data: {
|
||||
records: {
|
||||
ts: string;
|
||||
awardId: string; // endfield_attendance_1_2
|
||||
}[];
|
||||
resourceInfoMap: Record<
|
||||
string,
|
||||
{
|
||||
id: string; // endfield_attendance_1_2
|
||||
count: number;
|
||||
name: string;
|
||||
icon: string;
|
||||
}
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
type GameHubGiftCodeRedeem = {
|
||||
code: number; // 0=OK, 11004=ActivityExpired
|
||||
data: {
|
||||
redeemResult?: {
|
||||
recordId: string;
|
||||
};
|
||||
};
|
||||
msg: string; // ''=OK
|
||||
};
|
||||
|
||||
export type {
|
||||
LauncherLatestGame,
|
||||
LauncherLatestGameResources,
|
||||
@@ -383,4 +572,12 @@ export type {
|
||||
BindApiGeneralV1AuthAppList,
|
||||
WebViewRecordChar,
|
||||
WebViewRecordContent,
|
||||
ZonaiWebV1UserAuthGenCredByCode,
|
||||
ZonaiWebV1UserCheck,
|
||||
ZonaiWebV1WikiMe,
|
||||
ZonaiWebV2User,
|
||||
ZonaiApiV1GamePlayerBinding,
|
||||
ZonaiWebV1GameEndfieldAttendance,
|
||||
ZonaiWebV1GameEndfieldAttendanceRecord,
|
||||
GameHubGiftCodeRedeem,
|
||||
};
|
||||
|
||||
41
src/utils/api/akEndfield/gameHub.ts
Normal file
41
src/utils/api/akEndfield/gameHub.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import ky from 'ky';
|
||||
import * as TypesApiAkEndfield from '../../../types/api/akEndfield/Api.js';
|
||||
import config from '../../config.js';
|
||||
import defaultSettings from './defaultSettings.js';
|
||||
|
||||
const overrideDefSetKy = {
|
||||
...defaultSettings.ky,
|
||||
headers: {
|
||||
'User-Agent': config.network.userAgent.qtHgSdk,
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
giftcode: {
|
||||
redeem: async (
|
||||
channelId: number,
|
||||
serverId: number,
|
||||
platform: 'Windows' | 'iOS' | 'Android',
|
||||
code: string,
|
||||
token: string,
|
||||
confirm: boolean = false,
|
||||
) => {
|
||||
const rsp = await ky
|
||||
.post(`https://${config.network.api.akEndfield.base.gameHub}/giftcode/api/redeem`, {
|
||||
...overrideDefSetKy,
|
||||
headers: {
|
||||
...overrideDefSetKy.headers,
|
||||
Origin: 'https://' + config.network.api.akEndfield.base.webview,
|
||||
Referer:
|
||||
'https://' +
|
||||
config.network.api.akEndfield.base.webview +
|
||||
`/page/giftcode?u8_token=${encodeURIComponent(token)}&platform=${platform}&channel=${channelId}&subChannel=${channelId}&lang=en-us&server=${serverId}`,
|
||||
'Accept-Language': 'en-us',
|
||||
},
|
||||
json: { channelId: String(channelId), serverId: String(serverId), platform, code, token, confirm },
|
||||
})
|
||||
.json();
|
||||
return rsp as TypesApiAkEndfield.GameHubGiftCodeRedeem;
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,15 +1,19 @@
|
||||
import accountService from './accountService.js';
|
||||
import binding from './binding.js';
|
||||
import gameHub from './gameHub.js';
|
||||
import launcher from './launcher.js';
|
||||
import launcherWeb from './launcherWeb.js';
|
||||
import u8 from './u8.js';
|
||||
import webview from './webview.js';
|
||||
import zonai from './zonai.js';
|
||||
|
||||
export default {
|
||||
accountService,
|
||||
binding,
|
||||
gameHub,
|
||||
launcher,
|
||||
launcherWeb,
|
||||
u8,
|
||||
webview,
|
||||
zonai,
|
||||
};
|
||||
|
||||
159
src/utils/api/akEndfield/zonai.ts
Normal file
159
src/utils/api/akEndfield/zonai.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
// https://zonai.skport.com/web/v1/user/auth/generate_cred_by_code
|
||||
|
||||
import crypto from 'node:crypto';
|
||||
import ky from 'ky';
|
||||
import { DateTime } from 'luxon';
|
||||
import * as TypesApiAkEndfield from '../../../types/api/akEndfield/Api.js';
|
||||
import config from '../../config.js';
|
||||
import defaultSettings from './defaultSettings.js';
|
||||
|
||||
const overrideDefSetKy = {
|
||||
...defaultSettings.ky,
|
||||
headers: {
|
||||
'User-Agent': config.network.userAgent.chromeWindows,
|
||||
vname: '1.0.0',
|
||||
platform: '3',
|
||||
},
|
||||
};
|
||||
|
||||
function calcSignHeader(path: string, cred: string, salt: string) {
|
||||
const timestamp = DateTime.now().toUnixInteger().toString();
|
||||
const useV2Path: string[] = [
|
||||
'/web/v1/wiki/me',
|
||||
'/web/v2/user',
|
||||
'/api/v1/game/player/binding',
|
||||
'/web/v1/game/endfield/attendance',
|
||||
'/web/v1/game/endfield/attendance/record',
|
||||
];
|
||||
if (useV2Path.includes(path)) {
|
||||
const v2Payload = JSON.stringify({
|
||||
platform: String(overrideDefSetKy.headers.platform),
|
||||
timestamp,
|
||||
dId: '',
|
||||
vName: overrideDefSetKy.headers.vname,
|
||||
});
|
||||
return {
|
||||
sign: crypto
|
||||
.createHash('md5')
|
||||
.update(
|
||||
crypto
|
||||
.createHmac('sha256', salt)
|
||||
.update(path + timestamp + v2Payload)
|
||||
.digest('hex'),
|
||||
)
|
||||
.digest('hex'),
|
||||
timestamp,
|
||||
};
|
||||
} else {
|
||||
return { sign: crypto.hash('md5', `timestamp=${timestamp}&cred=${cred}`, 'hex'), timestamp };
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
web: {
|
||||
v1: {
|
||||
game: {
|
||||
endfield: {
|
||||
attendance: {
|
||||
get: async (cred: string, token: string, skGameRole: string) => {
|
||||
const path = '/web/v1/game/endfield/attendance';
|
||||
const rsp = await ky
|
||||
.get(`https://${config.network.api.akEndfield.base.zonai}` + path, {
|
||||
...overrideDefSetKy,
|
||||
headers: {
|
||||
...overrideDefSetKy.headers,
|
||||
cred,
|
||||
...calcSignHeader(path, cred, token),
|
||||
'sk-game-role': skGameRole,
|
||||
},
|
||||
})
|
||||
.json();
|
||||
return rsp as TypesApiAkEndfield.ZonaiWebV1GameEndfieldAttendance;
|
||||
},
|
||||
record: async (cred: string, token: string, skGameRole: string) => {
|
||||
const path = '/web/v1/game/endfield/attendance/record';
|
||||
const rsp = await ky
|
||||
.get(`https://${config.network.api.akEndfield.base.zonai}` + path, {
|
||||
...overrideDefSetKy,
|
||||
headers: {
|
||||
...overrideDefSetKy.headers,
|
||||
cred,
|
||||
...calcSignHeader(path, cred, token),
|
||||
'sk-game-role': skGameRole, // 3_4000000000_2
|
||||
},
|
||||
})
|
||||
.json();
|
||||
return rsp as TypesApiAkEndfield.ZonaiWebV1GameEndfieldAttendanceRecord;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
user: {
|
||||
auth: {
|
||||
generateCredByCode: async (code: string, kind: 1) => {
|
||||
const rsp = await ky
|
||||
.post(`https://${config.network.api.akEndfield.base.zonai}/web/v1/user/auth/generate_cred_by_code`, {
|
||||
...overrideDefSetKy,
|
||||
headers: { ...overrideDefSetKy.headers },
|
||||
json: { kind, code },
|
||||
})
|
||||
.json();
|
||||
return rsp as TypesApiAkEndfield.ZonaiWebV1UserAuthGenCredByCode;
|
||||
},
|
||||
},
|
||||
check: async (cred: string, token: string) => {
|
||||
const path = '/web/v1/user/check';
|
||||
const rsp = await ky
|
||||
.get(`https://${config.network.api.akEndfield.base.zonai}` + path, {
|
||||
...overrideDefSetKy,
|
||||
headers: { ...overrideDefSetKy.headers, cred, ...calcSignHeader(path, cred, token) },
|
||||
})
|
||||
.json();
|
||||
return rsp as TypesApiAkEndfield.ZonaiWebV1UserCheck;
|
||||
},
|
||||
},
|
||||
wiki: {
|
||||
me: async (cred: string, token: string) => {
|
||||
const path = '/web/v1/wiki/me';
|
||||
const rsp = await ky
|
||||
.get(`https://${config.network.api.akEndfield.base.zonai}` + path, {
|
||||
...overrideDefSetKy,
|
||||
headers: { ...overrideDefSetKy.headers, cred, ...calcSignHeader(path, cred, token) },
|
||||
})
|
||||
.json();
|
||||
return rsp as TypesApiAkEndfield.ZonaiWebV1WikiMe;
|
||||
},
|
||||
},
|
||||
},
|
||||
v2: {
|
||||
user: async (cred: string, token: string) => {
|
||||
const path = '/web/v2/user';
|
||||
const rsp = await ky
|
||||
.get(`https://${config.network.api.akEndfield.base.zonai}` + path, {
|
||||
...overrideDefSetKy,
|
||||
headers: { ...overrideDefSetKy.headers, cred, ...calcSignHeader(path, cred, token) },
|
||||
})
|
||||
.json();
|
||||
return rsp as TypesApiAkEndfield.ZonaiWebV2User;
|
||||
},
|
||||
},
|
||||
},
|
||||
api: {
|
||||
v1: {
|
||||
game: {
|
||||
player: {
|
||||
binding: async (cred: string, token: string) => {
|
||||
const path = '/api/v1/game/player/binding';
|
||||
const rsp = await ky
|
||||
.get(`https://${config.network.api.akEndfield.base.zonai}` + path, {
|
||||
...overrideDefSetKy,
|
||||
headers: { ...overrideDefSetKy.headers, cred, ...calcSignHeader(path, cred, token) },
|
||||
})
|
||||
.json();
|
||||
return rsp as TypesApiAkEndfield.ZonaiApiV1GamePlayerBinding;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -21,15 +21,23 @@ type ConfigType = AllRequired<
|
||||
accountService: { osWinRel: string; skport: string; binding: string };
|
||||
u8: { osWinRel: string };
|
||||
};
|
||||
channel: { osWinRel: number; cnWinRel: number };
|
||||
subChannel: { osWinRel: number; osWinRelEpic: number; osWinRelGooglePlay: number; cnWinRel: number };
|
||||
channel: { osWinRel: number; cnWinRel: number; cnWinRelBilibili: number };
|
||||
subChannel: {
|
||||
osWinRel: number;
|
||||
osWinRelEpic: number;
|
||||
osWinRelGooglePlay: number;
|
||||
cnWinRel: number;
|
||||
cnWinRelBilibili: number;
|
||||
};
|
||||
base: {
|
||||
accountService: string;
|
||||
gameHub: string;
|
||||
launcher: string;
|
||||
launcherCN: string;
|
||||
u8: string;
|
||||
binding: string;
|
||||
webview: string;
|
||||
zonai: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -37,6 +45,7 @@ type ConfigType = AllRequired<
|
||||
// UA to hide the fact that the access is from this tool
|
||||
minimum: string;
|
||||
chromeWindows: string;
|
||||
qtHgSdk: string;
|
||||
curl: string;
|
||||
ios: string;
|
||||
};
|
||||
@@ -69,15 +78,17 @@ const initialConfig: ConfigType = {
|
||||
accountService: { osWinRel: 'd9f6dbb6bbd6bb33', skport: '6eb76d4e13aa36e6', binding: '3dacefa138426cfe' },
|
||||
u8: { osWinRel: '973bd727dd11cbb6ead8' },
|
||||
},
|
||||
channel: { osWinRel: 6, cnWinRel: 1 },
|
||||
subChannel: { osWinRel: 6, osWinRelEpic: 801, osWinRelGooglePlay: 802, cnWinRel: 1 },
|
||||
channel: { osWinRel: 6, cnWinRel: 1, cnWinRelBilibili: 2 },
|
||||
subChannel: { osWinRel: 6, osWinRelEpic: 801, osWinRelGooglePlay: 802, cnWinRel: 1, cnWinRelBilibili: 2 },
|
||||
base: {
|
||||
accountService: 'YXMuZ3J5cGhsaW5lLmNvbQ==',
|
||||
gameHub: 'Z2FtZS1odWIuZ3J5cGhsaW5lLmNvbQ==',
|
||||
launcher: 'bGF1bmNoZXIuZ3J5cGhsaW5lLmNvbS9hcGk=',
|
||||
launcherCN: 'bGF1bmNoZXIuaHlwZXJncnlwaC5jb20vYXBp',
|
||||
u8: 'dTguZ3J5cGhsaW5lLmNvbQ==',
|
||||
binding: 'YmluZGluZy1hcGktYWNjb3VudC1wcm9kLmdyeXBobGluZS5jb20=',
|
||||
webview: 'ZWYtd2Vidmlldy5ncnlwaGxpbmUuY29t',
|
||||
zonai: 'em9uYWkuc2twb3J0LmNvbQ==',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -85,6 +96,8 @@ const initialConfig: ConfigType = {
|
||||
minimum: 'Mozilla/5.0',
|
||||
chromeWindows:
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36',
|
||||
qtHgSdk:
|
||||
'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.15.8 Chrome/87.0.4280.144 Safari/537.36 PC/WIN/HGSDK HGWebPC/1.30.1',
|
||||
curl: 'curl/8.4.0',
|
||||
ios: 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user