Commit Graph

12 Commits

Author SHA1 Message Date
Elie Habib
d4088fede5 fix(feeds): update dead RSS feed URLs (#1575)
- a16z: a16z.com/feed/ -> www.a16z.news/feed
- First Round Review: /feed.xml -> /articles/rss
- RAND: Google News proxy -> rand.org/pubs/articles.xml (direct)
- Add www.a16z.news to allowed domains
2026-03-14 16:00:35 +04:00
Elie Habib
cad24d8817 fix(predictions): move prediction-tags.json into scripts/data/ for Railway (#1518)
Railway deploys with rootDirectory=scripts/, so ../shared/ resolves to
/shared/ which doesn't exist. Move the canonical file to scripts/data/
and update all four consumers.
2026-03-13 08:52:49 +04:00
RaulC
bfcf7d88ec chore(predictions): extract shared tags and remove unused open_interest (#1512)
- Move GEOPOLITICAL_TAGS, TECH_TAGS, FINANCE_TAGS, and EXCLUDE_KEYWORDS
  to shared/prediction-tags.json so seed, RPC handler, and client all
  reference a single source of truth
- Remove open_interest proto field (always 0 for Polymarket, never
  displayed in UI) and corresponding openInterest assignments

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Elie Habib <elie.habib@gmail.com>
2026-03-13 07:59:12 +04:00
Elie Habib
09fc20fbdf fix: remove smartraveller.gov.au from RSS allowed domains (#1273)
Persistent relay timeouts from smartraveller.gov.au. Remove both
bare and www variants from all three allowed-domains files.
2026-03-08 14:35:50 +04:00
Elie Habib
dd127447c0 refactor: consolidate duplicated market data lists into shared JSON configs (#1212)
Adding a new item (crypto, ETF, stablecoin, gulf symbol, etc.) previously
required editing 2-4 files because the same list was hardcoded independently
in seed scripts, RPC handlers, and frontend config. Following the proven
shared/crypto.json pattern, extract 6 new shared JSON configs so each list
has a single source of truth.

New shared configs:
- shared/stablecoins.json (ids + coinpaprika mappings)
- shared/etfs.json (BTC spot ETF tickers + issuers)
- shared/gulf.json (GCC indices, currencies, oil benchmarks)
- shared/sectors.json (sector ETF symbols + names)
- shared/commodities.json (VIX, gold, oil, gas, silver, copper)
- shared/stocks.json (market symbols + yahoo-only set)

All seed scripts, RPC handlers, and frontend config now import from
these shared JSON files instead of maintaining independent copies.
2026-03-07 22:00:55 +04:00
Nicolas Dos Santos
7b9426299d fix: Tech Readiness toggle, Crypto top 10, FIRMS API key check (#1132, #979, #997) (#1135)
* fix: three panel issues — Tech Readiness toggle, Crypto top 10, FIRMS key check

1. #1132 — Add tech-readiness to FULL_PANELS so it appears in the
   Settings toggle list for Full/Geopolitical variant users.

2. #979 — Expand crypto panel from 4 coins to top 10 by market cap
   (BTC, ETH, USDT, BNB, SOL, XRP, USDC, ADA, DOGE, TRX) across
   client config, server metadata, CoinPaprika fallback map, and
   seed script.

3. #997 — Check isFeatureAvailable('nasaFirms') before loading FIRMS
   data. When the API key is missing, show a clear "not configured"
   message instead of the generic "No fire data available".

Closes #1132, closes #979, closes #997

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: replace stablecoins with AVAX/LINK, remove duplicate key, revert FIRMS change

- Replace USDT/USDC (stablecoins pegged ~$1) with AVAX and LINK
- Remove duplicate 'usd-coin' key in COINPAPRIKA_ID_MAP
- Add CoinPaprika fallback IDs for avalanche-2 and chainlink
- Revert FIRMS API key gating (handled differently now)
- Add sync comments across the 3 crypto config locations

* fix: update AIS relay + seed CoinPaprika fallback for all 10 coins

The AIS relay (primary seeder) still had the old 4-coin list.
The seed script's CoinPaprika fallback map was also missing the
new coins. Both now have all 10 entries.

* refactor: DRY crypto config into shared/crypto.json

Single source of truth for crypto IDs, metadata, and CoinPaprika
fallback mappings. All 4 consumers now import from shared/crypto.json:
- src/config/markets.ts (client)
- server/worldmonitor/market/v1/_shared.ts (server)
- scripts/seed-crypto-quotes.mjs (seed script)
- scripts/ais-relay.cjs (primary relay seeder)

Adding a new coin now requires editing only shared/crypto.json.

* chore: fix pre-existing markdown lint errors in README.md

Add blank lines between headings and lists per MD022/MD032 rules.

* fix: correct CoinPaprika XRP mapping and add crypto config test

- Fix xrp-ripple → xrp-xrp (current CoinPaprika id)
- Add tests/crypto-config.test.mjs: validates every coin has meta,
  coinpaprika mapping, unique symbols, no stablecoins, and valid
  id format — bad fallback ids now fail fast

* test: validate CoinPaprika ids against live API

The regex-only check wouldn't have caught the xrp-ripple typo.
New test fetches /v1/coins from CoinPaprika and asserts every
configured id exists. Gracefully skips if API is unreachable.

* fix(test): handle network failures in CoinPaprika API validation

Wrap fetch in try-catch so DNS failures, timeouts, and rate limits
skip gracefully instead of failing the test suite.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Elie Habib <elie.habib@gmail.com>
2026-03-07 18:23:32 +04:00
Elie Habib
f56f84d6f9 fix(webcams): MTV Lebanon as live stream, not RSS (reverts #1121) (#1122)
* Revert "feat(feeds): add MTV Lebanon News YouTube feed to Middle East region (#1121)"

This reverts commit 5bee51ab79.

* feat(webcams): add MTV Lebanon News live stream to Middle East region
2026-03-06 14:44:43 +04:00
Elie Habib
5bee51ab79 feat(feeds): add MTV Lebanon News YouTube feed to Middle East region (#1121) 2026-03-06 14:18:56 +04:00
JYR-AI
6745f47305 Variant/commodity (#1040)
* commod variants

* mining map layers complete

* metal news feed

* commod variant final

* readme update

* fix: clean up commodity variant for merge readiness

- Remove duplicate FEEDS definition (central feeds.ts is source of truth)
- Remove duplicate inline ALLOWED_DOMAINS in rss-proxy.js (use shared module)
- Add 14 commodity RSS domains to shared/rss-allowed-domains.json
- Remove invalid geopoliticalBoundaries property (not in MapLayers type)
- Fix broken mobile-map-integration-harness imports
- Remove Substack credit link from app header
- Rename i18n key commod → commodity
- Extract mineralColor() helper for DRY color mapping
- Add XSS-safe tooltips for mining sites, processing plants, commodity ports
- Add missing interface fields (annualOutput, materials, capacityTpa, annualVolumeMt)
- Comment out unused COMMODITY_MINERS export
- Isolate commodity DeckGL changes from unrelated basemap refactor

* fix: hide commodity variant from selector until testing complete

Only show the commodity option in the variant switcher when the user
is already on the commodity variant (same pattern as happy variant).
Other variants (full, tech, finance) won't see the commodity link.

---------

Co-authored-by: jroachell <jianyin.roachell@siriusxm.com>
Co-authored-by: Elie Habib <elie.habib@gmail.com>
2026-03-06 09:41:35 +04:00
Elie Habib
fe44cbe182 feat: expand happy variant RSS feeds, render GPS jamming as hexagons, fix layer toggle repaint (#1070)
- Add 7 RSS feed categories for happy variant: positive, science, nature,
  health, inspiring, community with sources like Mongabay, Yes! Magazine,
  Shareable, Conservation Optimism, My Modern Met, GNN subcategories
- Switch GPS jamming layer from ScatterplotLayer (circles) to
  H3HexagonLayer (tessellated hexagons) matching industry standard
- Fix layer toggle not visually updating by adding triggerRepaint()
  after all deck.gl setProps() calls — MapboxOverlay in interleaved
  mode requires MapLibre to repaint for changes to appear
2026-03-05 23:19:10 +04:00
Mert Efe Şensoy
f771114522 feat: aviation monitoring layer with flight tracking, airline intel panel, and news feeds (#907)
* feat: Implement comprehensive aviation monitoring service with flight search, status, news, and tracking.

* feat: Introduce Airline Intelligence Panel with aviation data tabs, map components, and localization.

* feat: Implement DeckGL-based map for advanced visualization, D3/SVG fallback, i18n support, and aircraft tracking.

* Update server/worldmonitor/aviation/v1/get-carrier-ops.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update server/worldmonitor/aviation/v1/search-flight-prices.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update server/worldmonitor/aviation/v1/track-aircraft.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update server/worldmonitor/aviation/v1/get-airport-ops-summary.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update proto/worldmonitor/aviation/v1/position_sample.proto

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update server/worldmonitor/aviation/v1/list-airport-flights.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update proto/worldmonitor/aviation/v1/price_quote.proto

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* feat: Add server-side endpoints for aviation news and aircraft tracking, and introduce a new DeckGLMap component for map visualization.

* Update server/worldmonitor/aviation/v1/list-airport-flights.ts

The cache key for listAirportFlights excludes limit, but the upstream fetch/simulated generator uses limit to determine how many flights to return. If the first request within TTL uses a small limit, larger subsequent requests will be incorrectly capped until cache expiry. Include limit (or a normalized bucket/max) in cacheKey, or always fetch/cache a fixed max then slice per request.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update server/worldmonitor/aviation/v1/get-flight-status.ts

getFlightStatus accepts origin, but cacheKey does not include it. This can serve cached results from an origin-less query to an origin-filtered query (or vice versa). Add origin (normalized) to the cache key or apply filtering after fetch to ensure cache correctness.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* feat: Implement DeckGL map for advanced visualization and new aviation data services.

* fix(aviation): prevent cache poisoning and keyboard shortcut in inputs

- get-carrier-ops: move minFlights filter post-cache to avoid cache
  fragmentation (different callers sharing cached full result)
- AviationCommandBar: guard Ctrl+J shortcut so it does not fire when
  focus is inside an INPUT or TEXTAREA element

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: introduce AviationCommandBar component for parsing user commands, fetching aviation data, and displaying results.

* feat: Implement aircraft tracking service with OpenSky and simulated data sources.

* feat: introduce DeckGLMap component for WebGL-accelerated map visualizations using deck.gl and maplibre-gl.

* fix(aviation): address code review findings for PR #907

Proto: add missing (sebuf.http.query) annotations on all GET request
fields across 6 proto files; add currency/market fields to
SearchFlightPricesRequest.

Server: add parseStringArray to aviation _shared.ts and apply to
get-airport-ops-summary, get-carrier-ops, list-aviation-news handlers
to prevent crash on comma-separated query params; remove leaked API
token from URL params in travelpayouts_data; fix identical simulated
flight statuses in list-airport-flights; remove unused endDate var;
normalize cache key entity casing in list-aviation-news.

Client: refactor AirlineIntelPanel to extend Panel base class and
register in DEFAULT_PANELS for full/tech/finance variants; fix
AviationCommandBar reference leak with proper destroy() cleanup in
panel-layout; rename priceUsd→priceAmount in display type and all
usages; change auto-refresh to call refresh() instead of loadOps().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: introduce aviation command bar component with aircraft tracking and flight information services.

* feat: Add `AirlineIntelPanel` component for displaying airline operations, flights, carriers, tracking, news, and prices in a tabbed interface.

* feat: Add endpoints for listing airport flights and fetching aviation news.

* Update proto/worldmonitor/aviation/v1/search_flight_prices.proto

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* feat: Add server endpoint for listing airport flights and client-side MapPopup types and utilities.

* feat: Introduce MapPopup component with support for various data types and responsive positioning for map features.

* feat: Add initial English localization file (en.json).

* fix(aviation): address PR review findings across aviation stack

- Add User-Agent header to Travelpayouts provider (server convention)
- Use URLSearchParams for API keys instead of raw URL interpolation
- Add input length validation on flightNumber (max 10 chars)
- Replace regex XML parsing with fast-xml-parser in aviation news
- Fix (f as any)._airport type escape with typed Map<FI, string>
- Extract DEFAULT_WATCHED_AIRPORTS constant from hardcoded arrays
- Use event delegation for AirlineIntelPanel price search listener
- Add bootstrap hydration key for flight delays
- Bump OpenSky cache TTL to 120s (anonymous tier rate limit)
- Match DeckGLMap aircraft poll interval to server cache (120s)
- Fix GeoJSON polygon winding order (shoelace check + auto-reversal)

* docs: add aviation env vars to .env.example

AVIATIONSTACK_API, ICAO_API_KEY, TRAVELPAYOUTS_API_TOKEN

* feat: Add aviation news listing API and introduce shared RSS allowed domains.

* fix: add trailing newline to rss-allowed-domains.json, remove unused ringIsClockwise

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Elie Habib <elie.habib@gmail.com>
2026-03-04 21:09:37 +04:00
Elie Habib
898ac7b1c4 perf(rss): route RSS direct to Railway, skip Vercel middleman (#961)
* perf(rss): route RSS direct to Railway, skip Vercel middleman

Vercel /api/rss-proxy has 65% error rate (207K failed invocations/12h).
Route browser RSS requests directly to Railway (proxy.worldmonitor.app)
via Cloudflare CDN, eliminating Vercel as middleman.

- Add VITE_RSS_DIRECT_TO_RELAY feature flag (default off) for staged rollout
- Centralize RSS proxy URL in rssProxyUrl() with desktop/dev/prod routing
- Make Railway /rss public (skip auth, keep rate limiting with CF-Connecting-IP)
- Add wildcard *.worldmonitor.app CORS + always emit Vary: Origin on /rss
- Extract ~290 RSS domains to shared/rss-allowed-domains.cjs (single source of truth)
- Convert Railway domain check to Set for O(1) lookups
- Remove rss-proxy from KEYED_CLOUD_API_PATTERN (no longer needs API key header)
- Add edge function test for shared domain list import

* fix(edge): replace node:module with JSON import for edge-compatible RSS domains

api/_rss-allowed-domains.js used createRequire from node:module which is
unsupported in Vercel Edge Runtime, breaking all edge functions (including
api/gpsjam). Replaced with JSON import attribute syntax that works in both
esbuild (Vercel build) and Node.js 22+ (tests).

Also fixed middleware.ts TS18048 error where VARIANT_OG[variant] could be
undefined.

* test(edge): add guard against node: built-in imports in api/ files

Scans ALL api/*.js files (including _ helpers) for node: module imports
which are unsupported in Vercel Edge Runtime. This would have caught the
createRequire(node:module) bug before it reached Vercel.

* fix(edge): inline domain array and remove NextResponse reference

- Replace `import ... with { type: 'json' }` in _rss-allowed-domains.js
  with inline array — Vercel esbuild doesn't support import attributes
- Replace `NextResponse.next()` with bare `return` in middleware.ts —
  NextResponse was never imported

* ci(pre-push): add esbuild bundle check and edge function tests

The pre-push hook now catches Vercel build failures locally:
- esbuild bundles each api/*.js entrypoint (catches import attribute
  syntax, missing modules, and other bundler errors)
- runs edge function test suite (node: imports, module isolation)
2026-03-04 18:42:00 +04:00