Split CurseForge API token into separate legacy and new tokens

This commit is contained in:
CPTProgrammer 2026-07-13 18:42:29 +08:00
parent 691ae86e00
commit 296b69bf1c
No known key found for this signature in database
4 changed files with 23 additions and 11 deletions

View File

@ -2,20 +2,27 @@ import { readErrorBody, summarizeFormData } from "../utils/fetch";
/** CurseForge API 客户端,封装两套 API 的鉴权与 User-Agent。 */
export class CurseForgeClient {
/** GET /v1/mods/{modId}/files 等只读接口 */
/** V1 API (api.curseforge.com)GET /v1/mods/{modId}/files 等只读接口 */
private apiBase = "https://api.curseforge.com";
/** 上传 / 更新文件、Game Version Types / Versions 等接口 */
/** Legacy API (minecraft.curseforge.com)上传 / 更新文件、Game Version Types / Versions 等接口 */
private uploadBase = "https://minecraft.curseforge.com";
private token: string;
/** 新 API (api.curseforge.com) 的 token */
private apiToken: string;
/** 旧 API (minecraft.curseforge.com) 的 token */
private legacyToken: string;
private userAgent: string;
constructor(
token: string,
apiToken: string,
legacyToken: string,
userAgent?: string,
) {
this.token = token;
this.apiToken = apiToken;
this.legacyToken = legacyToken;
this.userAgent =
userAgent ??
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36";
@ -23,13 +30,13 @@ export class CurseForgeClient {
/** V1 API 请求头x-api-key。 */
private apiHeaders(): Record<string, string> {
return { "x-api-key": this.token };
return { "x-api-key": this.apiToken };
}
/** Upload API 请求头X-Api-Token + browser User-Agent。 */
/** Legacy API 请求头X-Api-Token + browser User-Agent。 */
private uploadHeaders(): Record<string, string> {
return {
"X-Api-Token": this.token,
"X-Api-Token": this.legacyToken,
"User-Agent": this.userAgent,
};
}

View File

@ -3,7 +3,7 @@ import { CurseForgeClient } from "./client";
import { getVersionTypes, getGameVersions, getMinecraftVersions } from "./game";
import secrets from "../../../secrets.json";
const client = new CurseForgeClient(secrets.curseforge);
const client = new CurseForgeClient(secrets.curseforge, secrets.curseforge_legacy);
describe("getVersionTypes", () => {
test("GET /api/game/version-types", async () => {

View File

@ -33,4 +33,7 @@ export const modrinthClient = new ModrinthClient(
"ModReleaser (local)",
);
export const curseforgeClient = new CurseForgeClient(secrets.curseforge);
export const curseforgeClient = new CurseForgeClient(
secrets.curseforge,
secrets.curseforge_legacy,
);

View File

@ -73,8 +73,10 @@ export type Config = z.infer<typeof ConfigSchema>;
// region Secrets — secrets.json 结构
export const SecretsSchema = z.object({
/** CurseForge API Token */
/** CurseForge API (api.curseforge.com) Token */
curseforge: z.string().min(1),
/** CurseForge 旧 API (minecraft.curseforge.com) Token */
curseforge_legacy: z.string().min(1),
/** Modrinth Personal Access Token */
modrinth: z.string().min(1),
});