feat: 1-to-1 message render + web data-lake backend

This commit is contained in:
h
2026-05-31 01:27:40 +02:00
parent f0afb7ec5b
commit 75425d1bee
110 changed files with 10199 additions and 54 deletions
@@ -0,0 +1,27 @@
"""media unique_id for edit detection
Revision ID: a9c3e7f1d2b4
Revises: f7a2c9e1b3d5
Create Date: 2026-05-30 04:00:00.000000
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
revision: str = "a9c3e7f1d2b4"
down_revision: str | None = "f7a2c9e1b3d5"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
op.add_column("media", sa.Column("unique_id", sa.String(), nullable=True))
op.add_column("media_versions", sa.Column("unique_id", sa.String(), nullable=True))
def downgrade() -> None:
op.drop_column("media_versions", "unique_id")
op.drop_column("media", "unique_id")
@@ -0,0 +1,56 @@
"""media versions (keep every edited media)
Revision ID: f7a2c9e1b3d5
Revises: a3f1c8e94d72
Create Date: 2026-05-30 03:00:00.000000
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
revision: str = "f7a2c9e1b3d5"
down_revision: str | None = "a3f1c8e94d72"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
op.create_table(
"media_versions",
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
sa.Column("account_id", sa.Integer(), nullable=False),
sa.Column("chat_id", sa.BigInteger(), nullable=False),
sa.Column("message_id", sa.BigInteger(), nullable=False),
sa.Column(
"observed_at",
sa.DateTime(timezone=True),
server_default=sa.text("now()"),
nullable=False,
),
sa.Column("kind", sa.String(), nullable=False),
sa.Column("storage_key", sa.String(), nullable=False),
sa.Column("file_size", sa.BigInteger(), nullable=True),
sa.Column("mime", sa.String(), nullable=True),
sa.Column("ttl_seconds", sa.Integer(), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint(
"account_id",
"chat_id",
"message_id",
"storage_key",
name="uq_media_versions_content",
),
)
op.create_index(
"ix_media_versions_message",
"media_versions",
["account_id", "chat_id", "message_id", "observed_at"],
)
def downgrade() -> None:
op.drop_index("ix_media_versions_message", table_name="media_versions")
op.drop_table("media_versions")