68 lines
2.0 KiB
TypeScript
68 lines
2.0 KiB
TypeScript
import type { NextApiRequest, NextApiResponse } from 'next'
|
|
import sqlite3 from 'sqlite3'
|
|
import path from 'path'
|
|
|
|
interface RiskyDomain {
|
|
domain: string
|
|
source_count: number
|
|
avg_risk_level: number
|
|
max_risk_level: number
|
|
categories: string[]
|
|
}
|
|
|
|
export default async function handler(
|
|
req: NextApiRequest,
|
|
res: NextApiResponse<RiskyDomain[] | { error: string }>
|
|
) {
|
|
if (req.method !== 'GET') {
|
|
return res.status(405).json({ error: 'Method not allowed' })
|
|
}
|
|
|
|
const { limit = '20' } = req.query
|
|
|
|
const dbPath = path.join(process.cwd(), 'database', 'antihoax.db')
|
|
const db = new sqlite3.Database(dbPath)
|
|
|
|
try {
|
|
const riskyDomains = await new Promise<RiskyDomain[]>((resolve, reject) => {
|
|
db.all(
|
|
`SELECT
|
|
s.domain,
|
|
COUNT(*) as source_count,
|
|
AVG(s.risk_level) as avg_risk_level,
|
|
MAX(s.risk_level) as max_risk_level,
|
|
GROUP_CONCAT(DISTINCT 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.status = 'verified'
|
|
GROUP BY s.domain
|
|
HAVING AVG(s.risk_level) >= 3
|
|
ORDER BY avg_risk_level DESC, source_count DESC
|
|
LIMIT ?`,
|
|
[parseInt(limit as string)],
|
|
(err, rows: any[]) => {
|
|
if (err) reject(err)
|
|
else {
|
|
const domains = rows.map(row => ({
|
|
domain: row.domain,
|
|
source_count: row.source_count,
|
|
avg_risk_level: Math.round(row.avg_risk_level * 10) / 10,
|
|
max_risk_level: row.max_risk_level,
|
|
categories: row.categories ? row.categories.split(',') : []
|
|
}))
|
|
resolve(domains)
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
return res.status(200).json(riskyDomains)
|
|
|
|
} catch (error) {
|
|
console.error('Database error:', error)
|
|
return res.status(500).json({ error: 'Internal server error' })
|
|
} finally {
|
|
db.close()
|
|
}
|
|
} |