|
|
from __future__ import annotations |
|
|
|
|
|
import os |
|
|
from dataclasses import dataclass |
|
|
from datetime import datetime |
|
|
from typing import Any |
|
|
|
|
|
import gradio as gr |
|
|
import requests |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass |
|
|
class AbuseReport: |
|
|
date: str |
|
|
categories: str |
|
|
comment: str |
|
|
reporter: str |
|
|
|
|
|
|
|
|
@dataclass |
|
|
class IPCheckResult: |
|
|
ip_address: str |
|
|
abuse_confidence_score: int |
|
|
total_reports: int |
|
|
country_code: str |
|
|
domain: str |
|
|
isp: str |
|
|
last_reported: str |
|
|
reports: list[AbuseReport] |
|
|
|
|
|
def format_summary(self) -> str: |
|
|
"""Format a summary of the IP check result.""" |
|
|
return f""" |
|
|
IP Address: {self.ip_address} |
|
|
Abuse Confidence Score: {self.abuse_confidence_score}% |
|
|
Total Reports: {self.total_reports} |
|
|
Country: {self.country_code} |
|
|
Domain: {self.domain} |
|
|
ISP: {self.isp} |
|
|
Last Reported: {self.last_reported} |
|
|
""" |
|
|
|
|
|
|
|
|
def check_ip(ip_address: str, api_key: str, days: str = "30") -> dict[str, Any]: |
|
|
"""Query the AbuseIPDB API to check if an IP address has been reported. |
|
|
|
|
|
Args: |
|
|
ip_address: The IP address to check |
|
|
api_key: Your AbuseIPDB API key |
|
|
days: Number of days to check (default: 30) |
|
|
|
|
|
Returns: |
|
|
API response data as a dictionary |
|
|
""" |
|
|
url = "https://api.abuseipdb.com/api/v2/check" |
|
|
|
|
|
headers = {"Accept": "application/json", "Key": api_key} |
|
|
|
|
|
params = { |
|
|
"ipAddress": ip_address, |
|
|
"maxAgeInDays": days, |
|
|
"verbose": str(True), |
|
|
} |
|
|
|
|
|
try: |
|
|
response = requests.get( |
|
|
url, |
|
|
headers=headers, |
|
|
params=params, |
|
|
timeout=30, |
|
|
) |
|
|
response.raise_for_status() |
|
|
return response.json() |
|
|
except requests.exceptions.RequestException as e: |
|
|
return {"error": str(e)} |
|
|
|
|
|
|
|
|
def parse_response( |
|
|
response: dict[str, Any], |
|
|
) -> tuple[IPCheckResult | None, str]: |
|
|
"""Parse the API response into a dataclass. |
|
|
|
|
|
Args: |
|
|
response: The API response dictionary |
|
|
|
|
|
Returns: |
|
|
A tuple containing (result_object, error_message) |
|
|
If successful, error_message will be None |
|
|
If failed, result_object will be None |
|
|
""" |
|
|
if "error" in response: |
|
|
return None, f"Error: {response['error']}" |
|
|
|
|
|
data = response.get("data", {}) |
|
|
|
|
|
|
|
|
reports = [] |
|
|
if data.get("reports"): |
|
|
for report in data["reports"]: |
|
|
reported_at = datetime.fromisoformat( |
|
|
report["reportedAt"].replace("Z", "+00:00"), |
|
|
).strftime("%Y-%m-%d %H:%M:%S") |
|
|
categories = ", ".join([str(cat) for cat in report.get("categories", [])]) |
|
|
|
|
|
reports.append( |
|
|
AbuseReport( |
|
|
date=reported_at, |
|
|
categories=categories, |
|
|
comment=report.get("comment", ""), |
|
|
reporter=str(report.get("reporterId", "Anonymous")), |
|
|
), |
|
|
) |
|
|
|
|
|
|
|
|
result = IPCheckResult( |
|
|
ip_address=data.get("ipAddress", "N/A"), |
|
|
abuse_confidence_score=data.get("abuseConfidenceScore", 0), |
|
|
total_reports=data.get("totalReports", 0), |
|
|
country_code=data.get("countryCode", "N/A"), |
|
|
domain=data.get("domain", "N/A"), |
|
|
isp=data.get("isp", "N/A"), |
|
|
last_reported=data.get("lastReportedAt", "Never"), |
|
|
reports=reports, |
|
|
) |
|
|
|
|
|
return result, "" |
|
|
|
|
|
|
|
|
def query_abuseipdb(ip_address: str, days: int = 30) -> str: |
|
|
"""Query AbuseIP to find if an IP has been reported for abusive behavior. |
|
|
|
|
|
Args: |
|
|
ip_address: The IP address to check |
|
|
api_key: Your AbuseIPDB API key |
|
|
days: Number of days to check |
|
|
|
|
|
Returns: |
|
|
A tuple containing (summary_text, reports_text) |
|
|
""" |
|
|
if not ip_address: |
|
|
return "Please provide both an IP address and API key" |
|
|
|
|
|
api_key = os.environ["ABUSEIPDB_KEY"] |
|
|
|
|
|
response = check_ip(ip_address, api_key, str(days)) |
|
|
result, error = parse_response(response) |
|
|
|
|
|
if result: |
|
|
return result.format_summary() |
|
|
|
|
|
return error |
|
|
|
|
|
|
|
|
gr_query_abuseipdb = gr.Interface( |
|
|
fn=query_abuseipdb, |
|
|
inputs=gr.Textbox(label="ip"), |
|
|
outputs=gr.Text(label="Report on abusive behaviour"), |
|
|
title="AbuseIPDB IP Checker", |
|
|
description=( |
|
|
"Check if an IP address has been reported for abusive behavior" |
|
|
" using AbuseIP DB API" |
|
|
), |
|
|
examples=["5.252.155.14", "77.239.99.248"], |
|
|
example_labels=["👾 Malicious IP 1", "👾 Malicious IP 2"], |
|
|
) |
|
|
|