#!/usr/bin/env python3
"""Post a single abuse report to IRDB.

Usage:
    IRDB_URL=http://localhost:8081 IRDB_TOKEN=irdb_rep_... \\
        examples/reporters/python.py 203.0.113.42 brute_force '{"url":"/wp-login.php"}'

The third argument (metadata) is optional and must be valid JSON.

This script uses only the stdlib (`urllib`); no third-party deps.

fail2ban-action wrapper (drop into `/etc/fail2ban/action.d/irdb.conf`):

    [Definition]
    actionban = /usr/local/bin/irdb-report.py <ip> brute_force
                '{"jail":"<name>","host":"<ipfailures>"}'
    actionunban = true

    [Init]
    name = default

`<ip>` and `<name>` are substituted by fail2ban at action time. Set
IRDB_URL and IRDB_TOKEN in fail2ban's environment (e.g. via
`/etc/default/fail2ban`).
"""
from __future__ import annotations

import json
import os
import sys
import urllib.error
import urllib.request


def main(argv: list[str]) -> int:
    if len(argv) < 3:
        print(f"Usage: {argv[0]} <ip> <category> [<metadata-json>]", file=sys.stderr)
        return 64

    ip = argv[1]
    category = argv[2]
    metadata_raw = argv[3] if len(argv) > 3 else "{}"
    try:
        metadata = json.loads(metadata_raw)
    except json.JSONDecodeError as e:
        print(f"metadata must be valid JSON: {e}", file=sys.stderr)
        return 65

    url_base = os.environ.get("IRDB_URL")
    token = os.environ.get("IRDB_TOKEN")
    if not url_base or not token:
        print("IRDB_URL and IRDB_TOKEN must be set", file=sys.stderr)
        return 78

    body = json.dumps({"ip": ip, "category": category, "metadata": metadata}).encode()
    req = urllib.request.Request(
        f"{url_base.rstrip('/')}/api/v1/report",
        data=body,
        method="POST",
        headers={
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json",
        },
    )
    try:
        with urllib.request.urlopen(req, timeout=10) as resp:
            print(resp.read().decode())
            return 0
    except urllib.error.HTTPError as e:
        print(f"http {e.code}: {e.read().decode(errors='replace')}", file=sys.stderr)
        return 1
    except urllib.error.URLError as e:
        print(f"network error: {e}", file=sys.stderr)
        return 2


if __name__ == "__main__":
    sys.exit(main(sys.argv))
