"""SubscribeStarSeenMedia — per-source ledger of SubscribeStar media already downloaded+processed. Mirror of PatreonSeenMedia for the SubscribeStar native ingester (replacing gallery-dl). One queryable row per (source, media) so routine walks skip media we've already ingested; recovery mode bypasses the ledger to re-walk. `filehash` is a CDN content hash when the media URL carries one, else a synthesized ``:`` key (SubscribeStar URLs aren't always content-addressed) — hence String(128) rather than 32. """ from datetime import datetime from sqlalchemy import ForeignKey, Integer, String, UniqueConstraint, func from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.types import DateTime from .base import Base class SubscribeStarSeenMedia(Base): __tablename__ = "subscribestar_seen_media" __table_args__ = ( # Dedup key the downloader upserts against: one ledger row per # (source, media). A second sighting of the same media is a no-op. UniqueConstraint( "source_id", "filehash", name="uq_subscribestar_seen_media_source_id" ), ) id: Mapped[int] = mapped_column(Integer, primary_key=True) source_id: Mapped[int] = mapped_column( ForeignKey("source.id", ondelete="CASCADE"), nullable=False, index=True ) filehash: Mapped[str] = mapped_column(String(128), nullable=False) post_id: Mapped[str | None] = mapped_column(String(64), nullable=True) seen_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, server_default=func.now() )