mcasrom/nearme-osint

NearMe OSINT - Motor de agregación geográfica OSINT

1

stars

148

commits

HTML

primary language

Sep 9, 2026

updated

README

NearMe OSINT

📍 NearMe OSINT — Mapa de eventos en tiempo real

¿Qué está pasando a mi alrededor ahora mismo?

Demo en vivo Licencia MIT 15 fuentes Apoyar en Ko-fi

🔥 Incendios · 🚧 Tráfico · 🌡️ Meteorología · 🌫️ Calidad del aire · 🚆 Trenes · 🏚️ Terremotos · ⚡ Energía · 🏖️ Playas

NearMe OSINT en acción


Un agregador OSINT geográfico en tiempo real que une 15 fuentes de datos públicos y oficiales en un solo mapa interactivo con niveles de severidad, mediciones continuas y alertas personalizables. Funciona como una PWA instalable y offline.

💡 ¿Qué es esto en la práctica? En vez de revisar cinco apps distintas para saber si hay un incendio cerca, un retraso de tren, una alerta meteorológica o un corte de tráfico, NearMe lo agrupa todo en un flujo único de eventos geolocalizados.


🚀 Prueba la demo

→ Abrir NearMe OSINT en vivo

  • 📍 Busca una ubicación por texto, haz clic en el mapa o usa tu GPS
  • 🔥 Explora incendios reales detectados por satélite (NASA FIRMS)
  • 🚆 Consulta retrasos de tren (RENFE) e incidencias de tráfico (DGT)
  • 🔔 Activa alertas: "avísame si hay incendios a <15 km"
  • 📱 Instálala como app (PWA con soporte offline)

✨ Características

🗺️ Mapa en tiempo realLeaflet + MarkerCluster, iconos por tipo de evento y severidad
🔥 Incendios por satéliteNASA FIRMS (MODIS + VIIRS) con mapa de calor y gradiente por potencia (FRP)
🚧 TráficoDGT DATEX II: cortes, obras, accidentes y retenciones en la red estatal
🚆 TrenesRetrasos RENFE geolocalizados vía GTFS-RT (cercanías + AV/LD)
🌡️ MeteorologíaAEMET: 10.600 estaciones con informes continuos + alertas
🌫️ Calidad del aireMITECO ICA + OpenAQ (6 parámetros)
🏚️ SismologíaIGN (red nacional 24/7) + USGS (global M2.5+)
EnergíaDemanda eléctrica REE + precio PVPC (ESIOS) en tiempo real
🏖️ PlayasEstado de playas del País Vasco (bandera, oleaje, medusas)
☀️ Índice UVOpen-Meteo para 52 capitales + Ceuta/Melilla
🔔 Alertas personalizadasPor tipo, radio y nivel con notificaciones del navegador
📍 POI cercanosHospitales, farmacias, gasolineras y más (Overpass/OSM)
📤 CompartirTexto dinámico + Web Share API con enlaces a 𝕏, WhatsApp, Telegram, Bluesky y Mastodon
🟢 Estado del sistemaSemáforo por fuente, freshness badges y health indicator
📱 PWAInstalable, offline, auto-refresh cada 5 minutos
🔒 PrivacidadSin analytics, sin tracking, sin cookies, sin IPs

📊 Pipeline de datos

[15 colectores async] → [Pipeline (asyncio.gather)] → [PostgreSQL + PostGIS] → [FastAPI] → [Frontend Leaflet]

Cada ciclo de 15 minutos procesa ~6.000+ eventos:

