import type { NextApiRequest, NextApiResponse } from 'next' import sqlite3 from 'sqlite3' import path from 'path' import { rateLimit, getRateLimitHeaders } from '../../../lib/rate-limiter' type CheckResponse = { is_problematic: boolean risk_level: number categories: string[] message: string source_count: number } function extractDomain(url: string): string { try { // Clean up the URL first let cleanUrl = url.trim() if (!cleanUrl.startsWith('http://') && !cleanUrl.startsWith('https://')) { cleanUrl = 'https://' + cleanUrl } const urlObj = new URL(cleanUrl) let domain = urlObj.hostname.toLowerCase() // Remove common prefixes domain = domain.replace(/^www\./, '') domain = domain.replace(/^m\./, '') domain = domain.replace(/^mobile\./, '') domain = domain.replace(/^amp\./, '') // Handle subdomains for known patterns - extract main domain for common TLDs if (domain.includes('.')) { const parts = domain.split('.') if (parts.length > 2) { const tld = parts[parts.length - 1] const sld = parts[parts.length - 2] // Extract main domain for common TLDs if (['com', 'org', 'net', 'sk', 'cz', 'hu', 'pl', 'eu', 'info'].includes(tld)) { domain = `${sld}.${tld}` } } } return domain } catch { return '' } } export default async function handler( req: NextApiRequest, res: NextApiResponse ) { if (req.method !== 'GET') { return res.status(405).json({ error: 'Method not allowed' }) } // Rate limiting const clientIp = req.headers['x-forwarded-for'] || req.connection?.remoteAddress || 'unknown' const rateLimitResult = rateLimit(clientIp.toString()) const headers = getRateLimitHeaders(rateLimitResult) Object.entries(headers).forEach(([key, value]) => { res.setHeader(key, value) }) if (!rateLimitResult.allowed) { return res.status(429).json({ error: 'Too many requests' }) } const { url } = req.query if (!url || typeof url !== 'string') { return res.status(400).json({ error: 'URL parameter is required' }) } const domain = extractDomain(url) if (!domain) { return res.status(400).json({ error: 'Invalid URL format' }) } const dbPath = path.join(process.cwd(), 'database', 'antihoax.db') const db = new sqlite3.Database(dbPath) try { const sources = await new Promise((resolve, reject) => { db.all( `SELECT s.*, GROUP_CONCAT(c.name) as categories FROM sources s LEFT JOIN source_categories sc ON s.id = sc.source_id LEFT JOIN categories c ON sc.category_id = c.id WHERE s.domain = ? AND s.status = 'verified' GROUP BY s.id`, [domain], (err, rows) => { if (err) reject(err) else resolve(rows) } ) }) if (sources.length === 0) { return res.status(200).json({ is_problematic: false, risk_level: 0, categories: [], message: 'Stránka nie je v našej databáze problematických zdrojov', source_count: 0 }) } const maxRiskLevel = Math.max(...sources.map(s => s.risk_level)) const allCategories = sources .map(s => s.categories) .filter(Boolean) .join(',') .split(',') .filter(Boolean) const uniqueCategories = Array.from(new Set(allCategories)) let message = '' if (maxRiskLevel >= 4) { message = 'VYSOKÉ RIZIKO: Táto stránka šíri nebezpečné obsahy' } else if (maxRiskLevel >= 3) { message = 'STREDNÉ RIZIKO: Táto stránka môže obsahovať problematické informácie' } else { message = 'NÍZKE RIZIKO: Táto stránka je označená ako problematická' } return res.status(200).json({ is_problematic: true, risk_level: maxRiskLevel, categories: uniqueCategories, message, source_count: sources.length }) } catch (error) { console.error('Database error:', error) return res.status(500).json({ error: 'Internal server error' }) } finally { db.close() } }