osint-dashboard/alembic/versions/002_cameras.py

44 lines
1.6 KiB
Python
Raw Normal View History

"""cameras table for open-camera discovery
Revision ID: 002_cameras
Revises: 002_fires
Create Date: 2026-08-24
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import UUID
revision = '002_cameras'
down_revision = '002_fires'
branch_labels = None
depends_on = None
def upgrade() -> None:
op.create_table(
'cameras',
sa.Column('id', UUID(as_uuid=True), primary_key=True),
sa.Column('url_hash', sa.String(64), nullable=False),
sa.Column('source_url', sa.Text(), nullable=False),
sa.Column('snapshot_url', sa.Text()),
sa.Column('discovery_source', sa.String(128), nullable=False),
sa.Column('location_lat', sa.Float()),
sa.Column('location_lon', sa.Float()),
sa.Column('location_name', sa.String(512)),
sa.Column('vendor', sa.String(128)),
sa.Column('device_type', sa.String(64)),
sa.Column('first_seen', sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
sa.Column('last_seen', sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
sa.Column('raw', sa.JSON()),
)
op.create_index('ix_cameras_location', 'cameras', ['location_lat', 'location_lon'])
op.create_index('ix_cameras_last_seen', 'cameras', ['last_seen'])
# Dedupe key. NOTE: cameras is intentionally NOT a Timescale hypertable —
# it holds current state per camera (one row per url_hash), not time-series.
op.create_index('ix_cameras_url_hash', 'cameras', ['url_hash'], unique=True)
def downgrade() -> None:
op.drop_table('cameras')