import os import re import html import time import threading import requests from flask import Flask from pyrogram import Client, filters from pyrogram.enums import ParseMode from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton # ====================== # ENV VARIABLES # ====================== API_ID = int(os.environ["API_ID"]) API_HASH = os.environ["API_HASH"] BOT_TOKEN = os.environ["BOT_TOKEN"] CVE_API_BASE = os.environ["CVE_API_BASE"] # ====================== # HF SPACE URL (FILLED) # ====================== SPACE_URL = "https://cistern-opa.hf.space/" # ====================== # FLASK SERVER # ====================== web = Flask(__name__) @web.route("/") def home(): return {"status": "running"} def run_web(): web.run(host="0.0.0.0", port=7860) # ====================== # HEARTBEAT (REAL KEEP ALIVE) # ====================== def heartbeat(): while True: try: r = requests.get(SPACE_URL, timeout=10) print(f"Keep-alive ping sent: {r.status_code}") except Exception as e: print(f"Keep-alive failed: {e}") time.sleep(300) # ====================== # BOT # ====================== app = Client( "cvebot", api_id=API_ID, api_hash=API_HASH, bot_token=BOT_TOKEN, parse_mode=ParseMode.HTML ) # ====================== # HELPERS # ====================== def sev_emoji(sev): sev = str(sev).upper() return { "CRITICAL": "🔴", "HIGH": "🟠", "MEDIUM": "🟡", "LOW": "🟢" }.get(sev, "⚪") def get_desc(cna): for d in cna.get("descriptions", []): if d.get("lang") == "en": return d.get("value", "") return "No description available." def get_cvss(cna): for m in cna.get("metrics", []): for _, v in m.items(): if isinstance(v, dict) and "baseScore" in v: return v return None def get_cwes(cna): out = [] for p in cna.get("problemTypes", []): for d in p.get("descriptions", []): if d.get("cweId"): out.append(d["cweId"]) return out def get_products(cna): out = [] for a in cna.get("affected", []): out.append(f"{a.get('vendor','')} {a.get('product','')}".strip()) return out def get_refs(cna): return [r["url"] for r in cna.get("references", []) if r.get("url")] # ====================== # COMMANDS # ====================== @app.on_message(filters.command("start")) async def start(_, msg): await msg.reply_text( "🔎 CVE Bot Ready\n\nUse:\n/cve CVE-2021-1256" ) @app.on_message(filters.command("cve")) async def cve_lookup(_, msg): if len(msg.command) < 2: return await msg.reply_text("Usage: /cve CVE-XXXX-XXXX") cve_id = msg.command[1].upper() if not re.match(r"CVE-\d{4}-\d+", cve_id): return await msg.reply_text("❌ Invalid CVE format") url = f"{CVE_API_BASE}{cve_id}" try: r = requests.get(url, timeout=20) if r.status_code != 200: return await msg.reply_text(f"❌ CVE not found ({r.status_code})") data = r.json() cna = data.get("containers", {}).get("cna", {}) meta = data.get("cveMetadata", {}) desc = html.escape(get_desc(cna)) cwes = get_cwes(cna) products = get_products(cna) refs = get_refs(cna) cvss = get_cvss(cna) text = f"🚨 {cve_id}\n\n" if cna.get("title"): text += f"📌 {html.escape(cna['title'])}\n\n" if cvss: sev = cvss.get("baseSeverity", "Unknown") score = cvss.get("baseScore", "N/A") text += ( f"🎯 Severity\n" f"{sev_emoji(sev)} {sev}\n" f"Score: {score}\n\n" ) if cwes: text += "⚠️ CWE\n" text += "\n".join(f"• {c}" for c in cwes[:10]) + "\n\n" if products: text += "📦 Affected Products\n" text += "\n".join(f"• {p}" for p in products[:10]) + "\n\n" text += ( f"📝 Description\n" f"
{desc[:3000]}
\n\n" f"📅 Published\n{meta.get('datePublished','N/A')}\n\n" f"🔄 Updated\n{meta.get('dateUpdated','N/A')}\n" ) buttons = [[InlineKeyboardButton("🔗 MITRE CVE", url=url)]] if refs: buttons.append([InlineKeyboardButton("📎 Reference", url=refs[0])]) await msg.reply_text( text, reply_markup=InlineKeyboardMarkup(buttons) ) except Exception as e: await msg.reply_text(f"❌ Error: {e}") # ====================== # START # ====================== if __name__ == "__main__": threading.Thread(target=run_web, daemon=True).start() threading.Thread(target=heartbeat, daemon=True).start() print("Bot Started") app.run()