chore: cleanup all deprecated markdown list files

This commit is contained in:
daydreamer-json
2026-03-01 12:25:03 +09:00
parent ac53a34f86
commit 0ae153478f
15 changed files with 0 additions and 981 deletions

View File

@@ -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;