diff --git a/locales/en-US.json b/locales/en-US.json index c23f6bc33..aa5777995 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -492,6 +492,7 @@ "channel_tab_streams_label": "Livestreams", "channel_tab_podcasts_label": "Podcasts", "channel_tab_releases_label": "Releases", + "channel_tab_courses_label": "Courses", "channel_tab_playlists_label": "Playlists", "channel_tab_community_label": "Community", "channel_tab_channels_label": "Channels", diff --git a/src/invidious/channels/playlists.cr b/src/invidious/channels/playlists.cr index 91029fe38..9b45d0c86 100644 --- a/src/invidious/channels/playlists.cr +++ b/src/invidious/channels/playlists.cr @@ -44,3 +44,12 @@ def fetch_channel_releases(ucid, author, continuation) end return extract_items(initial_data, author, ucid) end + +def fetch_channel_courses(ucid, author, continuation) + if continuation + initial_data = YoutubeAPI.browse(continuation) + else + initial_data = YoutubeAPI.browse(ucid, params: "Egdjb3Vyc2Vz8gYFCgPCAQA%3D") + end + return extract_items(initial_data, author, ucid) +end diff --git a/src/invidious/frontend/channel_page.cr b/src/invidious/frontend/channel_page.cr index fe7d6d6ef..ee7ebe484 100644 --- a/src/invidious/frontend/channel_page.cr +++ b/src/invidious/frontend/channel_page.cr @@ -7,6 +7,7 @@ module Invidious::Frontend::ChannelPage Streams Podcasts Releases + Courses Playlists Community Channels diff --git a/src/invidious/routes/api/v1/channels.cr b/src/invidious/routes/api/v1/channels.cr index 588bbc2a7..a940ee682 100644 --- a/src/invidious/routes/api/v1/channels.cr +++ b/src/invidious/routes/api/v1/channels.cr @@ -368,6 +368,35 @@ module Invidious::Routes::API::V1::Channels end end + def self.courses(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_courses(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.community(env) locale = env.get("preferences").as(Preferences).locale diff --git a/src/invidious/routes/channels.cr b/src/invidious/routes/channels.cr index 7d634cbb6..9f2802515 100644 --- a/src/invidious/routes/channels.cr +++ b/src/invidious/routes/channels.cr @@ -197,6 +197,26 @@ module Invidious::Routes::Channels templated "channel" end + def self.courses(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_courses( + channel.ucid, channel.author, continuation + ) + + items = items.select(SearchPlaylist) + items.each(&.author = "") + + selected_tab = Frontend::ChannelPage::TabsAvailable::Courses + templated "channel" + end + def self.community(env) data = self.fetch_basic_information(env) if !data.is_a?(Tuple) @@ -307,7 +327,7 @@ module Invidious::Routes::Channels private KNOWN_TABS = { "home", "videos", "shorts", "streams", "podcasts", - "releases", "playlists", "community", "channels", "about", + "releases", "courses", "playlists", "community", "channels", "about", } # Redirects brand url channels to a normal /channel/:ucid route diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 9009062f1..101ff1c58 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -120,6 +120,7 @@ module Invidious::Routing get "/channel/:ucid/streams", Routes::Channels, :streams get "/channel/:ucid/podcasts", Routes::Channels, :podcasts get "/channel/:ucid/releases", Routes::Channels, :releases + get "/channel/:ucid/courses", Routes::Channels, :courses get "/channel/:ucid/playlists", Routes::Channels, :playlists get "/channel/:ucid/community", Routes::Channels, :community get "/channel/:ucid/channels", Routes::Channels, :channels @@ -249,6 +250,7 @@ module Invidious::Routing 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/courses", {{namespace}}::Channels, :courses get "/api/v1/channels/:ucid/playlists", {{namespace}}::Channels, :playlists get "/api/v1/channels/:ucid/community", {{namespace}}::Channels, :community get "/api/v1/channels/:ucid/channels", {{namespace}}::Channels, :channels diff --git a/src/invidious/views/channel.ecr b/src/invidious/views/channel.ecr index a84e44bc2..8f8789ead 100644 --- a/src/invidious/views/channel.ecr +++ b/src/invidious/views/channel.ecr @@ -11,6 +11,7 @@ when .channels? then "/channel/#{ucid}/channels" when .podcasts? then "/channel/#{ucid}/podcasts" when .releases? then "/channel/#{ucid}/releases" + when .courses? then "/channel/#{ucid}/courses" else "/channel/#{ucid}" end