FuenteQué aportaAutenticaciónActualización
NASA FIRMS🔥 Incendios satélite (MODIS+VIIRS)Sin clave15 min
DGT🚧 Incidencias tráfico (DATEX II)Sin clave5 min
AEMET🌡️ Meteo continuo + alertas (10.600 est.)API Key15 min
RENFE🚆 Retrasos tren (GTFS-RT)Sin clave15 min
MITECO🌫️ Calidad del aire ICA (620 est.)Sin clave30 min
OpenAQ🌫️ Calidad del aire (6 parámetros, v3)API Key30 min
USGS🏚️ Terremotos M2.5+ globalesSin clave15 min
Protección Civil⚠️ Avisos meteorológicos (CAP/AEMET)API Key30 min
REE⚡ Demanda eléctrica tiempo realSin clave15 min
IntelHub📰 Noticias + incendios RSS (24 fuentes, 9 países)Sin clave10 min
Playas Euskadi🏖️ Bandera, oleaje, temperatura, medusasSin clave60 min
Embalses🌊 Nivel de embalses (MITECO SAIH)Sin clave30 min
IGN🏚️ Sismología española (red 24/7)Sin clave15 min
Open-Meteo☀️ Índice UV máximo (52 capitales)Sin clave60 min
REE + ESIOS⚡ Demanda y precio PVPCSin clave15 min

Ciclo de vida de un evento

  1. Creación — el colector obtiene datos y hace upsert por (source, source_id)
  2. Actualización — si el evento sigue en la fuente, se renueva su expires_at
  3. Resolución — si deja de aparecer, resolve_events() lo marca como resolved
  4. Expiración por TTL — si no hay fin explícito, se limpia al superar su TTL (incendios 24 h, tráfico 12 h, …)
  5. Expiración explícita — se respeta el end_time de la fuente (p. ej. DGT overallEndTime)

Niveles de severidad

NivelColorEjemplo
info🔵 AzulDatos normales (clima, calidad del aire)
warning🟡 AmarilloPrecauciones (ICA ≥ 3, temperatura ≥ 35 °C)
alert🟠 NaranjaPeligro (FRP ≥ 100 MW, terremoto ≥ M5)
critical🔴 RojoEmergencia (severidad DGT highest)

Frescura

Cada evento lleva un badge según su updated_at: 🟢 <30 min · 🟠 30 min–2 h · 🔴 >2 h. El sidebar muestra un semáforo por fuente (🟢🟡🔴) actualizado cada 60 s desde /api/status.

📈 Análisis transversal

Además del mapa en vivo, NearMe genera analítica agregada nocturna:

  • zone_metrics — tabla diaria por CCAA: volumen de eventos, niveles de severidad, diversidad de fuentes, persistencia media e índice de convergencia (coincidencias espaciales <50 km y temporales <6 h entre fuentes distintas). Colector: scripts/compute_zone_metrics.py (cron 23:40, transacción por día).
  • Incendios × meteorología — página editorial estática que cruza detecciones FIRMS con temperatura/viento diarios (Open-Meteo) por CCAA y día, con metodología y límites visibles: https://radar.viajeinteligencia.com/incendios-meteorologia.html (regeneración diaria 07:20).

🛠️ Stack

  • Backend: FastAPI + uvicorn · async Python (httpx, asyncio.gather)
  • Base de datos: PostgreSQL + PostGIS con connection pooling (psycopg2)
  • Pipeline: cron */15 * * * * + monitoreo persistente en collector_runs
  • Frontend: Leaflet + Leaflet.markerCluster + Leaflet.heat + vanilla JS (PWA con Service Worker)
  • Auth: JWT + bcrypt (passlib)
  • Infra: Nginx + SSL Let's Encrypt · PM2 (nearme-api) · rsync

📁 Estructura del proyecto

nearme-osint/
├── run.py                      # Orquestador del pipeline (colectores async)
├── src/
│   ├── api/server.py           # FastAPI (frontend + API + auth)
│   ├── db.py                   # PostgreSQL/PostGIS con connection pooling
│   ├── config.py               # Constantes centralizadas (umbrales, URLs, TTLs)
│   ├── logging.py              # Logging JSON estructurado
│   ├── metrics.py              # PipelineMetrics (latencia y éxito por colector)
│   ├── models.py               # Event dataclass + EVENT_TYPES
│   └── collectors/
│       ├── aemet/              # Meteorología (observaciones + alertas)
│       ├── dgt/                # Tráfico DATEX II + USGS + NASA FIRMS
│       ├── renfe/              # Retrasos tren (GTFS-RT + CSV estaciones)
│       ├── ree/                # Demanda eléctrica
│       ├── miteco/             # Calidad del aire (ICA)
│       ├── openaq/             # Calidad del aire (fallback, 6 parámetros)
│       ├── proteccion_civil/   # Avisos meteorológicos (CAP)
│       ├── intelhub_bridge.py  # Noticias/incendios RSS (IntelHub)
│       ├── playas/             # Estado de playas Euskadi
│       ├── embalses/           # Nivel de embalses (SAIH + MITECO)
│       ├── ign/                # Sismología española (red 24/7)
│       ├── uv/                 # Índice UV (Open-Meteo)
│       ├── energy/             # Demanda REE + precio PVPC (ESIOS)
│       └── copernicus/         # Incendios GWIS (endpoints 404 — deshabilitado)
├── frontend/                   # Leaflet + MarkerCluster + vanilla JS (PWA)
├── analytics/                  # Reporte GoAccess (basic auth)
├── deploy.sh                   # rsync + PM2 restart
├── setup-server.sh             # Provisionamiento del servidor
├── requirements.txt
├── .env.example                # Template de credenciales (gitignored)
└── WAYAHEAD.md                 # Bitácora de desarrollo y sprints

