From 8fad19d8057d7d22e3de27ebbc88a9978c1df27b Mon Sep 17 00:00:00 2001 From: syeopite Date: Sat, 17 Apr 2021 04:04:30 -0700 Subject: [PATCH] Extract primary channel routes from invidious.cr Also removes timedtext_video stub since all it does is redirect to the homepage. However, Invidious's 404 handler already does this. --- src/invidious.cr | 183 +------------------------------ src/invidious/routes/channels.cr | 127 +++++++++++++++++++++ 2 files changed, 133 insertions(+), 177 deletions(-) create mode 100644 src/invidious/routes/channels.cr diff --git a/src/invidious.cr b/src/invidious.cr index 9b74fb42..a91b7464 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -308,6 +308,12 @@ Invidious::Routing.get "/", Invidious::Routes::Misc, :home Invidious::Routing.get "/privacy", Invidious::Routes::Misc, :privacy Invidious::Routing.get "/licenses", Invidious::Routes::Misc, :licenses +Invidious::Routing.get "/channel/:ucid", Invidious::Routes::Channels, :home +Invidious::Routing.get "/channel/:ucid/videos", Invidious::Routes::Channels, :videos +Invidious::Routing.get "/channel/:ucid/playlists", Invidious::Routes::Channels, :playlists +Invidious::Routing.get "/channel/:ucid/community", Invidious::Routes::Channels, :community +Invidious::Routing.get "/channel/:ucid/about", Invidious::Routes::Channels, :about + Invidious::Routing.get "/watch", Invidious::Routes::Watch, :handle Invidious::Routing.get "/watch/:id", Invidious::Routes::Watch, :redirect Invidious::Routing.get "/shorts/:id", Invidious::Routes::Watch, :redirect @@ -1653,12 +1659,6 @@ get "/attribution_link" do |env| env.redirect url end -# Page used by YouTube to provide captioning widget, since we -# don't support it we redirect to '/' -get "/timedtext_video" do |env| - env.redirect "/" -end - get "/user/:user" do |env| user = env.params.url["user"] env.redirect "/channel/#{user}" @@ -1674,177 +1674,6 @@ get "/user/:user/about" do |env| env.redirect "/channel/#{user}" end -get "/channel/:ucid" do |env| - locale = LOCALES[env.get("preferences").as(Preferences).locale]? - - user = env.get? "user" - if user - user = user.as(User) - subscriptions = user.subscriptions - end - subscriptions ||= [] of String - - ucid = env.params.url["ucid"] - - page = env.params.query["page"]?.try &.to_i? - page ||= 1 - - continuation = env.params.query["continuation"]? - - sort_by = env.params.query["sort_by"]?.try &.downcase - - begin - channel = get_about_info(ucid, locale) - rescue ex : ChannelRedirect - next env.redirect env.request.resource.gsub(ucid, ex.channel_id) - rescue ex - next error_template(500, ex) - end - - if channel.auto_generated - sort_options = {"last", "oldest", "newest"} - sort_by ||= "last" - - items, continuation = fetch_channel_playlists(channel.ucid, channel.author, continuation, sort_by) - items.uniq! do |item| - if item.responds_to?(:title) - item.title - elsif item.responds_to?(:author) - item.author - end - end - items = items.select(&.is_a?(SearchPlaylist)).map(&.as(SearchPlaylist)) - items.each { |item| item.author = "" } - else - sort_options = {"newest", "oldest", "popular"} - sort_by ||= "newest" - - count, items = get_60_videos(channel.ucid, channel.author, page, channel.auto_generated, sort_by) - items.reject! &.paid - end - - templated "channel" -end - -get "/channel/:ucid/videos" do |env| - locale = LOCALES[env.get("preferences").as(Preferences).locale]? - - ucid = env.params.url["ucid"] - params = env.request.query - - if !params || params.empty? - params = "" - else - params = "?#{params}" - end - - env.redirect "/channel/#{ucid}#{params}" -end - -get "/channel/:ucid/playlists" do |env| - locale = LOCALES[env.get("preferences").as(Preferences).locale]? - - user = env.get? "user" - if user - user = user.as(User) - subscriptions = user.subscriptions - end - subscriptions ||= [] of String - - ucid = env.params.url["ucid"] - - continuation = env.params.query["continuation"]? - - sort_options = {"last", "oldest", "newest"} - sort_by = env.params.query["sort_by"]?.try &.downcase - sort_by ||= "last" - - begin - channel = get_about_info(ucid, locale) - rescue ex : ChannelRedirect - next env.redirect env.request.resource.gsub(ucid, ex.channel_id) - rescue ex - next error_template(500, ex) - end - - if channel.auto_generated - next env.redirect "/channel/#{channel.ucid}" - end - - items, continuation = fetch_channel_playlists(channel.ucid, channel.author, continuation, sort_by) - items = items.select { |item| item.is_a?(SearchPlaylist) }.map { |item| item.as(SearchPlaylist) } - items.each { |item| item.author = "" } - - templated "playlists" -end - -get "/channel/:ucid/community" do |env| - locale = LOCALES[env.get("preferences").as(Preferences).locale]? - - user = env.get? "user" - if user - user = user.as(User) - subscriptions = user.subscriptions - end - subscriptions ||= [] of String - - ucid = env.params.url["ucid"] - - thin_mode = env.params.query["thin_mode"]? || env.get("preferences").as(Preferences).thin_mode - thin_mode = thin_mode == "true" - - continuation = env.params.query["continuation"]? - # sort_by = env.params.query["sort_by"]?.try &.downcase - - begin - channel = get_about_info(ucid, locale) - rescue ex : ChannelRedirect - next env.redirect env.request.resource.gsub(ucid, ex.channel_id) - rescue ex - next error_template(500, ex) - end - - if !channel.tabs.includes? "community" - next env.redirect "/channel/#{channel.ucid}" - end - - begin - items = JSON.parse(fetch_channel_community(ucid, continuation, locale, "json", thin_mode)) - rescue ex : InfoException - env.response.status_code = 500 - error_message = ex.message - rescue ex - next error_template(500, ex) - end - - templated "community" -end - -get "/channel/:ucid/about" do |env| - locale = LOCALES[env.get("preferences").as(Preferences).locale]? - - user = env.get? "user" - if user - user = user.as(User) - subscriptions = user.subscriptions - end - subscriptions ||= [] of String - - ucid = env.params.url["ucid"] - - continuation = env.params.query["continuation"]? - - begin - channel = get_about_info(ucid, locale) - rescue ex : ChannelRedirect - next env.redirect env.request.resource.gsub(ucid, ex.channel_id) - rescue ex - next error_template(500, ex) - end - - templated "channel_about" -end - # API Endpoints get "/api/v1/stats" do |env| diff --git a/src/invidious/routes/channels.cr b/src/invidious/routes/channels.cr new file mode 100644 index 00000000..b51ff714 --- /dev/null +++ b/src/invidious/routes/channels.cr @@ -0,0 +1,127 @@ +class Invidious::Routes::Channels < Invidious::Routes::BaseRoute + def home(env) + self.videos(env) + end + + def videos(env) + data = self.fetch_basic_information(env) + if !data.is_a?(Tuple) + return data + end + locale, user, subscriptions, continuation, ucid, channel = data + + page = env.params.query["page"]?.try &.to_i? + page ||= 1 + + sort_by = env.params.query["sort_by"]?.try &.downcase + + if channel.auto_generated + sort_options = {"last", "oldest", "newest"} + sort_by ||= "last" + + items, continuation = fetch_channel_playlists(channel.ucid, channel.author, continuation, sort_by) + items.uniq! do |item| + if item.responds_to?(:title) + item.title + elsif item.responds_to?(:author) + item.author + end + end + items = items.select(&.is_a?(SearchPlaylist)).map(&.as(SearchPlaylist)) + items.each { |item| item.author = "" } + else + sort_options = {"newest", "oldest", "popular"} + sort_by ||= "newest" + + count, items = get_60_videos(channel.ucid, channel.author, page, channel.auto_generated, sort_by) + items.reject! &.paid + end + + templated "channel" + end + + def playlists(env) + data = self.fetch_basic_information(env) + if !data.is_a?(Tuple) + return data + end + locale, user, subscriptions, continuation, ucid, channel = data + + sort_options = {"last", "oldest", "newest"} + sort_by = env.params.query["sort_by"]?.try &.downcase + sort_by ||= "last" + + if channel.auto_generated + return env.redirect "/channel/#{channel.ucid}" + end + + items, continuation = fetch_channel_playlists(channel.ucid, channel.author, continuation, sort_by) + items = items.select { |item| item.is_a?(SearchPlaylist) }.map { |item| item.as(SearchPlaylist) } + items.each { |item| item.author = "" } + + templated "playlists" + end + + def community(env) + data = self.fetch_basic_information(env) + if !data.is_a?(Tuple) + return data + end + locale, user, subscriptions, continuation, ucid, channel = data + + thin_mode = env.params.query["thin_mode"]? || env.get("preferences").as(Preferences).thin_mode + thin_mode = thin_mode == "true" + + continuation = env.params.query["continuation"]? + # sort_by = env.params.query["sort_by"]?.try &.downcase + + if !channel.tabs.includes? "community" + return env.redirect "/channel/#{channel.ucid}" + end + + begin + items = JSON.parse(fetch_channel_community(ucid, continuation, locale, "json", thin_mode)) + rescue ex : InfoException + env.response.status_code = 500 + error_message = ex.message + rescue ex + return error_template(500, ex) + end + + templated "community" + end + + def about(env) + data = self.fetch_basic_information(env) + if !data.is_a?(Tuple) + return data + end + locale, user, subscriptions, continuation, ucid, channel = data + + templated "channel_about" + end + + private def fetch_basic_information(env) + locale = LOCALES[env.get("preferences").as(Preferences).locale]? + + user = env.get? "user" + if user + user = user.as(User) + subscriptions = user.subscriptions + end + subscriptions ||= [] of String + + ucid = env.params.url["ucid"] + continuation = env.params.query["continuation"]? + + begin + channel = get_about_info(ucid, locale) + rescue ex : ChannelRedirect + return env.redirect env.request.resource.gsub(ucid, ex.channel_id) + rescue ex + return error_template(500, ex) + end + + return {locale, user, subscriptions, continuation, ucid, channel} + end +end