Skip to content

Commit 57916cb

Browse files
Merge pull request #21 from arandomguyhere/claude/evaluate-situation-monitor-bDXs1
Claude/evaluate situation monitor b d xs1
2 parents f1a8e71 + a325a8a commit 57916cb

File tree

2 files changed

+142
-28
lines changed

2 files changed

+142
-28
lines changed

README.md

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Geopolitical Threat Mapper
22

3-
A multi-layer situational awareness platform that correlates cyber threats, maritime activity, aviation data, GPS interference, and news events to provide real-time geopolitical intelligence.
3+
A multi-layer situational awareness platform that correlates cyber threats, maritime activity, aviation data, GPS interference, financial markets, and news events to provide real-time geopolitical intelligence.
4+
5+
[![CI](https://github.com/arandomguyhere/geopolitical-threat-mapper/actions/workflows/ci.yml/badge.svg)](https://github.com/arandomguyhere/geopolitical-threat-mapper/actions/workflows/ci.yml)
6+
[![Deploy to GitHub Pages](https://github.com/arandomguyhere/geopolitical-threat-mapper/actions/workflows/deploy-pages.yml/badge.svg)](https://github.com/arandomguyhere/geopolitical-threat-mapper/actions/workflows/deploy-pages.yml)
47

58
## Architecture
69

@@ -9,36 +12,41 @@ A multi-layer situational awareness platform that correlates cyber threats, mari
912
│ GEOPOLITICAL THREAT MAPPER │
1013
├─────────────────────────────────────────────────────────────────────┤
1114
│ │
12-
│ YOUR EXISTING REPOS (FOUNDATION) │
13-
│ ┌─────────────────────┐ ┌─────────────────────┐ │
14-
│ │ AIS_Tracker │ │ Google-News-Scraper │ │
15-
│ │ (Maritime Intel) │ │ (Threat News) │ │
16-
│ └──────────┬──────────┘ └──────────┬──────────┘ │
17-
│ │ │ │
18-
│ NEW DATA SOURCES │ │
19-
│ ┌──────────┴────────────────────────┴──────────┐ │
20-
│ │ Shodan │ Censys │ OTX │ OpenSky │ GPSJAM │ │
21-
│ └──────────────────────────────────────────────┘ │
15+
│ DATA SOURCES │
16+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
17+
│ │ AIS_Tracker │ │ News/RSS │ │ Financial │ │ Cyber Intel │ │
18+
│ │ (Maritime) │ │ (50+ feeds) │ │ (Markets) │ │ (APT/IOCs) │ │
19+
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
20+
│ │ │ │ │ │
21+
│ ┌──────┴───────────────┴───────────────┴───────────────┴──────┐ │
22+
│ │ OpenSky │ GPSJAM │ Shodan │ OTX │ VesselFinder │ FRED │ │
23+
│ └──────────────────────────────────────────────────────────────┘ │
2224
│ │ │
2325
│ ┌─────────────────┴──────────────────┐ │
2426
│ │ CORRELATION ENGINE │ │
27+
│ │ (6 domains: cyber, maritime, │ │
28+
│ │ aviation, GPS, news, financial) │ │
2529
│ └─────────────────┬──────────────────┘ │
2630
│ │ │
2731
│ ┌─────────────────┴──────────────────┐ │
28-
│ │ Threat Feed │ Heatmap │ Alerts │ │
32+
│ │ Threat Feed │ Dashboard │ Alerts │ │
2933
│ └────────────────────────────────────┘ │
3034
└─────────────────────────────────────────────────────────────────────┘
3135
```
3236

3337
## Features
3438

35-
- **Multi-Layer Correlation**: Connects cyber threats with maritime, aviation, and news data
39+
- **Multi-Layer Correlation**: Connects 6 intelligence domains (cyber, maritime, aviation, GPS, news, financial)
3640
- **Real-Time Monitoring**: Track 6 strategic chokepoints globally
41+
- **Financial Market Signals**: VIX, oil prices, defense ETFs, crypto for geopolitical correlation
42+
- **Narrative Tracking**: Disinformation detection with fringe → mainstream migration analysis
43+
- **50+ RSS Feeds**: Curated news from mainstream, defense, think tanks, and regional sources
3744
- **Cyber Threat Heatmap**: Regional exposure scoring from Shodan, OTX, and abuse.ch
3845
- **APT Tracking**: Integration with your Google-News-Scraper's 60+ APT groups
39-
- **Maritime Intelligence**: Leverages your AIS_Tracker for dark ships and sanctions
46+
- **Maritime Intelligence**: Leverages your AIS_Tracker + bulk vessel scraper fallback
4047
- **Aviation Overlay**: Military aircraft detection via OpenSky Network
4148
- **GPS Interference**: Spoofing/jamming detection from GPSJAM
49+
- **GitHub Pages Demo**: Static site deployment for live demos
4250

4351
## Monitored Regions
4452

@@ -146,11 +154,20 @@ python server.py --port 9000
146154
|--------|----------|------------------|
147155
| GPSJAM.org | Interference map | Daily |
148156

149-
### Events
157+
### Events & News
150158

151159
| Source | Use Case | Rate Limit |
152160
|--------|----------|------------|
153161
| GDELT Project | Global events | Unlimited |
162+
| 50+ RSS Feeds | Curated news sources | Unlimited |
163+
164+
### Financial Markets
165+
166+
| Source | Use Case | Rate Limit |
167+
|--------|----------|------------|
168+
| CoinGecko | Crypto prices (BTC, ETH, stablecoins) | Unlimited |
169+
| Yahoo Finance | VIX, commodities, sector ETFs | Unlimited |
170+
| FRED | Federal Reserve data | Unlimited |
154171

155172
## Output Files
156173

@@ -191,6 +208,14 @@ The web dashboard (`server.py`) provides an interactive map at **http://localhos
191208
- Chokepoints - Strategic maritime choke points
192209
- AIS Vessels - Ship tracking with risk visualization
193210
- Cyber Threats - IOC markers aggregated by country
211+
- Financial Signals - Market indicator markers
212+
213+
**Market Signals Panel:**
214+
- VIX fear index with color-coded levels
215+
- Crude oil price and daily change
216+
- Defense sector ETF performance
217+
- Bitcoin price as sanctions/capital flight indicator
218+
- Market momentum indicator (surging/rising/stable/declining)
194219

195220
**Settings UI:**
196221
- Configure all API keys from the web interface
@@ -222,22 +247,30 @@ See `config/correlation_rules.yaml` for full definitions.
222247
geopolitical-threat-mapper/
223248
├── main.py # Data collection orchestrator
224249
├── server.py # Web dashboard (port 8081)
250+
├── build_static.py # Static site generator for GitHub Pages
225251
├── requirements.txt
226252
├── .env.example # Environment template
253+
├── .github/
254+
│ └── workflows/
255+
│ ├── ci.yml # Lint, test, build
256+
│ └── deploy-pages.yml # GitHub Pages deployment
227257
├── scripts/
228258
│ ├── config/
229-
│ │ ├── sources.yaml # Data source configuration
259+
│ │ ├── sources.yaml # Data source + RSS feeds
230260
│ │ ├── correlation_rules.yaml # Correlation rule definitions
261+
│ │ ├── locations.yaml # Conflict zones, bases, cables
231262
│ │ └── chokepoints.geojson # Strategic chokepoint polygons
232263
│ ├── collectors/
233264
│ │ ├── cyber/ # Shodan, OTX, abuse.ch, NVD
234-
│ │ ├── maritime/ # AIS_Tracker integration
265+
│ │ ├── maritime/ # AIS_Tracker + VesselScraper
235266
│ │ ├── aviation/ # OpenSky/Airplanes.Live
267+
│ │ ├── financial/ # Markets, commodities, crypto
236268
│ │ ├── gps/ # GPSJAM interference
237269
│ │ └── news/ # News scraper integration
238270
│ └── processors/
239-
│ └── correlation_engine.py # Multi-source correlation
240-
├── tests/ # 40 unit tests
271+
│ ├── correlation_engine.py # Multi-source correlation
272+
│ └── narrative_tracker.py # Disinformation detection
273+
├── tests/ # Unit tests
241274
└── output/ # Generated files
242275
```
243276

@@ -315,9 +348,14 @@ NEWS_SCRAPER_FEED = "/path/to/Google-News-Scraper/docs/feed.json"
315348
- [x] Interactive Leaflet map (web dashboard)
316349
- [x] Settings UI for API key configuration
317350
- [x] Best-in-class vessel tracking (ship icons, details panel, search, risk scoring)
318-
- [x] Unit test suite (40 tests)
351+
- [x] Unit test suite
352+
- [x] Financial market integration (VIX, commodities, crypto, defense ETFs)
353+
- [x] Narrative/disinformation tracking
354+
- [x] 50+ RSS feed aggregation
355+
- [x] Bulk vessel scraper fallback
356+
- [x] GitHub Actions CI/CD
357+
- [x] GitHub Pages static deployment
319358
- [ ] GDELT integration
320-
- [ ] GitHub Actions automation
321359
- [ ] Alert notifications (Slack, Discord)
322360

323361
## Contributing

build_static.py

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -220,21 +220,84 @@ def modify_html_for_static(html: str, feed_data: dict, chokepoints: list) -> str
220220
</script>
221221
"""
222222

223-
# Replace fetch calls with static data
223+
# Replace fetch calls with live data fetchers
224224
static_loader = """
225225
<script>
226-
// Override fetch for static mode
226+
// Live data fetchers for static site
227+
window.LIVE_DATA_CACHE = {};
228+
window.LIVE_DATA_CACHE_TIME = {};
229+
const CACHE_TTL = 60000; // 1 minute cache
230+
231+
async function fetchLiveFinancial() {
232+
const now = Date.now();
233+
if (window.LIVE_DATA_CACHE.financial && (now - window.LIVE_DATA_CACHE_TIME.financial) < CACHE_TTL) {
234+
return window.LIVE_DATA_CACHE.financial;
235+
}
236+
237+
const data = { vix: {}, commodities: [], crypto: [], sectors: [], momentum: 'stable' };
238+
239+
try {
240+
// Fetch crypto from CoinGecko (public API)
241+
const cryptoResp = await fetch('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,ethereum,tether&vs_currencies=usd&include_24hr_change=true');
242+
if (cryptoResp.ok) {
243+
const crypto = await cryptoResp.json();
244+
data.crypto = [
245+
{ symbol: 'BTC', name: 'Bitcoin', price: crypto.bitcoin?.usd || 0, change_24h: crypto.bitcoin?.usd_24h_change || 0 },
246+
{ symbol: 'ETH', name: 'Ethereum', price: crypto.ethereum?.usd || 0, change_24h: crypto.ethereum?.usd_24h_change || 0 },
247+
{ symbol: 'USDT', name: 'Tether', price: crypto.tether?.usd || 1, change_24h: crypto.tether?.usd_24h_change || 0 }
248+
];
249+
}
250+
251+
// Fetch fear & greed as VIX proxy
252+
const fgiResp = await fetch('https://api.alternative.me/fng/?limit=1');
253+
if (fgiResp.ok) {
254+
const fgi = await fgiResp.json();
255+
const value = parseInt(fgi.data?.[0]?.value || 50);
256+
// Invert: fear (low) = high VIX, greed (high) = low VIX
257+
const vixProxy = Math.round((100 - value) * 0.4 + 10);
258+
data.vix = {
259+
value: vixProxy,
260+
level: vixProxy > 30 ? 'elevated' : vixProxy > 20 ? 'normal' : 'low',
261+
fear_greed: fgi.data?.[0]?.value_classification || 'Neutral'
262+
};
263+
}
264+
265+
// Calculate momentum from BTC change
266+
const btcChange = data.crypto[0]?.change_24h || 0;
267+
if (btcChange > 5) data.momentum = 'surging';
268+
else if (btcChange > 2) data.momentum = 'rising';
269+
else if (btcChange < -5) data.momentum = 'declining';
270+
else data.momentum = 'stable';
271+
272+
} catch (e) {
273+
console.warn('Live financial fetch error:', e);
274+
}
275+
276+
window.LIVE_DATA_CACHE.financial = data;
277+
window.LIVE_DATA_CACHE_TIME.financial = now;
278+
return data;
279+
}
280+
281+
async function fetchLiveGPS() {
282+
// GPS data requires scraping, return sample for demo
283+
return window.FEED_DATA?.gps || { interference_zones: [] };
284+
}
285+
286+
// Override fetch for static mode with live data
227287
if (window.STATIC_MODE) {
228288
const originalFetch = window.fetch;
229289
window.fetch = async function(url, options) {
230290
if (url === '/api/feed') {
231-
return { ok: true, json: async () => window.FEED_DATA };
291+
const financial = await fetchLiveFinancial();
292+
const feed = { ...window.FEED_DATA, financial, timestamp: new Date().toISOString() };
293+
return { ok: true, json: async () => feed };
232294
}
233295
if (url === '/api/chokepoints') {
234296
return { ok: true, json: async () => window.CHOKEPOINTS };
235297
}
236298
if (url === '/api/financial') {
237-
return { ok: true, json: async () => window.FEED_DATA.financial || {} };
299+
const financial = await fetchLiveFinancial();
300+
return { ok: true, json: async () => financial };
238301
}
239302
if (url === '/api/ais') {
240303
return { ok: true, json: async () => ({ vessels: [], statistics: {} }) };
@@ -244,15 +307,28 @@ def modify_html_for_static(html: str, feed_data: dict, chokepoints: list) -> str
244307
}
245308
return originalFetch(url, options);
246309
};
310+
311+
// Auto-refresh live data every 60 seconds
312+
setInterval(async () => {
313+
window.LIVE_DATA_CACHE = {};
314+
if (typeof loadData === 'function') loadData();
315+
}, 60000);
247316
}
248317
</script>
249318
"""
250319

251-
# Add static mode banner
320+
# Add live data banner
252321
static_banner = """
253-
<div id="static-mode-banner" style="position:fixed;top:0;left:50%;transform:translateX(-50%);background:#f39c12;color:#000;padding:5px 15px;border-radius:0 0 5px 5px;font-size:0.75rem;z-index:9999;">
254-
Static Demo Mode - Data may not be live
322+
<div id="static-mode-banner" style="position:fixed;top:0;left:50%;transform:translateX(-50%);background:#2ecc71;color:#000;padding:5px 15px;border-radius:0 0 5px 5px;font-size:0.75rem;z-index:9999;">
323+
<span id="live-indicator" style="display:inline-block;width:8px;height:8px;background:#fff;border-radius:50%;margin-right:6px;animation:pulse 2s infinite;"></span>
324+
Live Data - Crypto &amp; Fear/Greed Index
255325
</div>
326+
<style>
327+
@keyframes pulse {
328+
0%, 100% { opacity: 1; }
329+
50% { opacity: 0.3; }
330+
}
331+
</style>
256332
"""
257333

258334
# Insert scripts after <head>

0 commit comments

Comments
 (0)