From 8fb41383e6b92ebced7966bd6943c9742d0952f2 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Sat, 11 Jul 2026 18:11:23 +0200 Subject: [PATCH] =?UTF-8?q?chore(channels):=20Phase=202=20#3=20backend=20c?= =?UTF-8?q?leanup=20=E2=80=94=20extract=20blocked=20+=20summary=20helpers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Extract _is_blocked(db, user, channel_id): the BlockedChannel EXISTS query was copy-pasted in channel_detail, explore_channel, and block_channel. - Extract _channel_summary(ch): the shared id/title/handle/thumbnail/subscriber/ video_count projection was hand-rolled in list_channels and discover_channels (the detail dict interleaves these with extras, so it's left as-is). Behavior-neutral. ruff clean, localdev boots healthy. --- backend/app/routes/channels.py | 58 ++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/backend/app/routes/channels.py b/backend/app/routes/channels.py index adfa4b8..bdb5230 100644 --- a/backend/app/routes/channels.py +++ b/backend/app/routes/channels.py @@ -101,12 +101,7 @@ def list_channels( return [ { - "id": ch.id, - "title": ch.title, - "handle": ch.handle, - "thumbnail_url": ch.thumbnail_url, - "subscriber_count": ch.subscriber_count, - "video_count": ch.video_count, + **_channel_summary(ch), "stored_videos": (agg.get(ch.id) or {}).get("stored", 0), "last_video_at": (agg.get(ch.id) or {}).get("last_video_at"), "total_duration_seconds": (agg.get(ch.id) or {}).get("total_duration_seconds", 0), @@ -195,12 +190,7 @@ def discover_channels( return [ { - "id": ch.id, - "title": ch.title, - "handle": ch.handle, - "thumbnail_url": ch.thumbnail_url, - "subscriber_count": ch.subscriber_count, - "video_count": ch.video_count, + **_channel_summary(ch), "playlist_video_count": int(vid_count), "playlist_count": int(pl_count), "details_synced": ch.details_synced_at is not None, @@ -209,6 +199,18 @@ def discover_channels( ] +def _channel_summary(ch: Channel) -> dict: + """The channel fields common to the list and discovery projections.""" + return { + "id": ch.id, + "title": ch.title, + "handle": ch.handle, + "thumbnail_url": ch.thumbnail_url, + "subscriber_count": ch.subscriber_count, + "video_count": ch.video_count, + } + + def _channel_detail_dict( channel: Channel, *, subscribed: bool, explored: bool, blocked: bool, stored: int ) -> dict: @@ -268,11 +270,7 @@ def channel_detail( ExploredChannel.user_id == user.id, ExploredChannel.channel_id == channel_id ) ).first() is not None - blocked = db.execute( - select(BlockedChannel.id).where( - BlockedChannel.user_id == user.id, BlockedChannel.channel_id == channel_id - ) - ).first() is not None + blocked = _is_blocked(db, user, channel_id) stored = db.scalar(select(func.count(Video.id)).where(Video.channel_id == channel_id)) or 0 return _channel_detail_dict( channel, subscribed=subscribed, explored=explored, blocked=blocked, stored=int(stored) @@ -295,11 +293,7 @@ def explore_channel( channel = db.get(Channel, channel_id) if channel is None: raise HTTPException(status_code=404, detail="Unknown channel") - if db.execute( - select(BlockedChannel.id).where( - BlockedChannel.user_id == user.id, BlockedChannel.channel_id == channel_id - ) - ).first() is not None: + if _is_blocked(db, user, channel_id): raise HTTPException(status_code=403, detail="You've blocked this channel.") if quota.remaining_today(db) <= sysconfig.get_int(db, "backfill_quota_reserve"): raise HTTPException( @@ -359,6 +353,19 @@ def _user_subscription(db: Session, user: User, channel_id: str) -> Subscription return sub +def _is_blocked(db: Session, user: User, channel_id: str) -> bool: + """Whether this user has blocked this channel.""" + return ( + db.execute( + select(BlockedChannel.id).where( + BlockedChannel.user_id == user.id, + BlockedChannel.channel_id == channel_id, + ) + ).first() + is not None + ) + + @router.patch("/{channel_id}") def update_channel( channel_id: str, @@ -546,12 +553,7 @@ def block_channel( un-kept search/explore videos are reclaimed by the discovery-cleanup job in due course.""" if db.get(Channel, channel_id) is None: raise HTTPException(status_code=404, detail="Unknown channel") - exists = db.execute( - select(BlockedChannel.id).where( - BlockedChannel.user_id == user.id, BlockedChannel.channel_id == channel_id - ) - ).first() - if exists is None: + if not _is_blocked(db, user, channel_id): db.add(BlockedChannel(user_id=user.id, channel_id=channel_id)) # Stop any active exploration of it so it can be cleaned up. db.execute(