🔌 API

EndpointDescripción
GET /api/nearbyEventos activos (radio, tipos, niveles)
GET /api/statusEstado por colector (último run, latencia, stats 24 h)
GET /api/status/runs?n=50Últimas ejecuciones del pipeline
GET /api/metricsResumen agregado del pipeline
GET /api/poiPuntos de interés cercanos (proxy Overpass/OSM, con caché)
GET /api/statsVisitas (total, hoy, ayer)
GET /healthEstado de BD, pipeline y último run

Panel de operaciones: /admin (protegido con ADMIN_PASSWORD).

🚀 Puesta en marcha local

git clone git@github.com:mcasrom/nearme-osint.git
cd nearme-osint

# 1. Credenciales (AEMET_API_KEY, OPENAQ_API_KEY, DB_*, JWT_SECRET, ADMIN_PASSWORD)
cp .env.example .env

# 2. PostgreSQL con PostGIS
#    (ver setup-server.sh para el aprovisionamiento completo)

# 3. Instalar dependencias
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt

# 4. Ejecutar el pipeline (recolección → PostGIS)
python run.py

# 5. Arrancar la API
uvicorn src.api.server:app --host 0.0.0.0 --port 8100

👥 Contribuir

¿Te interesa el OSINT de código abierto o los datos abiertos de España? Todas las contribuciones son bienvenidas:

  • 🐛 Reporta bugs o sugerencias vía Issues
  • 📦 Añade un colector: implementa BaseCollector con async collect()list[Event], regístralo en run.py y añade su config en src/config.py
  • 🗺️ Nueva fuente o región: el pipeline es agnóstico a la fuente; añadir otro país es "escribir un colector nuevo"
  • 📄 Revisa WAYAHEAD.md para el contexto de desarrollo y sprints

🔒 Privacidad

Sin analytics, sin tracking, sin cookies, sin publicidad. Solo se guardan datos mínimos (usuario, email opcional y hash bcrypt) exclusivamente para el sistema de alertas y las ubicaciones favoritas. Sin IPs, sin geolocalización del usuario. Detalles en la app.

🧭 Roadmap

  • Alertas por email
  • Soporte multi-región (más países)
  • Más fuentes de datos abiertos
  • App móvil nativa (Android/iOS)
  • API pública documentada para terceros

☕ Apoyar el proyecto

Hecho por un desarrollador independiente en España. Si te resulta útil:

Contacto: nearme@viajeinteligencia.com

📄 Licencia

MIT — libre de usar, auditar y modificar. Las fuentes de datos conservan sus propias licencias.

  • /embed.html — mapa en vivo embebible (solo mapa + crédito fijo).
  • /incrustar — página howto para el usuario final (zona → código → colocación → ajustes).
  • Uso: <iframe src="https://nearme.viajeinteligencia.com/embed.html?lat=..&lon=..&radius=30" width="100%" height="500"></iframe>
  • Requisito: mantener el enlace de crédito a nearme.viajeinteligencia.com (backlink).

En el footer: enlaces directos a Radar (emergencias), Noticias, Datos por país y Ecosistema. Los enlaces siguen los journeys reales de los usuarios.

Contributors

mcasrom

148 commits

mcasrom/nearme-osint

