import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; import { numberReputationService, smsClassifierService, callAnalysisService, spamFeedbackService, } from '../services/spamshield'; export async function spamshieldRoutes(fastify: FastifyInstance) { // Classify SMS text fastify.post('/sms/classify', async (request: FastifyRequest, reply: FastifyReply) => { const authReq = request as FastifyRequest & { user?: { id: string } }; const userId = authReq.user?.id; if (!userId) { return reply.code(401).send({ error: 'User ID required' }); } const body = request.body as { text: string }; if (!body.text || typeof body.text !== 'string') { return reply.code(400).send({ error: 'text is required' }); } try { const result = await smsClassifierService.classify(body.text); return reply.send({ classification: { isSpam: result.isSpam, confidence: result.confidence, spamFeatures: result.spamFeatures, }, }); } catch (error) { const message = error instanceof Error ? error.message : 'Classification failed'; return reply.code(422).send({ error: message }); } }); // Check number reputation fastify.post('/number/reputation', async (request: FastifyRequest, reply: FastifyReply) => { const authReq = request as FastifyRequest & { user?: { id: string } }; const userId = authReq.user?.id; if (!userId) { return reply.code(401).send({ error: 'User ID required' }); } const body = request.body as { phoneNumber: string }; if (!body.phoneNumber || typeof body.phoneNumber !== 'string') { return reply.code(400).send({ error: 'phoneNumber is required' }); } try { const result = await numberReputationService.checkReputation(body.phoneNumber); return reply.send({ reputation: { isSpam: result.isSpam, confidence: result.confidence, spamType: result.spamType, reportCount: result.reportCount, }, }); } catch (error) { const message = error instanceof Error ? error.message : 'Reputation check failed'; return reply.code(422).send({ error: message }); } }); // Analyze incoming call fastify.post('/call/analyze', async (request: FastifyRequest, reply: FastifyReply) => { const authReq = request as FastifyRequest & { user?: { id: string } }; const userId = authReq.user?.id; if (!userId) { return reply.code(401).send({ error: 'User ID required' }); } const body = request.body as { phoneNumber: string; duration?: number; callTime: string; isVoip?: boolean; }; if (!body.phoneNumber || !body.callTime) { return reply.code(400).send({ error: 'phoneNumber and callTime are required' }); } try { const result = await callAnalysisService.analyzeCall({ phoneNumber: body.phoneNumber, duration: body.duration, callTime: new Date(body.callTime), isVoip: body.isVoip, }); return reply.send({ analysis: { decision: result.decision, confidence: result.confidence, reasons: result.reasons, }, }); } catch (error) { const message = error instanceof Error ? error.message : 'Call analysis failed'; return reply.code(422).send({ error: message }); } }); // Record spam feedback fastify.post('/feedback', async (request: FastifyRequest, reply: FastifyReply) => { const authReq = request as FastifyRequest & { user?: { id: string } }; const userId = authReq.user?.id; if (!userId) { return reply.code(401).send({ error: 'User ID required' }); } const body = request.body as { phoneNumber: string; isSpam: boolean; confidence?: number; metadata?: Record; }; if (!body.phoneNumber || typeof body.isSpam !== 'boolean') { return reply.code(400).send({ error: 'phoneNumber and isSpam are required' }); } try { const feedback = await spamFeedbackService.recordFeedback( userId, body.phoneNumber, body.isSpam, body.confidence, body.metadata ); return reply.code(201).send({ feedback: { id: feedback.id, phoneNumber: feedback.phoneNumber, isSpam: feedback.isSpam, createdAt: feedback.createdAt, }, }); } catch (error) { const message = error instanceof Error ? error.message : 'Feedback recording failed'; return reply.code(422).send({ error: message }); } }); // Get spam history fastify.get('/history', async (request: FastifyRequest, reply: FastifyReply) => { const authReq = request as FastifyRequest & { user?: { id: string } }; const userId = authReq.user?.id; if (!userId) { return reply.code(401).send({ error: 'User ID required' }); } const query = request.query as { limit?: string; isSpam?: string; startDate?: string; }; const results = await spamFeedbackService.getSpamHistory(userId, { limit: query.limit ? parseInt(query.limit, 10) : undefined, isSpam: query.isSpam !== undefined ? query.isSpam === 'true' : undefined, startDate: query.startDate ? new Date(query.startDate) : undefined, }); return reply.send({ history: results.map((r) => ({ id: r.id, phoneNumber: r.phoneNumber, isSpam: r.isSpam, createdAt: r.createdAt, })), }); }); // Get spam statistics fastify.get('/statistics', async (request: FastifyRequest, reply: FastifyReply) => { const authReq = request as FastifyRequest & { user?: { id: string } }; const userId = authReq.user?.id; if (!userId) { return reply.code(401).send({ error: 'User ID required' }); } try { const stats = await spamFeedbackService.getStatistics(userId); return reply.send({ statistics: stats }); } catch (error) { const message = error instanceof Error ? error.message : 'Statistics retrieval failed'; return reply.code(422).send({ error: message }); } }); }