import type { FastifyInstance } from 'fastify'; import { z } from 'zod'; import { requireAdmin, requireAuth, requireEditor } from '../auth/guard.js'; import { notFound } from '../errors.js'; import { prisma } from '../db.js'; import { knownSteamIds, listUnmatched, resolveUnmatched, scrapePlayers, unmatchedOverview, } from '../services/scraper.js'; import { contextOf, idParam, parseWith } from './helpers.js'; export async function scraperRoutes(app: FastifyInstance): Promise { /** * Gleicht die Profile bereits erfasster Spieler ab. Bewusst nur die * bekannten: der Abgleich soll vorhandene Konten ergänzen, nicht fremde * Profile auf Vorrat einsammeln. */ app.post('/api/scrape/run', { preHandler: requireEditor }, async (request) => { const body = parseWith( z.object({ playerIds: z.array(z.number().int().positive()).max(500).optional() }), request.body ?? {}, ); const all = await knownSteamIds(); const targets = body.playerIds ? all.filter((entry) => body.playerIds?.includes(entry.playerId)) : all; return scrapePlayers(targets, contextOf(request)); }); /** Einzelnes Profil abgleichen, etwa direkt von der Spielerseite aus. */ app.post('/api/scrape/player/:id', { preHandler: requireEditor }, async (request) => { const { id } = parseWith(idParam, request.params); const player = await prisma.player.findUnique({ where: { id }, select: { id: true, steamId: true }, }); if (!player) throw notFound('Spieler'); if (!player.steamId) { throw notFound('SteamID des Spielers'); } return scrapePlayers([{ playerId: player.id, steamId: player.steamId }], contextOf(request)); }); app.get('/api/scrape/unmatched', { preHandler: requireAuth }, async (request) => { const query = parseWith( z.object({ all: z.enum(['true', 'false']).default('false') }), request.query, ); return { items: await listUnmatched(query.all === 'false') }; }); app.get('/api/scrape/unmatched/overview', { preHandler: requireAuth }, async () => { return unmatchedOverview(); }); app.post('/api/scrape/unmatched/:id/resolve', { preHandler: requireAdmin }, async (request) => { const { id } = parseWith(idParam, request.params); const body = parseWith( z.object({ resolution: z.enum(['CC_PACKAGE', 'REDESIGN_PACKAGE', 'REDESIGN_KULANZ', 'IGNORE']), }), request.body, ); await resolveUnmatched(id, body.resolution, contextOf(request)); return { ok: true }; }); }