import cloud from "@lafjs/cloud"; import Utils from "@/Utils"; import { WUCAI_TYPE_AUTO_MIGRATED, WUCAI_TYPE_CHOSE_CURRENT, WUCAI_TYPE_CHOSE_WUCAI, WUCAI_TYPE_PENDING_CHOICE, addWucaiReward, fetchWucaiUser, hasWucaiRewardGranted, isValidWucaiType, normalizeWucaiUser, wucaiMatch, wucaiState, } from "./wucaiMigration"; const db = cloud.database(); export default async function wucaiTransfer(ctx: FunctionContext) { const body = ctx.body || {}; const uid = body.uid; const action = String(body.action || ""); if (body.gameName === "iaa") { return fail("WUCAI_UNSUPPORTED_GAME", "五彩账号迁移仅支持主用户库"); } if (!uid) { return fail("WUCAI_UID_REQUIRED", "未获取到uid"); } if (!isSupportedAction(action)) { return fail("WUCAI_INVALID_ACTION", "无效的五彩迁移动作"); } const userResult = await db.collection("users").where({ _id: uid }).getOne(); const user = userResult.data; if (!user) { return fail("WUCAI_USER_NOT_FOUND", "未获取到玩家信息"); } if (!user.token || !body.token || !Utils.checkToken(body.token, user.token)) { return fail("TOKEN_INVALID", "token校验失败"); } if (!isValidWucaiType(user.wucai_type)) { return fail("WUCAI_INVALID_STATE", "五彩迁移状态异常"); } const rewardGranted = hasWucaiRewardGranted(user); // A delayed claim response must not finish or reward a later selection round. if (action === "claim_reward" && rewardGranted) { return success(user, true); } if ((body.wucai_entry_id || "") !== (user.wucai_entry_id || "")) { return fail("WUCAI_STATE_CHANGED", "迁移轮次已经变化,请重新登录", wucaiState(user)); } const expectedType = action === "claim_reward" ? WUCAI_TYPE_AUTO_MIGRATED : WUCAI_TYPE_PENDING_CHOICE; const nextType = action === "choose_current" ? WUCAI_TYPE_CHOSE_CURRENT : WUCAI_TYPE_CHOSE_WUCAI; const currentType = Number(user.wucai_type); if (action === "ack_reward_popup") { return acknowledgeRewardPopup(uid, currentType, user); } if (currentType === nextType) { return success(user, action === "claim_reward"); } if (currentType !== expectedType) { return fail("WUCAI_INVALID_STATE", "当前状态不能执行该迁移动作", { wucai_type: currentType }); } let update: any; if (action === "choose_wucai") { const source = await fetchWucaiUser(user.unionid); if (!source) { return fail("WUCAI_SOURCE_UNAVAILABLE", "五彩数据获取失败,请重新进入游戏后重试"); } const migratedUser = normalizeWucaiUser(source); update = { ...migratedUser, monthCardReward: Math.max(migratedUser.monthCardReward, Number(user.monthCardReward) || 0), ...(!rewardGranted ? addWucaiReward(migratedUser) : {}), }; } else { update = !rewardGranted ? addWucaiReward(user) : {}; } Object.assign(update, { wucai_type: nextType, wucai_reward_granted: true, wucai_reward_popup_pending: user.wucai_reward_popup_pending === true || (!rewardGranted && action !== "claim_reward"), forcedUpdate: true, }); const updateResult = await (cloud.mongo.db as any).collection("users").updateOne( wucaiMatch(user, Object.keys(update)), { $set: update }, ); if (!updateResult.matchedCount) { const latestResult = await db.collection("users").where({ _id: uid }).getOne(); const latestType = Number(latestResult.data?.wucai_type); if (latestResult.data && (latestResult.data.wucai_entry_id || "") === (user.wucai_entry_id || "") && latestType === nextType) { return success(latestResult.data, action === "claim_reward"); } return fail("WUCAI_STATE_CHANGED", "迁移状态已经变化,请重新登录", { wucai_type: latestType }); } return success({ ...user, ...update }, action === "claim_reward"); } function isSupportedAction(action: string): boolean { return action === "claim_reward" || action === "choose_wucai" || action === "choose_current" || action === "ack_reward_popup"; } async function acknowledgeRewardPopup(uid: any, currentType: number, user: any) { if (currentType !== WUCAI_TYPE_CHOSE_WUCAI && currentType !== WUCAI_TYPE_CHOSE_CURRENT) { return fail("WUCAI_INVALID_STATE", "当前状态不能确认迁移奖励弹窗", { wucai_type: currentType }); } if (user.wucai_reward_popup_pending !== true) { return popupAcknowledged(user); } const updateResult = await (cloud.mongo.db as any).collection("users").updateOne( wucaiMatch(user), { $set: { wucai_reward_popup_pending: false } }, ); if (!updateResult.matchedCount) { const latestResult = await db.collection("users").where({ _id: uid }).getOne(); const latestType = Number(latestResult.data?.wucai_type); if (latestResult.data && (latestResult.data.wucai_entry_id || "") === (user.wucai_entry_id || "") && (latestType === WUCAI_TYPE_CHOSE_WUCAI || latestType === WUCAI_TYPE_CHOSE_CURRENT) && latestResult.data?.wucai_reward_popup_pending !== true) { return popupAcknowledged(latestResult.data); } return fail("WUCAI_STATE_CHANGED", "迁移奖励弹窗状态已经变化,请重新登录", { wucai_type: latestType, }); } return popupAcknowledged({ ...user, wucai_reward_popup_pending: false }); } function success(user: any, includeResources = false) { const rewardData = includeResources ? { coinAmount: Number(user.coinAmount), freezeAmount: Number(user.freezeAmount), hammerAmount: Number(user.hammerAmount), magicAmount: Number(user.magicAmount), } : {}; return { code: 1, data: { ...wucaiState(user), forcedUpdate: true, ...rewardData, }, msg: "五彩账号迁移处理成功", }; } function popupAcknowledged(user: any) { return { code: 1, data: wucaiState(user), msg: "迁移奖励弹窗已确认", }; } function fail(errorCode: string, msg: string, data: any = null) { return { code: 0, errorCode, data, msg }; }