// Seed du mode Images depuis PokéAPI : "devine le Pokémon" à partir de // l'artwork officiel (URL distante, pas d'upload). Réponses acceptées FR + EN. // bun run db:seed:images (gen 1, 151 Pokémon) // IMAGE_SEED_COUNT=50 bun run db:seed:images // Idempotent : déduplication par image_url (onConflictDoNothing). import { eq } from "drizzle-orm" import { drizzle } from "drizzle-orm/postgres-js" import postgres from "postgres" import { env } from "../env" import { quizCategory, quizQuestion, type NewQuizQuestion } from "./schema" if (!env.databaseUrl) { console.error("DATABASE_URL manquant — impossible de seeder.") process.exit(1) } const COUNT = Number(process.env.IMAGE_SEED_COUNT ?? 151) const CATEGORY = "Pokémon" const PROMPT = "Quel est ce Pokémon ?" const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)) const client = postgres(env.databaseUrl, { max: 1 }) const db = drizzle(client, { schema: { quizCategory, quizQuestion } }) async function upsertCategory(name: string): Promise { await db.insert(quizCategory).values({ name }).onConflictDoNothing() const [row] = await db .select({ id: quizCategory.id }) .from(quizCategory) .where(eq(quizCategory.name, name)) return row.id } interface Pokemon { name: string sprites: { other?: { ["official-artwork"]?: { front_default: string | null } } } } interface Species { names: { name: string; language: { name: string } }[] } async function fetchPokemon(id: number): Promise { try { const [pRes, sRes] = await Promise.all([ fetch(`https://pokeapi.co/api/v2/pokemon/${id}`), fetch(`https://pokeapi.co/api/v2/pokemon-species/${id}`), ]) if (!pRes.ok || !sRes.ok) { return null } const p = (await pRes.json()) as Pokemon const s = (await sRes.json()) as Species const art = p.sprites.other?.["official-artwork"]?.front_default if (!art) { return null } const fr = s.names.find((n) => n.language.name === "fr")?.name const en = s.names.find((n) => n.language.name === "en")?.name ?? p.name const answers = [...new Set([fr, en].filter(Boolean) as string[])] return { categoryId: "", // rempli plus bas format: "image_reveal", prompt: PROMPT, difficulty: 2, source: "pokeapi", lang: "fr", acceptedAnswers: answers, imageUrl: art, } } catch { return null } } console.log(`Seed Images depuis PokéAPI (${COUNT} Pokémon)…`) const categoryId = await upsertCategory(CATEGORY) let inserted = 0 for (let id = 1; id <= COUNT; id++) { const q = await fetchPokemon(id) if (q) { const res = await db .insert(quizQuestion) .values({ ...q, categoryId }) .onConflictDoNothing() .returning({ id: quizQuestion.id }) inserted += res.length } if (id % 25 === 0) { console.log(` ${id}/${COUNT}…`) } await sleep(40) // courtoisie envers l'API } console.log(`Terminé : ${inserted} Pokémon ajoutés (mode Images).`) await client.end()