feat(downloads): store + show a canonical "downloaded from" source URL

Every download now records the clean source page URL and shows it on the
Downloads page (open in a new tab, or copy to clipboard). The worker stores
yt-dlp's canonical webpage_url on the asset (migration 0043 adds
media_assets.source_webpage_url); the serializer prefers it and falls back to a
URL derived from source_kind+source_ref, so YouTube, external YouTube links and
external URLs (e.g. Facebook reels) all get a correct reference, and queued/older
rows work before the worker fills it. Edit clips return null (a clip's source is
the user's own earlier download, not a web page). i18n en/hu/de.
This commit is contained in:
npeter83 2026-07-04 21:25:37 +02:00
parent 0e1b24a93c
commit 42d465d760
9 changed files with 115 additions and 0 deletions

View file

@ -0,0 +1,27 @@
"""canonical source webpage URL on media assets
Revision ID: 0043_asset_source_url
Revises: 0042_download_links
Create Date: 2026-07-04
Stores yt-dlp's canonical `webpage_url` for a download's source, so the Downloads page can show a
clean "downloaded from" reference (copyable + openable). Nullable filled by the worker on
extraction; existing/queued rows fall back to a URL derived from source_kind+source_ref.
"""
from typing import Sequence, Union
import sqlalchemy as sa
from alembic import op
revision: str = "0043_asset_source_url"
down_revision: Union[str, None] = "0042_download_links"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
op.add_column("media_assets", sa.Column("source_webpage_url", sa.Text(), nullable=True))
def downgrade() -> None:
op.drop_column("media_assets", "source_webpage_url")