"use server"; import type { Config, Version, CurseForgeFile } from "@/types"; import { modrinthClient, curseforgeClient } from "./clients"; import { listVersions } from "@/lib/modrinth"; import { getFiles } from "@/lib/curseforge"; import { Template } from "@/lib/utils/template"; /** * 获取 Modrinth 项目的全部已有版本(不含 changelog 以减小响应体)。 */ export async function fetchModrinthVersions( config: Config, ): Promise { return listVersions(modrinthClient, config.modrinth.project_id, { include_changelog: false, }); } /** * 获取 CurseForge 项目的全部已有文件(自动遍历所有分页)。 */ export async function fetchCurseForgeVersions( config: Config, ): Promise { const pageSize = 50; let index = 0; const allFiles: CurseForgeFile[] = []; while (true) { const response = await getFiles(curseforgeClient, { modId: config.curseforge.project_id, index, pageSize, }); allFiles.push(...response.data); if (allFiles.length >= response.pagination.totalCount) { break; } index += pageSize; } return allFiles; } /** 单个 MC 版本的比较结果 */ export interface VersionMatch { exists: boolean; existingVersion?: Version; } /** 单个 MC 版本的文件比较结果 */ export interface FileMatch { exists: boolean; existingFile?: CurseForgeFile; } /** 版本确认的完整比较结果 */ export interface VersionComparison { modrinth: Record; curseforge: Record; } /** * 将待发布版本与两个平台的已有版本进行比对。 * * @param config 项目配置 * @param version 项目版本号(如 "1.0.0") * @param mc_versions 待发布的 MC 版本列表 * @returns 按 MC 版本分组的比对结果 */ export async function compareVersions( config: Config, version: string, mc_versions: string[], ): Promise { // 并行获取两个平台的已有版本 const [modrinthVersions, curseforgeFiles] = await Promise.all([ fetchModrinthVersions(config), fetchCurseForgeVersions(config), ]); // ── Modrinth:按 version 模板生成 version_number 后匹配 ── const modrinth: Record = {}; const modrinthTmpl = new Template(config.modrinth.version); for (const mc_version of mc_versions) { const generatedVersion = modrinthTmpl.format({ version, mc_version }); const existing = modrinthVersions.find( (v) => v.version_number === generatedVersion, ); modrinth[mc_version] = existing ? { exists: true, existingVersion: existing } : { exists: false }; } // ── CurseForge:按 filename_format 模板生成文件名后匹配 ── const curseforge: Record = {}; const curseforgeTmpl = new Template(config.filename_format); for (const mc_version of mc_versions) { const generatedFilename = curseforgeTmpl.format({ version, mc_version }); const existing = curseforgeFiles.find( (f) => f.fileName === generatedFilename, ); curseforge[mc_version] = existing ? { exists: true, existingFile: existing } : { exists: false }; } return { modrinth, curseforge }; }