Files
openclaw-market/app/api/v1/register/route.ts
richarjiang fa4c458eda init
2026-03-13 11:00:01 +08:00

90 lines
2.4 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { nanoid } from "nanoid";
import { db } from "@/lib/db";
import { lobsters } from "@/lib/db/schema";
import {
setLobsterOnline,
updateActiveLobsters,
incrementGlobalStat,
incrementRegionCount,
publishEvent,
} from "@/lib/redis";
import { generateApiKey } from "@/lib/auth/api-key";
import { getGeoLocation } from "@/lib/geo/ip-location";
import { registerSchema } from "@/lib/validators/schemas";
function getClientIp(req: NextRequest): string {
const forwarded = req.headers.get("x-forwarded-for");
if (forwarded) return forwarded.split(",")[0].trim();
const realIp = req.headers.get("x-real-ip");
if (realIp) return realIp.trim();
return "127.0.0.1";
}
export async function POST(req: NextRequest) {
try {
const body = await req.json();
const parsed = registerSchema.safeParse(body);
if (!parsed.success) {
return NextResponse.json(
{ error: "Validation failed", details: parsed.error.flatten() },
{ status: 400 }
);
}
const { name, model, platform } = parsed.data;
const lobsterId = nanoid(21);
const apiKey = generateApiKey();
const clientIp = getClientIp(req);
const geo = await getGeoLocation(clientIp);
const now = new Date();
await db.insert(lobsters).values({
id: lobsterId,
apiKey,
name,
model: model ?? null,
platform: platform ?? null,
ip: clientIp,
latitude: geo ? String(geo.latitude) : null,
longitude: geo ? String(geo.longitude) : null,
city: geo?.city ?? null,
country: geo?.country ?? null,
countryCode: geo?.countryCode ?? null,
region: geo?.region ?? null,
lastHeartbeat: now,
totalTasks: 0,
createdAt: now,
updatedAt: now,
});
await setLobsterOnline(lobsterId, clientIp);
await updateActiveLobsters(lobsterId);
await incrementGlobalStat("total_lobsters");
if (geo?.region) {
await incrementRegionCount(geo.region);
}
await publishEvent({
type: "online",
lobsterId,
lobsterName: name,
city: geo?.city ?? null,
country: geo?.country ?? null,
});
return NextResponse.json({
lobsterId,
apiKey,
endpoint: `${process.env.NEXT_PUBLIC_APP_URL}/api/v1`,
});
} catch (error) {
console.error("Register error:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 }
);
}
}