Trouve-KA — moteur de recherche web indépendant, Québec-first. Crawler distribué, index OpenSearch, ranking bilingue, galerie d'images. En prod : www.trouve-ka.com
Python 51.9%
TypeScript 32.7%
JavaScript 4.8%
CSS 4.1%
Shell 2.9%
HTML 1.8%
SQL 1.5%
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// Toggle d'un favori « Mon univers Ka » : pousse « add » / « remove » au hub3// groupe-ka.com (POST signé HMAC, SYNCHRONE — un échec remonte au client).4// item_id = identifiant stable du résultat, dérivé de son URL si absent.5import { NextRequest, NextResponse } from "next/server";6import { SESSION_COOKIE, readSession } from "@/lib/ka-auth";7import { cleanItem, hubToggle, itemIdForUrl } from "@/lib/hubfav";89export async function POST(req: NextRequest) {10 const session = readSession(req.cookies.get(SESSION_COOKIE)?.value);11 if (!session) {12 return NextResponse.json({ error: "Connexion KA ID requise." }, { status: 401 });13 }1415 let body: { action?: unknown; item?: unknown };16 try {17 body = await req.json();18 } catch {19 return NextResponse.json({ error: "Corps JSON invalide." }, { status: 400 });20 }2122 const action = body.action;23 if (action !== "add" && action !== "remove") {24 return NextResponse.json(25 { error: "action doit être « add » ou « remove »." },26 { status: 400 },27 );28 }29 if (typeof body.item !== "object" || body.item === null) {30 return NextResponse.json({ error: "item requis." }, { status: 400 });31 }3233 const item = cleanItem(body.item as Record<string, unknown>);34 if (!item.item_id && item.url) item.item_id = itemIdForUrl(item.url);35 if (!item.item_id) {36 return NextResponse.json(37 { error: "item.item_id ou item.url requis." },38 { status: 400 },39 );40 }41 if (action === "add" && !item.title) {42 return NextResponse.json({ error: "item.title requis." }, { status: 400 });43 }4445 const ok = await hubToggle(session.ka_id, action, item);46 if (!ok) {47 return NextResponse.json(48 { error: "Le hub Groupe KA est momentanément injoignable." },49 { status: 502 },50 );51 }52 return NextResponse.json({ ok: true, action, item_id: item.item_id });53}54