Files
wzdj/old/app/api/streamer/bind/route.ts
2026-04-20 14:56:28 +08:00

85 lines
3.3 KiB
TypeScript
Raw Permalink 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 { NextRequest, NextResponse } from "next/server"
import { ObjectId } from "mongodb"
import { getCollection } from "@/lib/db/mongo"
const BINDING_DAYS = Number(process.env.STREAMER_BINDING_DAYS) || 30
/**
* 主播绑定:用户通过主播链接进入并登录后,建立 30 天绑定关系(参考 Soul 创业实验)
* POST body: { userId: string, ref: string } 或 { userId: string, streamerId: string }
*/
export async function POST(request: NextRequest) {
try {
const body = await request.json().catch(() => ({}))
const userId = typeof body.userId === "string" ? body.userId.trim() : ""
const ref = typeof body.ref === "string" ? body.ref.trim() : ""
const streamerIdParam = typeof body.streamerId === "string" ? body.streamerId.trim() : ""
if (!userId) {
return NextResponse.json({ success: false, message: "缺少 userId" }, { status: 400 })
}
let streamerId: string
if (streamerIdParam) {
streamerId = streamerIdParam
} else if (ref) {
// ref 可为主播 _id 或短码,这里统一按 _id 处理24 位 hex若为短码可后续扩展查 streamers 表
if (ref.length === 24 && /^[a-f0-9]{24}$/i.test(ref)) {
streamerId = ref
} else {
// 短码:可扩展查 streamers 的 shortCode 等;此处仅尝试按 ObjectId 查(避免无效 ref 抛错)
const streamersColl = await getCollection("streamers")
let byId = null
if (ObjectId.isValid(ref)) {
try {
byId = await streamersColl.findOne({ _id: new ObjectId(ref) })
} catch {}
}
if (byId) {
streamerId = (byId as { _id: { toString(): string } })._id.toString()
} else {
return NextResponse.json({ success: false, message: "无效的主播标识 ref" }, { status: 400 })
}
}
} else {
return NextResponse.json({ success: false, message: "缺少 ref 或 streamerId" }, { status: 400 })
}
// 校验主播存在
const streamersColl = await getCollection("streamers")
const streamer = await streamersColl.findOne({ _id: new ObjectId(streamerId) })
if (!streamer) {
return NextResponse.json({ success: false, message: "主播不存在" }, { status: 404 })
}
const bindColl = await getCollection("streamerBindings")
const now = new Date()
const expiresAt = new Date(now.getTime() + BINDING_DAYS * 24 * 60 * 60 * 1000)
// 是否已有有效绑定:同一用户若已有未过期的绑定则不覆盖(与 Soul 一致:首次绑定优先)
const existing = await bindColl.findOne({
userId,
status: "active",
expiresAt: { $gt: now.toISOString() } as unknown as { $gt: string },
})
if (existing) {
return NextResponse.json({ success: true, message: "已有有效绑定,未变更" })
}
await bindColl.insertOne({
streamerId,
userId,
boundAt: now.toISOString(),
expiresAt: expiresAt.toISOString(),
status: "active",
createdAt: now.toISOString(),
updatedAt: now.toISOString(),
})
return NextResponse.json({ success: true, message: "绑定成功" })
} catch (e) {
console.error("POST /api/streamer/bind error:", e)
return NextResponse.json({ success: false, message: "绑定失败" }, { status: 500 })
}
}