diff --git a/locales/en-US.json b/locales/en-US.json index 44b40c249..129556654 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -475,5 +475,6 @@ "channel_tab_shorts_label": "Shorts", "channel_tab_streams_label": "Livestreams", "channel_tab_playlists_label": "Playlists", - "channel_tab_community_label": "Community" + "channel_tab_community_label": "Community", + "channel_tab_channels_label": "Channels" } diff --git a/src/invidious/channels/about.cr b/src/invidious/channels/about.cr index 09c3427a3..0054f8f24 100644 --- a/src/invidious/channels/about.cr +++ b/src/invidious/channels/about.cr @@ -16,12 +16,6 @@ record AboutChannel, tabs : Array(String), verified : Bool -record AboutRelatedChannel, - ucid : String, - author : String, - author_url : String, - author_thumbnail : String - def get_about_info(ucid, locale) : AboutChannel begin # "EgVhYm91dA==" is the base64-encoded protobuf object {"2:string":"about"} @@ -165,41 +159,15 @@ def get_about_info(ucid, locale) : AboutChannel ) end -def fetch_related_channels(about_channel : AboutChannel) : Array(AboutRelatedChannel) - # params is {"2:string":"channels"} encoded - channels = YoutubeAPI.browse(browse_id: about_channel.ucid, params: "EghjaGFubmVscw%3D%3D") - - tabs = channels.dig?("contents", "twoColumnBrowseResultsRenderer", "tabs").try(&.as_a?) || [] of JSON::Any - tab = tabs.find(&.dig?("tabRenderer", "title").try(&.as_s?).try(&.== "Channels")) - - return [] of AboutRelatedChannel if tab.nil? - - items = tab.dig?( - "tabRenderer", "content", - "sectionListRenderer", "contents", 0, - "itemSectionRenderer", "contents", 0, - "gridRenderer", "items" - ).try &.as_a? - - related = [] of AboutRelatedChannel - return related if (items.nil? || items.empty?) - - items.each do |item| - renderer = item["gridChannelRenderer"]? - next if !renderer - - related_id = renderer.dig("channelId").as_s - related_title = renderer.dig("title", "simpleText").as_s - related_author_url = renderer.dig("navigationEndpoint", "browseEndpoint", "canonicalBaseUrl").as_s - related_author_thumbnail = HelperExtractors.get_thumbnails(renderer) - - related << AboutRelatedChannel.new( - ucid: related_id, - author: related_title, - author_url: related_author_url, - author_thumbnail: related_author_thumbnail, - ) +def fetch_related_channels(about_channel : AboutChannel, continuation : String? = nil) : {Array(SearchChannel), String?} + if continuation.nil? + # params is {"2:string":"channels"} encoded + initial_data = YoutubeAPI.browse(browse_id: about_channel.ucid, params: "EghjaGFubmVscw%3D%3D") + else + initial_data = YoutubeAPI.browse(continuation) end - return related + items, continuation = extract_items(initial_data) + + return items.select(SearchChannel), continuation end diff --git a/src/invidious/frontend/channel_page.cr b/src/invidious/frontend/channel_page.cr index 7ac0e071c..53745dd5a 100644 --- a/src/invidious/frontend/channel_page.cr +++ b/src/invidious/frontend/channel_page.cr @@ -7,6 +7,7 @@ module Invidious::Frontend::ChannelPage Streams Playlists Community + Channels end def generate_tabs_links(locale : String, channel : AboutChannel, selected_tab : TabsAvailable) diff --git a/src/invidious/routes/api/v1/channels.cr b/src/invidious/routes/api/v1/channels.cr index 4e92b54e5..28ccdab94 100644 --- a/src/invidious/routes/api/v1/channels.cr +++ b/src/invidious/routes/api/v1/channels.cr @@ -102,31 +102,13 @@ module Invidious::Routes::API::V1::Channels json.array do # Fetch related channels begin - related_channels = fetch_related_channels(channel) + related_channels, _ = fetch_related_channels(channel) rescue ex - related_channels = [] of AboutRelatedChannel + related_channels = [] of SearchChannel end related_channels.each do |related_channel| - json.object do - json.field "author", related_channel.author - json.field "authorId", related_channel.ucid - json.field "authorUrl", related_channel.author_url - - json.field "authorThumbnails" do - json.array do - qualities = {32, 48, 76, 100, 176, 512} - - qualities.each do |quality| - json.object do - json.field "url", related_channel.author_thumbnail.gsub(/=\d+/, "=s#{quality}") - json.field "width", quality - json.field "height", quality - end - end - end - end - end + related_channel.to_json(locale, json) end end end # relatedChannels diff --git a/src/invidious/routes/channels.cr b/src/invidious/routes/channels.cr index 77d309fba..d3969d297 100644 --- a/src/invidious/routes/channels.cr +++ b/src/invidious/routes/channels.cr @@ -147,6 +147,26 @@ module Invidious::Routes::Channels templated "community" end + def self.channels(env) + data = self.fetch_basic_information(env) + return data if !data.is_a?(Tuple) + + locale, user, subscriptions, continuation, ucid, channel = data + + if channel.auto_generated + return env.redirect "/channel/#{channel.ucid}" + end + + items, next_continuation = fetch_related_channels(channel, continuation) + + # Featured/related channels can't be sorted + sort_options = [] of String + sort_by = nil + + selected_tab = Frontend::ChannelPage::TabsAvailable::Channels + templated "channel" + end + def self.about(env) data = self.fetch_basic_information(env) if !data.is_a?(Tuple) diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 0e6fba214..84dbed5bf 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -119,6 +119,7 @@ module Invidious::Routing get "/channel/:ucid/streams", Routes::Channels, :streams get "/channel/:ucid/playlists", Routes::Channels, :playlists get "/channel/:ucid/community", Routes::Channels, :community + get "/channel/:ucid/channels", Routes::Channels, :channels get "/channel/:ucid/about", Routes::Channels, :about get "/channel/:ucid/live", Routes::Channels, :live get "/user/:user/live", Routes::Channels, :live diff --git a/src/invidious/views/channel.ecr b/src/invidious/views/channel.ecr index 039f8752c..a29315ef8 100644 --- a/src/invidious/views/channel.ecr +++ b/src/invidious/views/channel.ecr @@ -8,6 +8,7 @@ when .shorts? then "/channel/#{ucid}/shorts" when .streams? then "/channel/#{ucid}/streams" when .playlists? then "/channel/#{ucid}/playlists" + when .channels? then "/channel/#{ucid}/channels" else "/channel/#{ucid}" end