Refactoring

This commit is contained in:
daydreamer-json
2026-01-22 21:03:44 +09:00
parent 24c78b048f
commit 070627b522
2 changed files with 101 additions and 129 deletions

View File

@@ -2,7 +2,7 @@
Monitor changes to responses from various Arknights Endfield APIs and record them in this repository.
Updates are checked hourly and automatically pushed via GitHub Actions.
Updates are checked about every 30 minutes and automatically pushed to GitHub Actions.
API outputs are stored in the [`output`](/output/) directory.
The APIs currently being monitored are as follows:

View File

@@ -7,24 +7,76 @@ import appConfig from '../utils/config.js';
import logger from '../utils/logger.js';
import mathUtils from '../utils/math.js';
function getObjectDiff(obj1: any, obj2: any) {
const diff: any = {};
const keys = new Set([...Object.keys(obj1 || {}), ...Object.keys(obj2 || {})]);
for (const key of keys) {
const val1 = obj1?.[key];
const val2 = obj2?.[key];
if (JSON.stringify(val1) !== JSON.stringify(val2)) {
if (typeof val1 === 'object' && val1 !== null && typeof val2 === 'object' && val2 !== null) {
const nestedDiff = getObjectDiff(val1, val2);
if (Object.keys(nestedDiff).length > 0) {
diff[key] = nestedDiff;
}
} else {
diff[key] = { old: val1, new: val2 };
}
}
}
return diff;
}
async function saveResult(
subPaths: string[],
version: string,
data: { req: any; rsp: any },
saveLatest: boolean = true,
) {
const outputDir = argvUtils.getArgv()['outputDir'];
const filePathBase = path.join(outputDir, ...subPaths);
const filesToCheck = [path.join(filePathBase, `v${version}.json`)];
if (saveLatest) {
filesToCheck.push(path.join(filePathBase, 'latest.json'));
}
const dataStr = JSON.stringify(data, null, 2);
const dataMinified = JSON.stringify(data);
for (const filePath of filesToCheck) {
const file = Bun.file(filePath);
const exists = await file.exists();
let currentData: any = null;
if (exists) {
currentData = await file.json();
}
if (!exists || JSON.stringify(currentData) !== dataMinified) {
if (exists) {
logger.trace(`Diff detected in ${filePath}:`, JSON.stringify(getObjectDiff(currentData, data), null, 2));
}
await Bun.write(filePath, dataStr);
}
}
const allFilePath = path.join(filePathBase, 'all.json');
const allFile = Bun.file(allFilePath);
let allData: any[] = [];
if (await allFile.exists()) {
allData = await allFile.json();
}
const exists = allData.some((e: any) => JSON.stringify({ req: e.req, rsp: e.rsp }) === dataMinified);
if (!exists) {
allData.push({ updatedAt: DateTime.now().toISO(), ...data });
await Bun.write(allFilePath, JSON.stringify(allData, null, 2));
}
}
async function mainCmdHandler() {
const cfg = appConfig.network.api.akEndfield;
// await (async () => {
// const channel = appConfig.network.api.akEndfield.channel.osWinRel;
// logger.debug('apiAkEndfield.launcher.web fetching ...');
// for (const fn of [
// apiUtils.apiAkEndfield.launcher.web.sidebar,
// apiUtils.apiAkEndfield.launcher.web.singleEnt,
// apiUtils.apiAkEndfield.launcher.web.mainBgImage,
// apiUtils.apiAkEndfield.launcher.web.banner,
// apiUtils.apiAkEndfield.launcher.web.announcement,
// ]) {
// console.dir(await fn(appConfig.network.api.akEndfield.appCode.osWinRel, channel, channel, 'ja-jp'), {
// depth: null,
// });
// }
// })();
const channelStr = String(cfg.channel.osWinRel);
await (async () => {
logger.debug('Fetching latestGame ...');
@@ -59,54 +111,31 @@ async function mainCmdHandler() {
},
rsp,
};
const filePathBase = path.join(
argvUtils.getArgv()['outputDir'],
'akEndfield',
'launcher',
'game',
String(cfg.channel.osWinRel),
);
for (const filePath of [path.join(filePathBase, 'latest.json'), path.join(filePathBase, `v${rsp.version}.json`)]) {
if (
(await Bun.file(filePath).exists()) === false ||
JSON.stringify(await Bun.file(filePath).json()) !== JSON.stringify(prettyRsp)
) {
await Bun.write(filePath, JSON.stringify(prettyRsp, null, 2));
}
}
await (async () => {
let needWrite: boolean = true;
const tmp: ({ updatedAt: string } & typeof prettyRsp)[] = await Bun.file(
path.join(filePathBase, 'all.json'),
).json();
for (const dataStr of tmp.map((e) => JSON.stringify({ req: e.req, rsp: e.rsp }))) {
if (dataStr === JSON.stringify(prettyRsp)) {
needWrite = false;
}
}
if (needWrite) {
tmp.push({ updatedAt: DateTime.now().toISO(), ...prettyRsp });
await Bun.write(path.join(filePathBase, 'all.json'), JSON.stringify(tmp, null, 2));
}
})();
await saveResult(['akEndfield', 'launcher', 'game', channelStr], rsp.version, prettyRsp);
})();
await (async () => {
logger.debug('Fetching latestGameRes ...');
const gameAllJsonPath = path.join(
argvUtils.getArgv()['outputDir'],
'akEndfield',
'launcher',
'game',
channelStr,
'all.json',
);
if (!(await Bun.file(gameAllJsonPath).exists())) {
logger.warn('Skipping latestGameRes: game/all.json not found');
return;
}
const versionInfoList = (
(
await Bun.file(
path.join(
argvUtils.getArgv()['outputDir'],
'akEndfield',
'launcher',
'game',
String(cfg.channel.osWinRel),
'all.json',
),
).json()
).map((e: any) => e.rsp) as Awaited<ReturnType<typeof apiUtils.apiAkEndfield.launcher.latestGame>>[]
(await Bun.file(gameAllJsonPath).json()).map((e: any) => e.rsp) as Awaited<
ReturnType<typeof apiUtils.apiAkEndfield.launcher.latestGame>
>[]
)
.map((e) => ({
version: e.version,
@@ -114,13 +143,6 @@ async function mainCmdHandler() {
randStr: /_([^/]+)\/.+?$/.exec(e.pkg.file_path)![1],
}))
.sort((a, b) => semver.compare(b.version, a.version));
const filePathBase = path.join(
argvUtils.getArgv()['outputDir'],
'akEndfield',
'launcher',
'game_resources',
String(cfg.channel.osWinRel),
);
let isLatestWrote: boolean = false;
for (const versionInfoEntry of versionInfoList) {
if (!versionInfoEntry.randStr) throw new Error('version rand_str not found');
@@ -140,36 +162,14 @@ async function mainCmdHandler() {
},
rsp,
};
if (isLatestWrote === false) {
if (
(await Bun.file(path.join(filePathBase, 'latest.json')).exists()) === false ||
JSON.stringify(await Bun.file(path.join(filePathBase, 'latest.json')).json()) !== JSON.stringify(prettyRsp)
) {
await Bun.write(path.join(filePathBase, 'latest.json'), JSON.stringify(prettyRsp, null, 2));
}
isLatestWrote = true;
}
for (const filePath of [path.join(filePathBase, `v${versionInfoEntry.version}.json`)]) {
if (
(await Bun.file(filePath).exists()) === false ||
JSON.stringify(await Bun.file(filePath).json()) !== JSON.stringify(prettyRsp)
) {
await Bun.write(filePath, JSON.stringify(prettyRsp, null, 2));
}
}
await (async () => {
let needWrite: boolean = true;
const tmp: ({ updatedAt: string } & typeof prettyRsp)[] = await Bun.file(
path.join(filePathBase, 'all.json'),
).json();
for (const dataStr of tmp.map((e) => JSON.stringify({ req: e.req, rsp: e.rsp }))) {
if (dataStr === JSON.stringify(prettyRsp)) needWrite = false;
}
if (needWrite) {
tmp.push({ updatedAt: DateTime.now().toISO(), ...prettyRsp });
await Bun.write(path.join(filePathBase, 'all.json'), JSON.stringify(tmp, null, 2));
}
})();
await saveResult(
['akEndfield', 'launcher', 'game_resources', channelStr],
versionInfoEntry.version,
prettyRsp,
!isLatestWrote,
);
isLatestWrote = true;
}
})();
@@ -194,40 +194,12 @@ async function mainCmdHandler() {
},
rsp,
};
const filePathBase = path.join(
argvUtils.getArgv()['outputDir'],
'akEndfield',
'launcher',
'launcher',
launcherTargetAppEntry,
String(cfg.channel.osWinRel),
await saveResult(
['akEndfield', 'launcher', 'launcher', launcherTargetAppEntry, channelStr],
rsp.version,
prettyRsp,
);
for (const filePath of [
path.join(filePathBase, 'latest.json'),
path.join(filePathBase, `v${rsp.version}.json`),
]) {
if (
(await Bun.file(filePath).exists()) === false ||
JSON.stringify(await Bun.file(filePath).json()) !== JSON.stringify(prettyRsp)
) {
await Bun.write(filePath, JSON.stringify(prettyRsp, null, 2));
}
}
await (async () => {
let needWrite: boolean = true;
const tmp: ({ updatedAt: string } & typeof prettyRsp)[] = await Bun.file(
path.join(filePathBase, 'all.json'),
).json();
for (const dataStr of tmp.map((e) => JSON.stringify({ req: e.req, rsp: e.rsp }))) {
if (dataStr === JSON.stringify(prettyRsp)) {
needWrite = false;
}
}
if (needWrite) {
tmp.push({ updatedAt: DateTime.now().toISO(), ...prettyRsp });
await Bun.write(path.join(filePathBase, 'all.json'), JSON.stringify(tmp, null, 2));
}
})();
}
})();
}