From e1b2eb2a7bd98ee9d8179e48977ec4f386fc71ba Mon Sep 17 00:00:00 2001 From: syeopite Date: Wed, 26 Mar 2025 14:04:57 -0700 Subject: [PATCH 1/4] Parse members only badges of videos --- src/invidious/helpers/serialized_yt_data.cr | 2 ++ src/invidious/yt_backend/extractors.cr | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/invidious/helpers/serialized_yt_data.cr b/src/invidious/helpers/serialized_yt_data.cr index f8e8f187..69dc91d6 100644 --- a/src/invidious/helpers/serialized_yt_data.cr +++ b/src/invidious/helpers/serialized_yt_data.cr @@ -9,6 +9,7 @@ enum VideoBadges VR180 VR360 ClosedCaptions + MembersOnly end struct SearchVideo @@ -133,6 +134,7 @@ struct SearchVideo json.field "isVr360", self.badges.vr360? json.field "is3d", self.badges.three_d? json.field "hasCaptions", self.badges.closed_captions? + json.field "isMembersOnly", self.badges.members_only? end end diff --git a/src/invidious/yt_backend/extractors.cr b/src/invidious/yt_backend/extractors.cr index edd7bf1b..c0994ffb 100644 --- a/src/invidious/yt_backend/extractors.cr +++ b/src/invidious/yt_backend/extractors.cr @@ -135,6 +135,10 @@ private module Parsers when "Premium" # TODO: Potentially available as item_contents["topStandaloneBadge"]["metadataBadgeRenderer"] badges |= VideoBadges::Premium + when "Members only" + # TODO: Identify based on style attribute instead of label + # It should be more resistant to Youtube changes. + badges |= VideoBadges::MembersOnly else nil # Ignore end end From 7c0117253a60f228a377b64bd55f8f291e871c05 Mon Sep 17 00:00:00 2001 From: syeopite Date: Wed, 26 Mar 2025 14:45:02 -0700 Subject: [PATCH 2/4] Add badge to UI to differentiate member videos --- assets/css/default.css | 37 +++++++++++++++++++++++++ locales/en-US.json | 3 +- src/invidious/views/components/item.ecr | 10 +++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/assets/css/default.css b/assets/css/default.css index 2cedcf0c..995b8440 100644 --- a/assets/css/default.css +++ b/assets/css/default.css @@ -550,6 +550,11 @@ span > select { color: #565d64; } +.light-theme .video-badges > span { + background: rgb(235, 235, 235); + color: #828282; +} + @media (prefers-color-scheme: light) { .no-theme a:hover, .no-theme a:active, @@ -596,6 +601,11 @@ span > select { .light-theme .pure-menu-heading { color: #565d64; } + + .no-theme .video-badges > span { + background: rgb(235, 235, 235); + color: #828282; + } } @@ -658,6 +668,12 @@ body.dark-theme { color: inherit; } +.dark-theme .video-badges > span { + background: rgb(50, 50, 50); + color: #9e9e9e; +} + + @media (prefers-color-scheme: dark) { .no-theme a:hover, .no-theme a:active, @@ -719,6 +735,11 @@ body.dark-theme { .no-theme footer a { color: #adadad !important; } + + .no-theme .video-badges > span { + background: rgb(50, 50, 50); + color: #9e9e9e; + } } @@ -816,3 +837,19 @@ h1, h2, h3, h4, h5, p, #download_widget { width: 100%; } + +.video-badges > span { + display: flex; + align-items: center; + gap: 5px; + + padding: 2px 10px; + border-radius: 10px; + + font-size: 12px; + font-weight: 600; +} + +.video-badges > i { + margin-right: 5px; +} \ No newline at end of file diff --git a/locales/en-US.json b/locales/en-US.json index 4f2c2770..78ec0203 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -501,5 +501,6 @@ "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`", + "video_badges_members_only": "Members only" } diff --git a/src/invidious/views/components/item.ecr b/src/invidious/views/components/item.ecr index c966a926..59282165 100644 --- a/src/invidious/views/components/item.ecr +++ b/src/invidious/views/components/item.ecr @@ -200,6 +200,16 @@ <% end %> + <% if item.responds_to?(:badges) && !item.badges.none? %> +
+ <% + # TODO Other types of badges + %> + <% if item.badges.members_only? %> + <%=translate(locale, "video_badges_members_only")%> + <% end %> +
+ <%end%> <% end %> From 643675490d45101b29411a94234a9cbde336c0ed Mon Sep 17 00:00:00 2001 From: syeopite Date: Wed, 26 Mar 2025 14:57:17 -0700 Subject: [PATCH 3/4] Add setting to hide member-only videos --- locales/en-US.json | 3 ++- src/invidious/config.cr | 1 + src/invidious/routes/preferences.cr | 5 +++++ src/invidious/user/preferences.cr | 2 ++ src/invidious/views/components/items_paginated.ecr | 3 +++ src/invidious/views/feeds/trending.ecr | 1 + src/invidious/views/user/preferences.ecr | 6 ++++++ 7 files changed, 20 insertions(+), 1 deletion(-) diff --git a/locales/en-US.json b/locales/en-US.json index 78ec0203..9a7ac3cf 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -502,5 +502,6 @@ "carousel_slide": "Slide {{current}} of {{total}}", "carousel_skip": "Skip the Carousel", "carousel_go_to": "Go to slide `x`", - "video_badges_members_only": "Members only" + "video_badges_members_only": "Members only", + "preferences_exclude_members_only_videos_label": "Hide channel member-only videos" } diff --git a/src/invidious/config.cr b/src/invidious/config.cr index 140b0daf..c1c00c5e 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -52,6 +52,7 @@ struct ConfigPreferences property vr_mode : Bool = true property show_nick : Bool = true property save_player_pos : Bool = false + property exclude_members_only_videos : Bool = false def to_tuple {% begin %} diff --git a/src/invidious/routes/preferences.cr b/src/invidious/routes/preferences.cr index 39ca77c0..87fc1c67 100644 --- a/src/invidious/routes/preferences.cr +++ b/src/invidious/routes/preferences.cr @@ -144,6 +144,10 @@ module Invidious::Routes::PreferencesRoute notifications_only ||= "off" notifications_only = notifications_only == "on" + exclude_members_only_videos = env.params.body["exclude_members_only_videos"]?.try &.as(String) + exclude_members_only_videos ||= "off" + exclude_members_only_videos = exclude_members_only_videos == "on" + # Convert to JSON and back again to take advantage of converters used for compatibility preferences = Preferences.from_json({ annotations: annotations, @@ -180,6 +184,7 @@ module Invidious::Routes::PreferencesRoute vr_mode: vr_mode, show_nick: show_nick, save_player_pos: save_player_pos, + exclude_members_only_videos: exclude_members_only_videos, }.to_json) if user = env.get? "user" diff --git a/src/invidious/user/preferences.cr b/src/invidious/user/preferences.cr index 0a8525f3..979c15d0 100644 --- a/src/invidious/user/preferences.cr +++ b/src/invidious/user/preferences.cr @@ -57,6 +57,8 @@ struct Preferences property volume : Int32 = CONFIG.default_user_preferences.volume property save_player_pos : Bool = CONFIG.default_user_preferences.save_player_pos + property exclude_members_only_videos : Bool = CONFIG.default_user_preferences.exclude_members_only_videos + module BoolToString def self.to_json(value : String, json : JSON::Builder) json.string value diff --git a/src/invidious/views/components/items_paginated.ecr b/src/invidious/views/components/items_paginated.ecr index f69df3fe..1863b7d4 100644 --- a/src/invidious/views/components/items_paginated.ecr +++ b/src/invidious/views/components/items_paginated.ecr @@ -1,7 +1,10 @@ <%= page_nav_html %> +<% exclude_members_only_videos = env.get("preferences").as(Preferences).exclude_members_only_videos %>
<%- items.each do |item| -%> + <% next if exclude_members_only_videos && item.responds_to?(:badges) && + item.is_a? SearchVideo && item.badges.members_only? %> <%= rendered "components/item" %> <%- end -%>
diff --git a/src/invidious/views/feeds/trending.ecr b/src/invidious/views/feeds/trending.ecr index 7dc416c6..002f3a72 100644 --- a/src/invidious/views/feeds/trending.ecr +++ b/src/invidious/views/feeds/trending.ecr @@ -42,6 +42,7 @@
<% trending.each do |item| %> + <% next %> <%= rendered "components/item" %> <% end %>
diff --git a/src/invidious/views/user/preferences.ecr b/src/invidious/views/user/preferences.ecr index cf8b5593..dd324879 100644 --- a/src/invidious/views/user/preferences.ecr +++ b/src/invidious/views/user/preferences.ecr @@ -194,6 +194,12 @@ <% end %> + +
+ + checked<% end %>> +
+ <% if env.get? "user" %>
From 2a50d20715dc01134dd60a466e32cebe651216f1 Mon Sep 17 00:00:00 2001 From: syeopite Date: Thu, 10 Apr 2025 01:21:00 -0700 Subject: [PATCH 4/4] Document `exclude_members_only_videos` --- config/config.example.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/config/config.example.yml b/config/config.example.yml index 8484c6be..ee608e7b 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -1008,3 +1008,12 @@ default_user_preferences: ## Default: false ## #extend_desc: false + + ## + ## Allows excluding videos that are exclusive to channel members + ## from the frontend + ## + ## Accepted values: true, false + ## Default: false + ## + #exclude_members_only_videos: false