my-kaiqiuwang/src/index.tsx
kyuuseiryuu 79c839db00 feat: add current-score grouping flow with cached uid score API
- move shared parsing/grouping helpers into serverUtils and update imports
- add xcxApi singleton in serverUtils
- add Redis-backed uid score store and /api/user/nowScores endpoint
- preload uid scores in event loader and tags in profile loader
- allow grouping prediction to switch sort mode between current/yearly score
- update tags component to consume loader-provided tags
- remove unused zustand game store
- add redis test scaffold and scoreboard component scaffold
2026-02-26 00:13:37 +09:00

92 lines
2.7 KiB
TypeScript

import { serve } from "bun";
import { getMatchInfo, listEvent } from "./utils/utils";
import index from "./index.html";
import { xcxApi } from "./utils/server";
import { getUidScore } from "./services/uidScoreStore";
if (!process.env.KAIQIUCC_TOKEN) {
console.error('env KAIQIUCC_TOKEN not found');
process.exit(1);
}
const server = serve({
port: process.env.PORT || 3000,
routes: {
// Serve index.html for all unmatched routes.
"/*": index,
"/api/events/:clubid": {
async GET(req) {
const data = await listEvent(req.params.clubid);
return Response.json(data);
}
},
"/api/match/:matchId": {
async GET(req) {
const data = await getMatchInfo(req.params.matchId);
return Response.json(data);
}
},
"/api/match/:matchId/:itemId": {
async GET(req) {
const { matchId, itemId } = req.params;
const data = await xcxApi.getMemberDetail(matchId, itemId);
return Response.json(data);
}
},
"/api/user/find": {
async GET(req) {
const searchParams = new URL(req.url).searchParams;
const key = searchParams.get('key') ?? '';
const page = Number(searchParams.get('page'));
const users = await xcxApi.findUser(key, page);
return Response.json(users);
}
},
"/api/user/nowScores": {
async GET(req) {
const searchParams = new URL(req.url).searchParams;
const uids = searchParams.get('uids')?.split(',') ?? [];
const uidScore = await getUidScore(uids);
return Response.json(uidScore);
}
},
"/api/user/:uid": {
async GET(req) {
const uid = req.params.uid;
if (uid === '0') return Response.json(null);
const profile = await xcxApi.getAdvProfile(uid);
return Response.json(profile);
},
},
"/api/user/:uid/games": {
async GET(req) {
const uid = req.params.uid;
if (uid === '0') return Response.json([]);
const search = new URL(req.url).searchParams;
const page = Number(search.get('page')) ?? 0;
const resp = await xcxApi.getGameList(uid, page);
return Response.json(resp);
},
},
"/api/user/:uid/tags": {
async GET(req) {
const uid = req.params.uid;
if (uid == '0') return Response.json([]);
const profile = await xcxApi.getPlayerTags(uid);
return Response.json(profile);
},
}
},
development: process.env.NODE_ENV !== "production" && {
// Enable browser hot reloading in development
hmr: true,
// Echo console logs from the browser to the server
console: true,
},
});
console.log(`🚀 Server running at ${server.url}`);