From 57cc097022ad44a3a4fbd75f25912e7d12a84eb3 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Mon, 14 Sep 2026 01:03:35 -0300 Subject: [PATCH] chore: Add Video ID validation to imported watched videos and improve SQL query --- src/invidious/routes/api/v1/authenticated.cr | 8 +++++--- src/invidious/user/imports.cr | 7 ++++++- src/invidious/users.cr | 14 ++------------ 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/invidious/routes/api/v1/authenticated.cr b/src/invidious/routes/api/v1/authenticated.cr index 11626a80..fa749a13 100644 --- a/src/invidious/routes/api/v1/authenticated.cr +++ b/src/invidious/routes/api/v1/authenticated.cr @@ -48,10 +48,12 @@ module Invidious::Routes::API::V1::Authenticated "{}" end Invidious::User::Import.from_invidious(user, body) - rescue + env.response.status_code = 204 + rescue ex : InfoException + return error_json(400, ex) + rescue ex + return error_json(500, ex) end - - env.response.status_code = 204 end def self.get_history(env) diff --git a/src/invidious/user/imports.cr b/src/invidious/user/imports.cr index c06c4ae9..02bb91f1 100644 --- a/src/invidious/user/imports.cr +++ b/src/invidious/user/imports.cr @@ -97,7 +97,12 @@ struct Invidious::User end if data["watch_history"]? - user.watched += data["watch_history"].as_a.map(&.as_s) + user.watched += data["watch_history"].as_a.map do |video_id| + video_id = video_id.as_s + # Sanity check for the imported video IDs + raise InvalidVideoID.new(video_id) unless validate_video_id(video_id) + video_id + end user.watched.reverse!.uniq!.reverse! Invidious::Database::Users.update_watch_history(user) end diff --git a/src/invidious/users.cr b/src/invidious/users.cr index 5158fc22..66dcb935 100644 --- a/src/invidious/users.cr +++ b/src/invidious/users.cr @@ -52,12 +52,7 @@ def get_subscription_feed(user, max_results = 40, page = 1) # Show latest video from a channel that a user hasn't watched # "unseen_only" isn't really correct here, more accurate would be "unwatched_only" - if user.watched.empty? - values = "'{}'" - else - values = "VALUES #{user.watched.map { |id| %(('#{id}')) }.join(",")}" - end - videos = PG_DB.query_all("SELECT DISTINCT ON (ucid) * FROM #{view_name} WHERE NOT id = ANY (#{values}) ORDER BY ucid, published DESC", as: ChannelVideo) + videos = PG_DB.query_all("SELECT DISTINCT ON (ucid) * FROM #{view_name} WHERE NOT id = ANY ($1::text[]) ORDER BY ucid, published DESC", user.watched, as: ChannelVideo) else # Show latest video from each channel @@ -69,12 +64,7 @@ def get_subscription_feed(user, max_results = 40, page = 1) if user.preferences.unseen_only # Only show unwatched - if user.watched.empty? - values = "'{}'" - else - values = "VALUES #{user.watched.map { |id| %(('#{id}')) }.join(",")}" - end - videos = PG_DB.query_all("SELECT * FROM #{view_name} WHERE NOT id = ANY (#{values}) ORDER BY published DESC LIMIT $1 OFFSET $2", limit, offset, as: ChannelVideo) + videos = PG_DB.query_all("SELECT * FROM #{view_name} WHERE NOT id = ANY ($1::text[]) ORDER BY published DESC LIMIT $2 OFFSET $3", user.watched, limit, offset, as: ChannelVideo) else # Sort subscriptions as normal