diff --git a/ransomware_fetcher.py b/ransomware_fetcher.py index e44c8c3..63780db 100644 --- a/ransomware_fetcher.py +++ b/ransomware_fetcher.py @@ -14,6 +14,8 @@ from typing import Dict, List, Optional, Tuple from urllib.parse import urlparse from html import escape +from bot_config import SEEN_RETENTION_DAYS, ALLOWED_RANSOMWARE_COUNTRIES + logger = logging.getLogger(__name__) API_BASE = "https://api-pro.ransomware.live" @@ -45,9 +47,15 @@ class RansomwareFetcher: "SELECT 1 FROM seen_victims WHERE victim_id = ?", (victim_id,) ).fetchone() is not None + def is_first_run(self) -> bool: + """True if no victims have ever been recorded as seen (fresh DB).""" + with sqlite3.connect(self.seen_file) as conn: + count = conn.execute("SELECT COUNT(1) FROM seen_victims").fetchone()[0] + return count == 0 + def mark_seen(self, victim_id: str): now = datetime.now(timezone.utc).isoformat() - cutoff = (datetime.now(timezone.utc) - timedelta(days=7)).isoformat() + cutoff = (datetime.now(timezone.utc) - timedelta(days=SEEN_RETENTION_DAYS)).isoformat() with sqlite3.connect(self.seen_file) as conn: conn.execute("DELETE FROM seen_victims WHERE seen_at < ?", (cutoff,)) conn.execute( @@ -95,6 +103,13 @@ class RansomwareFetcher: victims = await self._fetch_month(session, year, month) all_victims.extend(victims) + # Only care about victims in these countries — the general global feed + # is available directly on ransomware.live's own site. + all_victims = [ + v for v in all_victims + if (v.get("country") or "").strip().upper() in ALLOWED_RANSOMWARE_COUNTRIES + ] + new_victims = [] for v in all_victims: discovered_str = v.get("discovered", "") @@ -104,6 +119,8 @@ class RansomwareFetcher: discovered_dt = datetime.fromisoformat(discovered_str.replace("Z", "+00:00")) except ValueError: continue + if discovered_dt.tzinfo is None: + discovered_dt = discovered_dt.replace(tzinfo=timezone.utc) if discovered_dt < cutoff: continue @@ -167,13 +184,11 @@ class RansomwareFetcher: "url": victim.get("permalink", ""), "published_human": published_human, "source": "ransomware.live", - "category": "malware", - "feed_type": "malware", + "category": "ransomware", + "feed_type": "ransomware", "thumbnail": screenshot, "cves": [], "threat_actors": [], "malware_families": [group.title()], "mitre_techniques": [], - "iocs": {}, - "_victim_id": victim.get("id", ""), }