/// import { Router, Request, Response } from 'express'; import { getAllRecipes, getRecipeById, createRecipe, updateRecipe, deleteRecipe, getCategories, getDb } from '../db.js'; import { getTikTokData } from '../services/tiktok.js'; import { isAiAvailable, extractRecipe } from '../services/ai.js'; import { trackEvent } from '../analytics-db.js'; const router = Router(); router.get('/', (req: Request, res: Response) => { const { search, category, user_id } = req.query as { search?: string; category?: string; user_id?: string }; const recipes = getAllRecipes(search, category, user_id); res.json(recipes.map(r => ({ ...r, ingredients: JSON.parse(r.ingredients || '[]'), steps: JSON.parse(r.steps || '[]'), }))); }); router.get('/categories', (req: Request, res: Response) => { res.json(getCategories()); }); router.get('/authors', (req: Request, res: Response) => { const db = getDb(); const recipes = db.prepare('SELECT DISTINCT user_id FROM recipes WHERE user_id IS NOT NULL').all() as { user_id: number }[]; const authorIds = recipes.map(r => r.user_id); const authors = authorIds.map(id => { const user = db.prepare('SELECT id, username FROM users WHERE id = ?').get(id) as { id: number; username: string } | undefined; return { id, username: user ? user.username : `User #${id}` }; }).sort((a, b) => a.username.localeCompare(b.username)); res.json(authors); }); router.get('/ai-status', async (req: Request, res: Response) => { const available = await isAiAvailable(); res.json({ ai: available }); }); router.get('/:id', (req: Request, res: Response) => { const recipe = getRecipeById(req.params.id as string); if (!recipe) return res.status(404).json({ error: 'Rezept nicht gefunden' }); res.json({ ...recipe, ingredients: JSON.parse(recipe.ingredients || '[]'), steps: JSON.parse(recipe.steps || '[]'), }); }); router.post('/', (req: Request, res: Response) => { const recipe = createRecipe(req.body); const userId = req.body.user_id || null; trackEvent('recipe_created', userId, { recipe_id: recipe.id, recipe_name: recipe.name }); res.status(201).json(recipe); }); router.put('/:id', (req: Request, res: Response) => { const existing = getRecipeById(req.params.id as string); if (!existing) return res.status(404).json({ error: 'Rezept nicht gefunden' }); const updated = updateRecipe(req.params.id as string, req.body); trackEvent('recipe_updated', req.body.user_id || null, { recipe_id: Number(req.params.id), recipe_name: updated?.name }); res.json(updated); }); router.delete('/:id', (req: Request, res: Response) => { const existing = getRecipeById(req.params.id as string); if (!existing) return res.status(404).json({ error: 'Rezept nicht gefunden' }); deleteRecipe(req.params.id as string); trackEvent('recipe_deleted', null, { recipe_id: Number(req.params.id) }); res.json({ success: true }); }); router.post('/from-tiktok', async (req: Request, res: Response) => { try { const { url } = req.body; if (!url) return res.status(400).json({ error: 'URL erforderlich' }); const tiktokData = await getTikTokData(url); const aiAvailable = await isAiAvailable(); let extracted = null; let aiStatus = aiAvailable ? 'available' : 'unavailable'; let aiMessage = ''; if (aiAvailable && tiktokData.title) { try { extracted = await extractRecipe(tiktokData.title); aiStatus = 'success'; } catch (e: any) { console.error('KI Extraktion fehlgeschlagen:', e.message); aiStatus = 'error'; aiMessage = e.message; } } else if (!aiAvailable) { aiMessage = 'KI-Service nicht erreichbar'; } else if (!tiktokData.title) { aiMessage = 'Kein Titel im Video gefunden'; } res.json({ tiktok: tiktokData, ai: aiAvailable, aiStatus, aiMessage, extracted, }); } catch (error: any) { res.status(500).json({ error: error.message }); } }); export default router;