43 lines
1.6 KiB
TypeScript
43 lines
1.6 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { auth } from "@/lib/auth";
|
|
import { db } from "@/lib/db";
|
|
import { mcPlayers } from "@/lib/db/schema";
|
|
import { checkRateLimit, getClientIp } from "@/lib/security/rateLimit";
|
|
import { desc, like, or, eq } from "drizzle-orm";
|
|
|
|
export async function GET(req: NextRequest) {
|
|
const session = await auth.api.getSession({ headers: req.headers });
|
|
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
|
|
const ip = getClientIp(req);
|
|
const { allowed } = checkRateLimit(ip);
|
|
if (!allowed) return NextResponse.json({ error: "Too many requests" }, { status: 429 });
|
|
|
|
const { searchParams } = new URL(req.url);
|
|
const search = searchParams.get("q")?.trim() ?? "";
|
|
const onlineOnly = searchParams.get("online") === "true";
|
|
const bannedOnly = searchParams.get("banned") === "true";
|
|
const page = Math.max(1, parseInt(searchParams.get("page") ?? "1"));
|
|
const limit = Math.min(100, Math.max(1, parseInt(searchParams.get("limit") ?? "50")));
|
|
const offset = (page - 1) * limit;
|
|
|
|
let query = db.select().from(mcPlayers);
|
|
|
|
const conditions = [];
|
|
if (search) {
|
|
conditions.push(like(mcPlayers.username, `%${search}%`));
|
|
}
|
|
if (onlineOnly) conditions.push(eq(mcPlayers.isOnline, true));
|
|
if (bannedOnly) conditions.push(eq(mcPlayers.isBanned, true));
|
|
|
|
const rows = await db
|
|
.select()
|
|
.from(mcPlayers)
|
|
.where(conditions.length ? (conditions.length === 1 ? conditions[0] : or(...conditions)) : undefined)
|
|
.orderBy(desc(mcPlayers.lastSeen))
|
|
.limit(limit)
|
|
.offset(offset);
|
|
|
|
return NextResponse.json({ players: rows, page, limit });
|
|
}
|