#!/usr/bin/env python3 """ Sentinel Check — Brand Monitoring V1 Hourly check for crisis keywords on Google News RSS. Collects, runs pipeline, and dispatches alerts immediately. """ import feedparser import sqlite3 import datetime import urllib.parse import subprocess import os import yaml DB_PATH = "/opt/ai-os/products/ceo/brand-monitoring/data/brand-monitoring.db" BRAND_DIR = "/opt/ai-os/products/ceo/brand-monitoring/brands/fulbright" def load_keywords(): with open(f"{BRAND_DIR}/keywords.yaml", "r") as f: return yaml.safe_load(f) def run_sentinel(): keywords = load_keywords() triggers = keywords.get("crisis_triggers", []) # Construct search query # E.g. Fulbright (scandal OR "tranh cãi" OR "chỉ trích" OR "phàn nàn" OR "học phí" OR "kiểm định" OR "bê bối") query_parts = [] for t in triggers: if " " in t: query_parts.append(f'"{t}"') else: query_parts.append(t) or_query = " OR ".join(query_parts) search_query = f"Fulbright ({or_query})" encoded_query = urllib.parse.quote(search_query) url = f"https://news.google.com/rss/search?q={encoded_query}&hl=vi&gl=VN&ceid=VN:vi" print(f"Running Sentinel Check with query: {search_query}") print(f"Feed URL: {url}") feed = feedparser.parse(url) print(f"Found {len(feed.entries)} entries.") conn = sqlite3.connect(DB_PATH) cursor = conn.cursor() new_items_count = 0 for entry in feed.entries: try: url_link = entry.link title = entry.title published = entry.get("published", datetime.datetime.now().isoformat()) cursor.execute("SELECT id FROM raw_items WHERE url = ?", (url_link,)) if cursor.fetchone(): continue cursor.execute(""" INSERT INTO raw_items (source_id, url, title, published, fetched_at, brand_id, lang) VALUES (?, ?, ?, ?, ?, ?, ?) """, ("GoogleNews_Sentinel", url_link, title, published, datetime.datetime.now().isoformat(), "fulbright", "vi")) new_items_count += 1 except Exception as e: print(f"Error processing entry: {e}") conn.commit() conn.close() print(f"Sentinel collection done. {new_items_count} new raw items inserted.") # If new items, run pipeline and dispatcher if new_items_count > 0: print("Running pipeline...") script_dir = os.path.dirname(os.path.abspath(__file__)) subprocess.run(["python3", f"{script_dir}/pipeline.py"]) print("Running alert dispatcher...") subprocess.run(["python3", f"{script_dir}/alert_dispatcher.py"]) else: # Check if there are any lingering unprocessed items or pending alerts anyway print("No new items, but running pipeline + alert_dispatcher to ensure all processed.") script_dir = os.path.dirname(os.path.abspath(__file__)) subprocess.run(["python3", f"{script_dir}/pipeline.py"]) subprocess.run(["python3", f"{script_dir}/alert_dispatcher.py"]) if __name__ == "__main__": run_sentinel()