From 63f0ac74bc9bb34d46d04b5f8fc6682e1a1ac1e8 Mon Sep 17 00:00:00 2001 From: bot Date: Tue, 25 Aug 2026 12:19:37 +0300 Subject: [PATCH] Add bot_config.py: single source of truth for category/feed config Category labels, feed-file mappings, and emoji were copy-pasted across threat_intel_bot.py, check_feeds.py, and validation/run_validation.py, which is how the ransomware category split almost missed one of them. check_feeds.py now imports from bot_config.py instead of keeping its own copy. Co-Authored-By: Claude Sonnet 5 --- bot_config.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ check_feeds.py | 9 +-------- 2 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 bot_config.py diff --git a/bot_config.py b/bot_config.py new file mode 100644 index 0000000..7865e1d --- /dev/null +++ b/bot_config.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +""" +Shared category, feed-file, and tuning configuration. + +Single source of truth for values that used to be copy-pasted across +threat_intel_bot.py, check_feeds.py, and validation/run_validation.py — +edit here, not in the callers. +""" + +# category -> (display label, emoji) +CATEGORY_LABELS = { + "news": ("News", "📰"), + "malware": ("Malware", "🦠"), + "threat_intel": ("Threat Intel", "🛰️"), + "osint": ("OSINT", "🕵️"), + "research": ("Research", "🔬"), +} + +# category -> RSS feed list file. Every key here must also be in CATEGORY_LABELS. +CATEGORY_FEEDS = { + "news": "feeds/news_feeds.json", + "malware": "feeds/malware_feeds.json", + "threat_intel": "feeds/threat_intel_feeds.json", + "osint": "feeds/osint_feeds.json", + "research": "feeds/research_feeds.json", +} + +# Categories with no RSS feed of their own (e.g. fed by an API poller instead). +# Subscribable via /on_, but excluded from the RSS polling/status loops. +EXTRA_CATEGORY_LABELS = { + "ransomware": ("Ransomware", "💰"), +} + +CATEGORY_EMOJIS = { + key: emoji for key, (_label, emoji) in {**CATEGORY_LABELS, **EXTRA_CATEGORY_LABELS}.items() +} + +# How often the bot/validation monitor polls feeds and the ransomware.live API. +POLL_INTERVAL_SECONDS = 300 + +# How long "seen" fingerprints and recently-sent titles are kept for dedup. +# Only used to suppress re-alerting on the same story — no other retention need. +SEEN_RETENTION_DAYS = 14 + +# Only alert on ransomware.live victims headquartered in these ISO-2 countries. +# The general global feed is available directly on ransomware.live's own site. +ALLOWED_RANSOMWARE_COUNTRIES = {"LV", "EE", "LT"} + +# Cross-source near-duplicate title matching (catches the same story reported +# by two different outlets with different URLs/wording). +TITLE_DEDUP_WINDOW_HOURS = 72 +TITLE_SIMILARITY_THRESHOLD = 0.72 diff --git a/check_feeds.py b/check_feeds.py index 60dcca4..698f17a 100644 --- a/check_feeds.py +++ b/check_feeds.py @@ -4,14 +4,7 @@ Quick script to check all RSS feeds status """ import asyncio from rss_manager import RSSFeedManager - -CATEGORY_FEEDS = { - "news": "feeds/news_feeds.json", - "malware": "feeds/malware_feeds.json", - "threat_intel": "feeds/threat_intel_feeds.json", - "osint": "feeds/osint_feeds.json", - "research": "feeds/research_feeds.json", -} +from bot_config import CATEGORY_FEEDS async def check_all_feeds(): totals = {}