NearMe OSINT - Motor de agregación geográfica OSINT

1

stars

148

commits

HTML

primary language

Sep 9, 2026

updated

README

NearMe OSINT

📍 NearMe OSINT — Mapa de eventos en tiempo real

¿Qué está pasando a mi alrededor ahora mismo?

Demo en vivo Licencia MIT 15 fuentes Apoyar en Ko-fi

🔥 Incendios · 🚧 Tráfico · 🌡️ Meteorología · 🌫️ Calidad del aire · 🚆 Trenes · 🏚️ Terremotos · ⚡ Energía · 🏖️ Playas

NearMe OSINT en acción


Un agregador OSINT geográfico en tiempo real que une 15 fuentes de datos públicos y oficiales en un solo mapa interactivo con niveles de severidad, mediciones continuas y alertas personalizables. Funciona como una PWA instalable y offline.

💡 ¿Qué es esto en la práctica? En vez de revisar cinco apps distintas para saber si hay un incendio cerca, un retraso de tren, una alerta meteorológica o un corte de tráfico, NearMe lo agrupa todo en un flujo único de eventos geolocalizados.


🚀 Prueba la demo

→ Abrir NearMe OSINT en vivo

  • 📍 Busca una ubicación por texto, haz clic en el mapa o usa tu GPS
  • 🔥 Explora incendios reales detectados por satélite (NASA FIRMS)
  • 🚆 Consulta retrasos de tren (RENFE) e incidencias de tráfico (DGT)
  • 🔔 Activa alertas: "avísame si hay incendios a <15 km"
  • 📱 Instálala como app (PWA con soporte offline)

✨ Características

🗺️ Mapa en tiempo realLeaflet + MarkerCluster, iconos por tipo de evento y severidad
🔥 Incendios por satéliteNASA FIRMS (MODIS + VIIRS) con mapa de calor y gradiente por potencia (FRP)
🚧 TráficoDGT DATEX II: cortes, obras, accidentes y retenciones en la red estatal
🚆 TrenesRetrasos RENFE geolocalizados vía GTFS-RT (cercanías + AV/LD)
🌡️ MeteorologíaAEMET: 10.600 estaciones con informes continuos + alertas
🌫️ Calidad del aireMITECO ICA + OpenAQ (6 parámetros)
🏚️ SismologíaIGN (red nacional 24/7) + USGS (global M2.5+)
EnergíaDemanda eléctrica REE + precio PVPC (ESIOS) en tiempo real
🏖️ PlayasEstado de playas del País Vasco (bandera, oleaje, medusas)
☀️ Índice UVOpen-Meteo para 52 capitales + Ceuta/Melilla
🔔 Alertas personalizadasPor tipo, radio y nivel con notificaciones del navegador
📍 POI cercanosHospitales, farmacias, gasolineras y más (Overpass/OSM)
📤 CompartirTexto dinámico + Web Share API con enlaces a 𝕏, WhatsApp, Telegram, Bluesky y Mastodon
🟢 Estado del sistemaSemáforo por fuente, freshness badges y health indicator
📱 PWAInstalable, offline, auto-refresh cada 5 minutos
🔒 PrivacidadSin analytics, sin tracking, sin cookies, sin IPs

📊 Pipeline de datos

[15 colectores async] → [Pipeline (asyncio.gather)] → [PostgreSQL + PostGIS] → [FastAPI] → [Frontend Leaflet]

Cada ciclo de 15 minutos procesa ~6.000+ eventos:

FuenteQué aportaAutenticaciónActualización
NASA FIRMS🔥 Incendios satélite (MODIS+VIIRS)Sin clave15 min
DGT🚧 Incidencias tráfico (DATEX II)Sin clave5 min
AEMET🌡️ Meteo continuo + alertas (10.600 est.)API Key15 min
RENFE🚆 Retrasos tren (GTFS-RT)Sin clave15 min
MITECO🌫️ Calidad del aire ICA (620 est.)Sin clave30 min
OpenAQ🌫️ Calidad del aire (6 parámetros, v3)API Key30 min
USGS🏚️ Terremotos M2.5+ globalesSin clave15 min
Protección Civil⚠️ Avisos meteorológicos (CAP/AEMET)API Key30 min
REE⚡ Demanda eléctrica tiempo realSin clave15 min
IntelHub📰 Noticias + incendios RSS (24 fuentes, 9 países)Sin clave10 min
Playas Euskadi🏖️ Bandera, oleaje, temperatura, medusasSin clave60 min
Embalses🌊 Nivel de embalses (MITECO SAIH)Sin clave30 min
IGN🏚️ Sismología española (red 24/7)Sin clave15 min
Open-Meteo☀️ Índice UV máximo (52 capitales)Sin clave60 min
REE + ESIOS⚡ Demanda y precio PVPCSin clave15 min

