Popular tab now shows only flagged popular videos in rank order
Add channel_popular_videos table (channel_id, video_id, rank).
_fetch_popular_task clears and rewrites this table after each fetch.
GET /channels/{id}/videos?sort=popular now JOINs this table and orders
by rank instead of view_count, so the tab shows exactly the videos
YouTube returned in popularity order — nothing more.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -87,6 +87,14 @@ def on_startup():
|
||||
crawled_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)""",
|
||||
"ALTER TABLE playlists ADD COLUMN video_ids TEXT",
|
||||
"""CREATE TABLE IF NOT EXISTS channel_popular_videos (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
channel_id INTEGER NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
|
||||
video_id INTEGER NOT NULL REFERENCES videos(id) ON DELETE CASCADE,
|
||||
rank INTEGER NOT NULL,
|
||||
fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(channel_id, video_id)
|
||||
)""",
|
||||
"""CREATE TABLE IF NOT EXISTS search_history (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
|
||||
@@ -612,18 +612,35 @@ def get_channel_videos(
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
_get_channel_or_404(db, channel_id)
|
||||
order = {
|
||||
"newest": "v.published_at DESC NULLS LAST",
|
||||
"oldest": "v.published_at ASC NULLS LAST",
|
||||
"title": "v.title ASC",
|
||||
"unwatched":"COALESCE(uv.watched, 0) ASC, v.published_at DESC NULLS LAST",
|
||||
"popular": "v.view_count DESC NULLS LAST",
|
||||
}.get(sort, "v.published_at DESC NULLS LAST")
|
||||
params: dict = {"user_id": current_user.id, "channel_id": channel_id, "limit": limit, "offset": offset}
|
||||
q_clause = ""
|
||||
if q.strip():
|
||||
q_clause = "AND (v.title LIKE :q OR v.description LIKE :q)"
|
||||
params["q"] = f"%{q.strip()}%"
|
||||
|
||||
if sort == "popular":
|
||||
rows = db.execute(
|
||||
text(f"""
|
||||
SELECT v.id, v.youtube_video_id, v.title, v.thumbnail_url,
|
||||
v.duration_seconds, v.published_at, v.view_count,
|
||||
COALESCE(uv.downloaded, 0) AS is_downloaded,
|
||||
COALESCE(uv.watched, 0) AS is_watched
|
||||
FROM channel_popular_videos cpv
|
||||
JOIN videos v ON cpv.video_id = v.id
|
||||
LEFT JOIN user_videos uv ON v.id = uv.video_id AND uv.user_id = :user_id
|
||||
WHERE cpv.channel_id = :channel_id {q_clause}
|
||||
ORDER BY cpv.rank ASC
|
||||
LIMIT :limit OFFSET :offset
|
||||
"""),
|
||||
params,
|
||||
).mappings().all()
|
||||
else:
|
||||
order = {
|
||||
"newest": "v.published_at DESC NULLS LAST",
|
||||
"oldest": "v.published_at ASC NULLS LAST",
|
||||
"title": "v.title ASC",
|
||||
"unwatched":"COALESCE(uv.watched, 0) ASC, v.published_at DESC NULLS LAST",
|
||||
}.get(sort, "v.published_at DESC NULLS LAST")
|
||||
rows = db.execute(
|
||||
text(f"""
|
||||
SELECT v.id, v.youtube_video_id, v.title, v.thumbnail_url,
|
||||
@@ -705,7 +722,12 @@ def _fetch_popular_task(channel_id: int, youtube_channel_id: str):
|
||||
channel = db.query(Channel).filter_by(id=channel_id).first()
|
||||
if not channel:
|
||||
return
|
||||
for yt_id in video_ids:
|
||||
|
||||
# Clear previous popular list for this channel
|
||||
db.execute(text("DELETE FROM channel_popular_videos WHERE channel_id = :cid"), {"cid": channel_id})
|
||||
db.commit()
|
||||
|
||||
for rank, yt_id in enumerate(video_ids, start=1):
|
||||
meta = results.get(yt_id)
|
||||
if not meta:
|
||||
continue
|
||||
@@ -716,8 +738,9 @@ def _fetch_popular_task(channel_id: int, youtube_channel_id: str):
|
||||
existing.view_count = meta["view_count"]
|
||||
if meta.get("published_at") and not existing.published_at:
|
||||
existing.published_at = meta["published_at"]
|
||||
video_id = existing.id
|
||||
else:
|
||||
db.add(Video(
|
||||
v = Video(
|
||||
youtube_video_id=yt_id,
|
||||
channel_id=channel.id,
|
||||
title=meta.get("title", ""),
|
||||
@@ -726,7 +749,18 @@ def _fetch_popular_task(channel_id: int, youtube_channel_id: str):
|
||||
published_at=meta.get("published_at"),
|
||||
tags=meta.get("tags") or "[]",
|
||||
view_count=meta.get("view_count"),
|
||||
))
|
||||
)
|
||||
db.add(v)
|
||||
db.flush()
|
||||
video_id = v.id
|
||||
db.execute(
|
||||
text("""
|
||||
INSERT INTO channel_popular_videos (channel_id, video_id, rank)
|
||||
VALUES (:cid, :vid, :rank)
|
||||
ON CONFLICT(channel_id, video_id) DO UPDATE SET rank = :rank
|
||||
"""),
|
||||
{"cid": channel_id, "vid": video_id, "rank": rank},
|
||||
)
|
||||
db.commit()
|
||||
except Exception:
|
||||
db.rollback()
|
||||
|
||||
Reference in New Issue
Block a user