From 864893f4c75d79b725aba2ddfbf0d55a2b71111e Mon Sep 17 00:00:00 2001 From: Cameron Radmore Date: Thu, 5 Feb 2026 09:58:52 -0500 Subject: [PATCH 01/23] Channels: parse pronouns and display them on channel page (#5617) --- assets/css/default.css | 17 ++++++++++++++++- src/invidious/channels/about.cr | 17 +++++++++++++---- src/invidious/routes/api/v1/channels.cr | 1 + src/invidious/views/components/channel_info.ecr | 5 ++++- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/assets/css/default.css b/assets/css/default.css index 78ef7a60..ff07bdb4 100644 --- a/assets/css/default.css +++ b/assets/css/default.css @@ -75,6 +75,16 @@ body { height: auto; } +.channel-profile > .channel-name-pronouns { + display: inline-block; +} + +.channel-profile > .channel-name-pronouns > .channel-pronouns { + font-style: italic; + font-size: .8em; + font-weight: lighter; +} + body a.channel-owner { background-color: #008bec; color: #fff; @@ -406,7 +416,12 @@ input[type="search"]::-webkit-search-cancel-button { p.channel-name { margin: 0; overflow-wrap: anywhere;} p.video-data { margin: 0; font-weight: bold; font-size: 80%; } -.channel-profile > .channel-name { overflow-wrap: anywhere;} + +.channel-profile > .channel-name, +.channel-profile > .channel-name-pronouns > .channel-name +{ + overflow-wrap: anywhere; +} /* diff --git a/src/invidious/channels/about.cr b/src/invidious/channels/about.cr index 13909527..537aa034 100644 --- a/src/invidious/channels/about.cr +++ b/src/invidious/channels/about.cr @@ -12,6 +12,7 @@ record AboutChannel, sub_count : Int32, joined : Time, is_family_friendly : Bool, + pronouns : String?, allowed_regions : Array(String), tabs : Array(String), tags : Array(String), @@ -160,14 +161,21 @@ def get_about_info(ucid, locale) : AboutChannel end sub_count = 0 + pronouns = nil if (metadata_rows = initdata.dig?("header", "pageHeaderRenderer", "content", "pageHeaderViewModel", "metadata", "contentMetadataViewModel", "metadataRows").try &.as_a) metadata_rows.each do |row| - metadata_part = row.dig?("metadataParts").try &.as_a.find { |i| i.dig?("text", "content").try &.as_s.includes?("subscribers") } - if !metadata_part.nil? - sub_count = short_text_to_number(metadata_part.dig("text", "content").as_s.split(" ")[0]).to_i32 + subscribe_metadata_part = row.dig?("metadataParts").try &.as_a.find { |i| i.dig?("text", "content").try &.as_s.includes?("subscribers") } + if !subscribe_metadata_part.nil? + sub_count = short_text_to_number(subscribe_metadata_part.dig("text", "content").as_s.split(" ")[0]).to_i32 end - break if sub_count != 0 + + pronoun_metadata_part = row.dig?("metadataParts").try &.as_a.find { |i| i.dig?("tooltip").try &.as_s.includes?("Pronouns") } + if !pronoun_metadata_part.nil? + pronouns = pronoun_metadata_part.dig("text", "content").as_s + end + + break if sub_count != 0 && !pronouns.nil? end end @@ -184,6 +192,7 @@ def get_about_info(ucid, locale) : AboutChannel sub_count: sub_count, joined: joined, is_family_friendly: is_family_friendly, + pronouns: pronouns, allowed_regions: allowed_regions, tabs: tab_names, tags: tags, diff --git a/src/invidious/routes/api/v1/channels.cr b/src/invidious/routes/api/v1/channels.cr index 503b8c05..f8060342 100644 --- a/src/invidious/routes/api/v1/channels.cr +++ b/src/invidious/routes/api/v1/channels.cr @@ -104,6 +104,7 @@ module Invidious::Routes::API::V1::Channels json.field "tabs", channel.tabs json.field "tags", channel.tags json.field "authorVerified", channel.verified + json.field "pronouns", channel.pronouns json.field "latestVideos" do json.array do diff --git a/src/invidious/views/components/channel_info.ecr b/src/invidious/views/components/channel_info.ecr index 2c177b59..97a2d7da 100644 --- a/src/invidious/views/components/channel_info.ecr +++ b/src/invidious/views/components/channel_info.ecr @@ -12,7 +12,10 @@
- <%= author %><% if !channel.verified.nil? && channel.verified %> <% end %> +
+ <%= author %><% if !channel.verified.nil? && channel.verified %> <% end %> + <% if !channel.pronouns.nil? %>
<%= channel.pronouns %><% end %> +
From 84a699f7b7b3c1bc60598077f0da111219b621bc Mon Sep 17 00:00:00 2001 From: Cameron Radmore Date: Thu, 5 Feb 2026 09:59:27 -0500 Subject: [PATCH 02/23] Playlist API: return empty author url if ucid is empty (#5618) --- src/invidious/playlists.cr | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/invidious/playlists.cr b/src/invidious/playlists.cr index ec64bee4..eb084331 100644 --- a/src/invidious/playlists.cr +++ b/src/invidious/playlists.cr @@ -107,7 +107,11 @@ struct Playlist json.field "author", self.author json.field "authorId", self.ucid - json.field "authorUrl", "/channel/#{self.ucid}" + if !self.ucid.empty? + json.field "authorUrl", "/channel/#{self.ucid}" + else + json.field "authorUrl", "" + end json.field "subtitle", self.subtitle json.field "authorThumbnails" do From 7be6fbd75c9d680e1595bdeae32e62e5ddc5e745 Mon Sep 17 00:00:00 2001 From: ThatMatrix Date: Thu, 11 Jul 2024 01:53:58 +0200 Subject: [PATCH 03/23] Fix(user/importers): Fixed youtube csv playlist importer --- src/invidious/user/imports.cr | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/invidious/user/imports.cr b/src/invidious/user/imports.cr index 007eb666..0dbc9b03 100644 --- a/src/invidious/user/imports.cr +++ b/src/invidious/user/imports.cr @@ -30,22 +30,18 @@ struct Invidious::User return subscriptions end - def parse_playlist_export_csv(user : User, raw_input : String) + # Parse a CSV Google Takeout - Youtube Playlist file + def parse_playlist_export_csv(user : User, playlist_name : String, raw_input : String) # Split the input into head and body content raw_head, raw_body = raw_input.strip('\n').split("\n\n", limit: 2, remove_empty: true) # Create the playlist from the head content csv_head = CSV.new(raw_head.strip('\n'), headers: true) csv_head.next - title = csv_head[4] - description = csv_head[5] - visibility = csv_head[6] + title = playlist_name - if visibility.compare("Public", case_insensitive: true) == 0 - privacy = PlaylistPrivacy::Public - else - privacy = PlaylistPrivacy::Private - end + description = "This is the default description of an imported playlist. Feel Free to change it as you see fit." + privacy = PlaylistPrivacy::Private playlist = create_playlist(title, privacy, user) Invidious::Database::Playlists.update_description(playlist.id, description) @@ -204,10 +200,12 @@ struct Invidious::User end def from_youtube_pl(user : User, body : String, filename : String, type : String) : Bool - extension = filename.split(".").last + filename_array = filename.split(".") + playlist_name = filename_array.first + extension = filename_array.last if extension == "csv" || type == "text/csv" - playlist = parse_playlist_export_csv(user, body) + playlist = parse_playlist_export_csv(user, playlist_name,playlist_name, body) if playlist return true else @@ -219,6 +217,7 @@ struct Invidious::User end def from_youtube_wh(user : User, body : String, filename : String, type : String) : Bool + filename = filename.split(".") extension = filename.split(".").last if extension == "json" || type == "application/json" From 471857ce8bbb8397e75c9d16a781f5b859fe74b0 Mon Sep 17 00:00:00 2001 From: ThatMatrix Date: Thu, 11 Jul 2024 02:41:08 +0200 Subject: [PATCH 04/23] Fix(user/importers): Fixed typos --- docker-compose.yml | 2 +- src/invidious/user/imports.cr | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index cb53bdd6..899f2118 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -34,7 +34,7 @@ services: # domain: # https_only: false # statistics_enabled: false - hmac_key: "CHANGE_ME!!" + hmac_key: "ahyeef5xahyohliefi3A" healthcheck: test: wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/stats || exit 1 interval: 30s diff --git a/src/invidious/user/imports.cr b/src/invidious/user/imports.cr index 0dbc9b03..df93422f 100644 --- a/src/invidious/user/imports.cr +++ b/src/invidious/user/imports.cr @@ -33,7 +33,7 @@ struct Invidious::User # Parse a CSV Google Takeout - Youtube Playlist file def parse_playlist_export_csv(user : User, playlist_name : String, raw_input : String) # Split the input into head and body content - raw_head, raw_body = raw_input.strip('\n').split("\n\n", limit: 2, remove_empty: true) + raw_head, raw_body = raw_input.split("\n\n", limit: 2, remove_empty: true) # Create the playlist from the head content csv_head = CSV.new(raw_head.strip('\n'), headers: true) @@ -205,7 +205,7 @@ struct Invidious::User extension = filename_array.last if extension == "csv" || type == "text/csv" - playlist = parse_playlist_export_csv(user, playlist_name,playlist_name, body) + playlist = parse_playlist_export_csv(user, playlist_name, body) if playlist return true else @@ -217,7 +217,6 @@ struct Invidious::User end def from_youtube_wh(user : User, body : String, filename : String, type : String) : Bool - filename = filename.split(".") extension = filename.split(".").last if extension == "json" || type == "application/json" From 050032b18880a90118bc27f98ebdf7e5fe9bd67d Mon Sep 17 00:00:00 2001 From: ThatMatrix Date: Thu, 11 Jul 2024 02:52:39 +0200 Subject: [PATCH 05/23] fix(docker-compose.yml): removed hmac_key (randomly generated) used for testing --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 899f2118..cb53bdd6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -34,7 +34,7 @@ services: # domain: # https_only: false # statistics_enabled: false - hmac_key: "ahyeef5xahyohliefi3A" + hmac_key: "CHANGE_ME!!" healthcheck: test: wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/stats || exit 1 interval: 30s From e4beb00413e3a008d8d87442b6c4eab776406827 Mon Sep 17 00:00:00 2001 From: ThatMatrix Date: Thu, 11 Jul 2024 03:32:06 +0200 Subject: [PATCH 06/23] fix(user/imports.cr): splitting error fixed --- src/invidious/user/imports.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/user/imports.cr b/src/invidious/user/imports.cr index df93422f..bc149454 100644 --- a/src/invidious/user/imports.cr +++ b/src/invidious/user/imports.cr @@ -33,7 +33,7 @@ struct Invidious::User # Parse a CSV Google Takeout - Youtube Playlist file def parse_playlist_export_csv(user : User, playlist_name : String, raw_input : String) # Split the input into head and body content - raw_head, raw_body = raw_input.split("\n\n", limit: 2, remove_empty: true) + raw_head, raw_body = raw_input.split("\n", limit: 2, remove_empty: true) # Create the playlist from the head content csv_head = CSV.new(raw_head.strip('\n'), headers: true) From ce9494133df596ada104acee43dcc1b32e34bebc Mon Sep 17 00:00:00 2001 From: ThatMatrix Date: Thu, 11 Jul 2024 03:44:56 +0200 Subject: [PATCH 07/23] fix(user/imports.cr): double header removal caused first video to be skipped --- src/invidious/user/imports.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/user/imports.cr b/src/invidious/user/imports.cr index bc149454..7c4101cc 100644 --- a/src/invidious/user/imports.cr +++ b/src/invidious/user/imports.cr @@ -47,7 +47,7 @@ struct Invidious::User Invidious::Database::Playlists.update_description(playlist.id, description) # Add each video to the playlist from the body content - csv_body = CSV.new(raw_body.strip('\n'), headers: true) + csv_body = CSV.new(raw_body.strip('\n'), headers: false) csv_body.each do |row| video_id = row[0] if playlist From a3a97ccf073808d25900d661b79216625b4221f1 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Sun, 28 Sep 2025 00:38:23 -0300 Subject: [PATCH 08/23] Only generate companion CSP one time to reuse it --- src/invidious/routes/before_all.cr | 17 +++++++++++++++-- src/invidious/routes/embed.cr | 11 ----------- src/invidious/routes/watch.cr | 11 ----------- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/src/invidious/routes/before_all.cr b/src/invidious/routes/before_all.cr index 06746a12..347a6021 100644 --- a/src/invidious/routes/before_all.cr +++ b/src/invidious/routes/before_all.cr @@ -1,4 +1,17 @@ module Invidious::Routes::BeforeAll + struct CompanionCSP + property companion_urls : String = "" + + def initialize + self.companion_urls = CONFIG.invidious_companion.reject(&.builtin_proxy).map do |companion| + uri = + "#{companion.public_url.scheme}://#{companion.public_url.host}#{companion.public_url.port ? ":#{companion.public_url.port}" : ""}" + end.join(" ") + end + end + + private COMPANION_CSP = CompanionCSP.new + def self.handle(env) preferences = Preferences.from_json("{}") @@ -35,9 +48,9 @@ module Invidious::Routes::BeforeAll "style-src 'self' 'unsafe-inline'", "img-src 'self' data:", "font-src 'self' data:", - "connect-src 'self'", + "connect-src 'self' " + COMPANION_CSP.companion_urls, "manifest-src 'self'", - "media-src 'self' blob:", + "media-src 'self' blob: " + COMPANION_CSP.companion_urls, "child-src 'self' blob:", "frame-src 'self'", "frame-ancestors " + frame_ancestors, diff --git a/src/invidious/routes/embed.cr b/src/invidious/routes/embed.cr index d0a3b5c1..ec5a5804 100644 --- a/src/invidious/routes/embed.cr +++ b/src/invidious/routes/embed.cr @@ -208,17 +208,6 @@ module Invidious::Routes::Embed if CONFIG.invidious_companion.present? invidious_companion = CONFIG.invidious_companion.sample - invidious_companion_urls = CONFIG.invidious_companion.reject(&.builtin_proxy).map do |companion| - uri = - "#{companion.public_url.scheme}://#{companion.public_url.host}#{companion.public_url.port ? ":#{companion.public_url.port}" : ""}" - end.join(" ") - - if !invidious_companion_urls.empty? - env.response.headers["Content-Security-Policy"] = - env.response.headers["Content-Security-Policy"] - .gsub("media-src", "media-src #{invidious_companion_urls}") - .gsub("connect-src", "connect-src #{invidious_companion_urls}") - end end rendered "embed" diff --git a/src/invidious/routes/watch.cr b/src/invidious/routes/watch.cr index 4c181503..b829b0f5 100644 --- a/src/invidious/routes/watch.cr +++ b/src/invidious/routes/watch.cr @@ -193,17 +193,6 @@ module Invidious::Routes::Watch if CONFIG.invidious_companion.present? invidious_companion = CONFIG.invidious_companion.sample - invidious_companion_urls = CONFIG.invidious_companion.reject(&.builtin_proxy).map do |companion| - uri = - "#{companion.public_url.scheme}://#{companion.public_url.host}#{companion.public_url.port ? ":#{companion.public_url.port}" : ""}" - end.join(" ") - - if !invidious_companion_urls.empty? - env.response.headers["Content-Security-Policy"] = - env.response.headers["Content-Security-Policy"] - .gsub("media-src", "media-src #{invidious_companion_urls}") - .gsub("connect-src", "connect-src #{invidious_companion_urls}") - end end templated "watch" From 0ee92e329857e416a24815ba13a9f4d951b28946 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 4 Dec 2025 11:59:06 -0300 Subject: [PATCH 09/23] Update src/invidious/routes/before_all.cr Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/invidious/routes/before_all.cr | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/invidious/routes/before_all.cr b/src/invidious/routes/before_all.cr index 347a6021..6d374fff 100644 --- a/src/invidious/routes/before_all.cr +++ b/src/invidious/routes/before_all.cr @@ -4,8 +4,7 @@ module Invidious::Routes::BeforeAll def initialize self.companion_urls = CONFIG.invidious_companion.reject(&.builtin_proxy).map do |companion| - uri = - "#{companion.public_url.scheme}://#{companion.public_url.host}#{companion.public_url.port ? ":#{companion.public_url.port}" : ""}" + "#{companion.public_url.scheme}://#{companion.public_url.host}#{companion.public_url.port ? ":#{companion.public_url.port}" : ""}" end.join(" ") end end From cc7cb94095a27e2e544e21b11b85f027cd41de8f Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 12 Jun 2025 18:57:35 -0400 Subject: [PATCH 10/23] Document use of unix sockets for `db` --- config/config.example.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/config/config.example.yml b/config/config.example.yml index 7cc480c6..f3f43bba 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -8,6 +8,13 @@ ## Database configuration with separate parameters. ## This setting is MANDATORY, unless 'database_url' is used. ## +## Note: The 'db' setting allows the use of UNIX +## sockets. To do so, set 'host' to "" +## E.g: +## password: kemal +## host: "" +## port: 5432 +## db: user: kemal password: kemal From ffd9f4b11226c18cd06443917a438f667a323d6f Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Thu, 26 Jun 2025 19:15:12 +0000 Subject: [PATCH 11/23] pages/watch: HTML escape 'action' in download widget Caught in the review of PR 5224, but forgot to click on "send review" in time. I realized that too late, after the PR was already merged. --- src/invidious/frontend/watch_page.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/frontend/watch_page.cr b/src/invidious/frontend/watch_page.cr index 14e169e8..642ab4cc 100644 --- a/src/invidious/frontend/watch_page.cr +++ b/src/invidious/frontend/watch_page.cr @@ -36,7 +36,7 @@ module Invidious::Frontend::WatchPage return String.build(4000) do |str| str << "" From 067a426235b920bcb6d3c0fb36783f44c60dc7ba Mon Sep 17 00:00:00 2001 From: Fijxu Date: Fri, 16 Jan 2026 16:01:57 -0300 Subject: [PATCH 12/23] refactor: Move top level constants to it's own modules --- src/invidious.cr | 15 ++------------- src/invidious/comments/reddit.cr | 1 + src/invidious/helpers/helpers.cr | 2 ++ src/invidious/helpers/utils.cr | 2 ++ src/invidious/routes/api/v1/videos.cr | 5 ++++- src/invidious/routes/routes.cr | 21 +++++++++++++++++++++ src/invidious/routes/video_playback.cr | 2 ++ 7 files changed, 34 insertions(+), 14 deletions(-) create mode 100644 src/invidious/routes/routes.cr diff --git a/src/invidious.cr b/src/invidious.cr index ec518453..d7c5b80b 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -67,20 +67,9 @@ rescue ex puts "Check your 'config.yml' database settings or PostgreSQL settings." exit(1) end -ARCHIVE_URL = URI.parse("https://archive.org") -PUBSUB_URL = URI.parse("https://pubsubhubbub.appspot.com") -REDDIT_URL = URI.parse("https://www.reddit.com") -YT_URL = URI.parse("https://www.youtube.com") -HOST_URL = make_host_url(Kemal.config) - -CHARS_SAFE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" -TEST_IDS = {"AgbeGFYluEA", "BaW_jenozKc", "a9LDPn-MO4I", "ddFvjfvPnqk", "iqKdEhx-dD4"} +HOST_URL = make_host_url(Kemal.config) MAX_ITEMS_PER_PAGE = 1500 -REQUEST_HEADERS_WHITELIST = {"accept", "accept-encoding", "cache-control", "content-length", "if-none-match", "range"} -RESPONSE_HEADERS_BLACKLIST = {"access-control-allow-origin", "alt-svc", "server", "cross-origin-opener-policy-report-only", "report-to", "cross-origin", "timing-allow-origin", "cross-origin-resource-policy"} -HTTP_CHUNK_SIZE = 10485760 # ~10MB - CURRENT_BRANCH = {{ "#{`git branch | sed -n '/* /s///p'`.strip}" }} CURRENT_COMMIT = {{ "#{`git rev-list HEAD --max-count=1 --abbrev-commit`.strip}" }} CURRENT_VERSION = {{ "#{`git log -1 --format=%ci | awk '{print $1}' | sed s/-/./g`.strip}" }} @@ -97,7 +86,7 @@ SOFTWARE = { "branch" => "#{CURRENT_BRANCH}", } -YT_POOL = YoutubeConnectionPool.new(YT_URL, capacity: CONFIG.pool_size) +YT_POOL = YoutubeConnectionPool.new(URI.parse("https://www.youtube.com"), capacity: CONFIG.pool_size) # Image request pool diff --git a/src/invidious/comments/reddit.cr b/src/invidious/comments/reddit.cr index ba9c19f1..e128350c 100644 --- a/src/invidious/comments/reddit.cr +++ b/src/invidious/comments/reddit.cr @@ -1,5 +1,6 @@ module Invidious::Comments extend self + private REDDIT_URL = URI.parse("https://www.reddit.com") def fetch_reddit(id, sort_by = "confidence") client = make_client(REDDIT_URL) diff --git a/src/invidious/helpers/helpers.cr b/src/invidious/helpers/helpers.cr index 6add0237..ab694b1f 100644 --- a/src/invidious/helpers/helpers.cr +++ b/src/invidious/helpers/helpers.cr @@ -1,5 +1,7 @@ require "./macros" +TEST_IDS = {"AgbeGFYluEA", "BaW_jenozKc", "a9LDPn-MO4I", "ddFvjfvPnqk", "iqKdEhx-dD4"} + struct Nonce include DB::Serializable diff --git a/src/invidious/helpers/utils.cr b/src/invidious/helpers/utils.cr index 5637e533..24b20ed9 100644 --- a/src/invidious/helpers/utils.cr +++ b/src/invidious/helpers/utils.cr @@ -1,3 +1,5 @@ +PUBSUB_URL = URI.parse("https://pubsubhubbub.appspot.com") + # See http://www.evanmiller.org/how-not-to-sort-by-average-rating.html def ci_lower_bound(pos, n) if n == 0 diff --git a/src/invidious/routes/api/v1/videos.cr b/src/invidious/routes/api/v1/videos.cr index 6a3eb8ae..fc3de695 100644 --- a/src/invidious/routes/api/v1/videos.cr +++ b/src/invidious/routes/api/v1/videos.cr @@ -1,6 +1,9 @@ require "html" module Invidious::Routes::API::V1::Videos + private INTERNET_ARCHIVE_URL = URI.parse("https://archive.org") + private CHARS_SAFE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" + def self.videos(env) locale = env.get("preferences").as(Preferences).locale @@ -279,7 +282,7 @@ module Invidious::Routes::API::V1::Videos file = URI.encode_www_form("#{id[0, 3]}/#{id}.xml") - location = make_client(ARCHIVE_URL, &.get("/download/youtubeannotations_#{index}/#{id[0, 2]}.tar/#{file}")) + location = make_client(INTERNET_ARCHIVE_URL, &.get("/download/youtubeannotations_#{index}/#{id[0, 2]}.tar/#{file}")) if !location.headers["Location"]? env.response.status_code = location.status_code diff --git a/src/invidious/routes/routes.cr b/src/invidious/routes/routes.cr new file mode 100644 index 00000000..57f10d35 --- /dev/null +++ b/src/invidious/routes/routes.cr @@ -0,0 +1,21 @@ +module Invidious::Routes + private REQUEST_HEADERS_WHITELIST = { + "accept", + "accept-encoding", + "cache-control", + "content-length", + "if-none-match", + "range", + } + private RESPONSE_HEADERS_BLACKLIST = { + "access-control-allow-origin", + "alt-svc", + "server", + "cross-origin-opener-policy-report-only", + "report-to", + "cross-origin", + "timing-allow-origin", + "cross-origin-resource-policy + ", + } +end diff --git a/src/invidious/routes/video_playback.cr b/src/invidious/routes/video_playback.cr index 083087a9..7c01aa36 100644 --- a/src/invidious/routes/video_playback.cr +++ b/src/invidious/routes/video_playback.cr @@ -1,4 +1,6 @@ module Invidious::Routes::VideoPlayback + private HTTP_CHUNK_SIZE = 10485760 # ~10MB + # /videoplayback def self.get_video_playback(env) locale = env.get("preferences").as(Preferences).locale From 29c29f7c8d95da33898ebfed27752c4e0a8910dc Mon Sep 17 00:00:00 2001 From: Fijxu Date: Tue, 3 Feb 2026 17:32:22 -0300 Subject: [PATCH 13/23] Update src/invidious/routes/routes.cr Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/invidious/routes/routes.cr | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/invidious/routes/routes.cr b/src/invidious/routes/routes.cr index 57f10d35..68b1ff82 100644 --- a/src/invidious/routes/routes.cr +++ b/src/invidious/routes/routes.cr @@ -15,7 +15,6 @@ module Invidious::Routes "report-to", "cross-origin", "timing-allow-origin", - "cross-origin-resource-policy - ", + "cross-origin-resource-policy", } end From 118d635650f07b20ac6404afff30da99ef4e4c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milien=20=28perso=29?= <4016501+unixfox@users.noreply.github.com> Date: Sat, 7 Feb 2026 21:47:19 +0100 Subject: [PATCH 14/23] Release v2.20260207.0 (#5621) * Release v2.20260207.0 * Fix release notes for Crystal/OpenSSL * fix comment about pr #5566, #5338 Co-authored-by: Fijxu * fix comment about memory leaks Co-authored-by: Fijxu * Clarify release notes for proxy header stripping --------- Co-authored-by: Fijxu --- CHANGELOG.md | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++- shard.yml | 2 +- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe0c7a1a..f9bbb2e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,94 @@ # CHANGELOG -## vX.Y.0 (future) +## v2.20260207.0 + +### Wrap-up + +This release hardens the Invidious companion pipeline and cleans up a long list of UI papercuts. Companion downloads now work end-to-end, CSP headers and check identifiers are generated once and reused, proxy responses strip stray headers, and the final traces of the legacy signature helper are gone so the helper can be rolled out safely. + +Livestream navigation, playlists, and channel metadata also see overdue fixes: Trending once again lists livestreams, "Watch on YouTube" buttons stop jumping to arbitrary timestamps, playlist imports/API calls handle missing data, and channel pages now display creator pronouns and playlist thumbnails. Deployments benefit from compiling OpenSSL into docker images to mitigate a long-standing memory leak observed with Alpine-provided OpenSSL, Crystal pinned back to 1.16.3 for docker and OCI builds, a rewritten static file handler, clarified README/HTTP proxy/unix socket docs, and dozens of smaller cleanups. + +### New features & important changes +#### For Users + - Livestream experiences are restored: Trending shows livestreams again, the gaming feed remains accessible, and "Watch on YouTube" links stop carrying stale timestamps (#5480, #5555, #5481) + - Channel and playlist metadata is richer thanks to pronoun support, topic playlist thumbnails, and accurate related video counts (#5617, #5616, #5446) + - Downloads get smoother because download actions are URL-safe and downloads can flow through Invidious companion when available (#5367, #5561) + - Users see clearer feedback with Erroneous CAPTCHA messages, DMCA controls restored, and a footer link pointing at the current release (#5508, #5228, #4702) + +#### For instance owners + - Companion integration is sturdier: CSP is generated once, check identifiers persist, and the helper hyperlink is fixed (#5497, #5575, #5491) + - Proxied images and videoplayback strip unwanted response headers (shared header-strip list) (#5595) + - Runtime and packaging updates pin docker/OCI builds to Crystal 1.16.3, bring an optional Crystal 1.18.2 + Alpine 3.23 image, and compile OpenSSL from source to mitigate the memory leak seen with Alpine-provided OpenSSL (#5604, #5577, #5574, #5441) + - Configuration docs saw polish with unix socket instructions, refreshed HTTP proxy comments, and corrected README commands (#5347, #5586, #5607) + - Server stability improves via a larger `max_request_line_size` that is required to be able to access some next pages of Youtube channels videos and a rewritten static file handler (#5566, #5338) + +#### For developers + - Top-level constants moved into dedicated modules, preferences handling was cleaned up, and the legacy signature helper is finally removed (#5596, #5450, #5550) + - Crystal API updates replaced the deprecated `Socket#blocking` property and restored the shard target plus SPDX license metadata (#5538, #5608, #5552) + - CI/tooling stayed current with newer GitHub Actions, install-crystal releases, and cache/checkout bumps (#5569, #5544, #5530, #5499) + +### Bugs fixed +#### User-side + - Playlist importer edge cases, playlist API author URLs, and channel continuation tokens now handle empty values without crashing (#4787, #5618, #5614) + - Thin mode community posts, posts that reference unavailable videos, and DMCA content toggles work again (#5567, #5549, #5228) + - UI cleanups prevent channel name/button overflow, show explicit Erroneous CAPTCHA errors, and keep livestream timestamps clean (#5553, #5452, #5508, #5481) + - Trending feeds and related video counts regained accuracy alongside livestream/gaming categories (#5555, #5480, #5446) + +#### For instance owners + - Companion downloads, CSP reuse, and check id generation behave predictably even under load (#5561, #5497, #5575) + - Proxy responses drop stray headers and HTTP proxy examples in the config were clarified (#5595, #5586) + - Docker/OCI builds were pinned to stable Crystal releases with OpenSSL bundled to avoid memory leaks (#5604, #5577, #5441) + +#### For developers + - README commit instructions, shard targets, and unix socket docs were corrected (#5607, #5608, #5347) + - Thin mode preference comparisons no longer convert unnecessary strings (#5568) + - URL encoding fixes in the download widget and socket API updates prevent regressions when upgrading Crystal (#5367, #5538) + +### Full list of pull requests merged since the last release (newest first) + +* refactor: Move top level constants to it's own modules (https://github.com/iv-org/invidious/pull/5596, by @Fijxu) +* pages/watch: URL encode 'action' in download widget (https://github.com/iv-org/invidious/pull/5367, by @SamantazFox) +* Document use of unix sockets for `db` (https://github.com/iv-org/invidious/pull/5347, by @Fijxu) +* Generate companion CSP only once to reuse it (https://github.com/iv-org/invidious/pull/5497, by @Fijxu) +* Fix youtube CSV playlist importer (https://github.com/iv-org/invidious/pull/4787, by @ThatMatrix) +* Playlist API: return empty author url if ucid is empty (https://github.com/iv-org/invidious/pull/5618, by @radmorecameron) +* Channels: parse pronouns and display them on channel page (https://github.com/iv-org/invidious/pull/5617, by @radmorecameron) +* playlist: parse playlist thumbnails for topic autogenerated playlists (https://github.com/iv-org/invidious/pull/5616, by @radmorecameron) +* fix: add missing embedded protobuf message in continuation token for channel videos (https://github.com/iv-org/invidious/pull/5614, by @Fijxu) +* Update shard.yml to include target that was removed in commit 9d54cf9 (https://github.com/iv-org/invidious/pull/5608, by @Harm133) +* chore: Do not convert thin_mode preference to string to compare it in before_all (https://github.com/iv-org/invidious/pull/5568, by @Fijxu) +* Fix thin_mode preference for channel community page (https://github.com/iv-org/invidious/pull/5567, by @Fijxu) +* Fix commit command in README instructions, as per #5606 (https://github.com/iv-org/invidious/pull/5607, by @kirisakow) +* Revert "Bump crystallang/crystal from 1.16.3-alpine to 1.19.0-alpine in /docker" (https://github.com/iv-org/invidious/pull/5604, by @unixfox) +* Bump crystallang/crystal from 1.16.3-alpine to 1.19.0-alpine in /docker (https://github.com/iv-org/invidious/pull/5603, by @dependabot[bot]) +* doc: Update HTTP proxy configuration comments (https://github.com/iv-org/invidious/pull/5586, by @unixfox) +* Strip unwanted headers from response headers in images and videoplayback (https://github.com/iv-org/invidious/pull/5595, by @Fijxu) +* Generate companion check id one time and add missing companion check id on captions (https://github.com/iv-org/invidious/pull/5575, by @Fijxu) +* Downgrade Crystal to 1.16.3 in OCI (https://github.com/iv-org/invidious/pull/5577, by @Fijxu) +* Allow downloading via companion (https://github.com/iv-org/invidious/pull/5561, by @JeroenBoersma) +* chore: crystal 1.8.2 + alpine 3.23 (https://github.com/iv-org/invidious/pull/5574, by @unixfox) +* Replace deprecated `blocking` property of `Socket` (https://github.com/iv-org/invidious/pull/5538, by @Fijxu) +* Replace `Kemal::StaticFileHandler` with direct subclass of stdlib `HTTP::StaticFileHandler` on Crystal >= 1.17.0 (https://github.com/iv-org/invidious/pull/5338, by @syeopite) +* dockerfile: compile openssl instead of using the one bundled on the crystal alpine image. (https://github.com/iv-org/invidious/pull/5441, by @Fijxu) +* Bump actions/cache from 4 to 5 (https://github.com/iv-org/invidious/pull/5569, by @dependabot[bot]) +* Set Kemal `max_request_line_size` to 16384 for large channel continuation query parameters. (https://github.com/iv-org/invidious/pull/5566, by @Fijxu) +* Add link to GitHub release/tag/commit in footer (https://github.com/iv-org/invidious/pull/4702, by @shaedrich) +* Display "Erroneous CAPTCHA" for invalid captchas (https://github.com/iv-org/invidious/pull/5508, by @Fijxu) +* Fix channel name overflow (https://github.com/iv-org/invidious/pull/5553, by @Fijxu) +* Fix trending page by leaving livestream and gaming trending pages (https://github.com/iv-org/invidious/pull/5555, by @Fijxu) +* fix: restore dmca_content functionality (https://github.com/iv-org/invidious/pull/5228, by @Fijxu) +* Remove signature helper completely from Invidious (https://github.com/iv-org/invidious/pull/5550, by @Fijxu) +* Fix community posts when there is a unavailable video in a post (https://github.com/iv-org/invidious/pull/5549, by @Fijxu) +* chore: Update shard.yml to use SPDX license identifier (https://github.com/iv-org/invidious/pull/5552, by @Fijxu) +* Store `preferences` in a variable when reused and rename `prefs` to `preferences` (https://github.com/iv-org/invidious/pull/5450, by @Fijxu) +* Bump actions/checkout from 5 to 6 (https://github.com/iv-org/invidious/pull/5544, by @dependabot[bot]) +* Bump crystal-lang/install-crystal from 1.8.3 to 1.9.1 (https://github.com/iv-org/invidious/pull/5530, by @dependabot[bot]) +* Fix 0 view count on related videos section (https://github.com/iv-org/invidious/pull/5446, by @shiny-comic) +* Prevent timestamp from being set for Livestreams on "Watch on Youtube" links (https://github.com/iv-org/invidious/pull/5481, by @Fijxu) +* Add Livestreams to trending page (https://github.com/iv-org/invidious/pull/5480, by @Fijxu) +* Fix button overflow (https://github.com/iv-org/invidious/pull/5452, by @Fijxu) +* Bump crystal-lang/install-crystal from 1.8.2 to 1.8.3 (https://github.com/iv-org/invidious/pull/5499, by @dependabot[bot]) +* Fixed broken companion hyperlink (https://github.com/iv-org/invidious/pull/5491, by @ndsvw) ## v2.20250913.0 diff --git a/shard.yml b/shard.yml index dde1851e..d3977e98 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: invidious -version: 2.20250913.0-dev +version: 2.20260207.0 authors: - Invidious team From 11db343cfb412aa9f72d4630ac4bb13bff461d93 Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Sat, 7 Feb 2026 22:10:11 +0100 Subject: [PATCH 15/23] Prepare for next release --- CHANGELOG.md | 2 ++ shard.yml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9bbb2e6..86e1511c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # CHANGELOG +## vX.Y.0 (future) + ## v2.20260207.0 ### Wrap-up diff --git a/shard.yml b/shard.yml index d3977e98..95397dfd 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: invidious -version: 2.20260207.0 +version: 2.20260207.0-dev authors: - Invidious team From 60c31e3069e8fc900815f9ae8a093a628c0a5cae Mon Sep 17 00:00:00 2001 From: Fijxu Date: Mon, 16 Feb 2026 14:06:06 -0300 Subject: [PATCH 16/23] Remove sort by rating and date in video search filters (#5629) * Remove sort by rating and date in video search filters Closes https://github.com/iv-org/invidious/issues/5626 * Remove check of protobug generation of rating and date sort filters in Invidious spec --- spec/invidious/search/yt_filters_spec.cr | 2 -- src/invidious/search/filters.cr | 2 -- 2 files changed, 4 deletions(-) diff --git a/spec/invidious/search/yt_filters_spec.cr b/spec/invidious/search/yt_filters_spec.cr index 8abed5ce..a724fd25 100644 --- a/spec/invidious/search/yt_filters_spec.cr +++ b/spec/invidious/search/yt_filters_spec.cr @@ -48,9 +48,7 @@ FEATURE_FILTERS = { SORT_FILTERS = { Invidious::Search::Filters::Sort::Relevance => "8AEB", - Invidious::Search::Filters::Sort::Date => "CALwAQE%3D", Invidious::Search::Filters::Sort::Views => "CAPwAQE%3D", - Invidious::Search::Filters::Sort::Rating => "CAHwAQE%3D", } Spectator.describe Invidious::Search::Filters do diff --git a/src/invidious/search/filters.cr b/src/invidious/search/filters.cr index bc2715cf..d94bfc30 100644 --- a/src/invidious/search/filters.cr +++ b/src/invidious/search/filters.cr @@ -57,8 +57,6 @@ module Invidious::Search # Values correspond to { "1:varint": } enum Sort Relevance = 0 - Rating = 1 - Date = 2 Views = 3 end From e7f8b15b215f86f10ee788bc716b559527d4b801 Mon Sep 17 00:00:00 2001 From: Jeroen Boersma Date: Mon, 16 Feb 2026 20:39:44 +0100 Subject: [PATCH 17/23] Add title listen button time updates (#5625) When switching between Listen and Watching the timestamp in the url of the listen of watch button is now updated automatically. This means if you switch between listening and viewing you keep in sync with time. --- assets/js/player.js | 6 ++++++ src/invidious/views/watch.ecr | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/assets/js/player.js b/assets/js/player.js index ecdc0448..16312a1e 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -166,6 +166,12 @@ player.on('timeupdate', function () { let base_url_iv_other = elem_iv_other.getAttribute('data-base-url'); elem_iv_other.href = addCurrentTimeToURL(base_url_iv_other, domain); } + + let elem_iv_listen = document.getElementById('link-iv-listen'); + if (elem_iv_listen) { + let base_url_iv_listen = elem_iv_listen.getAttribute('data-base-url'); + elem_iv_listen.href = addCurrentTimeToURL(base_url_iv_listen, domain); + } }); diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index 923c2a83..11ab96d6 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -79,11 +79,11 @@ we're going to need to do it here in order to allow for translations.

<%= title %> <% if params.listen %> - " href="/watch?<%= env.params.query %>&listen=0"> + " id="link-iv-listen" data-base-url="/watch?<%= env.params.query %>&listen=0" href="/watch?<%= env.params.query %>&listen=0"> <% else %> - " href="/watch?<%= env.params.query %>&listen=1"> + " id="link-iv-listen" data-base-url="/watch?<%= env.params.query %>&listen=1" href="/watch?<%= env.params.query %>&listen=1"> <% end %> From fda8d1b528f1999b5eced404e4818f592a79702f Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 19 Feb 2026 14:28:22 -0300 Subject: [PATCH 18/23] Remove trailing whitespaces from codebase (#5634) Removes trailing whitespaces found across the codebase using `find . -type f -exec grep -lE ' +$' {} +` [skip ci] --- assets/js/_helpers.js | 4 ++-- assets/js/player.js | 8 ++++---- config/config.example.yml | 8 ++++---- scripts/git/pre-commit | 2 +- src/invidious/views/components/player.ecr | 2 +- src/invidious/views/template.ecr | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/assets/js/_helpers.js b/assets/js/_helpers.js index 8e18169e..ae3b157c 100644 --- a/assets/js/_helpers.js +++ b/assets/js/_helpers.js @@ -211,9 +211,9 @@ window.helpers = window.helpers || { helpers.storage.remove(key); } }, - set: function (key, value) { + set: function (key, value) { let encoded_value = encodeURIComponent(JSON.stringify(value)) - localStorage.setItem(key, encoded_value); + localStorage.setItem(key, encoded_value); }, remove: function (key) { localStorage.removeItem(key); } }; diff --git a/assets/js/player.js b/assets/js/player.js index 16312a1e..e9e9038d 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -143,7 +143,7 @@ player.on('timeupdate', function () { let base_url_yt_watch = elem_yt_watch.getAttribute('data-base-url'); elem_yt_watch.href = addCurrentTimeToURL(base_url_yt_watch); } - + let elem_yt_embed = document.getElementById('link-yt-embed'); if (elem_yt_embed) { let base_url_yt_embed = elem_yt_embed.getAttribute('data-base-url'); @@ -160,7 +160,7 @@ player.on('timeupdate', function () { let base_url_iv_embed = elem_iv_embed.getAttribute('data-base-url'); elem_iv_embed.href = addCurrentTimeToURL(base_url_iv_embed, domain); } - + let elem_iv_other = document.getElementById('link-iv-other'); if (elem_iv_other) { let base_url_iv_other = elem_iv_other.getAttribute('data-base-url'); @@ -634,7 +634,7 @@ function toggle_caption_window() { player.textTrackSettings.setValues({ windowOpacity: options.windowOpacity[newIndex] }); update_captions(); } - + function toggle_caption_opacity() { const numOptions = options.textOpacity.length; const textOpacity = player.textTrackSettings.getValues().textOpacity || '1'; @@ -739,7 +739,7 @@ addEventListener('keydown', function (e) { case '>': action = increase_playback_rate.bind(this, 1); break; case '<': action = increase_playback_rate.bind(this, -1); break; - + case '=': action = increase_caption_size.bind(this, 1); break; case '-': action = increase_caption_size.bind(this, -1); break; diff --git a/config/config.example.yml b/config/config.example.yml index f3f43bba..08005a12 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -53,7 +53,7 @@ db: ## ## When this setting is commented out, Invidious companion is not used. ## 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 @@ -63,7 +63,7 @@ db: ## The parameter private_url is required for the internal communication ## between Invidious companion and Invidious. ## -## The optional parameter public_url is the public URL from which +## The optional parameter public_url is the public URL from which ## Invidious companion is listening to the requests from the user(s). ## When this setting is commented out, Invidious proxy all requests to ## Invidious companion. Useful for simple setups. @@ -232,7 +232,7 @@ https_only: false ## Configuration for using a HTTP proxy ## If unset, then no HTTP proxy will be used. ## Proxy type supported: HTTP, HTTPS -## +## ## This is not used for loading the video streams from YouTube servers (circumvent YouTube restrictions) ## Please instead configure the proxy in Invidious companion: ## https://github.com/iv-org/invidious-companion/blob/master/config/config.example.toml @@ -885,7 +885,7 @@ default_user_preferences: ## Default: true ## #vr_mode: true - + ## ## Save the playback position ## Allow to continue watching at the previous position when diff --git a/scripts/git/pre-commit b/scripts/git/pre-commit index 4460b670..0b19802d 100644 --- a/scripts/git/pre-commit +++ b/scripts/git/pre-commit @@ -3,7 +3,7 @@ # Crystal linter # This is a modified version of the pre-commit hook from the crystal repo. https://github.com/crystal-lang/crystal/blob/master/scripts/git/pre-commit -# Please refer to that if you'd like an version that doesn't automatically format staged files. +# Please refer to that if you'd like an version that doesn't automatically format staged files. changed_cr_files=$(git diff --cached --name-only --diff-filter=ACM | grep '\.cr$') if [ ! -z "$changed_cr_files" ]; then if [ -x bin/crystal ]; then diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr index 26ba65f7..fbd472e0 100644 --- a/src/invidious/views/components/player.ecr +++ b/src/invidious/views/components/player.ecr @@ -25,7 +25,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 = invidious_companion.public_url.to_s + src_url + + src_url = invidious_companion.public_url.to_s + src_url + "&check=#{invidious_companion_check_id}" if (invidious_companion) bitrate = fmt["bitrate"] diff --git a/src/invidious/views/template.ecr b/src/invidious/views/template.ecr index 0e0f2e16..40f5544f 100644 --- a/src/invidious/views/template.ecr +++ b/src/invidious/views/template.ecr @@ -159,7 +159,7 @@ <% end %> @ <%= CURRENT_BRANCH %> <% if CURRENT_TAG != "" %> - ( + ( <% if CONFIG.modified_source_code_url %> <%= CURRENT_TAG %> <% else %> From 21d0d1041a749c7b8a4dec306371653a9a94e082 Mon Sep 17 00:00:00 2001 From: "Ashley :3" Date: Tue, 24 Feb 2026 03:36:12 +0300 Subject: [PATCH 19/23] Remove noreferrer since youtube now requires referrers on embeds (#5642) * Remove noreferer since youtube now requires referers on embeds * Update src/invidious/views/watch.ecr --------- Co-authored-by: Fijxu --- src/invidious/views/watch.ecr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index 11ab96d6..7cf6c51c 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -125,7 +125,7 @@ we're going to need to do it here in order to allow for translations. end -%> <%= translate(locale, "videoinfo_watch_on_youTube") %> - (<%= translate(locale, "videoinfo_youTube_embed_link") %>) + (<%= translate(locale, "videoinfo_youTube_embed_link") %>)

From cf9b6c4fcbeedc39c9c347cc568a7d02ff4b1861 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 09:59:26 +0100 Subject: [PATCH 20/23] Bump docker/setup-buildx-action from 3 to 4 (#5664) Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3 to 4. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-nightly-container.yml | 2 +- .github/workflows/build-stable-container.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-nightly-container.yml b/.github/workflows/build-nightly-container.yml index 44be0bae..0f15349b 100644 --- a/.github/workflows/build-nightly-container.yml +++ b/.github/workflows/build-nightly-container.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@v6 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Login to registry uses: docker/login-action@v3 diff --git a/.github/workflows/build-stable-container.yml b/.github/workflows/build-stable-container.yml index e119880d..be7f8901 100644 --- a/.github/workflows/build-stable-container.yml +++ b/.github/workflows/build-stable-container.yml @@ -30,7 +30,7 @@ jobs: uses: actions/checkout@v6 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Login to registry uses: docker/login-action@v3 From f07c9a72096f2d77ad9b242c9eef8ffcf2a4d971 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 09:59:34 +0100 Subject: [PATCH 21/23] Bump docker/metadata-action from 5 to 6 (#5663) Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5 to 6. - [Release notes](https://github.com/docker/metadata-action/releases) - [Commits](https://github.com/docker/metadata-action/compare/v5...v6) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-nightly-container.yml | 2 +- .github/workflows/build-stable-container.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-nightly-container.yml b/.github/workflows/build-nightly-container.yml index 0f15349b..b7c9d928 100644 --- a/.github/workflows/build-nightly-container.yml +++ b/.github/workflows/build-nightly-container.yml @@ -50,7 +50,7 @@ jobs: - name: Docker meta id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: quay.io/invidious/invidious flavor: | diff --git a/.github/workflows/build-stable-container.yml b/.github/workflows/build-stable-container.yml index be7f8901..db41bd4f 100644 --- a/.github/workflows/build-stable-container.yml +++ b/.github/workflows/build-stable-container.yml @@ -41,7 +41,7 @@ jobs: - name: Docker meta id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: quay.io/invidious/invidious flavor: | From d7361cbb9aa4368e33955c85b029ddf33ee15f68 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 09:59:44 +0100 Subject: [PATCH 22/23] Bump docker/build-push-action from 6 to 7 (#5662) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6 to 7. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6...v7) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-nightly-container.yml | 2 +- .github/workflows/build-stable-container.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-nightly-container.yml b/.github/workflows/build-nightly-container.yml index b7c9d928..6bb04402 100644 --- a/.github/workflows/build-nightly-container.yml +++ b/.github/workflows/build-nightly-container.yml @@ -62,7 +62,7 @@ jobs: quay.expires-after=12w - name: Build and push Docker ${{ matrix.name }} image for Push Event - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: context: . file: ${{ matrix.dockerfile }} diff --git a/.github/workflows/build-stable-container.yml b/.github/workflows/build-stable-container.yml index db41bd4f..5471faad 100644 --- a/.github/workflows/build-stable-container.yml +++ b/.github/workflows/build-stable-container.yml @@ -54,7 +54,7 @@ jobs: quay.expires-after=12w - name: Build and push Docker ${{ matrix.name }} image for Push Event - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: context: . file: ${{ matrix.dockerfile }} From 749791cdf1316bc89415d27d503042d3f6b3f398 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 09:59:52 +0100 Subject: [PATCH 23/23] Bump docker/login-action from 3 to 4 (#5661) Bumps [docker/login-action](https://github.com/docker/login-action) from 3 to 4. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v3...v4) --- updated-dependencies: - dependency-name: docker/login-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-nightly-container.yml | 2 +- .github/workflows/build-stable-container.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-nightly-container.yml b/.github/workflows/build-nightly-container.yml index 6bb04402..88051d15 100644 --- a/.github/workflows/build-nightly-container.yml +++ b/.github/workflows/build-nightly-container.yml @@ -42,7 +42,7 @@ jobs: uses: docker/setup-buildx-action@v4 - name: Login to registry - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} diff --git a/.github/workflows/build-stable-container.yml b/.github/workflows/build-stable-container.yml index 5471faad..ee4c6eab 100644 --- a/.github/workflows/build-stable-container.yml +++ b/.github/workflows/build-stable-container.yml @@ -33,7 +33,7 @@ jobs: uses: docker/setup-buildx-action@v4 - name: Login to registry - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: quay.io username: ${{ secrets.QUAY_USERNAME }}