From c23ad25899152c4837777dbc983809f436f7062a Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Tue, 9 Aug 2022 23:39:53 +0200 Subject: [PATCH 01/15] routing: remove HEAD from HTTP methods Kemal automatically creates an associated HEAD route for all GET routes --- src/invidious/routing.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index bd72c577..9e95f7db 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -1,5 +1,5 @@ module Invidious::Routing - {% for http_method in {"get", "post", "delete", "options", "patch", "put", "head"} %} + {% for http_method in {"get", "post", "delete", "options", "patch", "put"} %} macro {{http_method.id}}(path, controller, method = :handle) {{http_method.id}} \{{ path }} do |env| From e22cc73f32577afe8098c70184760d8b75ce0189 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Tue, 9 Aug 2022 23:56:34 +0200 Subject: [PATCH 02/15] routing: register user routes with a function, rather than a macro --- src/invidious.cr | 5 +--- src/invidious/routing.cr | 52 +++++++++++++++++++++------------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 070b4d18..91bf6935 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -389,7 +389,7 @@ end Invidious::Routing.get "/hashtag/:hashtag", Invidious::Routes::Search, :hashtag # User routes - define_user_routes() + Invidious::Routing.register_user_routes # Feeds Invidious::Routing.get "/view_all_playlists", Invidious::Routes::Feeds, :view_all_playlists_redirect @@ -410,9 +410,6 @@ end Invidious::Routing.post "/feed/webhook/:token", Invidious::Routes::Feeds, :push_notifications_post Invidious::Routing.get "/modify_notifications", Invidious::Routes::Notifications, :modify - - Invidious::Routing.post "/subscription_ajax", Invidious::Routes::Subscriptions, :toggle_subscription - Invidious::Routing.get "/subscription_manager", Invidious::Routes::Subscriptions, :subscription_manager {% end %} Invidious::Routing.get "/ggpht/*", Invidious::Routes::Images, :ggpht diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 9e95f7db..23119e62 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -1,4 +1,6 @@ module Invidious::Routing + extend self + {% for http_method in {"get", "post", "delete", "options", "patch", "put"} %} macro {{http_method.id}}(path, controller, method = :handle) @@ -8,33 +10,35 @@ module Invidious::Routing end {% end %} -end -macro define_user_routes - # User login/out - Invidious::Routing.get "/login", Invidious::Routes::Login, :login_page - Invidious::Routing.post "/login", Invidious::Routes::Login, :login - Invidious::Routing.post "/signout", Invidious::Routes::Login, :signout - Invidious::Routing.get "/Captcha", Invidious::Routes::Login, :captcha + def register_user_routes + # User login/out + get "/login", Routes::Login, :login_page + post "/login", Routes::Login, :login + post "/signout", Routes::Login, :signout + get "/Captcha", Routes::Login, :captcha - # User preferences - Invidious::Routing.get "/preferences", Invidious::Routes::PreferencesRoute, :show - Invidious::Routing.post "/preferences", Invidious::Routes::PreferencesRoute, :update - Invidious::Routing.get "/toggle_theme", Invidious::Routes::PreferencesRoute, :toggle_theme - Invidious::Routing.get "/data_control", Invidious::Routes::PreferencesRoute, :data_control - Invidious::Routing.post "/data_control", Invidious::Routes::PreferencesRoute, :update_data_control + # User preferences + get "/preferences", Routes::PreferencesRoute, :show + post "/preferences", Routes::PreferencesRoute, :update + get "/toggle_theme", Routes::PreferencesRoute, :toggle_theme + get "/data_control", Routes::PreferencesRoute, :data_control + post "/data_control", Routes::PreferencesRoute, :update_data_control - # User account management - Invidious::Routing.get "/change_password", Invidious::Routes::Account, :get_change_password - Invidious::Routing.post "/change_password", Invidious::Routes::Account, :post_change_password - Invidious::Routing.get "/delete_account", Invidious::Routes::Account, :get_delete - Invidious::Routing.post "/delete_account", Invidious::Routes::Account, :post_delete - Invidious::Routing.get "/clear_watch_history", Invidious::Routes::Account, :get_clear_history - Invidious::Routing.post "/clear_watch_history", Invidious::Routes::Account, :post_clear_history - Invidious::Routing.get "/authorize_token", Invidious::Routes::Account, :get_authorize_token - Invidious::Routing.post "/authorize_token", Invidious::Routes::Account, :post_authorize_token - Invidious::Routing.get "/token_manager", Invidious::Routes::Account, :token_manager - Invidious::Routing.post "/token_ajax", Invidious::Routes::Account, :token_ajax + # User account management + get "/change_password", Routes::Account, :get_change_password + post "/change_password", Routes::Account, :post_change_password + get "/delete_account", Routes::Account, :get_delete + post "/delete_account", Routes::Account, :post_delete + get "/clear_watch_history", Routes::Account, :get_clear_history + post "/clear_watch_history", Routes::Account, :post_clear_history + get "/authorize_token", Routes::Account, :get_authorize_token + post "/authorize_token", Routes::Account, :post_authorize_token + get "/token_manager", Routes::Account, :token_manager + post "/token_ajax", Routes::Account, :token_ajax + post "/subscription_ajax", Routes::Subscriptions, :toggle_subscription + get "/subscription_manager", Routes::Subscriptions, :subscription_manager + end end macro define_v1_api_routes From 176247091d5df6fe7d9b772ef3e1ff09d3bc9c1c Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Wed, 10 Aug 2022 00:07:47 +0200 Subject: [PATCH 03/15] routing: register API routes with a function, rather than a macro --- src/invidious.cr | 2 +- src/invidious/routing.cr | 113 +++++++++++++++++++++------------------ 2 files changed, 61 insertions(+), 54 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 91bf6935..1188710f 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -420,7 +420,7 @@ Invidious::Routing.get "/yts/img/:name", Invidious::Routes::Images, :yts_image Invidious::Routing.get "/vi/:id/:name", Invidious::Routes::Images, :thumbnails # API routes (macro) -define_v1_api_routes() +Invidious::Routing.register_api_v1_routes # Video playback (macros) define_api_manifest_routes() diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 23119e62..9e8ce34d 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -11,6 +11,10 @@ module Invidious::Routing {% end %} + # ------------------- + # Invidious routes + # ------------------- + def register_user_routes # User login/out get "/login", Routes::Login, :login_page @@ -39,75 +43,78 @@ module Invidious::Routing post "/subscription_ajax", Routes::Subscriptions, :toggle_subscription get "/subscription_manager", Routes::Subscriptions, :subscription_manager end -end -macro define_v1_api_routes - {{namespace = Invidious::Routes::API::V1}} - # Videos - Invidious::Routing.get "/api/v1/videos/:id", {{namespace}}::Videos, :videos - Invidious::Routing.get "/api/v1/storyboards/:id", {{namespace}}::Videos, :storyboards - Invidious::Routing.get "/api/v1/captions/:id", {{namespace}}::Videos, :captions - Invidious::Routing.get "/api/v1/annotations/:id", {{namespace}}::Videos, :annotations - Invidious::Routing.get "/api/v1/comments/:id", {{namespace}}::Videos, :comments + # ------------------- + # API routes + # ------------------- - # Feeds - Invidious::Routing.get "/api/v1/trending", {{namespace}}::Feeds, :trending - Invidious::Routing.get "/api/v1/popular", {{namespace}}::Feeds, :popular + def register_api_v1_routes + {% begin %} + {{namespace = Routes::API::V1}} - # Channels - Invidious::Routing.get "/api/v1/channels/:ucid", {{namespace}}::Channels, :home - {% for route in {"videos", "latest", "playlists", "community", "search"} %} - Invidious::Routing.get "/api/v1/channels/#{{{route}}}/:ucid", {{namespace}}::Channels, :{{route}} - Invidious::Routing.get "/api/v1/channels/:ucid/#{{{route}}}", {{namespace}}::Channels, :{{route}} - {% end %} + # Videos + get "/api/v1/videos/:id", {{namespace}}::Videos, :videos + get "/api/v1/storyboards/:id", {{namespace}}::Videos, :storyboards + get "/api/v1/captions/:id", {{namespace}}::Videos, :captions + get "/api/v1/annotations/:id", {{namespace}}::Videos, :annotations + get "/api/v1/comments/:id", {{namespace}}::Videos, :comments - # 301 redirects to new /api/v1/channels/community/:ucid and /:ucid/community - Invidious::Routing.get "/api/v1/channels/comments/:ucid", {{namespace}}::Channels, :channel_comments_redirect - Invidious::Routing.get "/api/v1/channels/:ucid/comments", {{namespace}}::Channels, :channel_comments_redirect + # Feeds + get "/api/v1/trending", {{namespace}}::Feeds, :trending + get "/api/v1/popular", {{namespace}}::Feeds, :popular + # Channels + get "/api/v1/channels/:ucid", {{namespace}}::Channels, :home + {% for route in {"videos", "latest", "playlists", "community", "search"} %} + get "/api/v1/channels/#{{{route}}}/:ucid", {{namespace}}::Channels, :{{route}} + get "/api/v1/channels/:ucid/#{{{route}}}", {{namespace}}::Channels, :{{route}} + {% end %} - # Search - Invidious::Routing.get "/api/v1/search", {{namespace}}::Search, :search - Invidious::Routing.get "/api/v1/search/suggestions", {{namespace}}::Search, :search_suggestions + # 301 redirects to new /api/v1/channels/community/:ucid and /:ucid/community + get "/api/v1/channels/comments/:ucid", {{namespace}}::Channels, :channel_comments_redirect + get "/api/v1/channels/:ucid/comments", {{namespace}}::Channels, :channel_comments_redirect - # Authenticated + # Search + get "/api/v1/search", {{namespace}}::Search, :search + get "/api/v1/search/suggestions", {{namespace}}::Search, :search_suggestions - # The notification APIs cannot be extracted yet! They require the *local* notifications constant defined in invidious.cr - # - # Invidious::Routing.get "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications - # Invidious::Routing.post "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications + # Authenticated - Invidious::Routing.get "/api/v1/auth/preferences", {{namespace}}::Authenticated, :get_preferences - Invidious::Routing.post "/api/v1/auth/preferences", {{namespace}}::Authenticated, :set_preferences + # The notification APIs cannot be extracted yet! They require the *local* notifications constant defined in invidious.cr + # + # Invidious::Routing.get "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications + # Invidious::Routing.post "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications - Invidious::Routing.get "/api/v1/auth/feed", {{namespace}}::Authenticated, :feed + get "/api/v1/auth/preferences", {{namespace}}::Authenticated, :get_preferences + post "/api/v1/auth/preferences", {{namespace}}::Authenticated, :set_preferences - Invidious::Routing.get "/api/v1/auth/subscriptions", {{namespace}}::Authenticated, :get_subscriptions - Invidious::Routing.post "/api/v1/auth/subscriptions/:ucid", {{namespace}}::Authenticated, :subscribe_channel - Invidious::Routing.delete "/api/v1/auth/subscriptions/:ucid", {{namespace}}::Authenticated, :unsubscribe_channel + get "/api/v1/auth/feed", {{namespace}}::Authenticated, :feed + get "/api/v1/auth/subscriptions", {{namespace}}::Authenticated, :get_subscriptions + post "/api/v1/auth/subscriptions/:ucid", {{namespace}}::Authenticated, :subscribe_channel + delete "/api/v1/auth/subscriptions/:ucid", {{namespace}}::Authenticated, :unsubscribe_channel - Invidious::Routing.get "/api/v1/auth/playlists", {{namespace}}::Authenticated, :list_playlists - Invidious::Routing.post "/api/v1/auth/playlists", {{namespace}}::Authenticated, :create_playlist - Invidious::Routing.patch "/api/v1/auth/playlists/:plid",{{namespace}}:: Authenticated, :update_playlist_attribute - Invidious::Routing.delete "/api/v1/auth/playlists/:plid", {{namespace}}::Authenticated, :delete_playlist + get "/api/v1/auth/playlists", {{namespace}}::Authenticated, :list_playlists + post "/api/v1/auth/playlists", {{namespace}}::Authenticated, :create_playlist + patch "/api/v1/auth/playlists/:plid",{{namespace}}:: Authenticated, :update_playlist_attribute + delete "/api/v1/auth/playlists/:plid", {{namespace}}::Authenticated, :delete_playlist + post "/api/v1/auth/playlists/:plid/videos", {{namespace}}::Authenticated, :insert_video_into_playlist + delete "/api/v1/auth/playlists/:plid/videos/:index", {{namespace}}::Authenticated, :delete_video_in_playlist + get "/api/v1/auth/tokens", {{namespace}}::Authenticated, :get_tokens + post "/api/v1/auth/tokens/register", {{namespace}}::Authenticated, :register_token + post "/api/v1/auth/tokens/unregister", {{namespace}}::Authenticated, :unregister_token - Invidious::Routing.post "/api/v1/auth/playlists/:plid/videos", {{namespace}}::Authenticated, :insert_video_into_playlist - Invidious::Routing.delete "/api/v1/auth/playlists/:plid/videos/:index", {{namespace}}::Authenticated, :delete_video_in_playlist + get "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications + post "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications - Invidious::Routing.get "/api/v1/auth/tokens", {{namespace}}::Authenticated, :get_tokens - Invidious::Routing.post "/api/v1/auth/tokens/register", {{namespace}}::Authenticated, :register_token - Invidious::Routing.post "/api/v1/auth/tokens/unregister", {{namespace}}::Authenticated, :unregister_token - - Invidious::Routing.get "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications - Invidious::Routing.post "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications - - # Misc - Invidious::Routing.get "/api/v1/stats", {{namespace}}::Misc, :stats - Invidious::Routing.get "/api/v1/playlists/:plid", {{namespace}}::Misc, :get_playlist - Invidious::Routing.get "/api/v1/auth/playlists/:plid", {{namespace}}::Misc, :get_playlist - Invidious::Routing.get "/api/v1/mixes/:rdid", {{namespace}}::Misc, :mixes + # Misc + get "/api/v1/stats", {{namespace}}::Misc, :stats + get "/api/v1/playlists/:plid", {{namespace}}::Misc, :get_playlist + get "/api/v1/auth/playlists/:plid", {{namespace}}::Misc, :get_playlist + get "/api/v1/mixes/:rdid", {{namespace}}::Misc, :mixes + {% end %} + end end macro define_api_manifest_routes From 389ae7a57395f1b3fbf540deebbad73d0674e715 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Wed, 10 Aug 2022 00:09:58 +0200 Subject: [PATCH 04/15] routing: register playback routes with a function, rather than a macro --- src/invidious.cr | 4 ++-- src/invidious/routing.cr | 50 ++++++++++++++++++++++------------------ 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 1188710f..f244cea5 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -423,8 +423,8 @@ Invidious::Routing.get "/vi/:id/:name", Invidious::Routes::Images, :thumbnails Invidious::Routing.register_api_v1_routes # Video playback (macros) -define_api_manifest_routes() -define_video_playback_routes() +Invidious::Routing.register_api_manifest_routes +Invidious::Routing.register_video_playback_routes error 404 do |env| if md = env.request.path.match(/^\/(?([a-zA-Z0-9_-]{11})|(\w+))$/) diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 9e8ce34d..25cbfa48 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -44,6 +44,33 @@ module Invidious::Routing get "/subscription_manager", Routes::Subscriptions, :subscription_manager end + # ------------------- + # Youtube routes + # ------------------- + + def register_api_manifest_routes + get "/api/manifest/dash/id/:id", Routes::API::Manifest, :get_dash_video_id + + get "/api/manifest/dash/id/videoplayback", Routes::API::Manifest, :get_dash_video_playback + get "/api/manifest/dash/id/videoplayback/*", Routes::API::Manifest, :get_dash_video_playback_greedy + + options "/api/manifest/dash/id/videoplayback", Routes::API::Manifest, :options_dash_video_playback + options "/api/manifest/dash/id/videoplayback/*", Routes::API::Manifest, :options_dash_video_playback + + get "/api/manifest/hls_playlist/*", Routes::API::Manifest, :get_hls_playlist + get "/api/manifest/hls_variant/*", Routes::API::Manifest, :get_hls_variant + end + + def register_video_playback_routes + get "/videoplayback", Routes::VideoPlayback, :get_video_playback + get "/videoplayback/*", Routes::VideoPlayback, :get_video_playback_greedy + + options "/videoplayback", Routes::VideoPlayback, :options_video_playback + options "/videoplayback/*", Routes::VideoPlayback, :options_video_playback + + get "/latest_version", Routes::VideoPlayback, :latest_version + end + # ------------------- # API routes # ------------------- @@ -116,26 +143,3 @@ module Invidious::Routing {% end %} end end - -macro define_api_manifest_routes - Invidious::Routing.get "/api/manifest/dash/id/:id", Invidious::Routes::API::Manifest, :get_dash_video_id - - Invidious::Routing.get "/api/manifest/dash/id/videoplayback", Invidious::Routes::API::Manifest, :get_dash_video_playback - Invidious::Routing.get "/api/manifest/dash/id/videoplayback/*", Invidious::Routes::API::Manifest, :get_dash_video_playback_greedy - - Invidious::Routing.options "/api/manifest/dash/id/videoplayback", Invidious::Routes::API::Manifest, :options_dash_video_playback - Invidious::Routing.options "/api/manifest/dash/id/videoplayback/*", Invidious::Routes::API::Manifest, :options_dash_video_playback - - Invidious::Routing.get "/api/manifest/hls_playlist/*", Invidious::Routes::API::Manifest, :get_hls_playlist - Invidious::Routing.get "/api/manifest/hls_variant/*", Invidious::Routes::API::Manifest, :get_hls_variant -end - -macro define_video_playback_routes - Invidious::Routing.get "/videoplayback", Invidious::Routes::VideoPlayback, :get_video_playback - Invidious::Routing.get "/videoplayback/*", Invidious::Routes::VideoPlayback, :get_video_playback_greedy - - Invidious::Routing.options "/videoplayback", Invidious::Routes::VideoPlayback, :options_video_playback - Invidious::Routing.options "/videoplayback/*", Invidious::Routes::VideoPlayback, :options_video_playback - - Invidious::Routing.get "/latest_version", Invidious::Routes::VideoPlayback, :latest_version -end From 3ac4390d11d7eecbd49e3db79376942e8706783b Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Wed, 10 Aug 2022 00:14:26 +0200 Subject: [PATCH 05/15] routing: move channel routes registration to Invidious::Routing --- src/invidious.cr | 21 +-------------------- src/invidious/routing.cr | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index f244cea5..969804a6 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -334,26 +334,7 @@ end 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/home", 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 "/channel/:ucid/live", Invidious::Routes::Channels, :live - Invidious::Routing.get "/user/:user/live", Invidious::Routes::Channels, :live - Invidious::Routing.get "/c/:user/live", Invidious::Routes::Channels, :live - - ["", "/videos", "/playlists", "/community", "/about"].each do |path| - # /c/LinusTechTips - Invidious::Routing.get "/c/:user#{path}", Invidious::Routes::Channels, :brand_redirect - # /user/linustechtips | Not always the same as /c/ - Invidious::Routing.get "/user/:user#{path}", Invidious::Routes::Channels, :brand_redirect - # /attribution_link?a=anything&u=/channel/UCZYTClx2T1of7BRZ86-8fow - Invidious::Routing.get "/attribution_link#{path}", Invidious::Routes::Channels, :brand_redirect - # /profile?user=linustechtips - Invidious::Routing.get "/profile/#{path}", Invidious::Routes::Channels, :profile - end + Invidious::Routing.register_channel_routes Invidious::Routing.get "/watch", Invidious::Routes::Watch, :handle Invidious::Routing.post "/watch_ajax", Invidious::Routes::Watch, :mark_watched diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 25cbfa48..203aa024 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -48,6 +48,29 @@ module Invidious::Routing # Youtube routes # ------------------- + def register_channel_routes + get "/channel/:ucid", Routes::Channels, :home + get "/channel/:ucid/home", Routes::Channels, :home + get "/channel/:ucid/videos", Routes::Channels, :videos + get "/channel/:ucid/playlists", Routes::Channels, :playlists + get "/channel/:ucid/community", Routes::Channels, :community + get "/channel/:ucid/about", Routes::Channels, :about + get "/channel/:ucid/live", Routes::Channels, :live + get "/user/:user/live", Routes::Channels, :live + get "/c/:user/live", Routes::Channels, :live + + ["", "/videos", "/playlists", "/community", "/about"].each do |path| + # /c/LinusTechTips + get "/c/:user#{path}", Routes::Channels, :brand_redirect + # /user/linustechtips | Not always the same as /c/ + get "/user/:user#{path}", Routes::Channels, :brand_redirect + # /attribution_link?a=anything&u=/channel/UCZYTClx2T1of7BRZ86-8fow + get "/attribution_link#{path}", Routes::Channels, :brand_redirect + # /profile?user=linustechtips + get "/profile/#{path}", Routes::Channels, :profile + end + end + def register_api_manifest_routes get "/api/manifest/dash/id/:id", Routes::API::Manifest, :get_dash_video_id From e2532de766bec9a2e967d551776823b83f44e995 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Wed, 10 Aug 2022 00:20:04 +0200 Subject: [PATCH 06/15] routing: move image proxy routes registration to Invidious::Routing --- src/invidious.cr | 7 +------ src/invidious/routing.cr | 9 +++++++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 969804a6..9daf5380 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -393,12 +393,7 @@ end Invidious::Routing.get "/modify_notifications", Invidious::Routes::Notifications, :modify {% end %} -Invidious::Routing.get "/ggpht/*", Invidious::Routes::Images, :ggpht -Invidious::Routing.options "/sb/:authority/:id/:storyboard/:index", Invidious::Routes::Images, :options_storyboard -Invidious::Routing.get "/sb/:authority/:id/:storyboard/:index", Invidious::Routes::Images, :get_storyboard -Invidious::Routing.get "/s_p/:id/:name", Invidious::Routes::Images, :s_p_image -Invidious::Routing.get "/yts/img/:name", Invidious::Routes::Images, :yts_image -Invidious::Routing.get "/vi/:id/:name", Invidious::Routes::Images, :thumbnails +Invidious::Routing.register_image_routes # API routes (macro) Invidious::Routing.register_api_v1_routes diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 203aa024..45ae7c6b 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -94,6 +94,15 @@ module Invidious::Routing get "/latest_version", Routes::VideoPlayback, :latest_version end + def register_image_routes + get "/ggpht/*", Routes::Images, :ggpht + options "/sb/:authority/:id/:storyboard/:index", Routes::Images, :options_storyboard + get "/sb/:authority/:id/:storyboard/:index", Routes::Images, :get_storyboard + get "/s_p/:id/:name", Routes::Images, :s_p_image + get "/yts/img/:name", Routes::Images, :yts_image + get "/vi/:id/:name", Routes::Images, :thumbnails + end + # ------------------- # API routes # ------------------- From 906466d7fb31686b208f04172dbd6ecaa9e1f1c6 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Wed, 10 Aug 2022 00:22:40 +0200 Subject: [PATCH 07/15] routing: move watch/embed routes registration to Invidious::Routing --- src/invidious.cr | 17 ++--------------- src/invidious/routing.cr | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 9daf5380..b9c88114 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -333,23 +333,10 @@ end 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.register_channel_routes - - Invidious::Routing.get "/watch", Invidious::Routes::Watch, :handle - Invidious::Routing.post "/watch_ajax", Invidious::Routes::Watch, :mark_watched - Invidious::Routing.get "/watch/:id", Invidious::Routes::Watch, :redirect - Invidious::Routing.get "/shorts/:id", Invidious::Routes::Watch, :redirect - Invidious::Routing.get "/clip/:clip", Invidious::Routes::Watch, :clip - Invidious::Routing.get "/w/:id", Invidious::Routes::Watch, :redirect - Invidious::Routing.get "/v/:id", Invidious::Routes::Watch, :redirect - Invidious::Routing.get "/e/:id", Invidious::Routes::Watch, :redirect Invidious::Routing.get "/redirect", Invidious::Routes::Misc, :cross_instance_redirect - Invidious::Routing.post "/download", Invidious::Routes::Watch, :download - - Invidious::Routing.get "/embed/", Invidious::Routes::Embed, :redirect - Invidious::Routing.get "/embed/:id", Invidious::Routes::Embed, :show + Invidious::Routing.register_channel_routes + Invidious::Routing.register_watch_routes Invidious::Routing.get "/create_playlist", Invidious::Routes::Playlists, :new Invidious::Routing.post "/create_playlist", Invidious::Routes::Playlists, :create diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 45ae7c6b..4f6db78c 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -71,6 +71,22 @@ module Invidious::Routing end end + def register_watch_routes + get "/watch", Routes::Watch, :handle + post "/watch_ajax", Routes::Watch, :mark_watched + get "/watch/:id", Routes::Watch, :redirect + get "/shorts/:id", Routes::Watch, :redirect + get "/clip/:clip", Routes::Watch, :clip + get "/w/:id", Routes::Watch, :redirect + get "/v/:id", Routes::Watch, :redirect + get "/e/:id", Routes::Watch, :redirect + + post "/download", Routes::Watch, :download + + get "/embed/", Routes::Embed, :redirect + get "/embed/:id", Routes::Embed, :show + end + def register_api_manifest_routes get "/api/manifest/dash/id/:id", Routes::API::Manifest, :get_dash_video_id From 5503914abe28eefdc89ca9a4762cc434a351f378 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Wed, 10 Aug 2022 00:26:41 +0200 Subject: [PATCH 08/15] routing: move playlist routes registration to Invidious::Routing --- src/invidious.cr | 14 ++------------ src/invidious/routing.cr | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index b9c88114..f134886f 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -338,18 +338,8 @@ end Invidious::Routing.register_channel_routes Invidious::Routing.register_watch_routes - Invidious::Routing.get "/create_playlist", Invidious::Routes::Playlists, :new - Invidious::Routing.post "/create_playlist", Invidious::Routes::Playlists, :create - Invidious::Routing.get "/subscribe_playlist", Invidious::Routes::Playlists, :subscribe - Invidious::Routing.get "/delete_playlist", Invidious::Routes::Playlists, :delete_page - Invidious::Routing.post "/delete_playlist", Invidious::Routes::Playlists, :delete - Invidious::Routing.get "/edit_playlist", Invidious::Routes::Playlists, :edit - Invidious::Routing.post "/edit_playlist", Invidious::Routes::Playlists, :update - Invidious::Routing.get "/add_playlist_items", Invidious::Routes::Playlists, :add_playlist_items_page - Invidious::Routing.post "/playlist_ajax", Invidious::Routes::Playlists, :playlist_ajax - Invidious::Routing.get "/playlist", Invidious::Routes::Playlists, :show - Invidious::Routing.get "/mix", Invidious::Routes::Playlists, :mix - Invidious::Routing.get "/watch_videos", Invidious::Routes::Playlists, :watch_videos + Invidious::Routing.register_iv_playlist_routes + Invidious::Routing.register_yt_playlist_routes Invidious::Routing.get "/opensearch.xml", Invidious::Routes::Search, :opensearch Invidious::Routing.get "/results", Invidious::Routes::Search, :results diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 4f6db78c..4074ef18 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -44,6 +44,18 @@ module Invidious::Routing get "/subscription_manager", Routes::Subscriptions, :subscription_manager end + def register_iv_playlist_routes + get "/create_playlist", Routes::Playlists, :new + post "/create_playlist", Routes::Playlists, :create + get "/subscribe_playlist", Routes::Playlists, :subscribe + get "/delete_playlist", Routes::Playlists, :delete_page + post "/delete_playlist", Routes::Playlists, :delete + get "/edit_playlist", Routes::Playlists, :edit + post "/edit_playlist", Routes::Playlists, :update + get "/add_playlist_items", Routes::Playlists, :add_playlist_items_page + post "/playlist_ajax", Routes::Playlists, :playlist_ajax + end + # ------------------- # Youtube routes # ------------------- @@ -87,6 +99,12 @@ module Invidious::Routing get "/embed/:id", Routes::Embed, :show end + def register_yt_playlist_routes + get "/playlist", Routes::Playlists, :show + get "/mix", Routes::Playlists, :mix + get "/watch_videos", Routes::Playlists, :watch_videos + end + def register_api_manifest_routes get "/api/manifest/dash/id/:id", Routes::API::Manifest, :get_dash_video_id From 0a4d793556e89e48b1a4caceaf8b8730b4b69d73 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Wed, 10 Aug 2022 00:31:15 +0200 Subject: [PATCH 09/15] routing: move search routes registration to Invidious::Routing --- src/invidious.cr | 5 +---- src/invidious/routing.cr | 11 +++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index f134886f..e880db19 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -341,10 +341,7 @@ end Invidious::Routing.register_iv_playlist_routes Invidious::Routing.register_yt_playlist_routes - Invidious::Routing.get "/opensearch.xml", Invidious::Routes::Search, :opensearch - Invidious::Routing.get "/results", Invidious::Routes::Search, :results - Invidious::Routing.get "/search", Invidious::Routes::Search, :search - Invidious::Routing.get "/hashtag/:hashtag", Invidious::Routes::Search, :hashtag + Invidious::Routing.register_search_routes # User routes Invidious::Routing.register_user_routes diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 4074ef18..828deaf9 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -105,6 +105,17 @@ module Invidious::Routing get "/watch_videos", Routes::Playlists, :watch_videos end + def register_search_routes + get "/opensearch.xml", Routes::Search, :opensearch + get "/results", Routes::Search, :results + get "/search", Routes::Search, :search + get "/hashtag/:hashtag", Routes::Search, :hashtag + end + + # ------------------- + # Media proxy routes + # ------------------- + def register_api_manifest_routes get "/api/manifest/dash/id/:id", Routes::API::Manifest, :get_dash_video_id From 223e74569aa3355857ee37f84b0eac2a8dd24b3d Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Wed, 10 Aug 2022 00:44:21 +0200 Subject: [PATCH 10/15] routing: move feed routes registration to Invidious::Routing --- src/invidious.cr | 14 +------------- src/invidious/routing.cr | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index e880db19..4a3b28b1 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -346,19 +346,7 @@ end # User routes Invidious::Routing.register_user_routes - # Feeds - Invidious::Routing.get "/view_all_playlists", Invidious::Routes::Feeds, :view_all_playlists_redirect - Invidious::Routing.get "/feed/playlists", Invidious::Routes::Feeds, :playlists - Invidious::Routing.get "/feed/popular", Invidious::Routes::Feeds, :popular - Invidious::Routing.get "/feed/trending", Invidious::Routes::Feeds, :trending - Invidious::Routing.get "/feed/subscriptions", Invidious::Routes::Feeds, :subscriptions - Invidious::Routing.get "/feed/history", Invidious::Routes::Feeds, :history - - # RSS Feeds - Invidious::Routing.get "/feed/channel/:ucid", Invidious::Routes::Feeds, :rss_channel - Invidious::Routing.get "/feed/private", Invidious::Routes::Feeds, :rss_private - Invidious::Routing.get "/feed/playlist/:plid", Invidious::Routes::Feeds, :rss_playlist - Invidious::Routing.get "/feeds/videos.xml", Invidious::Routes::Feeds, :rss_videos + Invidious::Routing.register_feed_routes # Support push notifications via PubSubHubbub Invidious::Routing.get "/feed/webhook/:token", Invidious::Routes::Feeds, :push_notifications_get diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 828deaf9..e9657bba 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -56,6 +56,22 @@ module Invidious::Routing post "/playlist_ajax", Routes::Playlists, :playlist_ajax end + def register_feed_routes + # Feeds + get "/view_all_playlists", Routes::Feeds, :view_all_playlists_redirect + get "/feed/playlists", Routes::Feeds, :playlists + get "/feed/popular", Routes::Feeds, :popular + get "/feed/trending", Routes::Feeds, :trending + get "/feed/subscriptions", Routes::Feeds, :subscriptions + get "/feed/history", Routes::Feeds, :history + + # RSS Feeds + get "/feed/channel/:ucid", Routes::Feeds, :rss_channel + get "/feed/private", Routes::Feeds, :rss_private + get "/feed/playlist/:plid", Routes::Feeds, :rss_playlist + get "/feeds/videos.xml", Routes::Feeds, :rss_videos + end + # ------------------- # Youtube routes # ------------------- From 1e25894f7ec37044698f9fddf60813e0199b921b Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Wed, 10 Aug 2022 00:48:09 +0200 Subject: [PATCH 11/15] routing: move the remaining routes registration to a wrapper function --- src/invidious.cr | 35 +---------------------------------- src/invidious/routing.cr | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 4a3b28b1..95e4c225 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -329,40 +329,7 @@ before_all do |env| env.set "current_page", URI.encode_www_form(current_page) end -{% unless flag?(:api_only) %} - 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 "/redirect", Invidious::Routes::Misc, :cross_instance_redirect - - Invidious::Routing.register_channel_routes - Invidious::Routing.register_watch_routes - - Invidious::Routing.register_iv_playlist_routes - Invidious::Routing.register_yt_playlist_routes - - Invidious::Routing.register_search_routes - - # User routes - Invidious::Routing.register_user_routes - - Invidious::Routing.register_feed_routes - - # Support push notifications via PubSubHubbub - Invidious::Routing.get "/feed/webhook/:token", Invidious::Routes::Feeds, :push_notifications_get - Invidious::Routing.post "/feed/webhook/:token", Invidious::Routes::Feeds, :push_notifications_post - - Invidious::Routing.get "/modify_notifications", Invidious::Routes::Notifications, :modify -{% end %} - -Invidious::Routing.register_image_routes - -# API routes (macro) -Invidious::Routing.register_api_v1_routes - -# Video playback (macros) -Invidious::Routing.register_api_manifest_routes -Invidious::Routing.register_video_playback_routes +Invidious::Routing.register_all error 404 do |env| if md = env.request.path.match(/^\/(?([a-zA-Z0-9_-]{11})|(\w+))$/) diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index e9657bba..8084b3e4 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -11,6 +11,37 @@ module Invidious::Routing {% end %} + def register_all + {% unless flag?(:api_only) %} + get "/", Routes::Misc, :home + get "/privacy", Routes::Misc, :privacy + get "/licenses", Routes::Misc, :licenses + get "/redirect", Routes::Misc, :cross_instance_redirect + + self.register_channel_routes + self.register_watch_routes + + self.register_iv_playlist_routes + self.register_yt_playlist_routes + + self.register_search_routes + + self.register_user_routes + self.register_feed_routes + + # Support push notifications via PubSubHubbub + get "/feed/webhook/:token", Routes::Feeds, :push_notifications_get + post "/feed/webhook/:token", Routes::Feeds, :push_notifications_post + + get "/modify_notifications", Routes::Notifications, :modify + {% end %} + + self.register_image_routes + self.register_api_v1_routes + self.register_api_manifest_routes + self.register_video_playback_routes + end + # ------------------- # Invidious routes # ------------------- From 870350fd612008a3694159ef933831943fca68b4 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Wed, 10 Aug 2022 00:52:09 +0200 Subject: [PATCH 12/15] routes: move before_all logic to its own module --- src/invidious.cr | 153 +---------------------------- src/invidious/routes/before_all.cr | 152 ++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+), 148 deletions(-) create mode 100644 src/invidious/routes/before_all.cr diff --git a/src/invidious.cr b/src/invidious.cr index 95e4c225..4a3b0003 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -178,155 +178,10 @@ def popular_videos Invidious::Jobs::PullPopularVideosJob::POPULAR_VIDEOS.get end +# Routing + before_all do |env| - preferences = Preferences.from_json("{}") - - begin - if prefs_cookie = env.request.cookies["PREFS"]? - preferences = Preferences.from_json(URI.decode_www_form(prefs_cookie.value)) - else - if language_header = env.request.headers["Accept-Language"]? - if language = ANG.language_negotiator.best(language_header, LOCALES.keys) - preferences.locale = language.header - end - end - end - rescue - preferences = Preferences.from_json("{}") - end - - env.set "preferences", preferences - env.response.headers["X-XSS-Protection"] = "1; mode=block" - env.response.headers["X-Content-Type-Options"] = "nosniff" - - # Allow media resources to be loaded from google servers - # TODO: check if *.youtube.com can be removed - if CONFIG.disabled?("local") || !preferences.local - extra_media_csp = " https://*.googlevideo.com:443 https://*.youtube.com:443" - else - extra_media_csp = "" - end - - # Only allow the pages at /embed/* to be embedded - if env.request.resource.starts_with?("/embed") - frame_ancestors = "'self' http: https:" - else - frame_ancestors = "'none'" - end - - # TODO: Remove style-src's 'unsafe-inline', requires to remove all - # inline styles (, style=" [..] ") - env.response.headers["Content-Security-Policy"] = { - "default-src 'none'", - "script-src 'self'", - "style-src 'self' 'unsafe-inline'", - "img-src 'self' data:", - "font-src 'self' data:", - "connect-src 'self'", - "manifest-src 'self'", - "media-src 'self' blob:" + extra_media_csp, - "child-src 'self' blob:", - "frame-src 'self'", - "frame-ancestors " + frame_ancestors, - }.join("; ") - - env.response.headers["Referrer-Policy"] = "same-origin" - - # Ask the chrom*-based browsers to disable FLoC - # See: https://blog.runcloud.io/google-floc/ - env.response.headers["Permissions-Policy"] = "interest-cohort=()" - - if (Kemal.config.ssl || CONFIG.https_only) && CONFIG.hsts - env.response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains; preload" - end - - next if { - "/sb/", - "/vi/", - "/s_p/", - "/yts/", - "/ggpht/", - "/api/manifest/", - "/videoplayback", - "/latest_version", - "/download", - }.any? { |r| env.request.resource.starts_with? r } - - if env.request.cookies.has_key? "SID" - sid = env.request.cookies["SID"].value - - if sid.starts_with? "v1:" - raise "Cannot use token as SID" - end - - # Invidious users only have SID - if !env.request.cookies.has_key? "SSID" - if email = Invidious::Database::SessionIDs.select_email(sid) - user = Invidious::Database::Users.select!(email: email) - csrf_token = generate_response(sid, { - ":authorize_token", - ":playlist_ajax", - ":signout", - ":subscription_ajax", - ":token_ajax", - ":watch_ajax", - }, HMAC_KEY, 1.week) - - preferences = user.preferences - env.set "preferences", preferences - - env.set "sid", sid - env.set "csrf_token", csrf_token - env.set "user", user - end - else - headers = HTTP::Headers.new - headers["Cookie"] = env.request.headers["Cookie"] - - begin - user, sid = get_user(sid, headers, false) - csrf_token = generate_response(sid, { - ":authorize_token", - ":playlist_ajax", - ":signout", - ":subscription_ajax", - ":token_ajax", - ":watch_ajax", - }, HMAC_KEY, 1.week) - - preferences = user.preferences - env.set "preferences", preferences - - env.set "sid", sid - env.set "csrf_token", csrf_token - env.set "user", user - rescue ex - end - end - end - - dark_mode = convert_theme(env.params.query["dark_mode"]?) || preferences.dark_mode.to_s - thin_mode = env.params.query["thin_mode"]? || preferences.thin_mode.to_s - thin_mode = thin_mode == "true" - locale = env.params.query["hl"]? || preferences.locale - - preferences.dark_mode = dark_mode - preferences.thin_mode = thin_mode - preferences.locale = locale - env.set "preferences", preferences - - current_page = env.request.path - if env.request.query - query = HTTP::Params.parse(env.request.query.not_nil!) - - if query["referer"]? - query["referer"] = get_referer(env, "/") - end - - current_page += "?#{query}" - end - - env.set "current_page", URI.encode_www_form(current_page) + Invidious::Routes::BeforeAll.handle(env) end Invidious::Routing.register_all @@ -386,6 +241,8 @@ static_headers do |response| response.headers.add("Cache-Control", "max-age=2629800") end +# Init Kemal + public_folder "assets" Kemal.config.powered_by_header = false diff --git a/src/invidious/routes/before_all.cr b/src/invidious/routes/before_all.cr new file mode 100644 index 00000000..8e2a253f --- /dev/null +++ b/src/invidious/routes/before_all.cr @@ -0,0 +1,152 @@ +module Invidious::Routes::BeforeAll + def self.handle(env) + preferences = Preferences.from_json("{}") + + begin + if prefs_cookie = env.request.cookies["PREFS"]? + preferences = Preferences.from_json(URI.decode_www_form(prefs_cookie.value)) + else + if language_header = env.request.headers["Accept-Language"]? + if language = ANG.language_negotiator.best(language_header, LOCALES.keys) + preferences.locale = language.header + end + end + end + rescue + preferences = Preferences.from_json("{}") + end + + env.set "preferences", preferences + env.response.headers["X-XSS-Protection"] = "1; mode=block" + env.response.headers["X-Content-Type-Options"] = "nosniff" + + # Allow media resources to be loaded from google servers + # TODO: check if *.youtube.com can be removed + if CONFIG.disabled?("local") || !preferences.local + extra_media_csp = " https://*.googlevideo.com:443 https://*.youtube.com:443" + else + extra_media_csp = "" + end + + # Only allow the pages at /embed/* to be embedded + if env.request.resource.starts_with?("/embed") + frame_ancestors = "'self' http: https:" + else + frame_ancestors = "'none'" + end + + # TODO: Remove style-src's 'unsafe-inline', requires to remove all + # inline styles (, style=" [..] ") + env.response.headers["Content-Security-Policy"] = { + "default-src 'none'", + "script-src 'self'", + "style-src 'self' 'unsafe-inline'", + "img-src 'self' data:", + "font-src 'self' data:", + "connect-src 'self'", + "manifest-src 'self'", + "media-src 'self' blob:" + extra_media_csp, + "child-src 'self' blob:", + "frame-src 'self'", + "frame-ancestors " + frame_ancestors, + }.join("; ") + + env.response.headers["Referrer-Policy"] = "same-origin" + + # Ask the chrom*-based browsers to disable FLoC + # See: https://blog.runcloud.io/google-floc/ + env.response.headers["Permissions-Policy"] = "interest-cohort=()" + + if (Kemal.config.ssl || CONFIG.https_only) && CONFIG.hsts + env.response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains; preload" + end + + return if { + "/sb/", + "/vi/", + "/s_p/", + "/yts/", + "/ggpht/", + "/api/manifest/", + "/videoplayback", + "/latest_version", + "/download", + }.any? { |r| env.request.resource.starts_with? r } + + if env.request.cookies.has_key? "SID" + sid = env.request.cookies["SID"].value + + if sid.starts_with? "v1:" + raise "Cannot use token as SID" + end + + # Invidious users only have SID + if !env.request.cookies.has_key? "SSID" + if email = Invidious::Database::SessionIDs.select_email(sid) + user = Invidious::Database::Users.select!(email: email) + csrf_token = generate_response(sid, { + ":authorize_token", + ":playlist_ajax", + ":signout", + ":subscription_ajax", + ":token_ajax", + ":watch_ajax", + }, HMAC_KEY, 1.week) + + preferences = user.preferences + env.set "preferences", preferences + + env.set "sid", sid + env.set "csrf_token", csrf_token + env.set "user", user + end + else + headers = HTTP::Headers.new + headers["Cookie"] = env.request.headers["Cookie"] + + begin + user, sid = get_user(sid, headers, false) + csrf_token = generate_response(sid, { + ":authorize_token", + ":playlist_ajax", + ":signout", + ":subscription_ajax", + ":token_ajax", + ":watch_ajax", + }, HMAC_KEY, 1.week) + + preferences = user.preferences + env.set "preferences", preferences + + env.set "sid", sid + env.set "csrf_token", csrf_token + env.set "user", user + rescue ex + end + end + end + + dark_mode = convert_theme(env.params.query["dark_mode"]?) || preferences.dark_mode.to_s + thin_mode = env.params.query["thin_mode"]? || preferences.thin_mode.to_s + thin_mode = thin_mode == "true" + locale = env.params.query["hl"]? || preferences.locale + + preferences.dark_mode = dark_mode + preferences.thin_mode = thin_mode + preferences.locale = locale + env.set "preferences", preferences + + current_page = env.request.path + if env.request.query + query = HTTP::Params.parse(env.request.query.not_nil!) + + if query["referer"]? + query["referer"] = get_referer(env, "/") + end + + current_page += "?#{query}" + end + + env.set "current_page", URI.encode_www_form(current_page) + end +end From 88ea794fdb6222011020b6fc778f6cd5da70484a Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Wed, 10 Aug 2022 01:00:44 +0200 Subject: [PATCH 13/15] routes: move error 404 logic to its own module --- src/invidious.cr | 44 +------------------------------ src/invidious/routes/errors.cr | 47 ++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 43 deletions(-) create mode 100644 src/invidious/routes/errors.cr diff --git a/src/invidious.cr b/src/invidious.cr index 4a3b0003..aff879e3 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -187,49 +187,7 @@ end Invidious::Routing.register_all error 404 do |env| - if md = env.request.path.match(/^\/(?([a-zA-Z0-9_-]{11})|(\w+))$/) - item = md["id"] - - # Check if item is branding URL e.g. https://youtube.com/gaming - response = YT_POOL.client &.get("/#{item}") - - if response.status_code == 301 - response = YT_POOL.client &.get(URI.parse(response.headers["Location"]).request_target) - end - - if response.body.empty? - env.response.headers["Location"] = "/" - halt env, status_code: 302 - end - - html = XML.parse_html(response.body) - ucid = html.xpath_node(%q(//link[@rel="canonical"])).try &.["href"].split("/")[-1] - - if ucid - env.response.headers["Location"] = "/channel/#{ucid}" - halt env, status_code: 302 - end - - params = [] of String - env.params.query.each do |k, v| - params << "#{k}=#{v}" - end - params = params.join("&") - - url = "/watch?v=#{item}" - if !params.empty? - url += "&#{params}" - end - - # Check if item is video ID - if item.match(/^[a-zA-Z0-9_-]{11}$/) && YT_POOL.client &.head("/watch?v=#{item}").status_code != 404 - env.response.headers["Location"] = url - halt env, status_code: 302 - end - end - - env.response.headers["Location"] = "/" - halt env, status_code: 302 + Invidious::Routes::ErrorRoutes.error_404(env) end error 500 do |env, ex| diff --git a/src/invidious/routes/errors.cr b/src/invidious/routes/errors.cr new file mode 100644 index 00000000..b138b562 --- /dev/null +++ b/src/invidious/routes/errors.cr @@ -0,0 +1,47 @@ +module Invidious::Routes::ErrorRoutes + def self.error_404(env) + if md = env.request.path.match(/^\/(?([a-zA-Z0-9_-]{11})|(\w+))$/) + item = md["id"] + + # Check if item is branding URL e.g. https://youtube.com/gaming + response = YT_POOL.client &.get("/#{item}") + + if response.status_code == 301 + response = YT_POOL.client &.get(URI.parse(response.headers["Location"]).request_target) + end + + if response.body.empty? + env.response.headers["Location"] = "/" + haltf env, status_code: 302 + end + + html = XML.parse_html(response.body) + ucid = html.xpath_node(%q(//link[@rel="canonical"])).try &.["href"].split("/")[-1] + + if ucid + env.response.headers["Location"] = "/channel/#{ucid}" + haltf env, status_code: 302 + end + + params = [] of String + env.params.query.each do |k, v| + params << "#{k}=#{v}" + end + params = params.join("&") + + url = "/watch?v=#{item}" + if !params.empty? + url += "&#{params}" + end + + # Check if item is video ID + if item.match(/^[a-zA-Z0-9_-]{11}$/) && YT_POOL.client &.head("/watch?v=#{item}").status_code != 404 + env.response.headers["Location"] = url + haltf env, status_code: 302 + end + end + + env.response.headers["Location"] = "/" + haltf env, status_code: 302 + end +end From 848a60aa9bfca457ae6e1a470d6fcf3ef03a1f38 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Wed, 10 Aug 2022 01:01:31 +0200 Subject: [PATCH 14/15] routes: remove useless 'locale' variable in error 505 handler --- src/invidious.cr | 1 - 1 file changed, 1 deletion(-) diff --git a/src/invidious.cr b/src/invidious.cr index aff879e3..0601d5b2 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -191,7 +191,6 @@ error 404 do |env| end error 500 do |env, ex| - locale = env.get("preferences").as(Preferences).locale error_template(500, ex) end From cb8a375c5e7ae79cad8daa9430b65c68f50e2885 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Wed, 10 Aug 2022 20:50:49 +0200 Subject: [PATCH 15/15] routing: Directly call Kemal's add_route function --- src/invidious/routing.cr | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 8084b3e4..b1cef086 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -4,7 +4,11 @@ module Invidious::Routing {% for http_method in {"get", "post", "delete", "options", "patch", "put"} %} macro {{http_method.id}}(path, controller, method = :handle) - {{http_method.id}} \{{ path }} do |env| + unless !Kemal::Utils.path_starts_with_slash?(\{{path}}) + raise Kemal::Exceptions::InvalidPathStartException.new({{http_method}}, \{{path}}) + end + + Kemal::RouteHandler::INSTANCE.add_route({{http_method.upcase}}, \{{path}}) do |env| \{{ controller }}.\{{ method.id }}(env) end end