85 lines
3.3 KiB
TypeScript
85 lines
3.3 KiB
TypeScript
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 })
|
||
}
|
||
}
|