@@ -314,7 +314,111 @@ async def api_event(request):
314314 async def index_handler (request ):
315315 return web .FileResponse (os .path .join (DIST_DIR , 'dashboard.html' ))
316316
317- # ------------------------------------------------------------------
317+ async def api_get_intel (request ):
318+ # 1. Top Families
319+ top_families = run_query ("""
320+ SELECT family as name, COUNT(*) as count
321+ FROM threats GROUP BY family ORDER BY count DESC LIMIT 10
322+ """ , fetch = True )
323+
324+ # 2. Engine Breakdown
325+ engine_bd = run_query ("""
326+ SELECT engine, COUNT(*) as count
327+ FROM threats GROUP BY engine
328+ """ , fetch = True )
329+
330+ # 3. Per Agent Stats
331+ per_agent = run_query ("""
332+ SELECT agent, COUNT(*) as count
333+ FROM threats GROUP BY agent ORDER BY count DESC
334+ """ , fetch = True )
335+
336+ # 4. Platform Breakdown (Deteksi dari awalan nama malware)
337+ all_threats = run_query ("SELECT name FROM threats" , fetch = True )
338+ plat_counts = {"Win" : 0 , "Linux" : 0 , "Android" : 0 , "Java" : 0 , "Html" : 0 , "Other" : 0 }
339+
340+ for t in all_threats :
341+ name = t ['name' ].lower ()
342+ if name .startswith ('win' ): plat_counts ['Win' ] += 1
343+ elif name .startswith ('linux' ): plat_counts ['Linux' ] += 1
344+ elif name .startswith ('android' ): plat_counts ['Android' ] += 1
345+ elif name .startswith ('java' ): plat_counts ['Java' ] += 1
346+ elif name .startswith ('html' ): plat_counts ['Html' ] += 1
347+ else : plat_counts ['Other' ] += 1
348+
349+ platforms = [{"platform" : k , "count" : v } for k , v in plat_counts .items () if v > 0 ]
350+ platforms .sort (key = lambda x : x ['count' ], reverse = True )
351+
352+ return web .json_response ({
353+ "top_families" : top_families ,
354+ "engine_breakdown" : engine_bd ,
355+ "platforms" : platforms ,
356+ "per_agent" : per_agent
357+ })
358+
359+ async def api_intel_lookup (request ):
360+ # Handler untuk fitur Hash Lookup di halaman Threat Intel
361+ hash_val = request .query .get ('hash' , '' ).strip ().lower ()
362+ if not hash_val :
363+ return web .json_response ({"found" : False })
364+
365+ rows = run_query ("SELECT * FROM threats WHERE hash=? LIMIT 1" , (hash_val ,), fetch = True )
366+ if rows :
367+ return web .json_response ({"found" : True , "threat" : rows [0 ]})
368+ return web .json_response ({"found" : False })
369+
370+ async def api_get_analytics (request ):
371+ # 1. Summary
372+ sum_rows = run_query ("""
373+ SELECT SUM(total_scanned) as tf, SUM(infected_count) as ti, COUNT(*) as ts
374+ FROM scan_reports
375+ """ , fetch = True )
376+
377+ tf = sum_rows [0 ]['tf' ] or 0
378+ ti = sum_rows [0 ]['ti' ] or 0
379+ ts = sum_rows [0 ]['ts' ] or 0
380+ det_rate = round ((ti / tf * 100 ), 2 ) if tf > 0 else 0
381+
382+ # 2. Daily Chart Activity
383+ chart_rows = run_query ("""
384+ SELECT date(scan_date) as date_val, SUM(total_scanned) as total, SUM(infected_count) as infected
385+ FROM scan_reports
386+ WHERE date(scan_date) >= date('now', '-6 days')
387+ GROUP BY date(scan_date) ORDER BY date(scan_date) ASC
388+ """ , fetch = True )
389+
390+ labels , clean_data , threat_data = [], [], []
391+ for r in chart_rows :
392+ labels .append (r ['date_val' ][5 :]) # Ambil MM-DD
393+ infected = r ['infected' ] or 0
394+ total = r ['total' ] or 0
395+ threat_data .append (infected )
396+ clean_data .append (total - infected )
397+
398+ # 3. Per Agent Performance
399+ agent_stats = run_query ("""
400+ SELECT agent, COUNT(*) as total_scans,
401+ SUM(total_scanned) as total_files, SUM(infected_count) as total_infected,
402+ ROUND(AVG(duration), 2) as avg_duration,
403+ ROUND(AVG(CAST(total_scanned AS FLOAT) / CASE WHEN duration = 0 THEN 1 ELSE duration END), 1) as avg_throughput
404+ FROM scan_reports GROUP BY agent
405+ """ , fetch = True )
406+
407+ # 4. Scan History
408+ history = run_query ("""
409+ SELECT agent, scan_date, total_scanned, infected_count,
410+ ROUND(CAST(total_scanned AS FLOAT) / CASE WHEN duration = 0 THEN 1 ELSE duration END, 1) as throughput
411+ FROM scan_reports ORDER BY id DESC LIMIT 15
412+ """ , fetch = True )
413+
414+ return web .json_response ({
415+ "summary" : {"total_files" : tf , "total_infected" : ti , "detection_rate" : det_rate , "total_sessions" : ts },
416+ "daily_chart" : {"labels" : labels , "threats" : threat_data , "clean" : clean_data },
417+ "per_agent_stats" : agent_stats ,
418+ "scan_history" : history
419+ })
420+
421+ # ------------------------------------------------------------------
318422 # APP SETUP
319423 # ------------------------------------------------------------------
320424 app = web .Application (middlewares = [auth_middleware ])
@@ -326,6 +430,9 @@ async def index_handler(request):
326430 app .router .add_get ('/api/threats' , api_get_threats )
327431 app .router .add_post ('/api/heartbeat' , api_heartbeat )
328432 app .router .add_post ('/api/event' , api_event )
433+ app .router .add_get ('/api/intel' , api_get_intel )
434+ app .router .add_get ('/api/intel/lookup' , api_intel_lookup )
435+ app .router .add_get ('/api/analytics' , api_get_analytics )
329436 app .router .add_get ('/' , index_handler )
330437 app .router .add_static ('/' , path = DIST_DIR , name = 'static' )
331438
0 commit comments