Add older content exploration: channel page + home feed Rediscover mode

Channel page:
- "Explore older videos" button fetches 100 videos at a time further back
  in the channel history using yt-dlp --playlist-start/--playlist-end
- "Fetch entire history" still available for full crawl
- Backend: /channels/{id}/explore?page=N endpoint + playlist offset support
  in fetch_channel_metadata(start_video=N)

Home feed:
- New "Rediscover" mode: older unwatched videos (90+ days old) from
  followed channels, randomly sampled then re-ranked by tag affinity

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 22:17:20 +02:00
parent 0b482b5d49
commit aa91156bbc
6 changed files with 131 additions and 10 deletions

View File

@@ -758,6 +758,54 @@ def index_channel_full(
return {"detail": "Full index started"}
@router.post("/{channel_id}/explore", status_code=status.HTTP_202_ACCEPTED)
def explore_channel_older(
channel_id: int,
page: int = 2,
background_tasks: BackgroundTasks = None,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Fetch a page of older videos from this channel (page 1 = newest 30, page 2 = next 100, etc.)."""
_get_channel_or_404(db, channel_id)
start = 1 if page <= 1 else (30 + (page - 2) * 100 + 1)
background_tasks.add_task(_index_channel_explore_task, channel_id, current_user.id, start, 100)
return {"detail": f"Fetching older videos (page {page})", "start": start}
def _index_channel_explore_task(channel_id: int, user_id: int, start_video: int, count: int):
from ..database import SessionLocal
db = SessionLocal()
try:
channel = db.query(Channel).filter_by(id=channel_id).first()
if not channel:
return
result = ytdlp.fetch_channel_metadata(channel.youtube_channel_id, max_videos=count, start_video=start_video)
if not result:
return
for vdata in result.get("videos", []):
yt_id = vdata.get("youtube_video_id")
if not yt_id or not vdata.get("published_at"):
continue
if not db.query(Video).filter_by(youtube_video_id=yt_id).first():
db.add(Video(
youtube_video_id=yt_id,
channel_id=channel.id,
title=vdata.get("title", ""),
description=vdata.get("description"),
thumbnail_url=vdata.get("thumbnail_url"),
duration_seconds=vdata.get("duration_seconds"),
published_at=vdata.get("published_at"),
tags=vdata.get("tags"),
category=vdata.get("category"),
))
db.commit()
except Exception:
db.rollback()
finally:
db.close()
@router.post("/follow-bulk", status_code=200)
def follow_bulk(
body: dict,