feat(channels): channel-explore backend — about metadata, ephemeral provenance, cleanup
Adds the backend for a dedicated channel page + ephemeral browsing of un-subscribed
channels:
- migration 0033: channels.{total_view_count,published_at,banner_url,external_links,
from_explore}, videos.via_explore, explored_channels (per-user, grace-clocked).
- enrich channels with part=brandingSettings (banner/links) + statistics.viewCount +
snippet.publishedAt — no extra quota.
- GET /api/channels/{id}: About detail + this user's relationship; lazy-enriches the new
About fields (published_at sentinel).
- POST /api/channels/{id}/explore (require_human, quota-reserve guarded): records the
exploration, flags the channel ephemeral unless followed, ingests one page of uploads
(via_explore) + enriches; returns next_page_token for load-more.
- feed: per-explorer gate — a via_explore video is visible only to users who explored or
subscribe to its channel, so exploration never leaks into everyone's catalog.
- subscribe = keep: clears from_explore + via_explore on the channel's videos.
- scheduler explore_cleanup job + explore_grace_days config: hard-delete explored-but-
unkept channels and their untouched ephemeral videos after a grace period.
This commit is contained in:
parent
bb7b9972fd
commit
bc4c362423
11 changed files with 481 additions and 4 deletions
|
|
@ -16,6 +16,7 @@ from app.models import SchedulerSetting
|
|||
from app.notifications import create_notification
|
||||
from app.state import is_sync_paused
|
||||
from app.sync.autotag import run_autotag_all
|
||||
from app.sync.explore import purge_unkept_explored
|
||||
from app.sync.maintenance import run_maintenance
|
||||
from app.sync.playlists import sync_all_playlists
|
||||
from app.sync.runner import (
|
||||
|
|
@ -57,6 +58,7 @@ JOB_INTERVALS: dict[str, int] = {
|
|||
"playlist_sync": settings.playlist_sync_minutes,
|
||||
"maintenance": settings.maintenance_interval_minutes,
|
||||
"demo_reset": settings.demo_reset_minutes,
|
||||
"explore_cleanup": settings.explore_cleanup_minutes,
|
||||
}
|
||||
|
||||
# Sane bounds for an admin-set interval (minutes).
|
||||
|
|
@ -268,6 +270,12 @@ def _demo_reset_job() -> None:
|
|||
_job("demo_reset", work)
|
||||
|
||||
|
||||
def _explore_cleanup_job() -> None:
|
||||
# Hard-delete explored-but-never-kept channels and their untouched ephemeral videos after
|
||||
# the grace period. 0 quota (pure DB), so no quota attribution.
|
||||
_job("explore_cleanup", purge_unkept_explored)
|
||||
|
||||
|
||||
# job_id -> wrapper. The single source of truth for which jobs exist and how to run one,
|
||||
# shared by start_scheduler (recurring registration) and trigger_job (manual "run now").
|
||||
JOB_FUNCS: dict[str, Callable[[], None]] = {
|
||||
|
|
@ -280,6 +288,7 @@ JOB_FUNCS: dict[str, Callable[[], None]] = {
|
|||
"playlist_sync": _playlist_sync_job,
|
||||
"maintenance": _maintenance_job,
|
||||
"demo_reset": _demo_reset_job,
|
||||
"explore_cleanup": _explore_cleanup_job,
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue