mirror of
				https://github.com/iv-org/invidious.git
				synced 2025-10-31 12:42:09 +00:00 
			
		
		
		
	Channels: Add support for releases and podcasts tabs (#3980)
This commit is contained in:
		| @@ -474,6 +474,8 @@ | ||||
|     "channel_tab_videos_label": "Videos", | ||||
|     "channel_tab_shorts_label": "Shorts", | ||||
|     "channel_tab_streams_label": "Livestreams", | ||||
|     "channel_tab_podcasts_label": "Podcasts", | ||||
|     "channel_tab_releases_label": "Releases", | ||||
|     "channel_tab_playlists_label": "Playlists", | ||||
|     "channel_tab_community_label": "Community", | ||||
|     "channel_tab_channels_label": "Channels" | ||||
|   | ||||
| @@ -26,3 +26,21 @@ def fetch_channel_playlists(ucid, author, continuation, sort_by) | ||||
|  | ||||
|   return extract_items(initial_data, author, ucid) | ||||
| end | ||||
|  | ||||
| def fetch_channel_podcasts(ucid, author, continuation) | ||||
|   if continuation | ||||
|     initial_data = YoutubeAPI.browse(continuation) | ||||
|   else | ||||
|     initial_data = YoutubeAPI.browse(ucid, params: "Eghwb2RjYXN0c_IGBQoDugEA") | ||||
|   end | ||||
|   return extract_items(initial_data, author, ucid) | ||||
| end | ||||
|  | ||||
| def fetch_channel_releases(ucid, author, continuation) | ||||
|   if continuation | ||||
|     initial_data = YoutubeAPI.browse(continuation) | ||||
|   else | ||||
|     initial_data = YoutubeAPI.browse(ucid, params: "EghyZWxlYXNlc_IGBQoDsgEA") | ||||
|   end | ||||
|   return extract_items(initial_data, author, ucid) | ||||
| end | ||||
|   | ||||
| @@ -5,6 +5,8 @@ module Invidious::Frontend::ChannelPage | ||||
|     Videos | ||||
|     Shorts | ||||
|     Streams | ||||
|     Podcasts | ||||
|     Releases | ||||
|     Playlists | ||||
|     Community | ||||
|     Channels | ||||
|   | ||||
| @@ -245,7 +245,7 @@ module Invidious::Routes::API::V1::Channels | ||||
|     channel = nil # Make the compiler happy | ||||
|     get_channel() | ||||
|  | ||||
|     items, continuation = fetch_channel_playlists(channel.ucid, channel.author, continuation, sort_by) | ||||
|     items, next_continuation = fetch_channel_playlists(channel.ucid, channel.author, continuation, sort_by) | ||||
|  | ||||
|     JSON.build do |json| | ||||
|       json.object do | ||||
| @@ -257,7 +257,65 @@ module Invidious::Routes::API::V1::Channels | ||||
|           end | ||||
|         end | ||||
|  | ||||
|         json.field "continuation", continuation | ||||
|         json.field "continuation", next_continuation if next_continuation | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def self.podcasts(env) | ||||
|     locale = env.get("preferences").as(Preferences).locale | ||||
|  | ||||
|     env.response.content_type = "application/json" | ||||
|  | ||||
|     ucid = env.params.url["ucid"] | ||||
|     continuation = env.params.query["continuation"]? | ||||
|  | ||||
|     # Use the macro defined above | ||||
|     channel = nil # Make the compiler happy | ||||
|     get_channel() | ||||
|  | ||||
|     items, next_continuation = fetch_channel_podcasts(channel.ucid, channel.author, continuation) | ||||
|  | ||||
|     JSON.build do |json| | ||||
|       json.object do | ||||
|         json.field "playlists" do | ||||
|           json.array do | ||||
|             items.each do |item| | ||||
|               item.to_json(locale, json) if item.is_a?(SearchPlaylist) | ||||
|             end | ||||
|           end | ||||
|         end | ||||
|  | ||||
|         json.field "continuation", next_continuation if next_continuation | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def self.releases(env) | ||||
|     locale = env.get("preferences").as(Preferences).locale | ||||
|  | ||||
|     env.response.content_type = "application/json" | ||||
|  | ||||
|     ucid = env.params.url["ucid"] | ||||
|     continuation = env.params.query["continuation"]? | ||||
|  | ||||
|     # Use the macro defined above | ||||
|     channel = nil # Make the compiler happy | ||||
|     get_channel() | ||||
|  | ||||
|     items, next_continuation = fetch_channel_releases(channel.ucid, channel.author, continuation) | ||||
|  | ||||
|     JSON.build do |json| | ||||
|       json.object do | ||||
|         json.field "playlists" do | ||||
|           json.array do | ||||
|             items.each do |item| | ||||
|               item.to_json(locale, json) if item.is_a?(SearchPlaylist) | ||||
|             end | ||||
|           end | ||||
|         end | ||||
|  | ||||
|         json.field "continuation", next_continuation if next_continuation | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|   | ||||
| @@ -27,7 +27,7 @@ module Invidious::Routes::Channels | ||||
|           item.author | ||||
|         end | ||||
|       end | ||||
|       items = items.select(SearchPlaylist).map(&.as(SearchPlaylist)) | ||||
|       items = items.select(SearchPlaylist) | ||||
|       items.each(&.author = "") | ||||
|     else | ||||
|       sort_options = {"newest", "oldest", "popular"} | ||||
| @@ -105,13 +105,53 @@ module Invidious::Routes::Channels | ||||
|       channel.ucid, channel.author, continuation, (sort_by || "last") | ||||
|     ) | ||||
|  | ||||
|     items = items.select(SearchPlaylist).map(&.as(SearchPlaylist)) | ||||
|     items = items.select(SearchPlaylist) | ||||
|     items.each(&.author = "") | ||||
|  | ||||
|     selected_tab = Frontend::ChannelPage::TabsAvailable::Playlists | ||||
|     templated "channel" | ||||
|   end | ||||
|  | ||||
|   def self.podcasts(env) | ||||
|     data = self.fetch_basic_information(env) | ||||
|     return data if !data.is_a?(Tuple) | ||||
|  | ||||
|     locale, user, subscriptions, continuation, ucid, channel = data | ||||
|  | ||||
|     sort_by = "" | ||||
|     sort_options = [] of String | ||||
|  | ||||
|     items, next_continuation = fetch_channel_podcasts( | ||||
|       channel.ucid, channel.author, continuation | ||||
|     ) | ||||
|  | ||||
|     items = items.select(SearchPlaylist) | ||||
|     items.each(&.author = "") | ||||
|  | ||||
|     selected_tab = Frontend::ChannelPage::TabsAvailable::Podcasts | ||||
|     templated "channel" | ||||
|   end | ||||
|  | ||||
|   def self.releases(env) | ||||
|     data = self.fetch_basic_information(env) | ||||
|     return data if !data.is_a?(Tuple) | ||||
|  | ||||
|     locale, user, subscriptions, continuation, ucid, channel = data | ||||
|  | ||||
|     sort_by = "" | ||||
|     sort_options = [] of String | ||||
|  | ||||
|     items, next_continuation = fetch_channel_releases( | ||||
|       channel.ucid, channel.author, continuation | ||||
|     ) | ||||
|  | ||||
|     items = items.select(SearchPlaylist) | ||||
|     items.each(&.author = "") | ||||
|  | ||||
|     selected_tab = Frontend::ChannelPage::TabsAvailable::Releases | ||||
|     templated "channel" | ||||
|   end | ||||
|  | ||||
|   def self.community(env) | ||||
|     data = self.fetch_basic_information(env) | ||||
|     if !data.is_a?(Tuple) | ||||
|   | ||||
| @@ -118,6 +118,8 @@ module Invidious::Routing | ||||
|     get "/channel/:ucid/videos", Routes::Channels, :videos | ||||
|     get "/channel/:ucid/shorts", Routes::Channels, :shorts | ||||
|     get "/channel/:ucid/streams", Routes::Channels, :streams | ||||
|     get "/channel/:ucid/podcasts", Routes::Channels, :podcasts | ||||
|     get "/channel/:ucid/releases", Routes::Channels, :releases | ||||
|     get "/channel/:ucid/playlists", Routes::Channels, :playlists | ||||
|     get "/channel/:ucid/community", Routes::Channels, :community | ||||
|     get "/channel/:ucid/channels", Routes::Channels, :channels | ||||
| @@ -228,6 +230,9 @@ module Invidious::Routing | ||||
|       get "/api/v1/channels/:ucid", {{namespace}}::Channels, :home | ||||
|       get "/api/v1/channels/:ucid/shorts", {{namespace}}::Channels, :shorts | ||||
|       get "/api/v1/channels/:ucid/streams", {{namespace}}::Channels, :streams | ||||
|       get "/api/v1/channels/:ucid/podcasts", {{namespace}}::Channels, :podcasts | ||||
|       get "/api/v1/channels/:ucid/releases", {{namespace}}::Channels, :releases | ||||
|  | ||||
|       get "/api/v1/channels/:ucid/channels", {{namespace}}::Channels, :channels | ||||
|  | ||||
|       {% for route in {"videos", "latest", "playlists", "community", "search"} %} | ||||
|   | ||||
| @@ -9,6 +9,8 @@ | ||||
|     when .streams?   then "/channel/#{ucid}/streams" | ||||
|     when .playlists? then "/channel/#{ucid}/playlists" | ||||
|     when .channels?  then "/channel/#{ucid}/channels" | ||||
|     when .podcasts?  then "/channel/#{ucid}/podcasts" | ||||
|     when .releases?  then "/channel/#{ucid}/releases" | ||||
|     else | ||||
|       "/channel/#{ucid}" | ||||
|     end | ||||
|   | ||||
| @@ -408,8 +408,8 @@ private module Parsers | ||||
|   # Returns nil when the given object isn't a RichItemRenderer | ||||
|   # | ||||
|   # A richItemRenderer seems to be a simple wrapper for a videoRenderer, used | ||||
|   # by the result page for hashtags. It is located inside a continuationItems | ||||
|   # container. | ||||
|   # by the result page for hashtags and for the podcast tab on channels. | ||||
|   # It is located inside a continuationItems container for hashtags. | ||||
|   # | ||||
|   module RichItemRendererParser | ||||
|     def self.process(item : JSON::Any, author_fallback : AuthorFallback) | ||||
| @@ -421,6 +421,7 @@ private module Parsers | ||||
|     private def self.parse(item_contents, author_fallback) | ||||
|       child = VideoRendererParser.process(item_contents, author_fallback) | ||||
|       child ||= ReelItemRendererParser.process(item_contents, author_fallback) | ||||
|       child ||= PlaylistRendererParser.process(item_contents, author_fallback) | ||||
|       return child | ||||
|     end | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Samantaz Fox
					Samantaz Fox