From 3f225e7647188f5e32aba6fa198748f4a8317f56 Mon Sep 17 00:00:00 2001 From: Mattias Tall Date: Tue, 26 May 2026 11:25:44 +0200 Subject: [PATCH] Add like count to videos Same pattern as view_count: model column, yt-dlp extraction, SQL select, VideoDetail field, startup migration, and display in Watch meta row. Co-Authored-By: Claude Sonnet 4.6 --- backend/database.py | 1 + backend/models.py | 1 + backend/routers/videos.py | 3 ++- backend/services/ytdlp.py | 1 + frontend/src/pages/Watch.jsx | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/database.py b/backend/database.py index b3c2725..1024ad0 100644 --- a/backend/database.py +++ b/backend/database.py @@ -84,6 +84,7 @@ def init_db(): try: # Column migrations — safe to run on every startup _add_column_if_missing(raw_conn, "videos", "view_count", "INTEGER") + _add_column_if_missing(raw_conn, "videos", "like_count", "INTEGER") raw_conn.commit() # executescript handles multi-statement SQL including trigger BEGIN...END blocks raw_conn.executescript(FTS_SETUP_SQL) diff --git a/backend/models.py b/backend/models.py index 2389a5b..b7aa343 100644 --- a/backend/models.py +++ b/backend/models.py @@ -61,6 +61,7 @@ class Video(Base): category = Column(String) chapters = Column(Text) # JSON array of {start_time, end_time, title} view_count = Column(Integer) + like_count = Column(Integer) class UserVideo(Base): diff --git a/backend/routers/videos.py b/backend/routers/videos.py index 85e7aac..cb65385 100644 --- a/backend/routers/videos.py +++ b/backend/routers/videos.py @@ -66,6 +66,7 @@ class VideoDetail(BaseModel): local_file_url: Optional[str] = None is_recommended: bool = False view_count: Optional[int] = None + like_count: Optional[int] = None model_config = {"from_attributes": True} @@ -422,7 +423,7 @@ def surprise_me( _VIDEO_SELECT = """ SELECT v.id, v.youtube_video_id, v.title, v.description, v.thumbnail_url, - v.duration_seconds, v.published_at, v.tags, v.category, v.view_count, + v.duration_seconds, v.published_at, v.tags, v.category, v.view_count, v.like_count, c.id AS channel_id, c.name AS channel_name, c.youtube_channel_id AS channel_youtube_id, COALESCE(uv.watched, 0) AS watched, COALESCE(uv.watch_progress_seconds, 0) AS watch_progress_seconds, diff --git a/backend/services/ytdlp.py b/backend/services/ytdlp.py index b0a53bd..b4792af 100644 --- a/backend/services/ytdlp.py +++ b/backend/services/ytdlp.py @@ -75,6 +75,7 @@ def _normalize_video(info: dict) -> dict: "category": info.get("category") or (info.get("categories") or [None])[0], "chapters": json.dumps(chapters) if chapters else None, "view_count": info.get("view_count"), + "like_count": info.get("like_count"), "channel": { "youtube_channel_id": info.get("channel_id"), "name": info.get("channel") or info.get("uploader", ""), diff --git a/frontend/src/pages/Watch.jsx b/frontend/src/pages/Watch.jsx index 116de0f..2a15a61 100644 --- a/frontend/src/pages/Watch.jsx +++ b/frontend/src/pages/Watch.jsx @@ -894,6 +894,7 @@ export default function Watch() {
{date && {date}} {video?.view_count > 0 && <>·{formatViews(video.view_count)}} + {video?.like_count > 0 && <>·👍 {formatViews(video.like_count).replace(" views", "")}} {video?.category && <>·{video.category}} {video?.duration_seconds && ( <>·