diff --git a/patches/6-disable-notifications.patch b/patches/6-disable-notifications.patch new file mode 100644 index 0000000..200de9c --- /dev/null +++ b/patches/6-disable-notifications.patch @@ -0,0 +1,32 @@ +From 09e382465cebd61aa7a8b67b0a87a939e8ab5a03 Mon Sep 17 00:00:00 2001 +From: Emilien Devos +Date: Wed, 26 Jan 2022 21:47:00 +0100 +Subject: [PATCH 1/1] disable notifications + +--- + src/invidious/database/users.cr | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/src/invidious/database/users.cr b/src/invidious/database/users.cr +index 53724dbf..3752a213 100644 +--- a/src/invidious/database/users.cr ++++ b/src/invidious/database/users.cr +@@ -127,7 +127,6 @@ module Invidious::Database::Users + WHERE $2 = ANY(subscriptions) + SQL + +- PG_DB.exec(request, video.id, video.ucid) + end + + def remove_notification(user : User, vid : String) +@@ -137,7 +136,6 @@ module Invidious::Database::Users + WHERE email = $2 + SQL + +- PG_DB.exec(request, vid, user.email) + end + + def clear_notifications(user : User) +-- +2.34.1 + diff --git a/patches/7-range-header.patch b/patches/7-range-header.patch new file mode 100644 index 0000000..dc67697 --- /dev/null +++ b/patches/7-range-header.patch @@ -0,0 +1,29 @@ +From fe858211e382daa8acefc61bbfbc26a5925d521c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=89milien=20Devos?= +Date: Thu, 28 Apr 2022 09:48:19 +0000 +Subject: [PATCH 1/1] use range query string instead of header + +--- + assets/js/player.js | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/assets/js/player.js b/assets/js/player.js +index 6ddb1158..94e2c9a9 100644 +--- a/assets/js/player.js ++++ b/assets/js/player.js +@@ -42,6 +42,12 @@ embed_url = location.origin + '/embed/' + video_data.id + embed_url.search; + var save_player_pos_key = 'save_player_pos'; + + videojs.Vhs.xhr.beforeRequest = function(options) { ++ if (options.headers){ ++ if (options.headers.Range) { ++ options.uri = options.uri + '&range=' + options.headers.Range.split("=")[1]; ++ delete options.headers.Range; ++ } ++ } + if (options.uri.indexOf('videoplayback') === -1 && options.uri.indexOf('local=true') === -1) { + options.uri = options.uri + '?local=true'; + } +-- +2.35.1 + diff --git a/patches/8-have-video-data-separated-per-node-name.patch b/patches/8-have-video-data-separated-per-node-name.patch new file mode 100644 index 0000000..9b89674 --- /dev/null +++ b/patches/8-have-video-data-separated-per-node-name.patch @@ -0,0 +1,65 @@ +From c766804112ac85680a18e86c4a82f8504fc4959e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=89milien=20Devos?= +Date: Sat, 23 Apr 2022 18:35:53 +0000 +Subject: [PATCH 1/1] have video data separated per node name + +--- + src/invidious/database/videos.cr | 9 +++++---- + src/invidious/videos.cr | 1 + + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/src/invidious/database/videos.cr b/src/invidious/database/videos.cr +index e1fa01c3..e02b4de8 100644 +--- a/src/invidious/database/videos.cr ++++ b/src/invidious/database/videos.cr +@@ -10,7 +10,7 @@ module Invidious::Database::Videos + ON CONFLICT (id) DO NOTHING + SQL + +- PG_DB.exec(request, video.id, video.info.to_json, video.updated) ++ PG_DB.exec(request, video.id + "-" + ENV.fetch("NODE_NAME", ""), video.info.to_json, video.updated) + end + + def delete(id) +@@ -19,7 +19,7 @@ module Invidious::Database::Videos + WHERE id = $1 + SQL + +- PG_DB.exec(request, id) ++ PG_DB.exec(request, id + "-" + ENV.fetch("NODE_NAME", "")) + end + + def update(video : Video) +@@ -29,7 +29,7 @@ module Invidious::Database::Videos + WHERE id = $1 + SQL + +- PG_DB.exec(request, video.id, video.info.to_json, video.updated) ++ PG_DB.exec(request, video.id + "-" + ENV.fetch("NODE_NAME", ""), video.info.to_json, video.updated) + end + + def select(id : String) : Video? +@@ -38,6 +38,7 @@ module Invidious::Database::Videos + WHERE id = $1 + SQL + +- return PG_DB.query_one?(request, id, as: Video) ++ #puts (PG_DB.query_one?(request, id + "-" + ENV.fetch("NODE_NAME", ""), as: Video))["id"] ++ return PG_DB.query_one?(request, id + "-" + ENV.fetch("NODE_NAME", ""), as: Video) + end + end +diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr +index 31ae90c7..1d0ff0ba 100644 +--- a/src/invidious/videos.cr ++++ b/src/invidious/videos.cr +@@ -1093,6 +1093,7 @@ def get_video(id, refresh = true, region = nil, force_refresh = false) + Invidious::Database::Videos.insert(video) if !region + end + ++ video.id = id + return video + rescue DB::Error + # Avoid common `DB::PoolRetryAttemptsExceeded` error and friends +-- +2.35.1 + diff --git a/patches/9-404.patch b/patches/9-404.patch new file mode 100644 index 0000000..1db1bca --- /dev/null +++ b/patches/9-404.patch @@ -0,0 +1,393 @@ +From c201ea53ba4b82195d9b3cd7dd939b93802d7a12 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=89milien=20Devos?= +Date: Fri, 27 May 2022 13:36:13 +0000 +Subject: [PATCH] Add 404 status code on all possible endpoints + +--- + src/invidious/channels/about.cr | 7 ++++++- + src/invidious/channels/community.cr | 8 ++++++-- + src/invidious/comments.cr | 4 ++-- + src/invidious/exceptions.cr | 4 ++++ + src/invidious/playlists.cr | 2 +- + src/invidious/routes/api/manifest.cr | 2 ++ + src/invidious/routes/api/v1/authenticated.cr | 2 ++ + src/invidious/routes/api/v1/channels.cr | 6 ++++++ + src/invidious/routes/api/v1/videos.cr | 8 ++++++++ + src/invidious/routes/channels.cr | 9 +++++++-- + src/invidious/routes/embed.cr | 6 ++++++ + src/invidious/routes/feeds.cr | 2 ++ + src/invidious/routes/playlists.cr | 14 +++++++++++++- + src/invidious/routes/video_playback.cr | 8 +++++++- + src/invidious/routes/watch.cr | 3 +++ + src/invidious/videos.cr | 6 +++++- + 16 files changed, 80 insertions(+), 11 deletions(-) + +diff --git a/src/invidious/channels/about.cr b/src/invidious/channels/about.cr +index da71e9a8c..31b19bbe1 100644 +--- a/src/invidious/channels/about.cr ++++ b/src/invidious/channels/about.cr +@@ -31,7 +31,12 @@ def get_about_info(ucid, locale) : AboutChannel + end + + if initdata.dig?("alerts", 0, "alertRenderer", "type") == "ERROR" +- raise InfoException.new(initdata["alerts"][0]["alertRenderer"]["text"]["simpleText"].as_s) ++ error_message = initdata["alerts"][0]["alertRenderer"]["text"]["simpleText"].as_s ++ if error_message == "This channel does not exist." ++ raise NotFoundException.new(error_message) ++ else ++ raise InfoException.new(error_message) ++ end + end + + if browse_endpoint = initdata["onResponseReceivedActions"]?.try &.[0]?.try &.["navigateAction"]?.try &.["endpoint"]?.try &.["browseEndpoint"]? +diff --git a/src/invidious/channels/community.cr b/src/invidious/channels/community.cr +index 4701ecbd6..ebef0edba 100644 +--- a/src/invidious/channels/community.cr ++++ b/src/invidious/channels/community.cr +@@ -6,7 +6,7 @@ def fetch_channel_community(ucid, continuation, locale, format, thin_mode) + end + + if response.status_code != 200 +- raise InfoException.new("This channel does not exist.") ++ raise NotFoundException.new("This channel does not exist.") + end + + ucid = response.body.match(/https:\/\/www.youtube.com\/channel\/(?UC[a-zA-Z0-9_-]{22})/).not_nil!["ucid"] +@@ -49,7 +49,11 @@ def fetch_channel_community(ucid, continuation, locale, format, thin_mode) + error_message = (message["text"]["simpleText"]? || + message["text"]["runs"]?.try &.[0]?.try &.["text"]?) + .try &.as_s || "" +- raise InfoException.new(error_message) ++ if error_message == "This channel does not exist." ++ raise NotFoundException.new(error_message) ++ else ++ raise InfoException.new(error_message) ++ end + end + + response = JSON.build do |json| +diff --git a/src/invidious/comments.cr b/src/invidious/comments.cr +index d84969784..f2e632659 100644 +--- a/src/invidious/comments.cr ++++ b/src/invidious/comments.cr +@@ -95,7 +95,7 @@ def fetch_youtube_comments(id, cursor, format, locale, thin_mode, region, sort_b + contents = body["contents"]? + header = body["header"]? + else +- raise InfoException.new("Could not fetch comments") ++ raise NotFoundException.new("Comments not found.") + end + + if !contents +@@ -290,7 +290,7 @@ def fetch_reddit_comments(id, sort_by = "confidence") + + thread = result[0].data.as(RedditListing).children[0].data.as(RedditLink) + else +- raise InfoException.new("Could not fetch comments") ++ raise NotFoundException.new("Comments not found.") + end + + client.close +diff --git a/src/invidious/exceptions.cr b/src/invidious/exceptions.cr +index bfaa3fd5d..1706ba6a8 100644 +--- a/src/invidious/exceptions.cr ++++ b/src/invidious/exceptions.cr +@@ -18,3 +18,7 @@ class BrokenTubeException < Exception + return "Missing JSON element \"#{@element}\"" + end + end ++ ++# Exception used to hold the bogus UCID during a channel search. ++class NotFoundException < InfoException ++end +diff --git a/src/invidious/playlists.cr b/src/invidious/playlists.cr +index aefa34ccc..c4eb75078 100644 +--- a/src/invidious/playlists.cr ++++ b/src/invidious/playlists.cr +@@ -317,7 +317,7 @@ def get_playlist(plid : String) + if playlist = Invidious::Database::Playlists.select(id: plid) + return playlist + else +- raise InfoException.new("Playlist does not exist.") ++ raise NotFoundException.new("Playlist does not exist.") + end + else + return fetch_playlist(plid) +diff --git a/src/invidious/routes/api/manifest.cr b/src/invidious/routes/api/manifest.cr +index 8bc36946b..f8766b660 100644 +--- a/src/invidious/routes/api/manifest.cr ++++ b/src/invidious/routes/api/manifest.cr +@@ -16,6 +16,8 @@ module Invidious::Routes::API::Manifest + video = get_video(id, region: region) + rescue ex : VideoRedirect + return env.redirect env.request.resource.gsub(id, ex.video_id) ++ rescue ex : NotFoundException ++ haltf env, status_code: 404 + rescue ex + haltf env, status_code: 403 + end +diff --git a/src/invidious/routes/api/v1/authenticated.cr b/src/invidious/routes/api/v1/authenticated.cr +index b559a01a0..1f5ad8eff 100644 +--- a/src/invidious/routes/api/v1/authenticated.cr ++++ b/src/invidious/routes/api/v1/authenticated.cr +@@ -237,6 +237,8 @@ module Invidious::Routes::API::V1::Authenticated + + begin + video = get_video(video_id) ++ rescue ex : NotFoundException ++ return error_json(404, ex) + rescue ex + return error_json(500, ex) + end +diff --git a/src/invidious/routes/api/v1/channels.cr b/src/invidious/routes/api/v1/channels.cr +index 8650976d5..6b81c5461 100644 +--- a/src/invidious/routes/api/v1/channels.cr ++++ b/src/invidious/routes/api/v1/channels.cr +@@ -13,6 +13,8 @@ module Invidious::Routes::API::V1::Channels + rescue ex : ChannelRedirect + env.response.headers["Location"] = env.request.resource.gsub(ucid, ex.channel_id) + return error_json(302, "Channel is unavailable", {"authorId" => ex.channel_id}) ++ rescue ex : NotFoundException ++ return error_json(404, ex) + rescue ex + return error_json(500, ex) + end +@@ -170,6 +172,8 @@ module Invidious::Routes::API::V1::Channels + rescue ex : ChannelRedirect + env.response.headers["Location"] = env.request.resource.gsub(ucid, ex.channel_id) + return error_json(302, "Channel is unavailable", {"authorId" => ex.channel_id}) ++ rescue ex : NotFoundException ++ return error_json(404, ex) + rescue ex + return error_json(500, ex) + end +@@ -205,6 +209,8 @@ module Invidious::Routes::API::V1::Channels + rescue ex : ChannelRedirect + env.response.headers["Location"] = env.request.resource.gsub(ucid, ex.channel_id) + return error_json(302, "Channel is unavailable", {"authorId" => ex.channel_id}) ++ rescue ex : NotFoundException ++ return error_json(404, ex) + rescue ex + return error_json(500, ex) + end +diff --git a/src/invidious/routes/api/v1/videos.cr b/src/invidious/routes/api/v1/videos.cr +index a9f891f5a..1b7b4fa70 100644 +--- a/src/invidious/routes/api/v1/videos.cr ++++ b/src/invidious/routes/api/v1/videos.cr +@@ -12,6 +12,8 @@ module Invidious::Routes::API::V1::Videos + rescue ex : VideoRedirect + env.response.headers["Location"] = env.request.resource.gsub(id, ex.video_id) + return error_json(302, "Video is unavailable", {"videoId" => ex.video_id}) ++ rescue ex : NotFoundException ++ return error_json(404, ex) + rescue ex + return error_json(500, ex) + end +@@ -42,6 +44,8 @@ module Invidious::Routes::API::V1::Videos + rescue ex : VideoRedirect + env.response.headers["Location"] = env.request.resource.gsub(id, ex.video_id) + return error_json(302, "Video is unavailable", {"videoId" => ex.video_id}) ++ rescue ex : NotFoundException ++ haltf env, 404 + rescue ex + haltf env, 500 + end +@@ -167,6 +171,8 @@ module Invidious::Routes::API::V1::Videos + rescue ex : VideoRedirect + env.response.headers["Location"] = env.request.resource.gsub(id, ex.video_id) + return error_json(302, "Video is unavailable", {"videoId" => ex.video_id}) ++ rescue ex : NotFoundException ++ haltf env, 404 + rescue ex + haltf env, 500 + end +@@ -324,6 +330,8 @@ module Invidious::Routes::API::V1::Videos + + begin + comments = fetch_youtube_comments(id, continuation, format, locale, thin_mode, region, sort_by: sort_by) ++ rescue ex : NotFoundException ++ return error_json(404, ex) + rescue ex + return error_json(500, ex) + end +diff --git a/src/invidious/routes/channels.cr b/src/invidious/routes/channels.cr +index cd2e33239..c6e02cbd6 100644 +--- a/src/invidious/routes/channels.cr ++++ b/src/invidious/routes/channels.cr +@@ -85,6 +85,9 @@ module Invidious::Routes::Channels + rescue ex : InfoException + env.response.status_code = 500 + error_message = ex.message ++ rescue ex : NotFoundException ++ env.response.status_code = 404 ++ error_message = ex.message + rescue ex + return error_template(500, ex) + end +@@ -118,7 +121,7 @@ module Invidious::Routes::Channels + resolved_url = YoutubeAPI.resolve_url("https://youtube.com#{env.request.path}#{yt_url_params.size > 0 ? "?#{yt_url_params}" : ""}") + ucid = resolved_url["endpoint"]["browseEndpoint"]["browseId"] + rescue ex : InfoException | KeyError +- raise InfoException.new(translate(locale, "This channel does not exist.")) ++ return error_template(404, translate(locale, "This channel does not exist.")) + end + + selected_tab = env.request.path.split("/")[-1] +@@ -141,7 +144,7 @@ module Invidious::Routes::Channels + + user = env.params.query["user"]? + if !user +- raise InfoException.new("This channel does not exist.") ++ return error_template(404, "This channel does not exist.") + else + env.redirect "/user/#{user}#{uri_params}" + end +@@ -197,6 +200,8 @@ module Invidious::Routes::Channels + channel = get_about_info(ucid, locale) + rescue ex : ChannelRedirect + return env.redirect env.request.resource.gsub(ucid, ex.channel_id) ++ rescue ex : NotFoundException ++ return error_template(404, ex) + rescue ex + return error_template(500, ex) + end +diff --git a/src/invidious/routes/embed.cr b/src/invidious/routes/embed.cr +index 207970b09..84da9993c 100644 +--- a/src/invidious/routes/embed.cr ++++ b/src/invidious/routes/embed.cr +@@ -7,6 +7,8 @@ module Invidious::Routes::Embed + playlist = get_playlist(plid) + offset = env.params.query["index"]?.try &.to_i? || 0 + videos = get_playlist_videos(playlist, offset: offset) ++ rescue ex : NotFoundException ++ return error_template(404, ex) + rescue ex + return error_template(500, ex) + end +@@ -60,6 +62,8 @@ module Invidious::Routes::Embed + playlist = get_playlist(plid) + offset = env.params.query["index"]?.try &.to_i? || 0 + videos = get_playlist_videos(playlist, offset: offset) ++ rescue ex : NotFoundException ++ return error_template(404, ex) + rescue ex + return error_template(500, ex) + end +@@ -119,6 +123,8 @@ module Invidious::Routes::Embed + video = get_video(id, region: params.region) + rescue ex : VideoRedirect + return env.redirect env.request.resource.gsub(id, ex.video_id) ++ rescue ex : NotFoundException ++ return error_template(404, ex) + rescue ex + return error_template(500, ex) + end +diff --git a/src/invidious/routes/feeds.cr b/src/invidious/routes/feeds.cr +index b5b583996..31120ecb0 100644 +--- a/src/invidious/routes/feeds.cr ++++ b/src/invidious/routes/feeds.cr +@@ -150,6 +150,8 @@ module Invidious::Routes::Feeds + channel = get_about_info(ucid, locale) + rescue ex : ChannelRedirect + return env.redirect env.request.resource.gsub(ucid, ex.channel_id) ++ rescue ex : NotFoundException ++ return error_atom(404, ex) + rescue ex + return error_atom(500, ex) + end +diff --git a/src/invidious/routes/playlists.cr b/src/invidious/routes/playlists.cr +index de981d81c..fe7e4e1c9 100644 +--- a/src/invidious/routes/playlists.cr ++++ b/src/invidious/routes/playlists.cr +@@ -66,7 +66,13 @@ module Invidious::Routes::Playlists + user = user.as(User) + + playlist_id = env.params.query["list"] +- playlist = get_playlist(playlist_id) ++ begin ++ playlist = get_playlist(playlist_id) ++ rescue ex : NotFoundException ++ return error_template(404, ex) ++ rescue ex ++ return error_template(500, ex) ++ end + subscribe_playlist(user, playlist) + + env.redirect "/playlist?list=#{playlist.id}" +@@ -304,6 +310,8 @@ module Invidious::Routes::Playlists + playlist_id = env.params.query["playlist_id"] + playlist = get_playlist(playlist_id).as(InvidiousPlaylist) + raise "Invalid user" if playlist.author != user.email ++ rescue ex : NotFoundException ++ return error_json(404, ex) + rescue ex + if redirect + return error_template(400, ex) +@@ -334,6 +342,8 @@ module Invidious::Routes::Playlists + + begin + video = get_video(video_id) ++ rescue ex : NotFoundException ++ return error_json(404, ex) + rescue ex + if redirect + return error_template(500, ex) +@@ -394,6 +404,8 @@ module Invidious::Routes::Playlists + + begin + playlist = get_playlist(plid) ++ rescue ex : NotFoundException ++ return error_template(404, ex) + rescue ex + return error_template(500, ex) + end +diff --git a/src/invidious/routes/video_playback.cr b/src/invidious/routes/video_playback.cr +index 3a92ef969..560f9c19a 100644 +--- a/src/invidious/routes/video_playback.cr ++++ b/src/invidious/routes/video_playback.cr +@@ -265,7 +265,13 @@ module Invidious::Routes::VideoPlayback + return error_template(403, "Administrator has disabled this endpoint.") + end + +- video = get_video(id, region: region) ++ begin ++ video = get_video(id, region: region) ++ rescue ex : NotFoundException ++ return error_template(404, ex) ++ rescue ex ++ return error_template(500, ex) ++ end + + fmt = video.fmt_stream.find(nil) { |f| f["itag"].as_i == itag } || video.adaptive_fmts.find(nil) { |f| f["itag"].as_i == itag } + url = fmt.try &.["url"]?.try &.as_s +diff --git a/src/invidious/routes/watch.cr b/src/invidious/routes/watch.cr +index 7280de4f2..fe1d8e548 100644 +--- a/src/invidious/routes/watch.cr ++++ b/src/invidious/routes/watch.cr +@@ -63,6 +63,9 @@ module Invidious::Routes::Watch + video = get_video(id, region: params.region) + rescue ex : VideoRedirect + return env.redirect env.request.resource.gsub(id, ex.video_id) ++ rescue ex : NotFoundException ++ LOGGER.error("get_video not found: #{id} : #{ex.message}") ++ return error_template(404, ex) + rescue ex + LOGGER.error("get_video: #{id} : #{ex.message}") + return error_template(500, ex) +diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr +index f65b05bb5..20204d815 100644 +--- a/src/invidious/videos.cr ++++ b/src/invidious/videos.cr +@@ -1159,7 +1159,11 @@ def fetch_video(id, region) + end + + if reason = info["reason"]? +- raise InfoException.new(reason.as_s || "") ++ if reason == "Video unavailable" ++ raise NotFoundException.new(reason.as_s || "") ++ else ++ raise InfoException.new(reason.as_s || "") ++ end + end + + video = Video.new({