Ciclo de vida de un evento

  1. Creación — el colector obtiene datos y hace upsert por (source, source_id)
  2. Actualización — si el evento sigue en la fuente, se renueva su expires_at
  3. Resolución — si deja de aparecer, resolve_events() lo marca como resolved
  4. Expiración por TTL — si no hay fin explícito, se limpia al superar su TTL (incendios 24 h, tráfico 12 h, …)
  5. Expiración explícita — se respeta el end_time de la fuente (p. ej. DGT overallEndTime)

Niveles de severidad

NivelColorEjemplo
info🔵 AzulDatos normales (clima, calidad del aire)
warning🟡 AmarilloPrecauciones (ICA ≥ 3, temperatura ≥ 35 °C)
alert🟠 NaranjaPeligro (FRP ≥ 100 MW, terremoto ≥ M5)
critical🔴 RojoEmergencia (severidad DGT highest)

Frescura

Cada evento lleva un badge según su updated_at: 🟢 <30 min · 🟠 30 min–2 h · 🔴 >2 h. El sidebar muestra un semáforo por fuente (🟢🟡🔴) actualizado cada 60 s desde /api/status.

📈 Análisis transversal

Además del mapa en vivo, NearMe genera analítica agregada nocturna:

  • zone_metrics — tabla diaria por CCAA: volumen de eventos, niveles de severidad, diversidad de fuentes, persistencia media e índice de convergencia (coincidencias espaciales <50 km y temporales <6 h entre fuentes distintas). Colector: scripts/compute_zone_metrics.py (cron 23:40, transacción por día).
  • Incendios × meteorología — página editorial estática que cruza detecciones FIRMS con temperatura/viento diarios (Open-Meteo) por CCAA y día, con metodología y límites visibles: https://radar.viajeinteligencia.com/incendios-meteorologia.html (regeneración diaria 07:20).

🛠️ Stack

  • Backend: FastAPI + uvicorn · async Python (httpx, asyncio.gather)
  • Base de datos: PostgreSQL + PostGIS con connection pooling (psycopg2)
  • Pipeline: cron */15 * * * * + monitoreo persistente en collector_runs
  • Frontend: Leaflet + Leaflet.markerCluster + Leaflet.heat + vanilla JS (PWA con Service Worker)
  • Auth: JWT + bcrypt (passlib)
  • Infra: Nginx + SSL Let's Encrypt · PM2 (nearme-api) · rsync

📁 Estructura del proyecto

nearme-osint/
├── run.py                      # Orquestador del pipeline (colectores async)
├── src/
│   ├── api/server.py           # FastAPI (frontend + API + auth)
│   ├── db.py                   # PostgreSQL/PostGIS con connection pooling
│   ├── config.py               # Constantes centralizadas (umbrales, URLs, TTLs)
│   ├── logging.py              # Logging JSON estructurado
│   ├── metrics.py              # PipelineMetrics (latencia y éxito por colector)
│   ├── models.py               # Event dataclass + EVENT_TYPES
│   └── collectors/
│       ├── aemet/              # Meteorología (observaciones + alertas)
│       ├── dgt/                # Tráfico DATEX II + USGS + NASA FIRMS
│       ├── renfe/              # Retrasos tren (GTFS-RT + CSV estaciones)
│       ├── ree/                # Demanda eléctrica
│       ├── miteco/             # Calidad del aire (ICA)
│       ├── openaq/             # Calidad del aire (fallback, 6 parámetros)
│       ├── proteccion_civil/   # Avisos meteorológicos (CAP)
│       ├── intelhub_bridge.py  # Noticias/incendios RSS (IntelHub)
│       ├── playas/             # Estado de playas Euskadi
│       ├── embalses/           # Nivel de embalses (SAIH + MITECO)
│       ├── ign/                # Sismología española (red 24/7)
│       ├── uv/                 # Índice UV (Open-Meteo)
│       ├── energy/             # Demanda REE + precio PVPC (ESIOS)
│       └── copernicus/         # Incendios GWIS (endpoints 404 — deshabilitado)
├── frontend/                   # Leaflet + MarkerCluster + vanilla JS (PWA)
├── analytics/                  # Reporte GoAccess (basic auth)
├── deploy.sh                   # rsync + PM2 restart
├── setup-server.sh             # Provisionamiento del servidor
├── requirements.txt
├── .env.example                # Template de credenciales (gitignored)
└── WAYAHEAD.md                 # Bitácora de desarrollo y sprints

