server/laf-cloud/functions/goldMiner/admin.ts
2026-09-24 17:59:52 +08:00

46 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import * as ConfigStore from "@/activityConfig/store";
import { timingSafeEqual } from "crypto";
import { TABLES as T, validateConfig, failure, reject, periodDates } from "@/goldMiner/config";
import { collection, controlId, periodById } from "@/goldMiner/service";
import { setupIndexes } from "@/goldMiner/jobs";
import { publishTestPeriod } from "@/goldMiner/testPeriods";
export default async function (ctx: FunctionContext) {
const body = ctx.body || {};
try {
const expected = process.env.ADMIN_TOKEN;
if (!expected || typeof body.adminToken !== "string") reject("UNAUTHORIZED");
const supplied = Buffer.from(body.adminToken), secret = Buffer.from(expected);
if (supplied.length !== secret.length || !timingSafeEqual(supplied, secret)) reject("UNAUTHORIZED");
if (body.action === "setup_indexes") { await setupIndexes(); return { code: 1, msg: "索引已准备" }; }
if (body.action === "publish_test_period") {
return { code: 1, data: await publishTestPeriod(body), msg: "测试临时期已发布" };
}
if (body.action === "publish") {
if (!body.config || typeof body.config !== "object" || Array.isArray(body.config)) reject("CONFIG_UNAVAILABLE", "config 必须为 JSON 对象,请把活动参数放在请求的 config 字段内");
const snapshot = validateConfig({ ...body.config, publishedAt: Date.now() });
if (periodDates(snapshot.effectiveFromPeriodId).startsAt <= Date.now()) reject("CONFIG_UNAVAILABLE", "只能发布未来期配置");
const { configVersion, publishedAt, ...config } = snapshot;
try {
const stored = await ConfigStore.publish("goldMiner", configVersion, periodDates(config.effectiveFromPeriodId).startsAt, config, body.enabled);
snapshot.publishedAt = stored.publishedAt;
}
catch (error: any) { reject("CONFIG_UNAVAILABLE", error.message); }
return { code: 1, data: { ...snapshot, enabled: body.enabled === undefined ? true : body.enabled }, msg: "后续期配置已发布" };
}
if (body.action === "set_purchasable") {
if (typeof body.purchaseEnabled !== "boolean") reject("INVALID_INPUT", "purchaseEnabled 必须为 JSON 布尔值 true 或 false,不能使用字符串");
if (typeof body.periodId !== "string") reject("INVALID_INPUT", "periodId 必须为字符串,请传入要调整购买开关的活动期 ID");
if (!await periodById(body.periodId)) reject("NOT_FOUND");
await collection(T.configs).updateOne({ _id: controlId(body.periodId) }, {
$set: {
activityId: "goldMiner", recordType: "control",
periodId: body.periodId, purchaseEnabled: body.purchaseEnabled, updatedAt: Date.now()
}
}, { upsert: true });
return { code: 1, msg: "购买开关已更新,已有权益不受影响" };
}
reject("INVALID_ACTION");
} catch (error) { return failure(error); }
}