osint-dashboard/app/camera_models.py

44 lines
1.6 KiB
Python
Raw Normal View History

"""Open IP camera discovery — models and migration helpers.
Cameras are stored in their own `cameras` table (TimescaleDB hypertable on
last_seen) alongside the existing `events` feed, deduped by URL hash.
"""
from __future__ import annotations
from sqlalchemy import (
Column, Float, Index, Integer, String, Text, DateTime, JSON,
func, Table, BigInteger,
)
from sqlalchemy.dialects.postgresql import UUID
import uuid
from database import metadata
cameras = Table(
"cameras",
metadata,
Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4),
# sha256 hex of the camera's source/snapshot URL — the dedupe key.
Column("url_hash", String(64), nullable=False, index=True),
Column("source_url", Text, nullable=False),
# Snapshot endpoint (may differ from the directory listing URL).
Column("snapshot_url", Text),
# Which discovery feed produced this record (e.g. "insecam", "camera_list").
Column("discovery_source", String(128), nullable=False, index=True),
Column("location_lat", Float),
Column("location_lon", Float),
Column("location_name", String(512)),
# Vendor / device type when detectable from the directory page or URL.
Column("vendor", String(128)),
Column("device_type", String(64)), # e.g. ip-cam, rtsp, mjpeg
Column("first_seen", DateTime(timezone=True), server_default=func.now(), nullable=False),
Column("last_seen", DateTime(timezone=True), server_default=func.now(), nullable=False),
Column("raw", JSON),
)
Index("ix_cameras_location", cameras.c.location_lat, cameras.c.location_lon)
Index("ix_cameras_last_seen", cameras.c.last_seen)