| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 |
- """Announcements from the Bambuddy maintainers, and who has read them.
- Fetched from a signed feed on GitHub (services/announcements.py). Only the ones
- that target this install are stored, and the feed is authoritative: a message
- withdrawn upstream is deleted here on the next fetch, together with its read
- markers.
- ``AnnouncementRead.user_id`` is nullable: with authentication off there are no
- users, and the install's read state is a single NULL-keyed row per message.
- """
- from __future__ import annotations
- from datetime import datetime
- from sqlalchemy import DateTime, ForeignKey, Integer, String, Text, UniqueConstraint, func
- from sqlalchemy.orm import Mapped, mapped_column
- from backend.app.core.database import Base
- class Announcement(Base):
- __tablename__ = "announcements"
- id: Mapped[int] = mapped_column(primary_key=True)
- # The feed's id for the message. Stable across edits upstream, so a corrected
- # typo does not come back as unread.
- public_id: Mapped[str] = mapped_column(String(64), unique=True, index=True)
- level: Mapped[str] = mapped_column(String(16)) # info | important | critical
- # JSON {"en": {"title", "body", "link_label"?}, ...}. Text for SQLite/Postgres
- # uniformity; the service serialises with json.dumps.
- texts: Mapped[str] = mapped_column(Text)
- link_url: Mapped[str | None] = mapped_column(String(500), nullable=True)
- # Naive UTC, like every other timestamp in Bambuddy.
- published_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
- expires_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
- created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
- class AnnouncementRead(Base):
- __tablename__ = "announcement_reads"
- __table_args__ = (UniqueConstraint("announcement_id", "user_id", name="uq_announcement_reads_user"),)
- id: Mapped[int] = mapped_column(primary_key=True)
- announcement_id: Mapped[int] = mapped_column(
- Integer, ForeignKey("announcements.id", ondelete="CASCADE"), index=True
- )
- user_id: Mapped[int | None] = mapped_column(
- Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=True, index=True
- )
- read_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
|