import { Router } from 'express'; import { getAllRecipes, getRecipeById, createRecipe, updateRecipe, deleteRecipe, getCategories, getDb } from '../db.js'; import { getTikTokData } from '../services/tiktok.js'; import { isOllamaAvailable, extractRecipe } from '../services/ai.js'; import { trackEvent } from '../analytics-db.js'; const router = Router(); router.get('/', (req, res) => { const { search, category, user_id } = req.query; 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, res) => { res.json(getCategories()); }); router.get('/authors', (req, res) => { const db = getDb(); const authorIds = [...new Set(db.recipes.filter(r => r.user_id).map(r => r.user_id))]; const authors = authorIds.map(id => { const user = db.users.find(u => u.id === id); 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, res) => { const available = await isOllamaAvailable(); res.json({ ollama: available }); }); router.get('/:id', (req, res) => { const recipe = getRecipeById(req.params.id); 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, res) => { 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, res) => { const existing = getRecipeById(req.params.id); if (!existing) return res.status(404).json({ error: 'Rezept nicht gefunden' }); const updated = updateRecipe(req.params.id, 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, res) => { const existing = getRecipeById(req.params.id); if (!existing) return res.status(404).json({ error: 'Rezept nicht gefunden' }); deleteRecipe(req.params.id); trackEvent('recipe_deleted', null, { recipe_id: Number(req.params.id) }); res.json({ success: true }); }); router.post('/from-tiktok', async (req, res) => { try { const { url } = req.body; if (!url) return res.status(400).json({ error: 'URL erforderlich' }); const tiktokData = await getTikTokData(url); const ollamaAvailable = await isOllamaAvailable(); let extracted = null; let aiStatus = ollamaAvailable ? 'available' : 'unavailable'; let aiMessage = ''; if (ollamaAvailable && tiktokData.title) { try { extracted = await extractRecipe(tiktokData.title); aiStatus = 'success'; } catch (e) { console.error('Ollama Extraktion fehlgeschlagen:', e.message); aiStatus = 'error'; aiMessage = e.message; } } else if (!ollamaAvailable) { aiMessage = 'Ollama-Server nicht erreichbar'; } else if (!tiktokData.title) { aiMessage = 'Kein Titel im Video gefunden'; } res.json({ tiktok: tiktokData, ollama: ollamaAvailable, aiStatus, aiMessage, extracted, }); } catch (error) { res.status(500).json({ error: error.message }); } }); export default router;