← back to Wine Finder Next
app/api/ingest/vivino/route.ts
103 lines
// app/api/ingest/vivino/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { getDb } from '@/lib/db';
export async function POST(req: NextRequest) {
try {
const body = await req.json();
const { wines } = body;
if (!Array.isArray(wines)) {
return NextResponse.json({ error: 'wines array required' }, { status: 400 });
}
const db = getDb();
const insertWine = db.prepare(`
INSERT OR REPLACE INTO wines (
name, varietal, vintage, region, country,
alc_percent, tasting_notes, vivino_id,
image_url, critic_scores
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
const insertPrice = db.prepare(`
INSERT INTO wine_prices (wine_id, vendor, price, collected_at, product_id, metadata)
VALUES (?, 'vivino', ?, datetime('now'), ?, ?)
`);
const insertRating = db.prepare(`
INSERT OR REPLACE INTO wine_ratings (wine_id, vendor, rating, review_count, collected_at)
VALUES (?, 'vivino', ?, ?, datetime('now'))
`);
let processed = 0;
let errors = 0;
for (const wine of wines) {
try {
// Insert or update wine
const wineResult = insertWine.run(
wine.name || '',
wine.grape || wine.varietal || null,
wine.vintage || null,
wine.region?.name || wine.region || null,
wine.region?.country?.name || wine.country || null,
wine.alcohol || null,
wine.taste?.description || wine.description || null,
wine.vivino_id || wine.id || null,
wine.image?.location || wine.image_url || null,
wine.style ? JSON.stringify(wine.style) : null
);
// Insert price if provided
if (wine.price?.amount) {
const metadata = {
currency: wine.price.currency,
discounted_from: wine.price.discounted_from,
bottle_size: wine.bottle_size
};
insertPrice.run(
wineResult.lastInsertRowid,
wine.price.amount,
wine.vivino_id || wine.id,
JSON.stringify(metadata)
);
}
// Insert rating if provided
if (wine.rating?.average) {
insertRating.run(
wineResult.lastInsertRowid,
wine.rating.average,
wine.rating.count || 0
);
}
processed++;
} catch (error) {
console.error('Error processing wine:', error);
errors++;
}
}
return NextResponse.json({
success: true,
processed,
errors,
message: `Processed ${processed} wines from Vivino`
});
} catch (error) {
console.error('Vivino ingest error:', error);
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
}
}
export async function GET() {
// Health check endpoint
return NextResponse.json({
status: 'Vivino ingest endpoint ready',
timestamp: new Date().toISOString()
});
}