From 8b135eb774ea8a1782fc0b7f758839983ee22ad1 Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Fri, 13 Dec 2024 21:11:08 +0100 Subject: [PATCH] update patch PR 4985 --- patches/024-4985.patch | 540 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 525 insertions(+), 15 deletions(-) diff --git a/patches/024-4985.patch b/patches/024-4985.patch index 94f7f10..27096ee 100644 --- a/patches/024-4985.patch +++ b/patches/024-4985.patch @@ -1,7 +1,7 @@ From 3dff7a76cf9f64ec70aac0a057a3b0bfa1edfc82 Mon Sep 17 00:00:00 2001 From: Emilien Devos <4016501+unixfox@users.noreply.github.com> Date: Sun, 20 Oct 2024 02:10:55 +0200 -Subject: [PATCH 01/15] add support for invidious companion +Subject: [PATCH 01/20] add support for invidious companion --- config/config.example.yml | 16 ++++++++++ @@ -175,7 +175,7 @@ index 8f5aa61d3..8a90a76ed 100644 From 73c84baf9fa6eaf9c5d4981bc199f81306ebe5a2 Mon Sep 17 00:00:00 2001 From: Emilien Devos <4016501+unixfox@users.noreply.github.com> Date: Sun, 20 Oct 2024 23:51:00 +0200 -Subject: [PATCH 02/15] redirect latest_version and dash manifest to invidious +Subject: [PATCH 02/20] redirect latest_version and dash manifest to invidious companion --- @@ -393,7 +393,7 @@ index 8a90a76ed..de2050348 100644 From 195446337159d2cb92b48510af7311fe0cc0f5bb Mon Sep 17 00:00:00 2001 From: Emilien Devos <4016501+unixfox@users.noreply.github.com> Date: Sun, 20 Oct 2024 23:53:08 +0200 -Subject: [PATCH 03/15] fix Shadowing outer local variable `response` +Subject: [PATCH 03/20] fix Shadowing outer local variable `response` --- src/invidious/yt_backend/youtube_api.cr | 8 ++++---- @@ -423,7 +423,7 @@ index de2050348..b04942038 100644 From c612423a4d64f0adbef135074fc55dcc1c362f84 Mon Sep 17 00:00:00 2001 From: Emilien Devos <4016501+unixfox@users.noreply.github.com> Date: Mon, 21 Oct 2024 01:20:16 +0200 -Subject: [PATCH 04/15] fixing condition for Content-Security-Policy +Subject: [PATCH 04/20] fixing condition for Content-Security-Policy --- src/invidious/routes/watch.cr | 2 +- @@ -446,7 +446,7 @@ index 961d7b311..2cf8a725b 100644 From 2cc204a0457665f8e334970d7e54b1843a667ab6 Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Fri, 1 Nov 2024 21:30:58 +0100 -Subject: [PATCH 05/15] throw error if inv_sig_helper and invidious_companion +Subject: [PATCH 05/20] throw error if inv_sig_helper and invidious_companion used same time --- @@ -475,7 +475,7 @@ From 1c9f5b0a2b38ad94fb8972764ffae98df1e41dc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milien=20=28perso=29?= <4016501+unixfox@users.noreply.github.com> Date: Tue, 5 Nov 2024 15:31:21 +0100 -Subject: [PATCH 06/15] Use sample instead of Random.rand +Subject: [PATCH 06/20] Use sample instead of Random.rand Co-authored-by: syeopite <70992037+syeopite@users.noreply.github.com> --- @@ -500,7 +500,7 @@ From 27b24f51abcccd1c68f4dc1c29c0c62ca26e604c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milien=20=28perso=29?= <4016501+unixfox@users.noreply.github.com> Date: Tue, 5 Nov 2024 15:31:45 +0100 -Subject: [PATCH 07/15] Remove debug puts functions +Subject: [PATCH 07/20] Remove debug puts functions Co-authored-by: syeopite <70992037+syeopite@users.noreply.github.com> --- @@ -525,7 +525,7 @@ From 409df4cff3cc69c5565a12feb307441eed36f937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milien=20=28perso=29?= <4016501+unixfox@users.noreply.github.com> Date: Tue, 5 Nov 2024 15:50:59 +0100 -Subject: [PATCH 08/15] modify the description for config.example.yaml about +Subject: [PATCH 08/20] modify the description for config.example.yaml about invidious companion --- @@ -560,7 +560,7 @@ index 1e342382c..76a9a077c 100644 From ff3305d52175c517b035d79b3c0c6a84809cbd0f Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Fri, 8 Nov 2024 21:05:17 +0100 -Subject: [PATCH 09/15] move config checks for invidious companion +Subject: [PATCH 09/20] move config checks for invidious companion --- config/config.example.yml | 12 +++++++++++- @@ -650,7 +650,7 @@ index ba4224ced..7cd4bbdc9 100644 From 1aa154b9787eddcdee960d06aed4c1c91f17c1c3 Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Sat, 16 Nov 2024 22:33:28 +0100 -Subject: [PATCH 10/15] separate invidious_companion logic + better config.yaml +Subject: [PATCH 10/20] separate invidious_companion logic + better config.yaml config --- @@ -1057,7 +1057,7 @@ index 68abcf48d..6a0e50a1f 100644 From 9f846127aea9b4f392acb062d662fff2cc58d1d0 Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Sat, 16 Nov 2024 22:38:00 +0100 -Subject: [PATCH 11/15] fixing "end" misplacement +Subject: [PATCH 11/20] fixing "end" misplacement --- src/invidious/videos/parser.cr | 1 - @@ -1079,7 +1079,7 @@ index 24729beb5..7a73be682 100644 From b51770dbdbdcca04d04849d37e5f11ce20948c73 Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Sat, 16 Nov 2024 23:00:48 +0100 -Subject: [PATCH 12/15] fix linting + use .empty? +Subject: [PATCH 12/20] fix linting + use .empty? --- src/invidious/config.cr | 2 +- @@ -1120,7 +1120,7 @@ index 7a73be682..4d0e0378a 100644 From bb2e3b2a3e5f53610b9dd602f8507303ec641450 Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Sun, 17 Nov 2024 12:26:35 +0100 -Subject: [PATCH 13/15] crystal handle decompression already by itself +Subject: [PATCH 13/20] crystal handle decompression already by itself --- src/invidious/config.cr | 8 ++++---- @@ -1177,7 +1177,7 @@ index 6a0e50a1f..8fef84724 100644 From 734e72503f88f9741279ab385e86f5d2b340c71b Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Sun, 17 Nov 2024 19:18:29 +0100 -Subject: [PATCH 14/15] fix download function when invidious companion used +Subject: [PATCH 14/20] fix download function when invidious companion used --- src/invidious/routes/video_playback.cr | 5 +---- @@ -1238,7 +1238,7 @@ index 69780d78b..740a15b2e 100644 From 1f51edd0b915ca64df7f195aa271f74c7ef093cb Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Mon, 18 Nov 2024 12:22:23 +0100 -Subject: [PATCH 15/15] fix linting +Subject: [PATCH 15/20] fix linting --- src/invidious/yt_backend/youtube_api.cr | 4 ++-- @@ -1259,3 +1259,513 @@ index 8fef84724..09f0936fd 100644 } # Logging + +From 7a070fa710b7807cdda061d413ca9369a0962353 Mon Sep 17 00:00:00 2001 +From: Emilien <4016501+unixfox@users.noreply.github.com> +Date: Mon, 18 Nov 2024 12:30:37 +0100 +Subject: [PATCH 16/20] invidious companion always used so always add CSP and + redirect latest_version + +--- + src/invidious/routes/embed.cr | 2 +- + src/invidious/routes/watch.cr | 2 +- + src/invidious/views/components/player.ecr | 4 ++-- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/invidious/routes/embed.cr b/src/invidious/routes/embed.cr +index 23f2bbe1f..df6970011 100644 +--- a/src/invidious/routes/embed.cr ++++ b/src/invidious/routes/embed.cr +@@ -201,7 +201,7 @@ module Invidious::Routes::Embed + return env.redirect url + end + +- if (!CONFIG.invidious_companion.empty? && (preferences.local || preferences.quality == "dash")) ++ if (!CONFIG.invidious_companion.empty?) + env.response.headers["Content-Security-Policy"] = + env.response.headers["Content-Security-Policy"] + .gsub("media-src", "media-src " + video.invidious_companion.not_nil!["baseUrl"].as_s) +diff --git a/src/invidious/routes/watch.cr b/src/invidious/routes/watch.cr +index 740a15b2e..b42ee12dc 100644 +--- a/src/invidious/routes/watch.cr ++++ b/src/invidious/routes/watch.cr +@@ -190,7 +190,7 @@ module Invidious::Routes::Watch + captions: video.captions + ) + +- if (!CONFIG.invidious_companion.empty? && (preferences.local || preferences.quality == "dash")) ++ if (!CONFIG.invidious_companion.empty?) + env.response.headers["Content-Security-Policy"] = + env.response.headers["Content-Security-Policy"] + .gsub("media-src", "media-src " + video.invidious_companion.not_nil!["baseUrl"].as_s) +diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr +index 59f432391..46c00137f 100644 +--- a/src/invidious/views/components/player.ecr ++++ b/src/invidious/views/components/player.ecr +@@ -22,7 +22,7 @@ + audio_streams.each_with_index do |fmt, i| + src_url = "/latest_version?id=#{video.id}&itag=#{fmt["itag"]}" + src_url += "&local=true" if params.local +- src_url = video.invidious_companion.not_nil!["baseUrl"].as_s + src_url if (!CONFIG.invidious_companion.empty? && params.local) ++ src_url = video.invidious_companion.not_nil!["baseUrl"].as_s + src_url if (!CONFIG.invidious_companion.empty?) + + bitrate = fmt["bitrate"] + mimetype = HTML.escape(fmt["mimeType"].as_s) +@@ -48,7 +48,7 @@ + fmt_stream.each_with_index do |fmt, i| + src_url = "/latest_version?id=#{video.id}&itag=#{fmt["itag"]}" + src_url += "&local=true" if params.local +- src_url = video.invidious_companion.not_nil!["baseUrl"].as_s + src_url if (!CONFIG.invidious_companion.empty? && params.local) ++ src_url = video.invidious_companion.not_nil!["baseUrl"].as_s + src_url if (!CONFIG.invidious_companion.empty?) + + quality = fmt["quality"] + mimetype = HTML.escape(fmt["mimeType"].as_s) + +From f710dd37bf4327748b43067d75025cc915b5639c Mon Sep 17 00:00:00 2001 +From: Emilien <4016501+unixfox@users.noreply.github.com> +Date: Sun, 8 Dec 2024 22:21:10 +0100 +Subject: [PATCH 17/20] apply all the suggestions + rework invidious_companion + parameter + +--- + config/config.example.yml | 21 +++++++++++++----- + src/invidious/config.cr | 27 ++++++----------------- + src/invidious/routes/api/manifest.cr | 9 ++++---- + src/invidious/routes/embed.cr | 6 ++--- + src/invidious/routes/video_playback.cr | 3 ++- + src/invidious/routes/watch.cr | 12 +++++----- + src/invidious/videos.cr | 2 +- + src/invidious/views/components/player.ecr | 6 ++--- + src/invidious/yt_backend/youtube_api.cr | 15 ++++++------- + 9 files changed, 49 insertions(+), 52 deletions(-) + +diff --git a/config/config.example.yml b/config/config.example.yml +index 06e535415..2273c8398 100644 +--- a/config/config.example.yml ++++ b/config/config.example.yml +@@ -59,16 +59,27 @@ db: + ## for loading the video streams from YouTube servers. + ## + ## When this setting is commented out, Invidious companion is not used. +-## +-## When this setting is configured, then Invidious will proxy the requests +-## to Invidious companion. +-## Or randomly choose one if multiple Invidious companion are configured. ++## Otherwise, Invidious will proxy the requests to Invidious companion. ++## ++## Note: multiple URL can be configured. In this case, invidious will ++## randomly pick one every time video data needs to be retrieved. This ++## URL is then kept in the video metadata cache to allow video playback ++## to work. Once said cache has expired, requesting that video's data ++## again will cause a new companion URL to be picked. ++## ++## The parameter private_url needs to be configured for the internal ++## communication between the companion and Invidious. ++## And public_url is the public URL from which companion is listening ++## to the requests from the user(s). ++## Both parameter can have identical URL when Invidious is hosted in ++## an internal network or at home. + ## + ## Accepted values: "http(s)://:" + ## Default: + ## + #invidious_companion: +-# - http://127.0.0.1:8282 ++# - private_url: "http://localhost:8282" ++# public_url: "http://localhost:8282" + + ## + ## API key for Invidious companion +diff --git a/src/invidious/config.cr b/src/invidious/config.cr +index 20268ed1f..916225764 100644 +--- a/src/invidious/config.cr ++++ b/src/invidious/config.cr +@@ -67,26 +67,14 @@ end + class Config + include YAML::Serializable + +- module URIArrayConverter +- def self.to_yaml(values : Array(URI), yaml : YAML::Nodes::Builder) +- yaml.sequence do +- values.each { |v| yaml.scalar v.to_s } +- end +- end ++ class CompanionConfig ++ include YAML::Serializable + +- def self.from_yaml(ctx : YAML::ParseContext, node : YAML::Nodes::Node) : Array(URI) +- if node.is_a?(YAML::Nodes::Sequence) +- node.map do |child| +- unless child.is_a?(YAML::Nodes::Scalar) +- node.raise "Expected scalar, not #{child.class}" +- end ++ @[YAML::Field(converter: Preferences::URIConverter)] ++ property private_url : URI = URI.parse("") + +- URI.parse(child.value) +- end +- else +- node.raise "Expected sequence, not #{node.class}" +- end +- end ++ @[YAML::Field(converter: Preferences::URIConverter)] ++ property public_url : URI = URI.parse("") + end + + # Number of threads to use for crawling videos from channels (for updating subscriptions) +@@ -174,8 +162,7 @@ class Config + property po_token : String? = nil + + # Invidious companion +- @[YAML::Field(converter: Config::URIArrayConverter)] +- property invidious_companion : Array(URI) = [] of URI ++ property invidious_companion : Array(CompanionConfig) = [] of CompanionConfig + + # Invidious companion API key + property invidious_companion_key : String = "" +diff --git a/src/invidious/routes/api/manifest.cr b/src/invidious/routes/api/manifest.cr +index 2892d1b4b..b6c5cbf38 100644 +--- a/src/invidious/routes/api/manifest.cr ++++ b/src/invidious/routes/api/manifest.cr +@@ -1,10 +1,6 @@ + module Invidious::Routes::API::Manifest + # /api/manifest/dash/id/:id + def self.get_dash_video_id(env) +- if !CONFIG.invidious_companion.empty? +- return error_template(403, "This endpoint is not permitted because it is handled by Invidious companion.") +- end +- + env.response.headers.add("Access-Control-Allow-Origin", "*") + env.response.content_type = "application/dash+xml" + +@@ -12,6 +8,11 @@ module Invidious::Routes::API::Manifest + id = env.params.url["id"] + region = env.params.query["region"]? + ++ if !CONFIG.invidious_companion.empty? ++ invidious_companion = CONFIG.invidious_companion.sample ++ return env.redirect "#{invidious_companion.public_url.to_s}/api/manifest/dash/id/#{id}?#{env.params.query}" ++ end ++ + # Since some implementations create playlists based on resolution regardless of different codecs, + # we can opt to only add a source to a representation if it has a unique height within that representation + unique_res = env.params.query["unique_res"]?.try { |q| (q == "true" || q == "1").to_unsafe } +diff --git a/src/invidious/routes/embed.cr b/src/invidious/routes/embed.cr +index df6970011..d023f61ed 100644 +--- a/src/invidious/routes/embed.cr ++++ b/src/invidious/routes/embed.cr +@@ -201,11 +201,11 @@ module Invidious::Routes::Embed + return env.redirect url + end + +- if (!CONFIG.invidious_companion.empty?) ++ if companion_base_url = video.invidious_companion.try &.["baseUrl"].as_s + env.response.headers["Content-Security-Policy"] = + env.response.headers["Content-Security-Policy"] +- .gsub("media-src", "media-src " + video.invidious_companion.not_nil!["baseUrl"].as_s) +- .gsub("connect-src", "connect-src " + video.invidious_companion.not_nil!["baseUrl"].as_s) ++ .gsub("media-src", "media-src #{companion_base_url}") ++ .gsub("connect-src", "connect-src #{companion_base_url}") + end + + rendered "embed" +diff --git a/src/invidious/routes/video_playback.cr b/src/invidious/routes/video_playback.cr +index 405e733b3..bac79b5cc 100644 +--- a/src/invidious/routes/video_playback.cr ++++ b/src/invidious/routes/video_playback.cr +@@ -254,7 +254,8 @@ module Invidious::Routes::VideoPlayback + # so we have a mechanism here to redirect to the latest version + def self.latest_version(env) + if !CONFIG.invidious_companion.empty? +- return error_template(403, "This endpoint is not permitted because it is handled by Invidious companion.") ++ invidious_companion = CONFIG.invidious_companion.sample ++ return env.redirect "#{invidious_companion.public_url.to_s}/latest_version?#{env.params.query}" + end + + id = env.params.query["id"]? +diff --git a/src/invidious/routes/watch.cr b/src/invidious/routes/watch.cr +index b42ee12dc..e9a076f39 100644 +--- a/src/invidious/routes/watch.cr ++++ b/src/invidious/routes/watch.cr +@@ -190,11 +190,11 @@ module Invidious::Routes::Watch + captions: video.captions + ) + +- if (!CONFIG.invidious_companion.empty?) ++ if companion_base_url = video.invidious_companion.try &.["baseUrl"].as_s + env.response.headers["Content-Security-Policy"] = + env.response.headers["Content-Security-Policy"] +- .gsub("media-src", "media-src " + video.invidious_companion.not_nil!["baseUrl"].as_s) +- .gsub("connect-src", "connect-src " + video.invidious_companion.not_nil!["baseUrl"].as_s) ++ .gsub("media-src", "media-src #{companion_base_url}") ++ .gsub("connect-src", "connect-src #{companion_base_url}") + end + + templated "watch" +@@ -327,18 +327,16 @@ module Invidious::Routes::Watch + env.params.query["label"] = URI.decode_www_form(label.as_s) + + return Invidious::Routes::API::V1::Videos.captions(env) +- elsif itag = download_widget["itag"]?.try &.as_i +- itag = itag.to_s ++ elsif itag = download_widget["itag"]?.try &.as_i.to_s + + # URL params specific to /latest_version + env.params.query["id"] = video_id +- env.params.query["itag"] = itag + env.params.query["title"] = filename + env.params.query["local"] = "true" + + if (!CONFIG.invidious_companion.empty?) + video = get_video(video_id) +- return env.redirect "#{video.invidious_companion.not_nil!["baseUrl"].as_s}/latest_version?id=#{video_id}&itag=#{itag}&local=true" ++ return env.redirect "#{video.invidious_companion["baseUrl"].as_s}/latest_version?#{env.params.query}" + else + return Invidious::Routes::VideoPlayback.latest_version(env) + end +diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr +index 7670e9a92..8cbbbf7a4 100644 +--- a/src/invidious/videos.cr ++++ b/src/invidious/videos.cr +@@ -193,7 +193,7 @@ struct Video + end + + def invidious_companion : Hash(String, JSON::Any)? +- info["invidiousCompanion"]?.try &.as_h ++ info["invidiousCompanion"]?.try &.as_h || {} of String => JSON::Any + end + + # Macros defining getters/setters for various types of data +diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr +index 46c00137f..975a25bec 100644 +--- a/src/invidious/views/components/player.ecr ++++ b/src/invidious/views/components/player.ecr +@@ -22,7 +22,7 @@ + audio_streams.each_with_index do |fmt, i| + src_url = "/latest_version?id=#{video.id}&itag=#{fmt["itag"]}" + src_url += "&local=true" if params.local +- src_url = video.invidious_companion.not_nil!["baseUrl"].as_s + src_url if (!CONFIG.invidious_companion.empty?) ++ src_url = video.invidious_companion["baseUrl"].as_s + src_url if (!CONFIG.invidious_companion.empty?) + + bitrate = fmt["bitrate"] + mimetype = HTML.escape(fmt["mimeType"].as_s) +@@ -37,7 +37,7 @@ + <% else %> + <% if params.quality == "dash" + src_url = "/api/manifest/dash/id/" + video.id + "?local=true&unique_res=1" +- src_url = video.invidious_companion.not_nil!["baseUrl"].as_s + src_url if (!CONFIG.invidious_companion.empty?) ++ src_url = video.invidious_companion["baseUrl"].as_s + src_url if (!CONFIG.invidious_companion.empty?) + %> + + <% end %> +@@ -48,7 +48,7 @@ + fmt_stream.each_with_index do |fmt, i| + src_url = "/latest_version?id=#{video.id}&itag=#{fmt["itag"]}" + src_url += "&local=true" if params.local +- src_url = video.invidious_companion.not_nil!["baseUrl"].as_s + src_url if (!CONFIG.invidious_companion.empty?) ++ src_url = video.invidious_companion["baseUrl"].as_s + src_url if (!CONFIG.invidious_companion.empty?) + + quality = fmt["quality"] + mimetype = HTML.escape(fmt["mimeType"].as_s) +diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr +index 09f0936fd..74f654494 100644 +--- a/src/invidious/yt_backend/youtube_api.cr ++++ b/src/invidious/yt_backend/youtube_api.cr +@@ -685,7 +685,7 @@ module YoutubeAPI + ) : Hash(String, JSON::Any) + headers = HTTP::Headers{ + "Content-Type" => "application/json; charset=UTF-8", +- "Authorization" => "Bearer " + CONFIG.invidious_companion_key, ++ "Authorization" => "Bearer #{CONFIG.invidious_companion_key}", + } + + # Logging +@@ -695,21 +695,20 @@ module YoutubeAPI + # Send the POST request + + begin +- response = make_client(CONFIG.invidious_companion.sample, ++ invidious_companion = CONFIG.invidious_companion.sample ++ response = make_client(invidious_companion.private_url, + &.post(endpoint, headers: headers, body: data.to_json)) + body = response.body + if (response.status_code != 200) +- raise Exception.new("Error while communicating with Invidious companion: \ +- status code: " + response.status_code.to_s + " and body: " + body) ++ raise Exception.new( ++ "Error while communicating with Invidious companion: \ ++ status code: #{response.status_code} and body: #{body.dump}" ++ ) + end + rescue ex + raise InfoException.new("Error while communicating with Invidious companion: " + (ex.message || "no extra info found")) + end + +- if body.nil? +- raise InfoException.new("Error while communicating with Invidious companion: no response data.") +- end +- + # Convert result to Hash + initial_data = JSON.parse(body).as_h + + +From a571eeaa381523f5efb29dea0f5fe097f4f1252c Mon Sep 17 00:00:00 2001 +From: Emilien <4016501+unixfox@users.noreply.github.com> +Date: Sun, 8 Dec 2024 22:22:08 +0100 +Subject: [PATCH 18/20] format watch.cr + +--- + src/invidious/routes/watch.cr | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/invidious/routes/watch.cr b/src/invidious/routes/watch.cr +index e9a076f39..91aca03e0 100644 +--- a/src/invidious/routes/watch.cr ++++ b/src/invidious/routes/watch.cr +@@ -328,7 +328,6 @@ module Invidious::Routes::Watch + + return Invidious::Routes::API::V1::Videos.captions(env) + elsif itag = download_widget["itag"]?.try &.as_i.to_s +- + # URL params specific to /latest_version + env.params.query["id"] = video_id + env.params.query["title"] = filename + +From ab72bbad7afb7d143883a7d0610145f68c06bac8 Mon Sep 17 00:00:00 2001 +From: Emilien <4016501+unixfox@users.noreply.github.com> +Date: Sun, 8 Dec 2024 22:24:57 +0100 +Subject: [PATCH 19/20] fix ameba Redundant use of `Object#to_s` in + interpolation + +--- + src/invidious/routes/api/manifest.cr | 2 +- + src/invidious/routes/video_playback.cr | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/invidious/routes/api/manifest.cr b/src/invidious/routes/api/manifest.cr +index b6c5cbf38..b2085666f 100644 +--- a/src/invidious/routes/api/manifest.cr ++++ b/src/invidious/routes/api/manifest.cr +@@ -10,7 +10,7 @@ module Invidious::Routes::API::Manifest + + if !CONFIG.invidious_companion.empty? + invidious_companion = CONFIG.invidious_companion.sample +- return env.redirect "#{invidious_companion.public_url.to_s}/api/manifest/dash/id/#{id}?#{env.params.query}" ++ return env.redirect "#{invidious_companion.public_url}/api/manifest/dash/id/#{id}?#{env.params.query}" + end + + # Since some implementations create playlists based on resolution regardless of different codecs, +diff --git a/src/invidious/routes/video_playback.cr b/src/invidious/routes/video_playback.cr +index bac79b5cc..391aa139a 100644 +--- a/src/invidious/routes/video_playback.cr ++++ b/src/invidious/routes/video_playback.cr +@@ -255,7 +255,7 @@ module Invidious::Routes::VideoPlayback + def self.latest_version(env) + if !CONFIG.invidious_companion.empty? + invidious_companion = CONFIG.invidious_companion.sample +- return env.redirect "#{invidious_companion.public_url.to_s}/latest_version?#{env.params.query}" ++ return env.redirect "#{invidious_companion.public_url}/latest_version?#{env.params.query}" + end + + id = env.params.query["id"]? + +From 1de20546182421e1280ec2b68c6d347abead7c54 Mon Sep 17 00:00:00 2001 +From: Emilien <4016501+unixfox@users.noreply.github.com> +Date: Fri, 13 Dec 2024 20:08:57 +0100 +Subject: [PATCH 20/20] add ability for invidious companion to check request + from invidious + +--- + config/config.example.yml | 1 + + src/invidious/config.cr | 3 +++ + src/invidious/helpers/utils.cr | 19 +++++++++++++++++++ + src/invidious/views/components/player.ecr | 9 ++++++--- + 4 files changed, 29 insertions(+), 3 deletions(-) + +diff --git a/config/config.example.yml b/config/config.example.yml +index 2273c8398..44b7c8064 100644 +--- a/config/config.example.yml ++++ b/config/config.example.yml +@@ -83,6 +83,7 @@ db: + + ## + ## API key for Invidious companion ++## The size of the key needs to be more or equal to 16. + ## + ## Needed when invidious_companion is configured + ## +diff --git a/src/invidious/config.cr b/src/invidious/config.cr +index 916225764..6508c8479 100644 +--- a/src/invidious/config.cr ++++ b/src/invidious/config.cr +@@ -250,6 +250,9 @@ class Config + elsif config.invidious_companion_key == "CHANGE_ME!!" + puts "Config: The value of 'invidious_companion_key' needs to be changed!!" + exit(1) ++ elsif config.invidious_companion_key.size < 16 ++ puts "Config: The value of 'invidious_companion_key' needs to be a size of 16 or more." ++ exit(1) + end + end + +diff --git a/src/invidious/helpers/utils.cr b/src/invidious/helpers/utils.cr +index 4d9bb28dc..85462eb84 100644 +--- a/src/invidious/helpers/utils.cr ++++ b/src/invidious/helpers/utils.cr +@@ -383,3 +383,22 @@ def parse_link_endpoint(endpoint : JSON::Any, text : String, video_id : String) + end + return text + end ++ ++def encrypt_ecb_without_salt(data, key) ++ cipher = OpenSSL::Cipher.new("aes-128-ecb") ++ cipher.encrypt ++ cipher.key = key ++ ++ io = IO::Memory.new ++ io.write(cipher.update(data)) ++ io.write(cipher.final) ++ io.rewind ++ ++ return io ++end ++ ++def invidious_companion_encrypt(data) ++ timestamp = Time.utc.to_unix ++ encrypted_data = encrypt_ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key) ++ return Base64.urlsafe_encode(encrypted_data) ++end +diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr +index 975a25bec..37f5f5869 100644 +--- a/src/invidious/views/components/player.ecr ++++ b/src/invidious/views/components/player.ecr +@@ -22,7 +22,8 @@ + audio_streams.each_with_index do |fmt, i| + src_url = "/latest_version?id=#{video.id}&itag=#{fmt["itag"]}" + src_url += "&local=true" if params.local +- src_url = video.invidious_companion["baseUrl"].as_s + src_url if (!CONFIG.invidious_companion.empty?) ++ src_url = video.invidious_companion["baseUrl"].as_s + src_url + ++ "&check=#{invidious_companion_encrypt(video.id)}" if (!CONFIG.invidious_companion.empty?) + + bitrate = fmt["bitrate"] + mimetype = HTML.escape(fmt["mimeType"].as_s) +@@ -37,7 +38,8 @@ + <% else %> + <% if params.quality == "dash" + src_url = "/api/manifest/dash/id/" + video.id + "?local=true&unique_res=1" +- src_url = video.invidious_companion["baseUrl"].as_s + src_url if (!CONFIG.invidious_companion.empty?) ++ src_url = video.invidious_companion["baseUrl"].as_s + src_url + ++ "&check=#{invidious_companion_encrypt(video.id)}" if (!CONFIG.invidious_companion.empty?) + %> + + <% end %> +@@ -48,7 +50,8 @@ + fmt_stream.each_with_index do |fmt, i| + src_url = "/latest_version?id=#{video.id}&itag=#{fmt["itag"]}" + src_url += "&local=true" if params.local +- src_url = video.invidious_companion["baseUrl"].as_s + src_url if (!CONFIG.invidious_companion.empty?) ++ src_url = video.invidious_companion["baseUrl"].as_s + src_url + ++ "&check=#{invidious_companion_encrypt(video.id)}" if (!CONFIG.invidious_companion.empty?) + + quality = fmt["quality"] + mimetype = HTML.escape(fmt["mimeType"].as_s)