mirror of
https://github.com/daydreamer-json/ak-endfield-api-archive.git
synced 2026-03-22 07:12:28 +01:00
chore: cleanup all deprecated markdown list files
This commit is contained in:
@@ -177,359 +177,6 @@ async function saveToGHMirror(url: string, name: string | null): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
async function generateGameListMd(target: GameTarget) {
|
||||
const outputDir = argvUtils.getArgv()['outputDir'];
|
||||
const gameAllJsonPath = path.join(outputDir, 'akEndfield', 'launcher', 'game', target.dirName, 'all.json');
|
||||
|
||||
if (!(await Bun.file(gameAllJsonPath).exists())) return;
|
||||
|
||||
const gameAllJson = (await Bun.file(gameAllJsonPath).json()) as StoredData<LatestGameResponse>[];
|
||||
const mdTexts: string[] = [];
|
||||
|
||||
const mirrorFileDb = await (async () => {
|
||||
const localJsonPath = path.join(outputDir, 'mirror_file_list.json');
|
||||
return (await Bun.file(localJsonPath).json()) as MirrorFileEntry[];
|
||||
})();
|
||||
|
||||
mdTexts.push(`# Game Packages (${target.region === 'cn' ? 'China' : 'Global'}, ${target.name})\n`);
|
||||
|
||||
// TOC
|
||||
for (const e of gameAllJson) {
|
||||
const version = e.rsp.version;
|
||||
const date = DateTime.fromISO(e.updatedAt, { setZone: true }).setZone('UTC+8');
|
||||
const dateStr = date.toFormat('yyyy/MM/dd HH:mm:ss');
|
||||
const anchorId = `ver-${version}-${Math.ceil(date.toSeconds())}`;
|
||||
mdTexts.push(`- [${version} (${dateStr})](#${anchorId})`);
|
||||
}
|
||||
mdTexts.push('');
|
||||
|
||||
// Content
|
||||
for (const e of gameAllJson) {
|
||||
const version = e.rsp.version;
|
||||
const date = DateTime.fromISO(e.updatedAt, { setZone: true }).setZone('UTC+8');
|
||||
const dateStr = date.toFormat('yyyy/MM/dd HH:mm:ss');
|
||||
const anchorId = `ver-${version}-${Math.ceil(date.toSeconds())}`;
|
||||
|
||||
const packedSize = mathUtils.arrayTotal(e.rsp.pkg.packs.map((f) => parseInt(f.package_size)));
|
||||
const unpackedSize = parseInt(e.rsp.pkg.total_size) - packedSize;
|
||||
|
||||
mdTexts.push(
|
||||
`<h2 id="${anchorId}">${version} (${dateStr})</h2>\n`,
|
||||
`<table>`,
|
||||
` <tr><td>Unpacked Size</td><td style="text-align: right;"><b>${formatBytes(unpackedSize)}</b></td></tr>`,
|
||||
` <tr><td>Packed Size</td><td style="text-align: right;"><b>${formatBytes(packedSize)}</b></td></tr>`,
|
||||
`</table>\n`,
|
||||
`|File|MD5 Checksum|Size|`,
|
||||
`|:--|:--|--:|`,
|
||||
);
|
||||
|
||||
for (const f of e.rsp.pkg.packs) {
|
||||
const fileName = new URL(f.url).pathname.split('/').pop() ?? '';
|
||||
const cleanUrl = new URL(f.url);
|
||||
cleanUrl.search = '';
|
||||
const mirrorUrlEntry = mirrorFileDb.find((g) => g.orig.includes(cleanUrl.toString()));
|
||||
const isFileAvail = {
|
||||
orig: await (async () => {
|
||||
try {
|
||||
await ky.head(f.url, {
|
||||
headers: { 'User-Agent': appConfig.network.userAgent.minimum },
|
||||
timeout: appConfig.network.timeout,
|
||||
retry: { limit: appConfig.network.retryCount },
|
||||
});
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
})(),
|
||||
mirror: Boolean(mirrorUrlEntry),
|
||||
};
|
||||
const fileLink = (() => {
|
||||
if (isFileAvail.orig && isFileAvail.mirror)
|
||||
return `${fileName} [Orig](${f.url}) / [Mirror](${mirrorUrlEntry!.mirror})`;
|
||||
else if (isFileAvail.mirror) return `[${fileName}](${mirrorUrlEntry!.mirror})`;
|
||||
else if (isFileAvail.orig) return `[${fileName}](${f.url})`;
|
||||
else return fileName;
|
||||
})();
|
||||
mdTexts.push('|' + [fileLink, `\`${f.md5}\``, formatBytes(parseInt(f.package_size))].join('|') + '|');
|
||||
}
|
||||
mdTexts.push('');
|
||||
}
|
||||
|
||||
await Bun.write(
|
||||
path.join(outputDir, 'akEndfield', 'launcher', 'game', target.dirName, 'list.md'),
|
||||
mdTexts.join('\n'),
|
||||
);
|
||||
}
|
||||
|
||||
async function generatePatchListMd(target: GameTarget) {
|
||||
const outputDir = argvUtils.getArgv()['outputDir'];
|
||||
const patchAllJsonPath = path.join(outputDir, 'akEndfield', 'launcher', 'game', target.dirName, 'all_patch.json');
|
||||
|
||||
if (!(await Bun.file(patchAllJsonPath).exists())) return;
|
||||
|
||||
const patchAllJson = (await Bun.file(patchAllJsonPath).json()) as StoredData<LatestGameResponse>[];
|
||||
const mdTexts: string[] = [];
|
||||
|
||||
const mirrorFileDb = await (async () => {
|
||||
const localJsonPath = path.join(outputDir, 'mirror_file_list.json');
|
||||
return (await Bun.file(localJsonPath).json()) as MirrorFileEntry[];
|
||||
})();
|
||||
|
||||
mdTexts.push(`# Game Patch Packages (${target.region === 'cn' ? 'China' : 'Global'}, ${target.name})\n`);
|
||||
|
||||
// TOC
|
||||
for (const e of patchAllJson) {
|
||||
if (!e.rsp.patch) continue;
|
||||
const version = e.rsp.version;
|
||||
const reqVersion = e.rsp.request_version;
|
||||
const date = DateTime.fromISO(e.updatedAt, { setZone: true }).setZone('UTC+8');
|
||||
const dateStr = date.toFormat('yyyy/MM/dd HH:mm:ss');
|
||||
const anchorId = `ver-${reqVersion}-${version}-${Math.ceil(date.toSeconds())}`;
|
||||
mdTexts.push(`- [${reqVersion} → ${version} (${dateStr})](#${anchorId})`);
|
||||
}
|
||||
mdTexts.push('');
|
||||
|
||||
// Content
|
||||
for (const e of patchAllJson) {
|
||||
if (!e.rsp.patch) continue;
|
||||
|
||||
const version = e.rsp.version;
|
||||
const reqVersion = e.rsp.request_version;
|
||||
const date = DateTime.fromISO(e.updatedAt, { setZone: true }).setZone('UTC+8');
|
||||
const dateStr = date.toFormat('yyyy/MM/dd HH:mm:ss');
|
||||
const anchorId = `ver-${reqVersion}-${version}-${Math.ceil(date.toSeconds())}`;
|
||||
|
||||
const packedSize = mathUtils.arrayTotal(e.rsp.patch.patches.map((f) => parseInt(f.package_size)));
|
||||
const unpackedSize = parseInt(e.rsp.patch.total_size) - packedSize;
|
||||
|
||||
mdTexts.push(
|
||||
`<h2 id="${anchorId}">${reqVersion} → ${version} (${dateStr})</h2>\n`,
|
||||
`<table>`,
|
||||
` <tr><td>Unpacked Size</td><td style="text-align: right;"><b>${formatBytes(unpackedSize)}</b></td></tr>`,
|
||||
` <tr><td>Packed Size</td><td style="text-align: right;"><b>${formatBytes(packedSize)}</b></td></tr>`,
|
||||
`</table>\n`,
|
||||
`|File|MD5 Checksum|Size|`,
|
||||
`|:--|:--|--:|`,
|
||||
);
|
||||
|
||||
if (e.rsp.patch.url) {
|
||||
const fileName = new URL(e.rsp.patch.url).pathname.split('/').pop() ?? '';
|
||||
const cleanUrl = new URL(e.rsp.patch.url);
|
||||
cleanUrl.search = '';
|
||||
const mirrorUrlEntry = mirrorFileDb.find((f) => f.orig.includes(cleanUrl.toString()));
|
||||
const isFileAvail = {
|
||||
orig: await (async () => {
|
||||
try {
|
||||
await ky.head(e.rsp.patch!.url, {
|
||||
headers: { 'User-Agent': appConfig.network.userAgent.minimum },
|
||||
timeout: appConfig.network.timeout,
|
||||
retry: { limit: appConfig.network.retryCount },
|
||||
});
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
})(),
|
||||
mirror: Boolean(mirrorUrlEntry),
|
||||
};
|
||||
const fileLink = (() => {
|
||||
if (isFileAvail.orig && isFileAvail.mirror)
|
||||
return `${fileName} [Orig](${e.rsp.patch.url}) / [Mirror](${mirrorUrlEntry!.mirror})`;
|
||||
else if (isFileAvail.mirror) return `[${fileName}](${mirrorUrlEntry!.mirror})`;
|
||||
else if (isFileAvail.orig) return `[${fileName}](${e.rsp.patch.url})`;
|
||||
else return fileName;
|
||||
})();
|
||||
mdTexts.push(
|
||||
'|' + [fileLink, `\`${e.rsp.patch.md5}\``, formatBytes(parseInt(e.rsp.patch.package_size))].join('|') + '|',
|
||||
);
|
||||
}
|
||||
|
||||
for (const f of e.rsp.patch.patches) {
|
||||
const fileName = new URL(f.url).pathname.split('/').pop() ?? '';
|
||||
const cleanUrl = new URL(f.url);
|
||||
cleanUrl.search = '';
|
||||
const mirrorUrlEntry = mirrorFileDb.find((g) => g.orig.includes(cleanUrl.toString()));
|
||||
const isFileAvail = {
|
||||
orig: await (async () => {
|
||||
try {
|
||||
await ky.head(f.url, {
|
||||
headers: { 'User-Agent': appConfig.network.userAgent.minimum },
|
||||
timeout: appConfig.network.timeout,
|
||||
retry: { limit: appConfig.network.retryCount },
|
||||
});
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
})(),
|
||||
mirror: Boolean(mirrorUrlEntry),
|
||||
};
|
||||
const fileLink = (() => {
|
||||
if (isFileAvail.orig && isFileAvail.mirror)
|
||||
return `${fileName} [Orig](${f.url}) / [Mirror](${mirrorUrlEntry!.mirror})`;
|
||||
else if (isFileAvail.mirror) return `[${fileName}](${mirrorUrlEntry!.mirror})`;
|
||||
else if (isFileAvail.orig) return `[${fileName}](${f.url})`;
|
||||
else return fileName;
|
||||
})();
|
||||
mdTexts.push('|' + [fileLink, `\`${f.md5}\``, formatBytes(parseInt(f.package_size))].join('|') + '|');
|
||||
}
|
||||
mdTexts.push('');
|
||||
}
|
||||
|
||||
await Bun.write(
|
||||
path.join(outputDir, 'akEndfield', 'launcher', 'game', target.dirName, 'list_patch.md'),
|
||||
mdTexts.join('\n'),
|
||||
);
|
||||
}
|
||||
|
||||
async function generateResourceListMd(gameTargets: GameTarget[]) {
|
||||
const sanitizedGameTargets = [
|
||||
...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;
|
||||
const outputDir = argvUtils.getArgv()['outputDir'];
|
||||
|
||||
for (const target of sanitizedGameTargets) {
|
||||
const mdTexts: string[] = [];
|
||||
mdTexts.push('# Game Resources\n', ...platforms.map((e) => `- [${e}](#res-${e})`), '');
|
||||
|
||||
const baseFolderPath = path.join(outputDir, 'akEndfield', 'launcher', 'game_resources', String(target.channel));
|
||||
for (const platform of platforms) {
|
||||
const resourceAllJsonPath = path.join(baseFolderPath, platform, 'all.json');
|
||||
|
||||
if (!(await Bun.file(resourceAllJsonPath).exists())) continue;
|
||||
|
||||
const gameAllJson = (await Bun.file(resourceAllJsonPath).json()) as StoredData<LatestGameResourcesResponse>[];
|
||||
const resVersionMap = new Map<string, { rsp: StoredData<LatestGameResourcesResponse>; versions: Set<string> }>();
|
||||
for (const e of gameAllJson) {
|
||||
const resVer = e.rsp.res_version;
|
||||
if (!resVersionMap.has(resVer)) {
|
||||
resVersionMap.set(resVer, { rsp: e, versions: new Set() });
|
||||
}
|
||||
resVersionMap.get(resVer)!.versions.add(e.req.version);
|
||||
}
|
||||
|
||||
const resVersionSet = Array.from(resVersionMap.values()).map((data) => ({
|
||||
resVersion: data.rsp.rsp.res_version,
|
||||
rsp: data.rsp,
|
||||
versions: Array.from(data.versions),
|
||||
}));
|
||||
|
||||
mdTexts.push(
|
||||
`<h2 id="res-${platform}">${platform}</h2>\n`,
|
||||
'|Date|Initial|Main|Kick|Game version|',
|
||||
'|--|--|--|--|',
|
||||
...resVersionSet.map(
|
||||
(resVerObj) =>
|
||||
'|' +
|
||||
[
|
||||
DateTime.fromISO(resVerObj.rsp.updatedAt, { setZone: true })
|
||||
.setZone('UTC+8')
|
||||
.toFormat('yyyy/MM/dd HH:mm:ss'),
|
||||
`[${resVerObj.rsp.rsp.resources.find((e) => e.name === 'initial')!.version}](${resVerObj.rsp.rsp.resources.find((e) => e.name === 'initial')!.path})`,
|
||||
`[${resVerObj.rsp.rsp.resources.find((e) => e.name === 'main')!.version}](${resVerObj.rsp.rsp.resources.find((e) => e.name === 'main')!.path})`,
|
||||
JSON.parse(resVerObj.rsp.rsp.configs).kick_flag === true ? '✅' : '',
|
||||
resVerObj.versions.sort((a, b) => semver.compare(b, a)).join(', '),
|
||||
].join('|') +
|
||||
'|',
|
||||
),
|
||||
'',
|
||||
);
|
||||
}
|
||||
await Bun.write(path.join(baseFolderPath, 'list.md'), mdTexts.join('\n'));
|
||||
}
|
||||
}
|
||||
|
||||
async function generateLauncherMd(type: 'zip' | 'exe') {
|
||||
const cfg = appConfig.network.api.akEndfield;
|
||||
const outputDir = argvUtils.getArgv()['outputDir'];
|
||||
const settings = {
|
||||
zip: {
|
||||
subdir: 'launcher',
|
||||
title: 'Launcher Packages (zip)',
|
||||
headers: ['Date', 'Version', 'File', 'MD5 Checksum', 'Unpacked', 'Packed'],
|
||||
align: ['---', '---', '---', '---', '--:', '--:'],
|
||||
},
|
||||
exe: {
|
||||
subdir: 'launcherExe',
|
||||
title: 'Launcher Packages (Installer)',
|
||||
headers: ['Date', 'Version', 'File', 'Size'],
|
||||
align: ['---', '---', '---', '--:'],
|
||||
},
|
||||
}[type];
|
||||
|
||||
const regions = [
|
||||
{ id: 'os' as const, apps: ['EndField', 'Official'] as const, channel: cfg.channel.osWinRel },
|
||||
{ id: 'cn' as const, apps: ['EndField', 'Arknights', 'Official'] as const, channel: cfg.channel.cnWinRel },
|
||||
];
|
||||
|
||||
const mdTexts: string[] = [
|
||||
`# ${settings.title}\n`,
|
||||
...regions.flatMap((r) =>
|
||||
r.apps.map((app) => `- [${r.id.toUpperCase()} ${app}](#launcher-${r.id}-${app.toLowerCase()})`),
|
||||
),
|
||||
'\n',
|
||||
];
|
||||
|
||||
const mirrorFileDb = await (async () => {
|
||||
const localJsonPath = path.join(outputDir, 'mirror_file_list.json');
|
||||
return (await Bun.file(localJsonPath).json()) as MirrorFileEntry[];
|
||||
})();
|
||||
|
||||
for (const region of regions) {
|
||||
for (const appName of region.apps) {
|
||||
const jsonPath = path.join(
|
||||
outputDir,
|
||||
'akEndfield',
|
||||
'launcher',
|
||||
settings.subdir,
|
||||
appName,
|
||||
String(region.channel),
|
||||
'all.json',
|
||||
);
|
||||
const jsonData = (await Bun.file(jsonPath).json()) as StoredData<any>[];
|
||||
|
||||
mdTexts.push(
|
||||
`<h2 id="launcher-${region.id}-${appName.toLowerCase()}">${region.id.toUpperCase()} ${appName}</h2>\n`,
|
||||
`|${settings.headers.join('|')}|`,
|
||||
`|${settings.align.join('|')}|`,
|
||||
);
|
||||
|
||||
for (const e of jsonData) {
|
||||
const url = type === 'zip' ? e.rsp.zip_package_url : e.rsp.exe_url;
|
||||
const fileName = new URL(url).pathname.split('/').pop() ?? '';
|
||||
const cleanUrl = new URL(url);
|
||||
cleanUrl.search = '';
|
||||
const mirrorUrlEntry = mirrorFileDb.find((f) => f.orig.includes(cleanUrl.toString()));
|
||||
const fileLink = mirrorUrlEntry
|
||||
? `${fileName} [Orig](${url}) / [Mirror](${mirrorUrlEntry.mirror})`
|
||||
: `[${fileName}](${url})`;
|
||||
const date = DateTime.fromISO(e.updatedAt, { setZone: true }).setZone('UTC+8').toFormat('yyyy/MM/dd HH:mm:ss');
|
||||
const row =
|
||||
type === 'zip'
|
||||
? [
|
||||
date,
|
||||
e.rsp.version,
|
||||
fileLink,
|
||||
`\`${e.rsp.md5}\``,
|
||||
formatBytes(parseInt(e.rsp.total_size) - parseInt(e.rsp.package_size)),
|
||||
formatBytes(parseInt(e.rsp.package_size)),
|
||||
]
|
||||
: [date, e.rsp.version, fileLink, formatBytes(parseInt(e.rsp.exe_size))];
|
||||
|
||||
mdTexts.push(`|${row.join('|')}|`);
|
||||
}
|
||||
mdTexts.push('');
|
||||
}
|
||||
}
|
||||
await Bun.write(path.join(outputDir, 'akEndfield', 'launcher', settings.subdir, 'list.md'), mdTexts.join('\n'));
|
||||
}
|
||||
|
||||
async function fetchAndSaveLatestGames(gameTargets: GameTarget[]) {
|
||||
logger.debug(`Fetching latestGame ...`);
|
||||
for (const target of gameTargets) {
|
||||
@@ -949,16 +596,6 @@ async function mainCmdHandler() {
|
||||
'GitHub Releases size total: ' + formatBytes(mathUtils.arrayTotal(ghRelInfo.assets.map((e) => e.size))),
|
||||
);
|
||||
}
|
||||
|
||||
logger.debug('Generating markdown ...');
|
||||
|
||||
for (const target of gameTargets) {
|
||||
await generateGameListMd(target);
|
||||
await generatePatchListMd(target);
|
||||
}
|
||||
await generateResourceListMd(gameTargets);
|
||||
await generateLauncherMd('zip');
|
||||
await generateLauncherMd('exe');
|
||||
}
|
||||
|
||||
export default mainCmdHandler;
|
||||
|
||||
Reference in New Issue
Block a user