🔌 API

EndpointDescripción
GET /api/nearbyEventos activos (radio, tipos, niveles)
GET /api/statusEstado por colector (último run, latencia, stats 24 h)
GET /api/status/runs?n=50Últimas ejecuciones del pipeline
GET /api/metricsResumen agregado del pipeline
GET /api/poiPuntos de interés cercanos (proxy Overpass/OSM, con caché)
GET /api/statsVisitas (total, hoy, ayer)
GET /healthEstado de BD, pipeline y último run

Panel de operaciones: /admin (protegido con ADMIN_PASSWORD).

🚀 Puesta en marcha local

git clone git@github.com:mcasrom/nearme-osint.git
cd nearme-osint

# 1. Credenciales (AEMET_API_KEY, OPENAQ_API_KEY, DB_*, JWT_SECRET, ADMIN_PASSWORD)
cp .env.example .env

# 2. PostgreSQL con PostGIS
#    (ver setup-server.sh para el aprovisionamiento completo)

# 3. Instalar dependencias
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt

# 4. Ejecutar el pipeline (recolección → PostGIS)
python run.py

# 5. Arrancar la API
uvicorn src.api.server:app --host 0.0.0.0 --port 8100

👥 Contribuir

¿Te interesa el OSINT de código abierto o los datos abiertos de España? Todas las contribuciones son bienvenidas:

  • 🐛 Reporta bugs o sugerencias vía Issues
  • 📦 Añade un colector: implementa BaseCollector con async collect()list[Event], regístralo en run.py y añade su config en src/config.py
  • 🗺️ Nueva fuente o región: el pipeline es agnóstico a la fuente; añadir otro país es "escribir un colector nuevo"
  • 📄 Revisa WAYAHEAD.md para el contexto de desarrollo y sprints

🔒 Privacidad

Sin analytics, sin tracking, sin cookies, sin publicidad. Solo se guardan datos mínimos (usuario, email opcional y hash bcrypt) exclusivamente para el sistema de alertas y las ubicaciones favoritas. Sin IPs, sin geolocalización del usuario. Detalles en la app.

🧭 Roadmap

  • Alertas por email
  • Soporte multi-región (más países)
  • Más fuentes de datos abiertos
  • App móvil nativa (Android/iOS)
  • API pública documentada para terceros

☕ Apoyar el proyecto

Hecho por un desarrollador independiente en España. Si te resulta útil:

Contacto: nearme@viajeinteligencia.com

📄 Licencia

MIT — libre de usar, auditar y modificar. Las fuentes de datos conservan sus propias licencias.

  • /embed.html — mapa en vivo embebible (solo mapa + crédito fijo).
  • /incrustar — página howto para el usuario final (zona → código → colocación → ajustes).
  • Uso: <iframe src="https://nearme.viajeinteligencia.com/embed.html?lat=..&lon=..&radius=30" width="100%" height="500"></iframe>
  • Requisito: mantener el enlace de crédito a nearme.viajeinteligencia.com (backlink).

En el footer: enlaces directos a Radar (emergencias), Noticias, Datos por país y Ecosistema. Los enlaces siguen los journeys reales de los usuarios.

Contributors

mcasrom

148 commits

Languages

HTML

74.4%

Python

24.2%