File size: 4,637 Bytes
0d4024a
5061d39
0d4024a
5061d39
0d4024a
 
 
5061d39
0d4024a
5061d39
 
 
 
0d4024a
5061d39
0d4024a
5061d39
 
 
 
 
 
 
0d4024a
5061d39
 
 
 
 
 
 
0d4024a
5061d39
 
0d4024a
5061d39
 
 
 
 
 
 
 
 
 
 
0d4024a
 
5061d39
 
 
 
 
 
 
 
 
0d4024a
5061d39
0d4024a
5061d39
 
0d4024a
 
 
5061d39
 
 
0d4024a
 
 
 
 
 
5061d39
 
 
 
 
 
0d4024a
 
 
 
5061d39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d4024a
5061d39
0d4024a
 
 
5061d39
 
0d4024a
 
 
 
 
 
 
 
5061d39
 
 
 
 
 
 
 
 
 
0d4024a
5061d39
 
0d4024a
5061d39
 
fe1b54e
0d4024a
5061d39
 
 
 
 
 
 
 
 
fe1b54e
5061d39
 
fe1b54e
 
5061d39
 
 
0d4024a
 
5061d39
0d4024a
5061d39
 
 
 
3e2bf63
 
5061d39
0d4024a
 
 
 
3e2bf63
 
5061d39
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
from __future__ import annotations

import os
from dataclasses import dataclass
from datetime import datetime
from typing import Any

import gradio as gr
import requests


# API docs: https://docs.abuseipdb.com/#check-endpoint


@dataclass
class AbuseReport:  # noqa: D101
    date: str
    categories: str
    comment: str
    reporter: str


@dataclass
class IPCheckResult:  # noqa: D101
    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()  # Raise exception for HTTP errors
        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", {})

    # Create a list of AbuseReport objects
    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")),
                ),
            )

    # Create the main result object
    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"],
)