diff options
Diffstat (limited to 'src/invidious.cr')
| -rw-r--r-- | src/invidious.cr | 358 |
1 files changed, 91 insertions, 267 deletions
diff --git a/src/invidious.cr b/src/invidious.cr index 5ad2dd91..18ec0b97 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -67,7 +67,7 @@ SOFTWARE = { "branch" => "#{CURRENT_BRANCH}", } -YT_POOL = YoutubeConnectionPool.new(YT_URL, capacity: CONFIG.pool_size, timeout: 2.0, use_quic: CONFIG.use_quic) +YT_POOL = YoutubeConnectionPool.new(YT_URL, capacity: CONFIG.pool_size, use_quic: CONFIG.use_quic) # CLI Kemal.config.extra_options do |parser| @@ -153,10 +153,6 @@ if CONFIG.popular_enabled Invidious::Jobs.register Invidious::Jobs::PullPopularVideosJob.new(PG_DB) end -if CONFIG.captcha_key - Invidious::Jobs.register Invidious::Jobs::BypassCaptchaJob.new -end - connection_channel = Channel({Bool, Channel(PQ::Notification)}).new(32) Invidious::Jobs.register Invidious::Jobs::NotificationJob.new(connection_channel, CONFIG.database_url) @@ -316,80 +312,89 @@ before_all do |env| env.set "current_page", URI.encode_www_form(current_page) 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.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 - -["", "/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.get "/watch", Invidious::Routes::Watch, :handle -Invidious::Routing.get "/watch/:id", Invidious::Routes::Watch, :redirect -Invidious::Routing.get "/shorts/:id", Invidious::Routes::Watch, :redirect -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.get "/embed/", Invidious::Routes::Embed, :redirect -Invidious::Routing.get "/embed/:id", Invidious::Routes::Embed, :show - -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 "/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 "/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 "/preferences", Invidious::Routes::PreferencesRoute, :show -Invidious::Routing.post "/preferences", Invidious::Routes::PreferencesRoute, :update -Invidious::Routing.get "/toggle_theme", Invidious::Routes::PreferencesRoute, :toggle_theme - -# 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 - -# 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 +{% 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 "/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 + + ["", "/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.get "/watch", Invidious::Routes::Watch, :handle + Invidious::Routing.get "/watch/:id", Invidious::Routes::Watch, :redirect + Invidious::Routing.get "/shorts/:id", Invidious::Routes::Watch, :redirect + 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.get "/embed/", Invidious::Routes::Embed, :redirect + Invidious::Routing.get "/embed/:id", Invidious::Routes::Embed, :show + + 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 "/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 "/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 "/preferences", Invidious::Routes::PreferencesRoute, :show + Invidious::Routing.post "/preferences", Invidious::Routes::PreferencesRoute, :update + Invidious::Routing.get "/toggle_theme", Invidious::Routes::PreferencesRoute, :toggle_theme + + # 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 + + # 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 +{% 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 # API routes (macro) define_v1_api_routes() @@ -1275,194 +1280,6 @@ post "/api/v1/auth/notifications" do |env| create_notification_stream(env, topics, connection_channel) end -get "/ggpht/*" do |env| - url = env.request.path.lchop("/ggpht") - - headers = HTTP::Headers{":authority" => "yt3.ggpht.com"} - REQUEST_HEADERS_WHITELIST.each do |header| - if env.request.headers[header]? - headers[header] = env.request.headers[header] - end - end - - begin - YT_POOL.client &.get(url, headers) do |response| - env.response.status_code = response.status_code - response.headers.each do |key, value| - if !RESPONSE_HEADERS_BLACKLIST.includes?(key.downcase) - env.response.headers[key] = value - end - end - - env.response.headers["Access-Control-Allow-Origin"] = "*" - - if response.status_code >= 300 - env.response.headers.delete("Transfer-Encoding") - break - end - - proxy_file(response, env) - end - rescue ex - end -end - -options "/sb/:authority/:id/:storyboard/:index" do |env| - env.response.headers["Access-Control-Allow-Origin"] = "*" - env.response.headers["Access-Control-Allow-Methods"] = "GET, OPTIONS" - env.response.headers["Access-Control-Allow-Headers"] = "Content-Type, Range" -end - -get "/sb/:authority/:id/:storyboard/:index" do |env| - authority = env.params.url["authority"] - id = env.params.url["id"] - storyboard = env.params.url["storyboard"] - index = env.params.url["index"] - - url = "/sb/#{id}/#{storyboard}/#{index}?#{env.params.query}" - - headers = HTTP::Headers.new - - headers[":authority"] = "#{authority}.ytimg.com" - - REQUEST_HEADERS_WHITELIST.each do |header| - if env.request.headers[header]? - headers[header] = env.request.headers[header] - end - end - - begin - YT_POOL.client &.get(url, headers) do |response| - env.response.status_code = response.status_code - response.headers.each do |key, value| - if !RESPONSE_HEADERS_BLACKLIST.includes?(key.downcase) - env.response.headers[key] = value - end - end - - env.response.headers["Connection"] = "close" - env.response.headers["Access-Control-Allow-Origin"] = "*" - - if response.status_code >= 300 - env.response.headers.delete("Transfer-Encoding") - break - end - - proxy_file(response, env) - end - rescue ex - end -end - -get "/s_p/:id/:name" do |env| - id = env.params.url["id"] - name = env.params.url["name"] - - url = env.request.resource - - headers = HTTP::Headers{":authority" => "i9.ytimg.com"} - REQUEST_HEADERS_WHITELIST.each do |header| - if env.request.headers[header]? - headers[header] = env.request.headers[header] - end - end - - begin - YT_POOL.client &.get(url, headers) do |response| - env.response.status_code = response.status_code - response.headers.each do |key, value| - if !RESPONSE_HEADERS_BLACKLIST.includes?(key.downcase) - env.response.headers[key] = value - end - end - - env.response.headers["Access-Control-Allow-Origin"] = "*" - - if response.status_code >= 300 && response.status_code != 404 - env.response.headers.delete("Transfer-Encoding") - break - end - - proxy_file(response, env) - end - rescue ex - end -end - -get "/yts/img/:name" do |env| - headers = HTTP::Headers.new - REQUEST_HEADERS_WHITELIST.each do |header| - if env.request.headers[header]? - headers[header] = env.request.headers[header] - end - end - - begin - YT_POOL.client &.get(env.request.resource, headers) do |response| - env.response.status_code = response.status_code - response.headers.each do |key, value| - if !RESPONSE_HEADERS_BLACKLIST.includes?(key.downcase) - env.response.headers[key] = value - end - end - - env.response.headers["Access-Control-Allow-Origin"] = "*" - - if response.status_code >= 300 && response.status_code != 404 - env.response.headers.delete("Transfer-Encoding") - break - end - - proxy_file(response, env) - end - rescue ex - end -end - -get "/vi/:id/:name" do |env| - id = env.params.url["id"] - name = env.params.url["name"] - - headers = HTTP::Headers{":authority" => "i.ytimg.com"} - - if name == "maxres.jpg" - build_thumbnails(id).each do |thumb| - if YT_POOL.client &.head("/vi/#{id}/#{thumb[:url]}.jpg", headers).status_code == 200 - name = thumb[:url] + ".jpg" - break - end - end - end - url = "/vi/#{id}/#{name}" - - REQUEST_HEADERS_WHITELIST.each do |header| - if env.request.headers[header]? - headers[header] = env.request.headers[header] - end - end - - begin - YT_POOL.client &.get(url, headers) do |response| - env.response.status_code = response.status_code - response.headers.each do |key, value| - if !RESPONSE_HEADERS_BLACKLIST.includes?(key.downcase) - env.response.headers[key] = value - end - end - - env.response.headers["Access-Control-Allow-Origin"] = "*" - - if response.status_code >= 300 && response.status_code != 404 - env.response.headers.delete("Transfer-Encoding") - break - end - - proxy_file(response, env) - end - rescue ex - end -end - get "/Captcha" do |env| headers = HTTP::Headers{":authority" => "accounts.google.com"} response = YT_POOL.client &.get(env.request.resource, headers) @@ -1551,4 +1368,11 @@ Kemal.config.logger = LOGGER Kemal.config.host_binding = Kemal.config.host_binding != "0.0.0.0" ? Kemal.config.host_binding : CONFIG.host_binding Kemal.config.port = Kemal.config.port != 3000 ? Kemal.config.port : CONFIG.port Kemal.config.app_name = "Invidious" + +# Use in kemal's production mode. +# Users can also set the KEMAL_ENV environmental variable for this to be set automatically. +{% if flag?(:release) || flag?(:production) %} + Kemal.config.env = "production" if !ENV.has_key?("KEMAL_ENV") +{% end %} + Kemal.run |
