--- name: iran-israel-alerts description: Monitor Iran-Israel-US military escalation and attack alerts using 85+ OSINT sources, satellite fire detection, seismic monitoring, cyber warfare tracking, military flight tracking, and real-time alert APIs. Includes interactive Leaflet strikes dashboard with 49K+ geolocated events, live feed pipeline, US/Iran military base overlays, PWA mobile support, and event type filtering. Use when checking for breaking military news, missile alerts, airstrikes, or geopolitical escalation between Iran, Israel, and the US. Triggers on questions about Iran attacks, Israel strikes, Middle East military alerts, OSINT updates, or escalation monitoring. --- # Iran-Israel Attack Alert Monitor Multi-source intelligence aggregation for Iran/Israel/US military escalation with adaptive threat-level system, 85+ source channels, real-time OSINT scanning, NASA satellite fire detection, USGS seismic monitoring, cyber warfare monitoring (19 hacktivist groups), wire service integration (Reuters/AP), multi-source breaking news corroboration, multi-channel bilingual dispatch with per-channel timezones, Hebrew-first OSINT prioritization for Hebrew channel, live feed data pipeline, and instant Telegram delivery with auto-generated intel maps and interactive strikes dashboard (PWA-enabled). ## Quick Start ```bash bash ctl.sh status # See what's running bash ctl.sh check # One-time full SITREP (stdout) bash ctl.sh post # Full check โ†’ post to Telegram bash ctl.sh start # Start real-time watcher (adaptive threat system) bash ctl.sh stop # Stop real-time watcher bash ctl.sh teardown # ๐Ÿ›‘ Kill everything (watcher + cron + state) ``` ## Architecture ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Real-Time Watcher (daemon) โ”‚ โ”‚ โ”‚ โ”‚ ๐Ÿšจ Oref sirens every 10-30s (threat-adaptive) โ”‚ โ”‚ ๐Ÿ“ก OSINT scanner every 30s-5min (threat-adaptive) โ”‚ โ”‚ โ”œโ”€ ๐Ÿ“ข 12 Telegram channels (t.me/s/ web preview) โ”‚ โ”‚ โ”œโ”€ ๐Ÿฆ 13 Twitter accounts (syndication API) โ”‚ โ”‚ โ”œโ”€ ๐Ÿ“ฐ 10 RSS feeds (TOI, JPost, AJ, TASS, Ynet, Reuters, โ”‚ โ”‚ โ”‚ AP, Maariv, Walla, Channel 13) โ”‚ โ”‚ โ””โ”€ ๐ŸŒ USGS seismic (Iran region, M3.5+) โ”‚ โ”‚ ๐Ÿ“Š Polymarket every 60s-5min (threat-adaptive) โ”‚ โ”‚ ๐Ÿ”ฅ NASA FIRMS fires every 3-15min (threat-adaptive) โ”‚ โ”‚ ๐ŸŒ USGS seismic every 3-15min (threat-adaptive) โ”‚ โ”‚ ๐Ÿ—บ๏ธ Intel map auto-generated on fire/quake alerts โ”‚ โ”‚ ๐ŸŒ Iran internet every 5-30min (blackout detection) โ”‚ โ”‚ โœˆ๏ธ Military flights every 5-30min (OpenSky ADS-B) โ”‚ โ”‚ โœˆ๏ธ Flight radar map hourly (FR24 air traffic + intel) โ”‚ โ”‚ ๐Ÿ›ก๏ธ Cyber warfare every 5-30min โ”‚ โ”‚ โ”œโ”€ ๐Ÿ“ข 25 hacktivist TG handles (19 groups) โ”‚ โ”‚ โ”œโ”€ ๐Ÿฆ 8 CTI Twitter accounts โ”‚ โ”‚ โ””โ”€ ๐Ÿ“ฐ 4 dark web / breach RSS feeds โ”‚ โ”‚ ๐Ÿšข Naval tracking every 5-30min (AIS vessel data) โ”‚ โ”‚ โš”๏ธ Strikes map data every 6h (ACLED + local sensors) โ”‚ โ”‚ ๐ŸŽฏ Strike correlation after every fire/seismic scan โ”‚ โ”‚ ๐Ÿ“Œ Pinned status edited every 60s + instant on threat โ”‚ โ”‚ โ”‚ level change โ”‚ โ”‚ ๐Ÿ“ก Live feed export every 5min (intel-feed.json โ†’ GitHub) โ”‚ โ”‚ โ”‚ โ”‚ โ†’ Instant Telegram push on changes โ”‚ โ”‚ โ†’ Breaking news corroboration (3+ reputable = CONFIRMED) โ”‚ โ”‚ โ†’ Confirmed topics suppressed after first alert โ”‚ โ”‚ โ†’ Hebrew-first OSINT prioritization for Hebrew channel โ”‚ โ”‚ โ†’ Auto-escalate/deescalate threat level โ”‚ โ”‚ โ†’ Per-channel timezones (EN=ET, HE=IST) โ”‚ โ”‚ โ†’ Pikud HaOref stand-down messages detected (no escalation) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Scheduled Reports โ”‚ โ”‚ ๐Ÿ“Š Hourly: intel map + Hebrew + English summaries โ†’ Telegram โ”‚ โ”‚ ๐ŸŽฌ Hourly: 24h time-lapse GIF โ†’ Telegram โ”‚ โ”‚ ๐Ÿ“‹ 2-Hour Full SITREP (Oref + RSS + Poly + Oil + ADS-B) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ dispatch.py โ†’ EN Channel (ET) + HE Channel (IST) ``` ## Sources (80+ channels) ### Real-Time Watcher Sources | # | Source | Channels | Method | Auth | |---|--------|----------|--------|------| | 1 | ๐Ÿšจ Pikud HaOref (sirens) | 1 | REST API (Israeli IP req.) | None | | 2 | ๐Ÿ“ข Telegram OSINT | 12 channels | Web preview scraping | None | | 3 | ๐Ÿฆ X/Twitter OSINT | 13 accounts | Syndication API | None | | 4 | ๐Ÿ“ฐ RSS News | 10 feeds (4 Hebrew, 6 English) | RSS/XML parsing | None | | 5 | ๐ŸŒ USGS Seismic | Iran region | REST API (GeoJSON) | None | | 6 | ๐Ÿ“Š Polymarket | Dynamic | REST API | None | | 7 | ๐Ÿ”ฅ NASA FIRMS | 4 satellites | Area CSV API | MAP_KEY | | 8 | ๐ŸŒ IODA Internet | Iran ASNs | Georgia Tech API | None | | 9 | ๐Ÿ” Direct Probes | 3 Iranian sites | HTTP health check | None | | 10 | โœˆ๏ธ OpenSky ADS-B | ME region | REST API | None | | 11 | โœˆ๏ธ FlightRadar24 | ME region | Public feed | None | | 12 | ๐Ÿ›ก๏ธ Cyber Hacktivist TG | 25 handles (19 groups) | Web preview scraping | None | | 13 | ๐Ÿ›ก๏ธ Cyber CTI Twitter | 8 accounts | Syndication API | None | | 14 | ๐Ÿ›ก๏ธ Cyber/DarkWeb RSS | 4 feeds | RSS/XML parsing | None | | 15 | ๐Ÿšข Naval AIS | Persian Gulf | AIS data feeds | None | | 16 | โš”๏ธ ACLED Strikes | ME region (9 countries) | REST API (OAuth2) | Free account | ### Telegram OSINT Channels - `warmonitors` โ€” War Monitors (fastest English breaking) - `intelslava` โ€” Intel Slava Z (military OSINT) - `liveuamap` โ€” Liveuamap (mapped conflict updates) - `AbuAliExpress` โ€” Abu Ali Express (Hebrew OSINT king) - `flash_news_il` โ€” Flash News IL (Hebrew breaking) - `idfonline` โ€” IDF Online (English) - `idfofficial` โ€” IDF Spokesman / ื“ื•ื‘ืจ ืฆื”ืดืœ (Hebrew, official) - `IDFarabic` โ€” IDF Arabic Spokesperson - `iranintl_en` โ€” Iran International English - `BBCPersian` โ€” BBC Persian - `kann_news` โ€” Kan News - `aharonyediot` โ€” Aharon Yediot (HIGH reliability Hebrew OSINT) ### RSS Feeds (10) - Times of Israel โ€” direct RSS - Jerusalem Post โ€” direct RSS - Al Jazeera โ€” direct RSS - TASS โ€” direct RSS - Ynet (Hebrew) โ€” direct RSS - **Reuters** โ€” via Google News RSS proxy (`site:reuters.com`) - **AP News** โ€” via Google News RSS proxy (`site:apnews.com`) - **ืžืขืจื™ื‘ (Maariv)** โ€” Hebrew RSS (direct) - **ื•ื•ืืœื” (Walla)** โ€” Hebrew RSS (direct) - **ื—ื“ืฉื•ืช 13 (Channel 13)** โ€” Hebrew RSS (direct) > **Note:** Direct Reuters/AP RSS feeds are behind Cloudflare/paywalls. Google News RSS filtered to `site:reuters.com` works reliably as a proxy, including `` tags for attribution. ### Twitter OSINT Accounts `@PenPizzaReport`, `@Conflict_Radar`, `@Worldsource24`, `@sentdefender`, `@beholdisrael`, `@Osint613`, `@Osinttechnical`, `@IsraelRadar_`, `@Intel_Sky`, `@ELINTNews`, `@IsraelWarRoom`, `@IDF`, `@IDFSpokesperson` ### SITREP-Only Sources (2-hour cron) | # | Source | Method | Auth | |---|--------|--------|------| | 8 | ๐Ÿ›ข๏ธ Oil/Commodities | OilPriceAPI | None | | 9 | โœˆ๏ธ Military Aviation | OpenSky ADS-B | None | ## ๐Ÿ”ฅ NASA FIRMS Satellite Fire Detection Monitors thermal anomalies across Iran using 4 NASA satellites to detect fires, explosions, and bombing near military/nuclear sites. ### How It Works ```bash # Standalone test python3 scripts/scan-fires.py config.json state # Scan for new fires python3 scripts/scan-fires.py config.json state --seed # Seed baseline (no alerts) python3 scripts/format-fires.py < fires.json # Format for Telegram ``` ### Satellites - **VIIRS SNPP** โ€” Suomi NPP (375m resolution) - **VIIRS NOAA-20** โ€” Joint Polar Satellite System - **VIIRS NOAA-21** โ€” Latest generation - **MODIS** โ€” Terra/Aqua (1km resolution, highest coverage) ### Features - **Point-in-polygon Iran filtering** โ€” Excludes Iraq/Afghanistan/Pakistan fires even if in bounding box - **FRP-based priority** โ€” Fire Radiative Power determines alert urgency (โ‰ฅ50 MW = HIGH, โ‰ฅ15 = MEDIUM) - **Proximity to 23 known sites** โ€” Nuclear (Natanz, Fordow, Isfahan, Bushehr, Arak), military (Parchin, Shahrud, Bandar Abbas), oil (Kharg Island), capital (Tehran) - **Reverse geocoding** โ€” Nominatim converts coordinates to city/province names (cached, 1 req/sec, max 20/scan) - **Deduplication** โ€” Tracks seen fires in `state/firms-seen.json`, only alerts on new detections - **API key required** โ€” Free, see [Getting a FIRMS API Key](#getting-a-firms-api-key) below. Store in `secrets/firms-map-key.txt` ### Priority Classification | Priority | Trigger | |----------|---------| | ๐Ÿšจ CRITICAL | Near nuclear site or capital (<30km) | | ๐Ÿ”ด HIGH | Near military/oil site (<30km) OR FRP โ‰ฅ50 MW | | ๐ŸŸก MEDIUM | FRP โ‰ฅ15 MW | | โšช LOW | FRP <15 MW, no nearby sites | ### Getting a FIRMS API Key NASA FIRMS requires a free API key (MAP_KEY). The registration form asks for an email โ€” they send the key instantly, no verification needed. **Quick method using a disposable email:** 1. Go to https://mail.tm or any temp email service 2. Copy the generated email address 3. Go to https://firms.modaps.eosdis.nasa.gov/api/area/ 4. Click "Get MAP_KEY" โ†’ enter the temp email 5. Check the temp inbox โ€” key arrives within seconds 6. Save it: ```bash mkdir -p secrets echo "YOUR_KEY_HERE" > secrets/firms-map-key.txt ``` The key is permanent and has no rate limits for the area CSV endpoint. No real email required โ€” NASA just needs *something* to send the key to. **Alternative:** Use your real email at the same URL if you prefer. Same instant delivery. ## ๐ŸŒ USGS Seismic Activity Monitoring Real-time earthquake detection in Iran (M2.5+) via USGS FDSNWS API. Identifies potentially suspicious seismic events near nuclear facilities. ### How It Works ```bash # Standalone test python3 scripts/scan-seismic.py config.json state # Scan for new quakes python3 scripts/scan-seismic.py config.json state --seed # Seed baseline python3 scripts/scan-seismic.py config.json state --days 7 # Look back 7 days python3 scripts/format-seismic.py < seismic.json # Format for Telegram ``` ### Features - **Iran bounding box** โ€” lat 25-40, lon 44-63.5 (full coverage) - **Proximity to 10 known sites** โ€” Same nuclear/military/oil sites as fire detection - **Suspicious event flagging** โ€” Shallow (<10km depth) + moderate magnitude (โ‰ฅ3.5) near nuclear sites - **Explosion type detection** โ€” USGS classifies some events as "explosion" โ€” auto-flagged CRITICAL - **Deduplication** โ€” Tracks in `state/seismic-seen.json`, 7-day retention - **No API key needed** โ€” USGS is free and open ### Priority Classification | Priority | Trigger | |----------|---------| | ๐Ÿšจ CRITICAL | Type = explosion, OR shallow + near nuclear site | | ๐Ÿ”ด HIGH | M5.0+ OR near nuclear site | | ๐ŸŸก MEDIUM | M4.0+ | | โšช LOW | M2.5-3.9 | ### Why It Matters Shallow high-magnitude events near nuclear facilities could indicate: - Underground nuclear tests - Bunker-buster strikes on hardened facilities - Large conventional bombing campaigns ## ๐Ÿ—บ๏ธ Auto-Generated Intel Map Every fire/seismic alert includes a satellite imagery map sent as a Telegram photo. ### Features - **ESRI satellite tile basemap** (zoom level 5, 768x512px) - **Country borders** โ€” GeoJSON from Natural Earth, all neighbors labeled - **Iran highlighted** โ€” Gold border with subtle fill tint - **Fire dots** โ€” Color-coded by priority, sized by FRP, glow effects - **Earthquake markers** โ€” Concentric ring style with magnitude + depth labels - **Suspicious triangle** โ€” Purple โš ๏ธ overlay for suspicious seismic events - **Known sites** โ€” Diamond markers with labels (Natanz, Fordow, etc.) - **Legend** โ€” Dynamic, shows active layers (fires/quakes/both) - **Timestamp** โ€” UTC time in title bar ```bash # Standalone generation python3 scripts/generate-fire-map.py fires.json output.png python3 scripts/generate-fire-map.py fires.json output.png --seismic seismic.json ``` ### Dependencies - `Pillow` (PIL) โ€” `pip3 install Pillow` - Downloads ESRI tiles at runtime (6 tiles per map, cached by OS) - Border data in `references/borders.geojson` (17 countries, 473KB) ## Adaptive Threat-Level System The watcher automatically adjusts monitoring frequency based on siren activity: | Level | Hebrew | Trigger | Oref | OSINT | Poly | Fires | Intel (blackout+flights+cyber) | |-------|--------|---------|------|-------|------|-------|-------------------------------| | ๐ŸŸข GREEN | ืฉื’ืจื” | No sirens >30min | 30s | 5min | 5min | 15min | 30min | | ๐ŸŸก ELEVATED | ืžื•ื’ื‘ืจ | Sirens <30min ago | 15s | 2min | 2min | 10min | 15min | | ๐Ÿ”ด HIGH | ื’ื‘ื•ื” | Active sirens NOW | 10s | 60s | 60s | 5min | 10min | | โšซ CRITICAL | ืงืจื™ื˜ื™ | Major cities under fire | 10s | 30s | 60s | 3min | 5min | All threat levels and transition reasons are fully translated for the Hebrew channel โ€” e.g., "ืจืžืช ืื™ื•ื: ืžื•ื’ื‘ืจ" (not "THREAT LEVEL: ELEVATED"). ### Pikud HaOref Stand-Down Detection The watcher classifies every Oref API response before escalating: - **THREAT** alerts (cat 1-7: missiles, rockets, UAVs) โ†’ escalate normally - **STANDDOWN** alerts ("ื ื™ืชืŸ ืœืฆืืช ืžื”ืžืจื—ื‘ ื”ืžื•ื’ืŸ") โ†’ send โœ… message, NO escalation - Prevents false escalation on informational "you can leave shelter" broadcasts ## ๐ŸŒ Iran Internet Blackout Detection Monitors Iran's internet connectivity as an early warning signal โ€” Iran has historically cut internet before/during military operations. ### Sources 1. **IODA (Georgia Tech)** โ€” BGP, active probing, Google traffic, MERIT telescope data for Iran ASNs 2. **Direct probes** โ€” HTTP pings to irna.ir, president.ir, mehrnews.com with latency tracking ### Assessment Levels | Level | Score | Description | |-------|-------|-------------| | ๐ŸŸข NORMAL | 0-9 | Internet operating normally | | ๐ŸŸ  MINOR_ISSUES | 10-24 | Some connectivity fluctuations (common, may not be military) | | ๐ŸŸก DEGRADED | 25-49 | Significant disruptions โ€” possible throttling | | โšซ BLACKOUT | 50+ | Major outage โ€” internet appears cut off | ### Features - **24h history graph** โ€” Visual bar chart in Telegram showing connectivity trend - **Threat meter** โ€” `โ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘ 20/100` visual bar - **Probe latency** โ€” Shows each Iranian website's response time - **Throttled alerts** โ€” Max once/hour (every 15 min for BLACKOUT level) - **State tracking** โ€” `state/blackout-state.json` + `state/blackout-history.json` ```bash python3 scripts/scan-blackout.py config.json state # Check status python3 scripts/scan-blackout.py config.json state --seed # Seed baseline ``` ## ๐ŸŽฏ Strike Correlation Engine Automatically correlates fire + seismic events to detect possible kinetic strikes. When a fire and earthquake occur within 50km and 30 minutes of each other, it's flagged as a possible strike. ### How It Works - Loads recent fires from `firms-seen.json` (parses lat/lon from key format `lat_lon_date`) - Loads recent quakes from `seismic-seen.json` + USGS API for coordinates - Computes haversine distance between all fire-quake pairs - Scores confidence based on distance + time proximity - Identifies nearest known military/nuclear site ### Confidence Scoring | Factor | Score | |--------|-------| | Distance <10km | +0.3 | | Distance 10-30km | +0.2 | | Time <10min apart | +0.3 | | Near known site | +0.2 | | Base | +0.1 | ```bash python3 scripts/correlate-strikes.py state # Run correlation ``` Runs automatically after every fire+seismic scan in the watcher loop. ## โœˆ๏ธ US Military Flight Tracking Monitors military aircraft over the Middle East using OpenSky Network ADS-B data. ### Coverage - **Bounding box**: lat 20-42, lon 40-65 (full ME region) - **Classification by callsign prefix**: RCH/REACH (airlift), DUKE/DARK (ISR), DOOM/BONE (bomber), SHELL/TEXACO (tanker), SNTRY/MAGIC (C2) - **Classification by ICAO24 hex ranges**: US military transponder blocks - **Categories**: ISR, BOMBER, TANKER, C2, AIRLIFT, NUCLEAR_CAPABLE, UNKNOWN_MIL ### Alerts - New military aircraft entering the zone triggers Telegram alert - Shows callsign, altitude, speed, aircraft category - Heavy tanker/bomber activity may indicate imminent strike sortie ```bash python3 scripts/scan-military-flights.py config.json state # Scan python3 scripts/scan-military-flights.py config.json state --seed # Seed baseline ``` ## โœˆ๏ธ Flight Radar Map (Air Traffic Intelligence) FlightRadar24-style live map of Middle East air traffic, generated hourly as part of the intel report. ### Data Source - **Primary**: FlightRadar24 public feed (300-400+ aircraft, full ADS-B coverage) - **Fallback**: OpenSky Network API (~80 aircraft, free tier) - FR24 provides aircraft type, callsign, origin/dest airports, altitude, speed, airline, registration ### Map Features - **Dark Palantir-style map** with country borders from GeoJSON - **Aircraft arrows** showing heading direction (yellow=civil, red=over Iran, green=US/IL military) - **Iran airspace highlighted** with red border and dark fill - **Side intel panel** with: - Traffic count (total + over Iran) - Airport disruption status (Iran/Iraq/Syria/Israel/Lebanon/Jordan) - US / Israeli military aircraft with role descriptions (e.g. "Tactical airlift", "SIGINT reconnaissance", "Strategic bomber") - Top origin airports ### US/Israeli Military Detection - **US callsign prefixes**: RCH, REACH, EVAC, FORTE, JAKE, SAM, AF1, AF2, NAVY, CNV, DOOM, BOLT, IRON, LANCE, ETHYL, SHELL, TEXAS, HOMER, SNOOP, EPIC, GHOST, SNTRY, etc. - **Israeli callsign prefixes**: IAF, ISF - **Aircraft type matching**: C-17, KC-135, E-3, RC-135, B-52, F-35, RQ-4, MQ-9, G550, etc. - **Registration heuristics**: N-prefix (US), 4X-prefix (Israel) for unidentified military types - Filters out non-US/IL military (Saudi, Omani, RAF, etc.) โ€” only shows relevant assets ### Aircraft Role Descriptions (50+ types mapped) | Type | Role | |------|------| | F-35 | Stealth strike fighter | | B-52 | Strategic bomber | | KC-135 | Aerial refueling tanker | | RC-135 | SIGINT reconnaissance | | E-3 | AWACS airborne radar | | E-6 | Nuclear command relay | | C-17 | Strategic airlift | | C-130 | Tactical airlift | | RQ-4 | High-alt surveillance drone | | MQ-9 | Armed recon drone | | P-8A | Maritime patrol / ASW | | G550 | SIGINT / early warning | ### Airport Disruption Monitoring Tracks live flight counts for airports in conflict zone countries: - **Iran**: THR, IKA, MHD, ISF, TBZ, SYZ, KER, AWZ, BND + 20 more - **Israel**: TLV, SDV, VDA, ETH, BEV, RPN, HFA - **Iraq**: BGW, BSR, EBL, NJF, SDA - **Syria**: DAM, ALP, LTK - **Lebanon**: BEY - **Jordan**: AMM, AQJ Status: `[X] CLOSED` (0 flights), `[!] Limited` (<5 flights), `[+] Operating` (5+ flights) ### Data Logging Two structured logs updated on every scan: **`state/flight-history.jsonl`** (7-day retention) โ€” Full snapshot: ```json { "ts": 1772305939, "utc": "2026-02-28T19:12:19+00:00", "source": "fr24", "total": 332, "over_iran": 36, "iran_flights": 0, "israel_flights": 1, "airports": {"Iran": {"count": 0, "status": "CLOSED"}, ...}, "military": [{"callsign": "CNV3869", "type": "C130", "tag": "US", "role": "Tactical airlift", ...}], "top_origins": {"JED": 33, "IST": 25, ...}, "top_dests": {"JED": 38, "CAI": 18, ...} } ``` **`state/intel-log.jsonl`** (`flight_scan` event) โ€” Summary for hourly reports: ```json { "type": "flight_scan", "data": { "total": 332, "over_iran": 36, "military_count": 2, "military_callsigns": ["CNV3869", "C130"], "airports_closed": ["Iran", "Iraq", "Syria"], "airports_limited": ["Israel:1", "Lebanon:3"] } } ``` ### Bilingual Captions - English channel: `โœˆ๏ธ Air Traffic โ€” 332 aircraft, 36 over Iran` - Hebrew channel: `โœˆ๏ธ ืชื ื•ืขื” ืื•ื•ื™ืจื™ืช โ€” 332 ืžื˜ื•ืกื™ื, 36 ืžืขืœ ืื™ืจืืŸ` ```bash python3 scripts/generate-flight-map.py config.json state output.png ``` Sent automatically with every hourly report. Image dispatched to both channels with language-appropriate captions via `dispatch.py`. ## ๐Ÿšข Naval Vessel Tracking Monitors military vessel movements in Persian Gulf, Strait of Hormuz, Gulf of Oman. ### Features - **US Navy vessel database** โ€” CVNs (carriers), DDGs (destroyers), CGs (cruisers), SSGNs (subs), LHDs - **IRGC Navy detection** โ€” Iranian fast attack boats, frigates, support ships - **Zone classification** โ€” Strait of Hormuz, Persian Gulf, Gulf of Oman, Arabian Sea - **Naval base proximity** โ€” Bandar Abbas, NSA Bahrain (5th Fleet), Jask, Bushehr, Al Dhafra, Duqm, Diego Garcia ```bash python3 scripts/scan-naval.py config.json state # Scan python3 scripts/scan-naval.py config.json state --seed # Seed baseline ``` Note: Most AIS APIs are paywalled. Script structure supports multiple data sources; currently uses public AIS feeds. ## ๐ŸŽฌ 24h Time-Lapse GIF Animated satellite map showing fire + seismic event progression over the last 24 hours. ### Features - **ESRI satellite tile basemap** with Iran gold border + all neighbor borders - **Known sites marked** โ€” Natanz, Fordow, Isfahan, Bushehr, Arak, Tehran, Parchin, Shahrud, etc. - **Fire dots** animate in chronologically โ€” color by priority, sized by FRP, glow effects - **Earthquake rings** pulse with magnitude labels - **Progress bar + timestamp** header, event counter, legend - **Smart frame pacing** โ€” slow start (empty map), fast event progression, hold on final state - **36 frames**, variable duration per frame ```bash python3 scripts/generate-timelapse.py config.json state output.gif --hours 24 ``` Sent automatically with every hourly report. ## ๐Ÿ“Œ Pinned Live Status Message A single Telegram message edited every 60 seconds with current system status โ€” pinned to the top of the channel. ### Shows - Current threat level with visual bar - System online/offline status - Monitoring grid (all source types active/inactive) - Iran Watch: tracked fires, quakes, nuclear/military sites - Scan frequency by current threat level - Last update timestamp **Escalation** is instant (sirens detected โ†’ immediately bump level). **Deescalation** is gradual (cooldown timers prevent premature step-down). Major cities triggering CRITICAL: ืชืœ ืื‘ื™ื‘, ื™ืจื•ืฉืœื™ื, ื—ื™ืคื”, ื‘ืืจ ืฉื‘ืข, ืคืชื— ืชืงื•ื•ื”, ืจืืฉื•ืŸ ืœืฆื™ื•ืŸ, ืจืžืช ื’ืŸ, ื‘ื ื™ ื‘ืจืง, ื—ื•ืœื•ืŸ, ื‘ืช ื™ื, ื”ืจืฆืœื™ื”, ื ืชื ื™ื”, ืืฉื“ื•ื“, ืืฉืงืœื•ืŸ, ืจื—ื•ื‘ื•ืช, ืžื•ื“ื™ืขื™ืŸ, ื’ื‘ืขืชื™ื™ื ## Hourly Status Report Automated hourly report sent to Telegram via cron โ€” five items: 1. ๐Ÿ—บ๏ธ **Intel Map** โ€” Fresh satellite map with fires, quakes, borders 2. โœˆ๏ธ **Flight Radar Map** โ€” FR24 air traffic with airport disruptions, US/IL military tracker, role descriptions 3. ๐Ÿ‡ฎ๐Ÿ‡ฑ **Hebrew Summary** (ืกื™ื›ื•ื ืžืฆื‘ ืฉืขืชื™ โ€” ืžื’ืŸ ื™ื”ื•ื“ื”) โ€” Confident Israeli analyst style, cheers up the audience, references ืฆื”ืดืœ, ื›ื™ืคืช ื‘ืจื–ืœ, ื—ืฅ. Motivational sign-offs adjusted by threat level. 4. ๐Ÿ‡บ๐Ÿ‡ธ **English Summary** (HOURLY INTEL SUMMARY โ€” Magen Yehuda) โ€” Professional analyst style with personality. "Am Yisrael Chai!" energy. 5. ๐ŸŽฌ **24h Time-Lapse GIF** โ€” Animated fire + seismic progression Both summaries include: sirens, OSINT highlights, fire/seismic detections, market moves, threat changes, and an analyst assessment section. Cron: `0 * * * *` โ€” runs `scripts/hourly-report.sh` ## Intel Logging Every alert the watcher sends to Telegram is also saved to `state/intel-log.jsonl` for hourly summary generation. ### Event Types Logged | Type | Description | |------|-------------| | `siren` | Pikud HaOref siren alerts with details | | `siren_standdown` | Pikud HaOref stand-down messages | | `breaking_news` | Breaking news alerts (with corroboration status) | | `osint` | OSINT batch (Telegram, Twitter, RSS alerts with full text) | | `seismic_osint` | Seismic events from OSINT scanner | | `seismic` | USGS seismic from dedicated scanner | | `fires` | NASA FIRMS fire detections | | `polymarket` | Market spike alerts | | `blackout` | Iran internet blackout status changes | | `cyber` | Cyber warfare alerts (hacktivist, CTI, breach) | | `threat_change` | Threat level transitions with reason | | `flight_scan` | Air traffic snapshot (total, over Iran, military, airport status) | | `strike_correlation` | Fire + seismic coincidence detection | | `strikes_map` | Strikes map image with hourly report | ### Usage ```bash # Read last 2 hours of intel python3 scripts/log-intel.py state --read --since 2 # Read only siren events python3 scripts/log-intel.py state --read --type siren # Rotate old entries (keeps 48h) python3 scripts/log-intel.py state --rotate ``` - Auto-rotates at 5MB, retains 48 hours of data - Each line is a JSON object with `logged_at` (epoch) and `logged_utc` timestamps ## OSINT Scanner The unified Python scanner (`scripts/scan-osint.py`) handles Telegram, Twitter, RSS, and inline seismic: ```bash python3 scripts/scan-osint.py config.json state --source all python3 scripts/scan-osint.py config.json state --source telegram python3 scripts/scan-osint.py config.json state --source twitter python3 scripts/scan-osint.py config.json state --source rss python3 scripts/scan-osint.py config.json state --source seismic ``` Features: - Keyword filtering (52 keywords, Hebrew + English) - Deduplication via per-source seen-state files - NordVPN proxy support for rate-limited sources - Graceful error handling per source - JSON output for integration with watcher ## ๐Ÿšจ Breaking News Detection The OSINT scanner automatically detects breaking news by matching **topic triggers** against **credibility signals**. Both must match for an alert to be flagged as breaking. ### Topic Categories - **Leader elimination** โ€” Khamenei, Nasrallah, Sinwar (Hebrew + English variants, 20+ phrasings) - **Nuclear events** โ€” Detonation, nuclear strike, nuclear bomb - **Compound matching** โ€” Words appearing anywhere in text (e.g., "khamenei" + "dead") ### Credible Sources Reuters, AP News, IDF Official (`idfonline`), Kan News, Flash News IL, Iran International, BBC Persian, Aharonovic (`aharonyediot`), BeholdIsrael, SentDefender, IsraelRadar ### Credible Attribution Keywords Netanyahu, Biden, Trump, IDF confirms, Pentagon confirms, Reuters, Associated Press, AFP, BBC confirms, "official statement" ### Flow 1. OSINT scanner matches text against topic trigger phrases 2. Checks if source channel is credible OR text contains credible attribution 3. Both must match โ†’ alert flagged `breaking: true` with topic string 4. Watcher dispatches as `breaking_news` event at `CRITICAL` severity 5. **Corroboration engine** tracks all sources per topic (see below) ### Multi-Source Corroboration Breaking alerts are tracked per topic in `state/breaking-corroboration.json`. When **3+ reputable sources** report the same topic within a 2-hour window, the alert upgrades from UNVERIFIED to CONFIRMED: | Reputable Sources | Status | Header | |-------------------|--------|--------| | 1-2 | โš ๏ธ UNVERIFIED | "BREAKING NEWS" / "ื™ื“ื™ืขื” ื—ื“ืฉื•ืชื™ืช ื“ื—ื•ืคื”" | | 3+ | โœ… CONFIRMED | "CONFIRMED" / "ื™ื“ื™ืขื” ืžืื•ืžืชืช" | **Reputable source list** (30+): Reuters, AP, BBC, CNN, Times of Israel, Ynet, Haaretz, Jerusalem Post, Al Jazeera, Sky News, France24, NY Times, Washington Post, Wall Street Journal, plus trusted OSINT accounts (SentDefender, IntelPoint, Aurora Intel, etc.) **Rules:** - Same outlet doesn't count twice (deduplication by source name) - Entries auto-expire after 2 hours (24 hours if confirmed) - CONFIRMED alerts display the full list of corroborating sources - **Full alert suppression after confirmation** โ€” `confirmed_sent` flag blocks ALL re-alerts (both confirmed AND unverified) for the same topic - **Unverified dedup** โ€” `alerted_at_count` tracks source count at last alert; only fires when NEW sources found, not every scan cycle - State persists across scan cycles in `breaking-corroboration.json` - Expiry preserves `confirmed_sent` and `alerted_at_count` flags via sentinel entries ### Hebrew-First OSINT Prioritization Both `format-osint.py` (real-time alerts) and `generate-summary.py` (hourly report) filter OSINT by language: | Channel | Priority | Behavior | |---------|----------|----------| | Hebrew (@opssheagathaariupdates) | Hebrew sources first | Ynet, Maariv, Walla, Ch13, Kann, IDF, AbuAli, flash_news_il prioritized; English fills remaining slots | | English (@magenyehudaupdates) | English sources first | Reuters, AP, TASS, warmonitors, intelslava prioritized; Hebrew fills remaining | **Hebrew detection:** Channel name match against known Hebrew sources OR Hebrew Unicode chars (\\u0590-\\u05FF) in text. ## ๐Ÿ“ก Multi-Channel Dispatch (`dispatch.py`) Central routing module that sends alerts to multiple Telegram channels with language-specific formatting. ### Config ```json { "outputs": [ { "id": "main", "chat_id": "@english_channel", "language": "en", "timezone": "America/New_York", "content": ["all"], "min_severity": "LOW", "images": "all" }, { "id": "hebrew", "chat_id": "@hebrew_channel", "language": "he", "timezone": "Asia/Jerusalem", "content": ["siren", "siren_standdown", "siren_clear", "breaking_news", "threat_change", "osint", "fires", "seismic", "strike_correlation", "blackout", "military_flights", "cyber", "polymarket", "map", "flight_map", "summary_he", "timelapse", "pinned_status"], "images": "high_only" } ] } ``` ### Output Options | Field | Values | Description | |-------|--------|-------------| | `language` | `"en"`, `"he"`, `"both"` | Which language text to send | | `timezone` | IANA tz string | Timestamps for this output (e.g. `"America/New_York"`, `"Asia/Jerusalem"`) | | `content` | `["all"]` or specific types | Event type filter | | `min_severity` | `"LOW"` to `"CRITICAL"` | Minimum severity to send | | `images` | `"all"`, `"high_only"`, `"critical_only"`, `"none"` | Image inclusion policy | ### Event Types `siren`, `siren_standdown`, `siren_clear`, `breaking_news`, `threat_change`, `osint`, `fires`, `seismic`, `strike_correlation`, `blackout`, `military_flights`, `cyber`, `polymarket`, `map`, `flight_map`, `summary_he`, `summary_en`, `timelapse`, `pinned_status` ### Usage from Python ```python from dispatch import Dispatcher d = Dispatcher("config.json") d.emit("breaking_news", "CRITICAL", text_he="...", text_en="...", image_path="map.png", image_importance="high", image_caption_he="...") ``` ### Usage from Bash (stdin) ```bash echo '{"type":"fires","severity":"HIGH","text_en":"...","text_he":"..."}' \ | python3 scripts/dispatch.py config.json ``` ### Features - Backward-compatible: works with single `telegram_chat_id` if no `outputs` array - Image importance decided at call site (low/medium/high/critical) - Separate `image_caption` vs `image_caption_he` for bilingual captions - Supports text, photo, GIF animation, and message editing - Dispatch audit log: `state/dispatch-log.jsonl` (7-day retention, auto-rotates at 2MB) ## ๐Ÿ“ฐ Wire Service Integration (Reuters/AP) Direct Reuters and AP News RSS feeds are behind Cloudflare/paywalls. **Google News RSS** is used as a reliable proxy: ``` # Reuters filtered to Iran+Israel https://news.google.com/rss/search?q=site:reuters.com+iran+OR+israel&hl=en-US&gl=US&ceid=US:en # AP News filtered to Iran+Israel https://news.google.com/rss/search?q=site:apnews.com+iran+OR+israel&hl=en-US&gl=US&ceid=US:en ``` - Google News RSS items include `Reuters` tags for attribution - Both are in the `CREDIBLE_SOURCES` set โ€” alerts from Reuters/AP skip "UNVERIFIED" labeling - Returns dozens of items per feed, updates frequently ## โš”๏ธ Strikes Map (`scan_strikes.py` + `generate-strikes-map.py`) Comprehensive geolocated strikes database and visual map covering the entire Middle East theater since October 7, 2023. ### Data Layers 1. **ACLED API** โ€” Structured conflict events with lat/lon, actors, fatalities (1-3 day lag, analyst-verified) 2. **NASA FIRMS** โ€” Satellite thermal anomalies near known military sites 3. **USGS Seismic** โ€” Earthquake events in Iran region 4. **Strike Correlation** โ€” Fire+seismic coincidence detections from correlation engine 5. **OSINT Text Extraction** โ€” Location mentions in intel-log.jsonl matched against 80+ known cities/sites ### ACLED Registration (required for Layer 1) 1. Register at [acleddata.com/register](https://acleddata.com/register/) โ€” free, institutional email recommended 2. Accept non-commercial terms, verify email 3. Add credentials: `secrets/acled-creds.txt` (line 1: email, line 2: password) OR `config.json โ†’ strikes.acled_email/acled_password` 4. Scanner auto-handles OAuth2 (24h access token, 14-day refresh, auto-refresh) ### Config (`config.json โ†’ strikes`) | Field | Default | Description | |-------|---------|-------------| | `start_date` | `"2023-10-07"` | How far back to collect | | `window_days` | `null` | Rolling window (overrides start_date) | | `countries` | 9 countries | ACLED country filter | | `event_types` | 3 types | Explosions, Battles, Violence against civilians | | `sub_event_types` | 7 types | Air/drone strike, shelling, etc. | | `poll_interval_hours` | `6` | ACLED refresh frequency | | `max_events` | `50000` | API row limit | | `include_firms/seismic/correlations/osint` | `true` | Toggle each data layer | | `min_fatalities` | `0` | Fatality filter | | `actor_filter` | `[]` | Empty=all, or `["Israel","Iran"]` | | `map_width/map_height` | `1600ร—1000` | Output image size | | `highlight_recent_hours` | `48` | Yellow outline threshold | ### Map Visual - Color-coded by actor side: ๐Ÿ”ต Israel, ๐Ÿ”ด Iran, ๐ŸŸ  Proxies, ๐Ÿ”ต US - Shape by event type: โ— Airstrike, โ—† Missile, โ–ฒ Ground, โœš Satellite, โ—‹ Seismic - Size scaled by fatalities, opacity by confidence - Sent with hourly report via dispatch ### Integration - Watcher: `check_strikes()` runs on extended intel interval (5-30min) - Hourly report: `--backfill` refresh + map generation + dispatch as `strikes_map` event - State files: `strikes-data.json`, `strikes-last-fetch.json`, `strikes-map.png`, `acled-token.json` ## ๐Ÿ—บ๏ธ Interactive Strikes Dashboard Standalone Leaflet-based HTML dashboard for theater operations visualization. Hosted on GitHub Pages at `https://magen-yehuda-intel.github.io/magen-yehuda-bot/`. ### Features - **48,900+ geolocated events** from ACLED + FIRMS + OSINT + Pikud HaOref - **Dark military theme** โ€” CartoDB dark tiles, Orbitron/JetBrains Mono fonts, scanline overlay - **Theater select** โ€” ALL, Iran, IL/Gaza, Lebanon, Syria, Iraq, Yemen, Red Sea, Persian Gulf (with event count badges) - **15 conflict phase presets** โ€” Oct 7, Ground Op, True Promise I/II, USโ†’Houthis, Days of Repentance, US+ILโ†’Tehran, Iran-Israel War 2, etc. - **Force disposition bars** โ€” Israel (IDF), Iran (IRGC), Iran Proxies, Syria (SAA), US (CENTCOM), Gulf States - **Country breakdown grid** with event counts and toggles - **Zoomable timeline** โ€” mouse wheel zoom, +/โˆ’/FIT buttons, brush selection, 13 annotated key events, starts collapsed - **Timeline auto-fits** to active filter range with 15% padding - **Search bar** โ€” instant results with fly-to popups - **Analytics panel** โ€” stats cards, escalation gauge, sparkline, casualties chart, top actors - **Keyboard shortcuts** โ€” 1-9 for theaters, Escape to clear, F for fullscreen, S for search - **URL hash state** โ€” shareable URLs preserve map view, filters, and time range - **Fullscreen mode** โ€” F11 or F key - **Marker/font size controls** โ€” adjustable marker scale (0.5ร—โ€“3ร—) and font scale (0.7ร—โ€“1.5ร—) - **Collapsible panel sections** โ€” click any section title to toggle - **PWA support** โ€” add to home screen on mobile with native app feel ### Live Feed Pipeline - `scripts/export-feed.py` โ€” cron every 5 min, exports last 48h OSINT โ†’ `docs/intel-feed.json` - Dashboard fetches `intel-feed.json` on load + polls every 60s - Deduplication via date|source|notes[:60] keys - ๐ŸŸข LIVE indicator shows event count + freshness - Only commits+pushes to GitHub if data changed (MD5 hash check) ### Map Overlays - **20 US/Coalition bases** โ€” Al Udeid (CENTCOM HQ), Al Dhafra, NSA Bahrain (5th Fleet), Incirlik, Akrotiri, Nevatim, Diego Garcia, etc. Toggleable ON/OFF - **28 Iran military sites** โ€” nuclear (โ˜ข๏ธ Natanz, Isfahan, Fordow, Bushehr, Arak), missile (๐Ÿš€ Dezful, Semnan, Khojir, Bid Kaneh), naval (โš“ Bandar Abbas, Chabahar, Jask), airbases (โœˆ๏ธ Mehrabad, Isfahan, Bushehr, Hamadan), air defense (๐Ÿ›ก๏ธ S-300 Tehran, Isfahan, Bushehr). Toggleable ON/OFF - **14 Iran key sites** with proximity event counts โ€” click to fly-to ### Event Type Filtering - 9 event subtypes: Air/drone strike, Shelling/artillery/missile, Armed clash, Attack, Remote explosive/IED, Possible strike (FIRMS), Thermal anomaly (FIRMS), Location mention in OSINT, Suicide bomb - Click any type to isolate on map; click again to clear; multi-select supported - FIRMS markers: orange (#ff8800), confidence-based radius (high=5, medium=3.5, low=2.5) ### Data Sources | Source | Events | Coverage | |--------|--------|----------| | ACLED | ~48,000 | Oct 7, 2023 โ†’ Feb 2025 (analyst-verified, ~1yr lag) | | NASA FIRMS | ~380 | Real-time satellite fire detections in Iran | | OSINT | ~930 | Intel-log OSINT events (48h rolling merge) | | Pikud HaOref | 1+ | Siren events with coordinates | ### Mobile Support - Full-screen map with 5-tab bottom bar (Map, Phase, Feed, Forces, Layers) - Persistent search bar above tabs โ€” accessible from any tab - Swipe between tabs (touch gesture left/right) - Card-style mobile feed with source, location, headline, timestamp, fly-to-on-tap - Slide-up sheets for panel content - PWA manifest โ€” add to home screen with native app feel - Responsive CSS for โ‰ค768px screens ### Files - **Template:** `scripts/strikes-dashboard.html` (~2,300 lines, no inline data) - **Standalone:** `scripts/strikes-dashboard-standalone.html` (~5.4MB, data embedded) - **Pages:** `docs/index.html` (copy of standalone for GitHub Pages) - **Live feed:** `docs/intel-feed.json` (auto-updated every 5 min by cron) - **Feed exporter:** `scripts/export-feed.py` (cron job) - **GitHub Gist:** `cce8ab4f861d240f21dc2916e7cd187e` - **GitHub Pages:** `https://magen-yehuda-intel.github.io/magen-yehuda-bot/` ### Local Timezone Support All times displayed in the user's local timezone (auto-detected via `Intl.DateTimeFormat`): - **Clock** โ€” shows local time + timezone name (e.g., `03/01/2026 03:36:00 America/New_York`) - **Feed timestamps** โ€” `fmtFeedTime(ev)` shows `MM-DD HH:MM` in local time for events with real timestamps - **Popup times** โ€” `fmtPopupTime(ev)` shows full date + local HH:MM + timezone name - **Feed sorting** โ€” `feedSortKey(ev)` sorts by unix timestamp (newest first), falls back to date string ### Rebuild Standalone ```bash python3 scripts/build-standalone.py ``` The build script (`scripts/build-standalone.py`) reads `state/strikes-data.json`, compacts events into ultra-compact array format (day_num, latร—1000, lonร—1000, country_idx, side_idx, fatalities, subtype_idx, location_idx, actor1, actor2, confidence, notes, timestamp), replaces `COMPACT_DATA` placeholder in the template, and writes both `scripts/strikes-dashboard-standalone.html` and `docs/index.html`. ### UI/UX Overhaul (Mar 1 โ€” in progress) 3-hour improvement plan (`UI-IMPROVEMENT-PLAN.md`): **Hour 1: Custom SVG Icons + Larger Defaults** - 10 custom SVG marker icons per event type: starburst explosion (shelling), jet silhouette (airstrike), crossed swords (armed clash), crosshair (attack), bomb (IED), radar pulse (OSINT), skull (suicide bomb), flame (FIRMS fire), heat shimmer (thermal), siren beacon (alert) - Dual rendering: `L.circleMarker` at zoom <7 (performance), `L.divIcon` + SVG at zoom โ‰ฅ7 (detail) - `SVG_ICONS` dict with color-parameterized factory functions + `_iconCache` for memoization - Icon scaling: base 16-48px by fatalities ร— `markerScale`; hover scale 1.3ร— with CSS transition - Default `markerScale` raised from 1ร— to 1.5ร—; `MARKER_STEPS = [0.75, 1, 1.5, 2, 2.5, 3]` - Default `fontScale` raised from 1ร— to 1.15ร—; `FONT_STEPS = [0.85, 1, 1.15, 1.3, 1.5, 1.7]` **Hour 2: Panel & Feed UI Overhaul** - All font sizes increased: section titles 8โ†’10px, body 9โ†’12px, stats 9โ†’12px, feed items 9โ†’12px, theater/phase buttons 9โ†’11px, HUD stats 9โ†’11px, logo 11โ†’14px, clock 9โ†’11px - HUD bar height 40โ†’48px, panel width 320โ†’360px - Event type legend shows emoji icons next to each type name - Feed item headlines 8โ†’11px, type tags 7โ†’9px - Force disposition bars wider (48px) and taller (5px) - Legend panel larger (max-width 220px, font 11px) - Popup fonts 12โ†’13px with 14px header - Mobile feed cards larger (source 13px, text 13px, time 11px) - Mobile tab bar taller (52px) with bigger icons (22px) - Stat numbers in analytics 16โ†’18px - All 7px labels upgraded to 9px minimum **Hour 3: Mobile UX + Visual Polish** (planned) - Mobile gesture refinements, loading screen, marker hover glow, legend with SVG icons ## ๐Ÿ›ก๏ธ Cyber Warfare Monitor (`scan_cyber.py`) Monitors 19 hacktivist groups (25 TG handles), 8 CTI Twitter accounts, and 4 dark web/breach RSS feeds for Iran-Israel cyber operations. Classifies attacks, identifies targets, and dispatches bilingual alerts. ### Sources **1. Hacktivist Telegram Channels (~25 channels)** Directly monitors the public preview (`t.me/s/`) of known hacktivist group channels: | Side | Group | Affiliation | Threat | TTPs | |------|-------|-------------|--------|------| | ๐Ÿ‡ฎ๐Ÿ‡ท | **Handala Hack** | IRGC-linked | HIGH | Data leak, wiper, TG hijack | | ๐Ÿ‡ฎ๐Ÿ‡ท | **CyberAv3ngers** | IRGC | CRITICAL | ICS/SCADA, PLC exploit | | ๐Ÿ‡ฎ๐Ÿ‡ท | **Moses Staff** | IRGC | HIGH | Data leak, encryption, extortion | | ๐Ÿ‡ฎ๐Ÿ‡ท | **Cyber Toufan** | Iran-linked | HIGH | Hack-and-leak, data destruction | | ๐Ÿ‡ฎ๐Ÿ‡ท | **DieNet** | Pro-Iran | MEDIUM | DDoS, defacement, psyop | | ๐Ÿ‡ฎ๐Ÿ‡ท | **Dark Storm Team** | Pro-Palestine/Russia | MEDIUM | DDoS-for-hire | | ๐Ÿ‡ฎ๐Ÿ‡ท | **RipperSec** | Pro-Palestine (MY) | MEDIUM | DDoS, SCADA intrusion | | ๐Ÿ‡ฎ๐Ÿ‡ท | **Cyber Fattah** | Pro-Iran | MEDIUM | Data leak, recon | | ๐Ÿ‡ฎ๐Ÿ‡ท | **Arabian Ghosts** | Pro-Iran | MEDIUM | DDoS, defacement | | ๐Ÿ‡ฎ๐Ÿ‡ท | **Fatimion Cyber Team** | Iran proxy | LOW | DDoS | | ๐Ÿ‡ฎ๐Ÿ‡ท | **Cyber Islamic Resistance** | Hezbollah-linked | HIGH | ICS recon, surveillance | | ๐Ÿ‡ฎ๐Ÿ‡ฑ | **Predatory Sparrow** | Israel-linked | HIGH | ICS attack, financial disruption | | ๐Ÿ‡ฎ๐Ÿ‡ฑ | **Israeli Elite Force** | Pro-Israel | MEDIUM | Financial, data leak | | ๐Ÿ‡ฎ๐Ÿ‡ฑ | **WeRedEvils** | Pro-Israel | LOW | DDoS, defacement | Plus CTI aggregator channels: `FalconFeedsio`, `DarkWebInformer`, `cyaboreh`, `vaboreh`, `Ransomware_gang_report` **2. Cyber Threat Intel Twitter (8 accounts)** `@FalconFeedsio` ยท `@CyberKnow20` ยท `@DarkWebInformer` ยท `@HackManac` ยท `@MonThreat` ยท `@cybaboreh` ยท `@BrettCallow` ยท `@vaboreh` **3. Dark Web / Breach RSS Feeds (4 default)** - Darkfeed Ransomware tracker - CISA Advisories (US govt) - The Hacker News - BleepingComputer ### Attack Classification The scanner automatically classifies attacks using keyword matching: | Type | Severity | Indicators | |------|----------|------------| | ๐Ÿญ ICS/SCADA | CRITICAL | SCADA, PLC, water system, power grid, gas station | | ๐Ÿ“‚ Data Breach | HIGH | Data leak, exfiltrated, database, credentials | | ๐Ÿ’€ Ransomware/Wiper | HIGH | Ransomware, wiper, encrypted, destroyed | | ๐Ÿ•ต๏ธ Espionage | HIGH | APT, spyware, backdoor, surveillance | | ๐ŸŒ DDoS | MEDIUM | DDoS, denial of service, offline | | ๐ŸŽจ Defacement | LOW | Defaced, website hacked | ### Target Detection Determines who is being targeted (Israel ๐Ÿ‡ฎ๐Ÿ‡ฑ or Iran ๐Ÿ‡ฎ๐Ÿ‡ท) based on: 1. Entity mentions in text (IDF, Mossad, IRGC, Tehran, etc.) 2. Group affiliation fallback (Pro-Iran โ†’ targets Israel, Pro-Israel โ†’ targets Iran) ### Config Add custom cyber channels/accounts/feeds in `config.json`: ```json { "cyber_telegram_channels": ["my_custom_channel"], "cyber_twitter_accounts": ["my_cti_analyst"], "cyber_rss_feeds": [ {"name": "My Feed", "url": "https://...", "type": "cyber_news"} ] } ``` ## Pikud HaOref โ€” Israeli IP Requirement The Oref siren API is **geo-restricted to Israeli IPs**. The script handles this with a fallback chain: 1. **Custom proxy** โ†’ `secrets/proxy-override.txt` 2. **NordVPN** โ†’ `secrets/nordvpn-auth.txt` routes through `il66.nordvpn.com:89` 3. **Direct** โ†’ Falls back to direct connection 4. **Graceful failure** โ†’ Reports Oref unavailable; all other sources still work ### Setup options ```bash mkdir -p secrets # Option A: NordVPN (service credentials, NOT login) echo "USERNAME\nPASSWORD" > secrets/nordvpn-auth.txt # Option B: Any HTTPS/SOCKS5 proxy echo "https://user:pass@host:port" > secrets/proxy-override.txt # Option C: SSH tunnel ssh -D 1080 user@israeli-vps echo "socks5://localhost:1080" > secrets/proxy-override.txt # Option D: Skip it โ€” most sources still work globally ``` ## Safety Rules โš ๏ธ **Never say "all clear"** โ€” Only Pikud HaOref can tell people it's safe to leave shelter. The system shows "NO NEW ALERTS BROADCASTING" when sirens stop, with a warning to follow official instructions. ## Threat Level Scoring (SITREP) | Signal | Points | |--------|--------| | Active Pikud HaOref sirens | +30 | | Major oil spike (>10%) | +25 | | Polymarket price spike (โ‰ฅ5pp) | +15 | | High oil move (5-10%) | +15 | | Heavy news cycle (>8 headlines) | +8 | | Elevated oil (3-5%) | +8 | | Active news (4-8 headlines) | +5 | | Score | Level | Action | |-------|-------|--------| | 0-7 | ๐ŸŸข LOW | No auto-post (use `--force`) | | 8-19 | ๐ŸŸก ELEVATED | Auto-post | | 20-39 | ๐ŸŸ  HIGH | Auto-post | | 40+ | ๐Ÿ”ด CRITICAL | Immediate alert | ## `ctl.sh` Commands | Command | Description | |---------|-------------| | `start` | Start real-time watcher daemon | | `stop` | Stop watcher | | `status` | Show watcher state, cron, last threat level | | `dashboard` | ๐Ÿ“Š Full dashboard: processes, state, logs, resources | | `check` | One-time full check (JSON to stdout) | | `post` | Full check โ†’ format โ†’ post to Telegram | | `log [N]` | Show last N lines of watcher log | | `rotate` | Force log rotation + show archive status | | `install-launchd` | Auto-start watcher on boot (macOS) | | `teardown` | ๐Ÿ›‘ Kill everything: watcher, cron, launchd, state | Aliases: `dash`, `ps` โ†’ `dashboard` ## Log Rotation - Watcher log rotates at **500KB** (checked every 5min during runtime + on start) - Keeps **5 archived logs** in `state/logs/` - `ctl.sh rotate` forces rotation check + shows archive status - `ctl.sh dashboard` shows log size and archive count ## Scan Overlap Protection - OSINT scan uses a lock file (`state/osint-scan.lock`) to prevent concurrent scans - If a scan is still running when the next cycle fires, it skips with a log message - Stale locks (>120s) auto-break to prevent permanent deadlock - Twitter/Telegram scraping goes through NordVPN proxy (curl subprocess) to avoid home IP rate limits ## File Structure ``` iran-israel-alerts/ โ”œโ”€โ”€ SKILL.md # This file โ”œโ”€โ”€ README.md # Open-source documentation โ”œโ”€โ”€ ctl.sh # Master control (start/stop/status/teardown) โ”œโ”€โ”€ config.example.json # Template โ€” copy to config.json โ”œโ”€โ”€ config.json # Your config (gitignored) โ”œโ”€โ”€ .gitignore โ”œโ”€โ”€ scripts/ โ”‚ โ”œโ”€โ”€ realtime-watcher.sh # Background daemon (adaptive threat system) โ”‚ โ”œโ”€โ”€ check-alerts.sh # Full SITREP (structured JSON output) โ”‚ โ”œโ”€โ”€ post-telegram.sh # Check โ†’ format โ†’ post to Telegram โ”‚ โ”œโ”€โ”€ format-telegram.py # JSON โ†’ war-room HTML formatter โ”‚ โ”œโ”€โ”€ scan-osint.py # Unified OSINT scanner (TG + X + RSS + seismic) โ”‚ โ”œโ”€โ”€ scan-fires.py # NASA FIRMS fire scanner for Iran โ”‚ โ”œโ”€โ”€ scan-seismic.py # USGS earthquake scanner for Iran โ”‚ โ”œโ”€โ”€ scan-blackout.py # Iran internet blackout detector (IODA + probes) โ”‚ โ”œโ”€โ”€ scan-military-flights.py # US military ADS-B flight tracker (OpenSky) โ”‚ โ”œโ”€โ”€ scan-naval.py # Naval vessel tracker (Persian Gulf AIS) โ”‚ โ”œโ”€โ”€ scan_cyber.py # Cyber warfare & hacktivist monitor (30+ groups) โ”‚ โ”œโ”€โ”€ correlate-strikes.py # Fire + seismic strike correlation engine โ”‚ โ”œโ”€โ”€ generate-fire-map.py # Satellite intel map generator โ”‚ โ”œโ”€โ”€ generate-flight-map.py # FR24 air traffic map + intel panel โ”‚ โ”œโ”€โ”€ generate-timelapse.py # 24h animated time-lapse GIF โ”‚ โ”œโ”€โ”€ generate-summary.py # Hourly Hebrew + English analyst summaries โ”‚ โ”œโ”€โ”€ generate-strikes-map.py # Dark-themed ME strikes map โ”‚ โ”œโ”€โ”€ strikes-dashboard.html # Interactive Leaflet dashboard (template) โ”‚ โ”œโ”€โ”€ strikes-dashboard-standalone.html # Standalone (~5.4MB, data embedded) โ”‚ โ”œโ”€โ”€ build-standalone.py # Compaction build script โ†’ standalone + docs/index.html โ”‚ โ”œโ”€โ”€ marker-icons.js # 10 custom SVG marker icon definitions (reference/standalone) โ”‚ โ”œโ”€โ”€ pinned-status.py # Live pinned status message (every 60s + immediate on threat change) โ”‚ โ”œโ”€โ”€ dispatch.py # Multi-channel alert dispatcher (EN/HE routing) โ”‚ โ”œโ”€โ”€ format-fires.py # Fire data โ†’ Telegram HTML formatter โ”‚ โ”œโ”€โ”€ format-seismic.py # Seismic data โ†’ Telegram HTML formatter โ”‚ โ”œโ”€โ”€ format-osint.py # OSINT bilingual formatter (EN/HE channel names) โ”‚ โ”œโ”€โ”€ log-intel.py # JSONL intel event logger โ”‚ โ””โ”€โ”€ hourly-report.sh # Hourly: map + summaries + GIF โ†’ Telegram โ”œโ”€โ”€ references/ โ”‚ โ”œโ”€โ”€ sources.md # Full source list with ratings โ”‚ โ””โ”€โ”€ borders.geojson # Country borders GeoJSON (17 countries) โ”œโ”€โ”€ secrets/ # gitignored, chmod 600 โ”‚ โ”œโ”€โ”€ nordvpn-auth.txt # NordVPN service credentials (optional) โ”‚ โ”œโ”€โ”€ proxy-override.txt # Custom proxy override (optional) โ”‚ โ””โ”€โ”€ firms-map-key.txt # NASA FIRMS API key โ””โ”€โ”€ state/ # Auto-created, runtime data (gitignored) โ”œโ”€โ”€ watcher.pid / watcher.log โ”œโ”€โ”€ watcher-threat-level.txt โ”œโ”€โ”€ firms-seen.json โ”œโ”€โ”€ seismic-seen.json โ”œโ”€โ”€ blackout-state.json / blackout-history.json โ”œโ”€โ”€ military-flights.json โ”œโ”€โ”€ naval-state.json โ”œโ”€โ”€ strike-correlations.json โ”œโ”€โ”€ intel-log.jsonl โ”œโ”€โ”€ flight-history.jsonl # Air traffic snapshots (7-day, JSONL) โ”œโ”€โ”€ dispatch-log.jsonl # Dispatch audit trail (7-day) โ”œโ”€โ”€ breaking-corroboration.json # Multi-source breaking news tracker (2h window) โ”œโ”€โ”€ flight-map.png # Latest flight radar map โ”œโ”€โ”€ intel-map-latest.png โ”œโ”€โ”€ pinned-message-id-main.txt # EN channel pinned msg ID โ”œโ”€โ”€ pinned-message-id-hebrew.txt # HE channel pinned msg ID โ”œโ”€โ”€ last-standdown-ts.txt # Standdown throttle timestamp โ”œโ”€โ”€ watcher-oref-last.txt # Last Oref API response โ”œโ”€โ”€ poly_current.json # Current Polymarket state โ”œโ”€โ”€ osint-{telegram,twitter,rss,seismic}-seen.json โ”œโ”€โ”€ cyber-{telegram,twitter,rss}-seen.json โ”œโ”€โ”€ strikes-data.json # Unified strikes database โ”œโ”€โ”€ strikes-last-fetch.json # ACLED poll timestamp โ”œโ”€โ”€ strikes-map.png # Latest strikes map โ”œโ”€โ”€ acled-token.json # ACLED OAuth2 token cache โ””โ”€โ”€ logs/ # Rotated watcher logs (max 5) ``` ## Setup ### Requirements - Python 3.9+ with `Pillow` (`pip3 install Pillow`) - `curl`, `jq`, `bash` - NASA FIRMS API key (free: https://firms.modaps.eosdis.nasa.gov/api/area/) ### Quick Setup ```bash cp config.example.json config.json # Edit config.json with your Telegram bot token, chat ID, FIRMS key mkdir -p secrets echo "YOUR_FIRMS_KEY" > secrets/firms-map-key.txt bash ctl.sh start ``` ### Cron Jobs **Important:** crontab must include Homebrew Python in PATH for Pillow/PIL: ```bash # First line of crontab: PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin # Hourly status report (auto-installed) 0 * * * * bash scripts/hourly-report.sh # 2-hour full SITREP 0 */2 * * * bash scripts/post-telegram.sh --force ``` > โš ๏ธ Without `PATH=/opt/homebrew/bin`, cron uses macOS system Python (3.9) which lacks Pillow โ€” causing silent failures in fire map / timelapse / flight map generation. ## V2 CENTCOM Dashboard Interactive Leaflet map with real-time data layers, deployed to GitHub Pages as the main dashboard. **URL:** `https://magen-yehuda-intel.github.io/magen-yehuda-bot/` ### Features - US/Iran military bases with MarkerCluster (cyan/orange bubble clusters) - Pulsing red siren markers from Pikud HaOref - NASA FIRMS fire hotspots - OSINT event markers synced with live feed filters - Pikud HaOref live banner (green "no alerts" / red pulsing "ACTIVE", 3-state toggle) - Live feed panel with time filters (15M/1H/6H/24H/48H/ALL) and side filters (Iran/Israel/US/Proxy) - CNN-style breaking news ticker - Click-to-highlight with pulsing cyan ring - Source links for Telegram channels and Twitter accounts - Mobile bottom toolbar with 6 action buttons - Keyboard shortcuts for all layers - NASA Black Marble night satellite imagery ### Data Pipeline ``` Watcher (Mac) โ†’ log-intel.py โ†’ JSONL file + Azure Table DB (best-effort) โ†“ export-feed.py (cron 5min) โ†’ intel-feed.json + DB sync โ†’ git push โ†’ GitHub Pages โ†“ Watcher โ†’ push/oref โ†’ Azure API (on siren detect/clear) โ†“ Dashboard loads: API (DB, real-time) + static JSON (backup) โ†’ merged + deduped ``` The dashboard hardcodes the Azure API URL and merges both data sources for maximum coverage. ### Files - `docs/index.html` โ€” Main dashboard (V2, promoted from /v2/) - `docs/v2-data.js` โ€” Military bases, nuclear sites, missile sites, energy, IRGC, air defense data (354 lines) - `docs/v1/index.html` โ€” Archived V1 dashboard (5.6MB legacy) - `docs/v2/index.html` โ€” Redirect to root - `docs/intel-feed.json` โ€” Static backup feed (exported every 5min) - `docs/oref-alerts.json` โ€” Static Oref backup (exported every 5min) ## Azure Cloud Backend ### Container App API (`magen-yehuda-api`) Flask/gunicorn API deployed on Azure Container Apps (consumption plan, ~$0/month). **URL:** `https://magen-yehuda-api.blackfield-628213bb.eastus.azurecontainerapps.io` **Endpoints:** | Endpoint | Method | Description | |----------|--------|-------------| | `/api/oref` | GET | Pikud HaOref alerts (from watcher push) | | `/api/oref/last` | GET | Most recent Oref alert from DB | | `/api/oref/history` | GET | Oref alert history (`?hours=`, `?limit=`) | | `/api/fires` | GET | NASA FIRMS hotspots (self-polling, 5min) | | `/api/intel-feed` | GET | Intel events from Azure Table (`?hours=`, `?side=`, `?limit=`) | | `/api/aircraft` | GET | Live aircraft from FR24 (~400 in ME, 60s). `?filter=military` for military only | | `/api/seismic` | GET | USGS earthquakes M2.5+ in ME (50 latest, 2min refresh) | | `/api/threat` | GET | Current threat level (GREEN/ELEVATED/HIGH/CRITICAL) | | `/api/health` | GET | Health check with cache ages | | `/api/debug` | GET | Debug info | | `/api/push/oref` | POST | Push Oref data (API key auth) | | `/api/push/intel` | POST | Push intel events (API key auth) | | `/api/push/threat` | POST | Push threat level changes (API key auth) | **Project:** `~/.openclaw/workspace/projects/magen-yehuda-api/` ### Azure Table Storage Primary data store for intel events and Oref alerts. Practically free (~$0.01/month). - **Account:** `magenyehudadata` (eastus) - **Auth:** Entra ID (shared key blocked by tenant policy) - **Managed identity:** Container app has `Storage Table Data Contributor` role #### Table: `intelevents` - **Schema:** `PartitionKey=YYYY-MM-DD`, `RowKey=SHA256(src+text[:60])[:32]` - **Fields:** `ts`, `src`, `text`, `side`, `type`, `sub_event_type`, `lat`, `lon`, `location`, `breaking`, `confidence`, `link` #### Table: `orefalerts` - **Schema:** `PartitionKey=YYYY-MM-DD`, `RowKey=SHA256(title+cat+areas[:5])[:32]` - **Fields:** `ts`, `title`, `cat`, `area_count`, `areas` (JSON array), `cleared_ts`, `duration_s` - **API:** `/api/oref/last` (most recent), `/api/oref/history?hours=24&limit=50` ### Azure Resources | Resource | Type | Location | |----------|------|----------| | `magen-yehuda-intel` | Resource Group | eastus | | `magenyehudacr` | Container Registry | eastus | | `magen-yehuda-env` | Container App Environment | eastus | | `magen-yehuda-api` | Container App | eastus | | `magenyehudadata` | Storage Account | eastus | ### Key Notes - Oref API is geo-blocked outside Israel โ€” watcher pushes siren data from Mac (via NordVPN IL proxy) to the API - DB sync happens via `export-feed.py` (compares DB vs static by content key, inserts missing) - Empty events are rejected by `db.py` and filtered by dashboard - Container builds: `az acr build --registry magenyehudacr --image magen-yehuda-api:latest .` - Push API key: set as `PUSH_API_KEY` env var on container ## Troubleshooting ### Known Issues & Fixes (Febโ€“Mar 2026) | Issue | Root Cause | Fix | |-------|-----------|-----| | Hourly report cron silently fails | Cron's PATH uses `/usr/bin/python3` (3.9.6) missing Pillow โ€” `set -euo pipefail` kills script | Add `PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin` as first line of crontab | | Polymarket tracks 0 markets | `STATE_DIR` bash variable not exported โ†’ Python `os.environ.get()` gets `.` โ†’ writes state to wrong path | Add `export STATE_DIR` after assignment in `realtime-watcher.sh` | | Cyber alerts found but never dispatched | `scan-cyber.py` (hyphen) can't be Python-imported โ†’ `from scan_cyber import format_cyber_summary` fails | Renamed to `scan_cyber.py` (underscore); format uses heredoc-based Python | | OpenSky returns HTTP 429 | Rate limiting (no API key configured) | Register free OpenSky account for higher limits, or rely on FR24 for hourly flight maps | | Darkfeed RSS returns 404 | Feed URL changed or removed | Replace with alternative ransomware feed, or remove from config | | Hourly summary shows "Threat Level: UNKNOWN" | `generate-summary.py` parsed watcher.log for threat level but regex didn't match log format (emoji prefixes, startup lines) | Fixed: reads `state/watcher-threat-level.txt` first (written by watcher), falls back to log parsing | | Cyber config has empty source arrays | `config.json` cyber section had no Telegram channels, Twitter accounts, or RSS feeds configured | Add sources to `cyber.telegram_channels`, `cyber.twitter_accounts`, `cyber.rss_feeds` in config.json | | Duplicate threat level alerts on restart | Watcher initialized `THREAT_LEVEL=GREEN` on every start, then detected stale `OREF_LAST` โ†’ spammed GREENโ†’CRITICAL | Fixed: watcher reads `watcher-threat-level.txt` on startup to restore last known level | | Hebrew channel missing some content types | Hebrew output had explicit content allowlist โ€” new event types silently dropped | Switched to `content: ["all"]` + `content_exclude: ["summary_en"]`; added `content_exclude` support to `dispatch.py` | | OSINT scan "still running" skips | Slow proxy causes scan to exceed cycle interval โ†’ lock file blocks next scan | Stale locks auto-break at 120s; check proxy latency if persistent | | Literal `\u200F` in Telegram messages | macOS bash 3.2 doesn't support `\u` escapes in `$'...'` syntax | Use `RLM=$(printf '\xe2\x80\x8f')` variable; Python files are fine | | FIRMS time filter shows 0 or all fires | `acq` format is `YYYY-MM-DD HHMM` (no colon, 3-4 digit time) โ€” `new Date()` returns NaN | Parse manually: pad to 4 digits, build ISO. Also: satellites pass few times/day so short time windows show 0 | | 4800+ fire markers clutter map | Most are agricultural/brush fires | Filter by FRP intensity (>10MW) instead of time window | | Threat indicator stuck at HIGH | Watcher died, API cached stale level | Push correct level via `/api/push/threat`; indicator now hidden when GREEN | | Ballistic arcs flicker/disappear | Each arc faded independently โ€” some faded while others still launching | Moved cleanup to barrage level; ALL arcs fade together after last missile lands | | Ballistic arcs look like growing arrows | Progressive `strokeDashoffset` reveal | Draw full arc instantly, no progressive reveal | | Azure Container App `latest` tag no-op | `latest` doesn't trigger new revision | Use explicit versioned tags (e.g. `v18`) | | DB query returns stale events | Azure Table returns by RowKey (hash), early `break` at limit grabbed random old rows | Collect ALL matching, sort by `ts` desc, THEN limit | | Duplicate DB rows from re-scraping | `_row_key()` included `ts` in hash | Use `src + text[:60]` only | ### Debugging Tips ```bash # Test hourly report under simulated cron environment env -i HOME="$HOME" PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin" \ bash scripts/hourly-report.sh # Test single monitor python3 scripts/scan_cyber.py config.json state python3 scripts/scan-blackout.py config.json state python3 scripts/scan-fires.py config.json state # Check watcher health bash ctl.sh dashboard # Binary search for bash syntax errors for end in $(seq 900 1000); do head -$end scripts/realtime-watcher.sh | bash -n 2>&1 && continue; echo "Error at line $end"; break; done ``` ### Environment Variables The watcher uses these bash variables โ€” **`STATE_DIR` must be exported** for inline Python: | Variable | Usage | Exported? | |----------|-------|-----------| | `SKILL_DIR` | Base directory for all paths | No (bash only) | | `STATE_DIR` | Runtime state files directory | **Yes** (Python reads via `os.environ`) | | `CONFIG_FILE` | Path to config.json | No (passed as arg) | | `THREAT_LEVEL` | Current threat level string | No (bash only) | ### Updates (Mar 2 2026) **New Data Tables (Azure Table Storage):** - `seismicevents` โ€” USGS earthquakes, polled every 2min - `fireevents` โ€” NASA FIRMS hotspots (FRP>10MW), polled every 5min - Strike correlation engine: `/api/correlate?hours=1&radius_km=50` - Historical endpoints: `/api/seismic/history`, `/api/fires/history` **Dashboard Additions:** - 40 regional energy assets (Qatar, UAE, Saudi, Iraq, Kuwait, Bahrain, Oman, Israel, Egypt) - DAMAGED_FACILITIES overlay: ๐Ÿ’ฅ struck / โš ๏ธ shutdown / ๐Ÿšซ blocked markers with pulsing borders - All 23 sidebar layer toggles now functional (7 were missing) - Feed auto-refreshes every 30s regardless of panel state - Oref banner shows English category names via `OREF_CAT_EN` dictionary **Strikes Map Rewrite:** - Replaced PIL rectangle-based rendering with Cartopy + Matplotlib - Real Natural Earth coastlines, borders, ocean. Country labels. Dual legends. - Dependencies: cartopy, pyproj, shapely, pyshp **API v19 deployed** โ€” revision `magen-yehuda-api--0000019`