From e613e3c08c0b807e012ce08e41afa565d57ed39d Mon Sep 17 00:00:00 2001 From: Richard Lora Date: Tue, 30 Apr 2024 16:34:40 -0400 Subject: [PATCH 01/17] feat: optional `trending_enabled` and `search_enabled` params added --- config/config.example.yml | 16 ++++++ src/invidious/config.cr | 2 + src/invidious/routes/api/v1/feeds.cr | 5 ++ src/invidious/routes/api/v1/search.cr | 5 ++ src/invidious/routes/feeds.cr | 25 +++++---- src/invidious/routes/preferences.cr | 8 +++ src/invidious/routes/search.cr | 67 +++++++++++++----------- src/invidious/views/user/preferences.ecr | 9 ++++ 8 files changed, 96 insertions(+), 41 deletions(-) diff --git a/config/config.example.yml b/config/config.example.yml index 38085a20..9f0c252a 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -210,6 +210,22 @@ https_only: false ## #popular_enabled: true +## +## Enable/Disable the "Trending" tab on the main page. +## +## Accepted values: true, false +## Default: true +## +#trending_enabled: true + +## +## Enable/Disable "Search" on the main page. +## +## Accepted values: true, false +## Default: true +## +#search_enabled: true + ## ## Enable/Disable statstics (available at /api/v1/stats). ## The following data is available: diff --git a/src/invidious/config.cr b/src/invidious/config.cr index 09c2168b..f6146cd7 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -91,6 +91,8 @@ class Config # Subscribe to channels using PubSubHubbub (requires domain, hmac_key) property use_pubsub_feeds : Bool | Int32 = false property popular_enabled : Bool = true + property trending_enabled : Bool = true + property search_enabled : Bool = true property captcha_enabled : Bool = true property login_enabled : Bool = true property registration_enabled : Bool = true diff --git a/src/invidious/routes/api/v1/feeds.cr b/src/invidious/routes/api/v1/feeds.cr index 41865f34..f6feab5f 100644 --- a/src/invidious/routes/api/v1/feeds.cr +++ b/src/invidious/routes/api/v1/feeds.cr @@ -4,6 +4,11 @@ module Invidious::Routes::API::V1::Feeds env.response.content_type = "application/json" + if !CONFIG.trending_enabled + error_message = {"error" => "Administrator has disabled this endpoint."}.to_json + haltf env, 400, error_message + end + region = env.params.query["region"]? trending_type = env.params.query["type"]? diff --git a/src/invidious/routes/api/v1/search.cr b/src/invidious/routes/api/v1/search.cr index 2922b060..526914b0 100644 --- a/src/invidious/routes/api/v1/search.cr +++ b/src/invidious/routes/api/v1/search.cr @@ -5,6 +5,11 @@ module Invidious::Routes::API::V1::Search env.response.content_type = "application/json" + if !CONFIG.search_enabled + error_message = {"error" => "Administrator has disabled this endpoint."}.to_json + haltf env, 400, error_message + end + query = Invidious::Search::Query.new(env.params.query, :regular, region) begin diff --git a/src/invidious/routes/feeds.cr b/src/invidious/routes/feeds.cr index e20a7139..22a23a7e 100644 --- a/src/invidious/routes/feeds.cr +++ b/src/invidious/routes/feeds.cr @@ -44,20 +44,25 @@ module Invidious::Routes::Feeds def self.trending(env) locale = env.get("preferences").as(Preferences).locale + + if CONFIG.trending_enabled + trending_type = env.params.query["type"]? + trending_type ||= "Default" - trending_type = env.params.query["type"]? - trending_type ||= "Default" + region = env.params.query["region"]? + region ||= env.get("preferences").as(Preferences).region - region = env.params.query["region"]? - region ||= env.get("preferences").as(Preferences).region + begin + trending, plid = fetch_trending(trending_type, region, locale) + rescue ex + return error_template(500, ex) + end - begin - trending, plid = fetch_trending(trending_type, region, locale) - rescue ex - return error_template(500, ex) + templated "feeds/trending" + else + message = translate(locale, "The Trending feed has been disabled by the administrator.") + templated "message" end - - templated "feeds/trending" end def self.subscriptions(env) diff --git a/src/invidious/routes/preferences.cr b/src/invidious/routes/preferences.cr index 112535bd..9aee0d8c 100644 --- a/src/invidious/routes/preferences.cr +++ b/src/invidious/routes/preferences.cr @@ -198,6 +198,14 @@ module Invidious::Routes::PreferencesRoute popular_enabled ||= "off" CONFIG.popular_enabled = popular_enabled == "on" + trending_enabled = env.params.body["trending_enabled"]?.try &.as(String) + trending_enabled ||= "off" + CONFIG.trending_enabled = trending_enabled == "on" + + search_enabled = env.params.body["search_enabled"]?.try &.as(String) + search_enabled ||= "off" + CONFIG.search_enabled = search_enabled == "on" + captcha_enabled = env.params.body["captcha_enabled"]?.try &.as(String) captcha_enabled ||= "off" CONFIG.captcha_enabled = captcha_enabled == "on" diff --git a/src/invidious/routes/search.cr b/src/invidious/routes/search.cr index 5be33533..ae7d9833 100644 --- a/src/invidious/routes/search.cr +++ b/src/invidious/routes/search.cr @@ -40,41 +40,46 @@ module Invidious::Routes::Search prefs = env.get("preferences").as(Preferences) locale = prefs.locale - region = env.params.query["region"]? || prefs.region + if CONFIG.search_enabled + region = env.params.query["region"]? || prefs.region - query = Invidious::Search::Query.new(env.params.query, :regular, region) + query = Invidious::Search::Query.new(env.params.query, :regular, region) - if query.empty? - # Display the full page search box implemented in #1977 - env.set "search", "" - templated "search_homepage", navbar_search: false - else - user = env.get? "user" - - begin - items = query.process - rescue ex : ChannelSearchException - return error_template(404, "Unable to find channel with id of '#{HTML.escape(ex.channel)}'. Are you sure that's an actual channel id? It should look like 'UC4QobU6STFB0P71PMvOGN5A'.") - rescue ex - return error_template(500, ex) - end - - redirect_url = Invidious::Frontend::Misc.redirect_url(env) - - # Pagination - page_nav_html = Frontend::Pagination.nav_numeric(locale, - base_url: "/search?#{query.to_http_params}", - current_page: query.page, - show_next: (items.size >= 20) - ) - - if query.type == Invidious::Search::Query::Type::Channel - env.set "search", "channel:#{query.channel} #{query.text}" + if query.empty? + # Display the full page search box implemented in #1977 + env.set "search", "" + templated "search_homepage", navbar_search: false else - env.set "search", query.text - end + user = env.get? "user" - templated "search" + begin + items = query.process + rescue ex : ChannelSearchException + return error_template(404, "Unable to find channel with id of '#{HTML.escape(ex.channel)}'. Are you sure that's an actual channel id? It should look like 'UC4QobU6STFB0P71PMvOGN5A'.") + rescue ex + return error_template(500, ex) + end + + redirect_url = Invidious::Frontend::Misc.redirect_url(env) + + # Pagination + page_nav_html = Frontend::Pagination.nav_numeric(locale, + base_url: "/search?#{query.to_http_params}", + current_page: query.page, + show_next: (items.size >= 20) + ) + + if query.type == Invidious::Search::Query::Type::Channel + env.set "search", "channel:#{query.channel} #{query.text}" + else + env.set "search", query.text + end + + templated "search" + end + else + message = translate(locale, "Search has been disabled by the administrator.") + templated "message" end end diff --git a/src/invidious/views/user/preferences.ecr b/src/invidious/views/user/preferences.ecr index 55349c5a..4cda8421 100644 --- a/src/invidious/views/user/preferences.ecr +++ b/src/invidious/views/user/preferences.ecr @@ -287,6 +287,15 @@ checked<% end %>> +
+ + checked<% end %>> +
+ +
+ + checked<% end %>> +
From 5fa293541b05aa9fc0be404e5e872cb991cbe423 Mon Sep 17 00:00:00 2001 From: Richard Lora Date: Fri, 3 May 2024 10:36:43 -0400 Subject: [PATCH 02/17] fix(feeds.cr): http status code --- src/invidious/routes/api/v1/feeds.cr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/invidious/routes/api/v1/feeds.cr b/src/invidious/routes/api/v1/feeds.cr index f6feab5f..3a483526 100644 --- a/src/invidious/routes/api/v1/feeds.cr +++ b/src/invidious/routes/api/v1/feeds.cr @@ -6,7 +6,7 @@ module Invidious::Routes::API::V1::Feeds if !CONFIG.trending_enabled error_message = {"error" => "Administrator has disabled this endpoint."}.to_json - haltf env, 400, error_message + haltf env, 403, error_message end region = env.params.query["region"]? @@ -36,7 +36,7 @@ module Invidious::Routes::API::V1::Feeds if !CONFIG.popular_enabled error_message = {"error" => "Administrator has disabled this endpoint."}.to_json - haltf env, 400, error_message + haltf env, 403, error_message end JSON.build do |json| From 3abf21625cc88d92815814a6217d7a173eec1336 Mon Sep 17 00:00:00 2001 From: Richard Lora Date: Fri, 3 May 2024 10:38:57 -0400 Subject: [PATCH 03/17] fix(search.cr): http status code --- src/invidious/routes/api/v1/search.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/routes/api/v1/search.cr b/src/invidious/routes/api/v1/search.cr index 526914b0..3c44a989 100644 --- a/src/invidious/routes/api/v1/search.cr +++ b/src/invidious/routes/api/v1/search.cr @@ -7,7 +7,7 @@ module Invidious::Routes::API::V1::Search if !CONFIG.search_enabled error_message = {"error" => "Administrator has disabled this endpoint."}.to_json - haltf env, 400, error_message + haltf env, 403, error_message end query = Invidious::Search::Query.new(env.params.query, :regular, region) From e0f20b06418e1a93ae6c0e27e8e2871970c92803 Mon Sep 17 00:00:00 2001 From: Richard Lora Date: Fri, 3 May 2024 14:00:28 -0400 Subject: [PATCH 04/17] style(feeds.cr): fix code formatting --- src/invidious/routes/feeds.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/routes/feeds.cr b/src/invidious/routes/feeds.cr index 22a23a7e..693becb8 100644 --- a/src/invidious/routes/feeds.cr +++ b/src/invidious/routes/feeds.cr @@ -44,7 +44,7 @@ module Invidious::Routes::Feeds def self.trending(env) locale = env.get("preferences").as(Preferences).locale - + if CONFIG.trending_enabled trending_type = env.params.query["type"]? trending_type ||= "Default" From da422fae05da70740be881c12f82c955f9fb14b7 Mon Sep 17 00:00:00 2001 From: Richard Lora Date: Sun, 30 Jun 2024 18:05:26 -0400 Subject: [PATCH 05/17] feat(invidious): specific pages are disabled with the use of an array --- config/config.example.yml | 27 ++++++------------------ src/invidious.cr | 2 +- src/invidious/config.cr | 9 +++++--- src/invidious/routes/api/v1/feeds.cr | 4 ++-- src/invidious/routes/api/v1/search.cr | 2 +- src/invidious/routes/feeds.cr | 4 ++-- src/invidious/routes/preferences.cr | 19 ++++++----------- src/invidious/routes/search.cr | 4 ++-- src/invidious/views/user/preferences.ecr | 6 +++--- 9 files changed, 30 insertions(+), 47 deletions(-) diff --git a/config/config.example.yml b/config/config.example.yml index 9f0c252a..8749ec57 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -203,28 +203,13 @@ https_only: false # ----------------------------- ## -## Enable/Disable the "Popular" tab on the main page. +## Enable/Disable specific pages on the main page. +## Example: +## pages_enabled: +## trending: true +## popular: true +## search: true ## -## Accepted values: true, false -## Default: true -## -#popular_enabled: true - -## -## Enable/Disable the "Trending" tab on the main page. -## -## Accepted values: true, false -## Default: true -## -#trending_enabled: true - -## -## Enable/Disable "Search" on the main page. -## -## Accepted values: true, false -## Default: true -## -#search_enabled: true ## ## Enable/Disable statstics (available at /api/v1/stats). diff --git a/src/invidious.cr b/src/invidious.cr index e0bd0101..d0a02a3d 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -176,7 +176,7 @@ if (CONFIG.use_pubsub_feeds.is_a?(Bool) && CONFIG.use_pubsub_feeds.as(Bool)) || Invidious::Jobs.register Invidious::Jobs::SubscribeToFeedsJob.new(PG_DB, HMAC_KEY) end -if CONFIG.popular_enabled +if CONFIG.page_enabled?("popular") Invidious::Jobs.register Invidious::Jobs::PullPopularVideosJob.new(PG_DB) end diff --git a/src/invidious/config.cr b/src/invidious/config.cr index f6146cd7..085aeef8 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -90,9 +90,7 @@ class Config property domain : String? # Subscribe to channels using PubSubHubbub (requires domain, hmac_key) property use_pubsub_feeds : Bool | Int32 = false - property popular_enabled : Bool = true - property trending_enabled : Bool = true - property search_enabled : Bool = true + property pages_enabled : Hash(String, Bool) = {"trending" => true, "popular" => true, "search" => true} property captcha_enabled : Bool = true property login_enabled : Bool = true property registration_enabled : Bool = true @@ -154,6 +152,11 @@ class Config end end + def page_enabled?(page : String) : Bool + @pages_enabled[page]? || false + end + + def self.load # Load config from file or YAML string env var env_config_file = "INVIDIOUS_CONFIG_FILE" diff --git a/src/invidious/routes/api/v1/feeds.cr b/src/invidious/routes/api/v1/feeds.cr index 3a483526..bfec4fb6 100644 --- a/src/invidious/routes/api/v1/feeds.cr +++ b/src/invidious/routes/api/v1/feeds.cr @@ -4,7 +4,7 @@ module Invidious::Routes::API::V1::Feeds env.response.content_type = "application/json" - if !CONFIG.trending_enabled + if !CONFIG.page_enabled?("trending") error_message = {"error" => "Administrator has disabled this endpoint."}.to_json haltf env, 403, error_message end @@ -34,7 +34,7 @@ module Invidious::Routes::API::V1::Feeds env.response.content_type = "application/json" - if !CONFIG.popular_enabled + if !CONFIG.page_enabled?("popular") error_message = {"error" => "Administrator has disabled this endpoint."}.to_json haltf env, 403, error_message end diff --git a/src/invidious/routes/api/v1/search.cr b/src/invidious/routes/api/v1/search.cr index 3c44a989..48df3a2b 100644 --- a/src/invidious/routes/api/v1/search.cr +++ b/src/invidious/routes/api/v1/search.cr @@ -5,7 +5,7 @@ module Invidious::Routes::API::V1::Search env.response.content_type = "application/json" - if !CONFIG.search_enabled + if !CONFIG.page_enabled?("search") error_message = {"error" => "Administrator has disabled this endpoint."}.to_json haltf env, 403, error_message end diff --git a/src/invidious/routes/feeds.cr b/src/invidious/routes/feeds.cr index 693becb8..114b9edc 100644 --- a/src/invidious/routes/feeds.cr +++ b/src/invidious/routes/feeds.cr @@ -34,7 +34,7 @@ module Invidious::Routes::Feeds def self.popular(env) locale = env.get("preferences").as(Preferences).locale - if CONFIG.popular_enabled + if CONFIG.page_enabled?("popular") templated "feeds/popular" else message = translate(locale, "The Popular feed has been disabled by the administrator.") @@ -45,7 +45,7 @@ module Invidious::Routes::Feeds def self.trending(env) locale = env.get("preferences").as(Preferences).locale - if CONFIG.trending_enabled + if CONFIG.page_enabled?("trending") trending_type = env.params.query["type"]? trending_type ||= "Default" diff --git a/src/invidious/routes/preferences.cr b/src/invidious/routes/preferences.cr index 9aee0d8c..9106d4cf 100644 --- a/src/invidious/routes/preferences.cr +++ b/src/invidious/routes/preferences.cr @@ -194,17 +194,12 @@ module Invidious::Routes::PreferencesRoute end CONFIG.default_user_preferences.feed_menu = admin_feed_menu - popular_enabled = env.params.body["popular_enabled"]?.try &.as(String) - popular_enabled ||= "off" - CONFIG.popular_enabled = popular_enabled == "on" - - trending_enabled = env.params.body["trending_enabled"]?.try &.as(String) - trending_enabled ||= "off" - CONFIG.trending_enabled = trending_enabled == "on" - - search_enabled = env.params.body["search_enabled"]?.try &.as(String) - search_enabled ||= "off" - CONFIG.search_enabled = search_enabled == "on" + pages_enabled = { + "popular" => (env.params.body["popular_enabled"]?.try &.as(String) || "off") == "on", + "trending" => (env.params.body["trending_enabled"]?.try &.as(String) || "off") == "on", + "search" => (env.params.body["search_enabled"]?.try &.as(String) || "off") == "on" + } + CONFIG.pages_enabled = pages_enabled captcha_enabled = env.params.body["captcha_enabled"]?.try &.as(String) captcha_enabled ||= "off" @@ -355,4 +350,4 @@ module Invidious::Routes::PreferencesRoute env.redirect referer end -end +end \ No newline at end of file diff --git a/src/invidious/routes/search.cr b/src/invidious/routes/search.cr index ae7d9833..f825ffc7 100644 --- a/src/invidious/routes/search.cr +++ b/src/invidious/routes/search.cr @@ -40,7 +40,7 @@ module Invidious::Routes::Search prefs = env.get("preferences").as(Preferences) locale = prefs.locale - if CONFIG.search_enabled + if CONFIG.page_enabled?("search") region = env.params.query["region"]? || prefs.region query = Invidious::Search::Query.new(env.params.query, :regular, region) @@ -115,4 +115,4 @@ module Invidious::Routes::Search templated "hashtag" end -end +end \ No newline at end of file diff --git a/src/invidious/views/user/preferences.ecr b/src/invidious/views/user/preferences.ecr index 4cda8421..564eca9e 100644 --- a/src/invidious/views/user/preferences.ecr +++ b/src/invidious/views/user/preferences.ecr @@ -284,17 +284,17 @@
- checked<% end %>> + checked<% end %>>
- checked<% end %>> + checked<% end %>>
- checked<% end %>> + checked<% end %>>
From ba7e504fd1eb6fe2932089a3de267a24cdc037fa Mon Sep 17 00:00:00 2001 From: Richard Lora Date: Sun, 30 Jun 2024 18:11:56 -0400 Subject: [PATCH 06/17] chore(search.cr): add newline at end of file --- src/invidious/routes/search.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/routes/search.cr b/src/invidious/routes/search.cr index f825ffc7..8c500e02 100644 --- a/src/invidious/routes/search.cr +++ b/src/invidious/routes/search.cr @@ -115,4 +115,4 @@ module Invidious::Routes::Search templated "hashtag" end -end \ No newline at end of file +end From bfe51590b1bae0a8a86ad68c0b35c3ba63e4d390 Mon Sep 17 00:00:00 2001 From: Richard Lora Date: Mon, 1 Jul 2024 14:48:55 -0400 Subject: [PATCH 07/17] chore(lint): format with crystal tool --- src/invidious/config.cr | 1 - src/invidious/routes/preferences.cr | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/invidious/config.cr b/src/invidious/config.cr index 085aeef8..4adadc48 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -156,7 +156,6 @@ class Config @pages_enabled[page]? || false end - def self.load # Load config from file or YAML string env var env_config_file = "INVIDIOUS_CONFIG_FILE" diff --git a/src/invidious/routes/preferences.cr b/src/invidious/routes/preferences.cr index 9106d4cf..1dfc472a 100644 --- a/src/invidious/routes/preferences.cr +++ b/src/invidious/routes/preferences.cr @@ -195,9 +195,9 @@ module Invidious::Routes::PreferencesRoute CONFIG.default_user_preferences.feed_menu = admin_feed_menu pages_enabled = { - "popular" => (env.params.body["popular_enabled"]?.try &.as(String) || "off") == "on", + "popular" => (env.params.body["popular_enabled"]?.try &.as(String) || "off") == "on", "trending" => (env.params.body["trending_enabled"]?.try &.as(String) || "off") == "on", - "search" => (env.params.body["search_enabled"]?.try &.as(String) || "off") == "on" + "search" => (env.params.body["search_enabled"]?.try &.as(String) || "off") == "on", } CONFIG.pages_enabled = pages_enabled @@ -350,4 +350,4 @@ module Invidious::Routes::PreferencesRoute env.redirect referer end -end \ No newline at end of file +end From 2ec34f36f5e3bd1f5905b7d970281ee52d30db91 Mon Sep 17 00:00:00 2001 From: Richard Lora Date: Mon, 1 Jul 2024 19:32:53 -0400 Subject: [PATCH 08/17] Update config/config.example.yml Co-authored-by: Samantaz Fox --- config/config.example.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/config/config.example.yml b/config/config.example.yml index 8749ec57..2b0e2323 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -204,11 +204,11 @@ https_only: false ## ## Enable/Disable specific pages on the main page. -## Example: -## pages_enabled: -## trending: true -## popular: true -## search: true +## +#pages_enabled: +# trending: true +# popular: true +# search: true ## ## From b0cbd29563d3d03d8e978dab24270f93a5724a5a Mon Sep 17 00:00:00 2001 From: Richard Lora Date: Mon, 1 Jul 2024 19:36:14 -0400 Subject: [PATCH 09/17] feat(en-US.json): add translation key and value --- locales/en-US.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/locales/en-US.json b/locales/en-US.json index 3987f796..faf98fff 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -496,5 +496,7 @@ "toggle_theme": "Toggle Theme", "carousel_slide": "Slide {{current}} of {{total}}", "carousel_skip": "Skip the Carousel", - "carousel_go_to": "Go to slide `x`" + "carousel_go_to": "Go to slide `x`", + "preferences_trending_enabled_label": "Trending enabled: ", + "preferences_search_enabled_label": "Search enabled: " } From fdec9046b1352eb7877a24df3235a84fe7fdc3f2 Mon Sep 17 00:00:00 2001 From: Richard Lora Date: Mon, 1 Jul 2024 19:36:33 -0400 Subject: [PATCH 10/17] Update src/invidious/views/user/preferences.ecr Co-authored-by: Samantaz Fox --- src/invidious/views/user/preferences.ecr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/invidious/views/user/preferences.ecr b/src/invidious/views/user/preferences.ecr index 564eca9e..e1633cbc 100644 --- a/src/invidious/views/user/preferences.ecr +++ b/src/invidious/views/user/preferences.ecr @@ -288,12 +288,12 @@
- + checked<% end %>>
- + checked<% end %>>
From aeb2b1046d4f17c68a24cf019c92ba206e029c41 Mon Sep 17 00:00:00 2001 From: Norkz Date: Wed, 21 May 2025 19:44:35 -0400 Subject: [PATCH 11/17] feat: test --- locales/en-US.json | 6 +- src/invidious/config.cr | 35 +++++++--- src/invidious/routes/search.cr | 114 +++++++++++++-------------------- 3 files changed, 74 insertions(+), 81 deletions(-) diff --git a/locales/en-US.json b/locales/en-US.json index 2d0adc27..1aa2ab92 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -504,5 +504,7 @@ "preferences_search_enabled_label": "Search enabled: ", "timeline_parse_error_placeholder_heading": "Unable to parse item", "timeline_parse_error_placeholder_message": "Invidious encountered an error while trying to parse this item. For more information see below:", - "timeline_parse_error_show_technical_details": "Show technical details" -} + "timeline_parse_error_show_technical_details": "Show technical details", + "Search has been disabled by the administrator.": "Search has been disabled by the administrator.", + "This helps protect our community. Learn more": "This helps protect our community. Learn more" +} \ No newline at end of file diff --git a/src/invidious/config.cr b/src/invidious/config.cr index 9bf5be44..36cb40a3 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -111,13 +111,29 @@ class Config # Used to tell Invidious it is behind a proxy, so links to resources should be https:// property https_only : Bool? + # HMAC signing key for CSRF tokens and verifying pubsub subscriptions property hmac_key : String = "" # Domain to be used for links to resources on the site where an absolute URL is required property domain : String? # Subscribe to channels using PubSubHubbub (requires domain, hmac_key) property use_pubsub_feeds : Bool | Int32 = false - property pages_enabled : Hash(String, Bool) = {"trending" => true, "popular" => true, "search" => true} + + # ————————————————————————————————————————————————————————————————————————————————————— + # DEPRECATED: use `pages_enabled["popular"]` instead. + @[Deprecated("`popular_enabled` will be removed in a future release; use pages_enabled[\"popular\"] instead")] + property popular_enabled : Bool = true + + # Global per-page feature toggles. + # Valid keys: "trending", "popular", "search" + # If someone sets both `popular_enabled` and `pages_enabled["popular"]`, the latter takes precedence. + property pages_enabled : Hash(String, Bool) = { + "trending" => true, + "popular" => true, + "search" => true, + } + # ————————————————————————————————————————————————————————————————————————————————————— + property captcha_enabled : Bool = true property login_enabled : Bool = true property registration_enabled : Bool = true @@ -188,18 +204,21 @@ class Config when Bool return disabled when Array - if disabled.includes? option - return true - else - return false - end + disabled.includes?(option) else - return false + false end end + # Centralized page toggle with legacy fallback for `popular_enabled` def page_enabled?(page : String) : Bool - @pages_enabled[page]? || false + if pages_enabled.has_key?(page) + pages_enabled[page] + elsif page == "popular" + popular_enabled + else + true + end end def self.load diff --git a/src/invidious/routes/search.cr b/src/invidious/routes/search.cr index cbae9183..bd76775d 100644 --- a/src/invidious/routes/search.cr +++ b/src/invidious/routes/search.cr @@ -40,79 +40,51 @@ module Invidious::Routes::Search prefs = env.get("preferences").as(Preferences) locale = prefs.locale - if CONFIG.page_enabled?("search") - region = env.params.query["region"]? || prefs.region - - query = Invidious::Search::Query.new(env.params.query, :regular, region) - - if query.empty? - # Display the full page search box implemented in #1977 - env.set "search", "" - templated "search_homepage", navbar_search: false - else - user = env.get? "user" - - # An URL was copy/pasted in the search box. - # Redirect the user to the appropriate page. - if query.url? - return env.redirect UrlSanitizer.process(query.text).to_s - end - - begin - if user - items = query.process(user.as(User)) - else - items = query.process - end - rescue ex : ChannelSearchException - return error_template(404, "Unable to find channel with id of '#{HTML.escape(ex.channel)}'. Are you sure that's an actual channel id? It should look like 'UC4QobU6STFB0P71PMvOGN5A'.") - rescue ex - return error_template(500, ex) - end - - redirect_url = Invidious::Frontend::Misc.redirect_url(env) - - # Pagination - page_nav_html = Frontend::Pagination.nav_numeric(locale, - base_url: "/search?#{query.to_http_params}", - current_page: query.page, - show_next: (items.size >= 20) - ) - - if query.type == Invidious::Search::Query::Type::Channel - env.set "search", "channel:#{query.channel} #{query.text}" - else - user = env.get? "user" - - begin - items = query.process - rescue ex : ChannelSearchException - return error_template(404, "Unable to find channel with id of '#{HTML.escape(ex.channel)}'. Are you sure that's an actual channel id? It should look like 'UC4QobU6STFB0P71PMvOGN5A'.") - rescue ex - return error_template(500, ex) - end - - redirect_url = Invidious::Frontend::Misc.redirect_url(env) - - # Pagination - page_nav_html = Frontend::Pagination.nav_numeric(locale, - base_url: "/search?#{query.to_http_params}", - current_page: query.page, - show_next: (items.size >= 20) - ) - - if query.type == Invidious::Search::Query::Type::Channel - env.set "search", "channel:#{query.channel} #{query.text}" - else - env.set "search", query.text - end - - templated "search" - end - else + # if search is disabled, show the “disabled” message immediately + unless CONFIG.page_enabled?("search") message = translate(locale, "Search has been disabled by the administrator.") - templated "message" + return templated "message" end + + # otherwise, do a normal search + region = env.params.query["region"]? || prefs.region + query = Invidious::Search::Query.new(env.params.query, :regular, region) + + # empty query → show homepage + if query.empty? + env.set "search", "" + return templated "search_homepage", navbar_search: false + end + + # non‐empty query → process it + user = env.get?("user") + if query.url? + return env.redirect UrlSanitizer.process(query.text).to_s + end + + begin + items = user ? query.process(user.as(User)) : query.process + rescue ex : ChannelSearchException + return error_template 404, "Unable to find channel with id “#{HTML.escape(ex.channel)}”…" + rescue ex + return error_template 500, ex + end + + # Pagination + page_nav_html = Frontend::Pagination.nav_numeric(locale, + base_url: "/search?#{query.to_http_params}", + current_page: query.page, + show_next: (items.size >= 20) + ) + + # If it's a channel search, prefix the box; otherwise just show the text + if query.type == Invidious::Search::Query::Type::Channel + env.set "search", "channel:#{query.channel} #{query.text}" + else + env.set "search", query.text + end + + templated "search" end def self.hashtag(env : HTTP::Server::Context) From ce0a9faaaef07ec1c286f8fb7f40712c0c1727b5 Mon Sep 17 00:00:00 2001 From: Norkz Date: Wed, 21 May 2025 21:21:45 -0400 Subject: [PATCH 12/17] feat: test2 --- locales/en-US.json | 1 + src/invidious/routes/search.cr | 2 ++ 2 files changed, 3 insertions(+) diff --git a/locales/en-US.json b/locales/en-US.json index 1aa2ab92..eb0dfe2d 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -4,6 +4,7 @@ "Answer": "Answer", "Search for videos": "Search for videos", "The Popular feed has been disabled by the administrator.": "The Popular feed has been disabled by the administrator.", + "The Trending feed has been disabled by the administrator": "The Trending feed has been disabled by the administrator", "generic_channels_count": "{{count}} channel", "generic_channels_count_plural": "{{count}} channels", "generic_views_count": "{{count}} view", diff --git a/src/invidious/routes/search.cr b/src/invidious/routes/search.cr index bd76775d..eb253d2c 100644 --- a/src/invidious/routes/search.cr +++ b/src/invidious/routes/search.cr @@ -70,6 +70,8 @@ module Invidious::Routes::Search return error_template 500, ex end + redirect_url = Invidious::Frontend::Misc.redirect_url(env) + # Pagination page_nav_html = Frontend::Pagination.nav_numeric(locale, base_url: "/search?#{query.to_http_params}", From 171bac97d1742b99bdf24dfe2d37d8561e92325c Mon Sep 17 00:00:00 2001 From: Richard Lora Date: Sat, 24 May 2025 10:01:50 -0400 Subject: [PATCH 13/17] Update locales/en-US.json Co-authored-by: Fijxu --- locales/en-US.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/en-US.json b/locales/en-US.json index eb0dfe2d..de9df452 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -3,8 +3,8 @@ "Add to playlist: ": "Add to playlist: ", "Answer": "Answer", "Search for videos": "Search for videos", - "The Popular feed has been disabled by the administrator.": "The Popular feed has been disabled by the administrator.", - "The Trending feed has been disabled by the administrator": "The Trending feed has been disabled by the administrator", + "popular_page_disabled": "The Popular feed has been disabled by the administrator.", + "trending_page_disabled": "The Trending feed has been disabled by the administrator.", "generic_channels_count": "{{count}} channel", "generic_channels_count_plural": "{{count}} channels", "generic_views_count": "{{count}} view", From e1d134f6a06f9fa2f28c22766f625890da6efe59 Mon Sep 17 00:00:00 2001 From: Richard Lora Date: Sat, 24 May 2025 10:02:00 -0400 Subject: [PATCH 14/17] Update locales/en-US.json Co-authored-by: Fijxu --- locales/en-US.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/en-US.json b/locales/en-US.json index de9df452..e5d340cf 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -506,6 +506,6 @@ "timeline_parse_error_placeholder_heading": "Unable to parse item", "timeline_parse_error_placeholder_message": "Invidious encountered an error while trying to parse this item. For more information see below:", "timeline_parse_error_show_technical_details": "Show technical details", - "Search has been disabled by the administrator.": "Search has been disabled by the administrator.", + "search_page_disabled": "Search has been disabled by the administrator.", "This helps protect our community. Learn more": "This helps protect our community. Learn more" } \ No newline at end of file From 9fbce527e7a3a1bb5256c0e900c516f78bf01443 Mon Sep 17 00:00:00 2001 From: NorkzYT Date: Sat, 24 May 2025 14:20:34 +0000 Subject: [PATCH 15/17] =?UTF-8?q?=F0=9F=93=9D=20(locales/en-US.json):=20re?= =?UTF-8?q?move=20redundant=20translation=20strings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/en-US.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/locales/en-US.json b/locales/en-US.json index e5d340cf..d5276edf 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -506,6 +506,5 @@ "timeline_parse_error_placeholder_heading": "Unable to parse item", "timeline_parse_error_placeholder_message": "Invidious encountered an error while trying to parse this item. For more information see below:", "timeline_parse_error_show_technical_details": "Show technical details", - "search_page_disabled": "Search has been disabled by the administrator.", - "This helps protect our community. Learn more": "This helps protect our community. Learn more" + "search_page_disabled": "Search has been disabled by the administrator." } \ No newline at end of file From 3eeec8632d73c122ea7c1736d7bb4064318c8928 Mon Sep 17 00:00:00 2001 From: NorkzYT Date: Sat, 24 May 2025 14:50:58 +0000 Subject: [PATCH 16/17] =?UTF-8?q?=F0=9F=8C=90=20(feeds.cr,=20search.cr):?= =?UTF-8?q?=20update=20translation=20keys=20for=20disabled=20feeds=20and?= =?UTF-8?q?=20search=20messages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/invidious/routes/feeds.cr | 4 ++-- src/invidious/routes/search.cr | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/invidious/routes/feeds.cr b/src/invidious/routes/feeds.cr index 672f6280..c1852f5e 100644 --- a/src/invidious/routes/feeds.cr +++ b/src/invidious/routes/feeds.cr @@ -37,7 +37,7 @@ module Invidious::Routes::Feeds if CONFIG.page_enabled?("popular") templated "feeds/popular" else - message = translate(locale, "The Popular feed has been disabled by the administrator.") + message = translate(locale, "popular_page_disabled") templated "message" end end @@ -60,7 +60,7 @@ module Invidious::Routes::Feeds templated "feeds/trending" else - message = translate(locale, "The Trending feed has been disabled by the administrator.") + message = translate(locale, "trending_page_disabled") templated "message" end end diff --git a/src/invidious/routes/search.cr b/src/invidious/routes/search.cr index eb253d2c..8a9a2d2b 100644 --- a/src/invidious/routes/search.cr +++ b/src/invidious/routes/search.cr @@ -42,7 +42,7 @@ module Invidious::Routes::Search # if search is disabled, show the “disabled” message immediately unless CONFIG.page_enabled?("search") - message = translate(locale, "Search has been disabled by the administrator.") + message = translate(locale, "search_page_disabled") return templated "message" end From e238624e8fdb21d4fd8894677adcc1b8507f9757 Mon Sep 17 00:00:00 2001 From: NorkzYT Date: Sat, 7 Jun 2025 11:52:13 +0000 Subject: [PATCH 17/17] feat(config.cr): introduce PagesEnabled struct for managing feature toggles for pages refactor(routes): replace direct page_enabled checks with centralized logic in before_all.cr for cleaner endpoint management chore(routes): remove redundant page_enabled checks from individual routes to streamline code and improve maintainability --- src/invidious/config.cr | 43 ++++++++++++++++++++++----- src/invidious/routes/api/v1/feeds.cr | 10 ------- src/invidious/routes/api/v1/search.cr | 5 ---- src/invidious/routes/before_all.cr | 22 ++++++++++++++ src/invidious/routes/feeds.cr | 34 +++++++-------------- src/invidious/routes/preferences.cr | 6 ++-- src/invidious/routes/search.cr | 6 ---- 7 files changed, 71 insertions(+), 55 deletions(-) diff --git a/src/invidious/config.cr b/src/invidious/config.cr index 36cb40a3..59380cb8 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -71,6 +71,37 @@ struct HTTPProxyConfig property port : Int32 end +# Structure used for global per-page feature toggles +struct PagesEnabled + include YAML::Serializable + + property trending : Bool = true + property popular : Bool = true + property search : Bool = true + + def has_key?(key : String) : Bool + %w(trending popular search).includes?(key) + end + + def [](key : String) : Bool + case key + when "trending" then @trending + when "popular" then @popular + when "search" then @search + else raise KeyError.new("Unknown page '#{key}'") + end + end + + def []=(key : String, value : Bool) + case key + when "trending" then @trending = value + when "popular" then @popular = value + when "search" then @search = value + else raise KeyError.new("Unknown page '#{key}'") + end + end +end + class Config include YAML::Serializable @@ -127,11 +158,7 @@ class Config # Global per-page feature toggles. # Valid keys: "trending", "popular", "search" # If someone sets both `popular_enabled` and `pages_enabled["popular"]`, the latter takes precedence. - property pages_enabled : Hash(String, Bool) = { - "trending" => true, - "popular" => true, - "search" => true, - } + property pages_enabled : PagesEnabled = PagesEnabled.new # ————————————————————————————————————————————————————————————————————————————————————— property captcha_enabled : Bool = true @@ -212,10 +239,10 @@ class Config # Centralized page toggle with legacy fallback for `popular_enabled` def page_enabled?(page : String) : Bool - if pages_enabled.has_key?(page) - pages_enabled[page] + if @pages_enabled.has_key?(page) + @pages_enabled[page] elsif page == "popular" - popular_enabled + @popular_enabled else true end diff --git a/src/invidious/routes/api/v1/feeds.cr b/src/invidious/routes/api/v1/feeds.cr index bfec4fb6..2e8328cb 100644 --- a/src/invidious/routes/api/v1/feeds.cr +++ b/src/invidious/routes/api/v1/feeds.cr @@ -4,11 +4,6 @@ module Invidious::Routes::API::V1::Feeds env.response.content_type = "application/json" - if !CONFIG.page_enabled?("trending") - error_message = {"error" => "Administrator has disabled this endpoint."}.to_json - haltf env, 403, error_message - end - region = env.params.query["region"]? trending_type = env.params.query["type"]? @@ -34,11 +29,6 @@ module Invidious::Routes::API::V1::Feeds env.response.content_type = "application/json" - if !CONFIG.page_enabled?("popular") - error_message = {"error" => "Administrator has disabled this endpoint."}.to_json - haltf env, 403, error_message - end - JSON.build do |json| json.array do popular_videos.each do |video| diff --git a/src/invidious/routes/api/v1/search.cr b/src/invidious/routes/api/v1/search.cr index 3d978c17..59a30745 100644 --- a/src/invidious/routes/api/v1/search.cr +++ b/src/invidious/routes/api/v1/search.cr @@ -5,11 +5,6 @@ module Invidious::Routes::API::V1::Search env.response.content_type = "application/json" - if !CONFIG.page_enabled?("search") - error_message = {"error" => "Administrator has disabled this endpoint."}.to_json - haltf env, 403, error_message - end - query = Invidious::Search::Query.new(env.params.query, :regular, region) begin diff --git a/src/invidious/routes/before_all.cr b/src/invidious/routes/before_all.cr index b5269668..5f6a1daa 100644 --- a/src/invidious/routes/before_all.cr +++ b/src/invidious/routes/before_all.cr @@ -102,6 +102,28 @@ module Invidious::Routes::BeforeAll preferences.locale = locale env.set "preferences", preferences + path = env.request.path + page_key = case path + when "/feed/popular", "/api/v1/popular" + "popular" + when "/feed/trending", "/api/v1/trending" + "trending" + when "/search", "/api/v1/search" + "search" + else + nil + end + + if page_key && !CONFIG.page_enabled?(page_key) + if path.starts_with?("/api/") + error_message = {error: "Administrator has disabled this endpoint."}.to_json + haltf env, 403, error_message + else + message = "#{page_key}_page_disabled" + return error_template(403, message) + end + end + # Allow media resources to be loaded from google servers # TODO: check if *.youtube.com can be removed # diff --git a/src/invidious/routes/feeds.cr b/src/invidious/routes/feeds.cr index c1852f5e..de82e1fb 100644 --- a/src/invidious/routes/feeds.cr +++ b/src/invidious/routes/feeds.cr @@ -33,36 +33,24 @@ module Invidious::Routes::Feeds def self.popular(env) locale = env.get("preferences").as(Preferences).locale - - if CONFIG.page_enabled?("popular") - templated "feeds/popular" - else - message = translate(locale, "popular_page_disabled") - templated "message" - end + templated "feeds/popular" end def self.trending(env) locale = env.get("preferences").as(Preferences).locale + trending_type = env.params.query["type"]? + trending_type ||= "Default" - if CONFIG.page_enabled?("trending") - trending_type = env.params.query["type"]? - trending_type ||= "Default" + region = env.params.query["region"]? + region ||= env.get("preferences").as(Preferences).region - region = env.params.query["region"]? - region ||= env.get("preferences").as(Preferences).region - - begin - trending, plid = fetch_trending(trending_type, region, locale) - rescue ex - return error_template(500, ex) - end - - templated "feeds/trending" - else - message = translate(locale, "trending_page_disabled") - templated "message" + begin + trending, plid = fetch_trending(trending_type, region, locale) + rescue ex + return error_template(500, ex) end + + templated "feeds/trending" end def self.subscriptions(env) diff --git a/src/invidious/routes/preferences.cr b/src/invidious/routes/preferences.cr index 34cea387..3852f8a9 100644 --- a/src/invidious/routes/preferences.cr +++ b/src/invidious/routes/preferences.cr @@ -200,9 +200,9 @@ module Invidious::Routes::PreferencesRoute CONFIG.default_user_preferences.feed_menu = admin_feed_menu pages_enabled = { - "popular" => (env.params.body["popular_enabled"]?.try &.as(String) || "off") == "on", - "trending" => (env.params.body["trending_enabled"]?.try &.as(String) || "off") == "on", - "search" => (env.params.body["search_enabled"]?.try &.as(String) || "off") == "on", + popular: (env.params.body["popular_enabled"]?.try &.as(String) || "on") == "on", + trending: (env.params.body["trending_enabled"]?.try &.as(String) || "on") == "on", + search: (env.params.body["search_enabled"]?.try &.as(String) || "on") == "on", } CONFIG.pages_enabled = pages_enabled diff --git a/src/invidious/routes/search.cr b/src/invidious/routes/search.cr index 8a9a2d2b..5b10887c 100644 --- a/src/invidious/routes/search.cr +++ b/src/invidious/routes/search.cr @@ -40,12 +40,6 @@ module Invidious::Routes::Search prefs = env.get("preferences").as(Preferences) locale = prefs.locale - # if search is disabled, show the “disabled” message immediately - unless CONFIG.page_enabled?("search") - message = translate(locale, "search_page_disabled") - return templated "message" - end - # otherwise, do a normal search region = env.params.query["region"]? || prefs.region query = Invidious::Search::Query.new(env.params.query, :regular, region)