mirror of
				https://gitea.invidious.io/iv-org/invidious
				synced 2025-06-05 23:29:12 +02:00 
			
		
		
		
	Bountiful changes
- Use haltf in more locations - Fix wrong URL params - Rename API modules - Remove API routing file and move everything to general iv routing file
This commit is contained in:
		| @@ -1,4 +1,4 @@ | ||||
| module Invidious::Routes::APIManifest | ||||
| module Invidious::Routes::API::Manifest | ||||
|   # /api/manifest/dash/id/:id | ||||
|   def self.get_dash_video_id(env) | ||||
|     env.response.headers.add("Access-Control-Allow-Origin", "*") | ||||
| @@ -222,16 +222,3 @@ module Invidious::Routes::APIManifest | ||||
|     manifest | ||||
|   end | ||||
| end | ||||
|  | ||||
| macro define_api_manifest_routes | ||||
|   Invidious::Routing.get "/api/manifest/dash/id/:id", Invidious::Routes::APIManifest, :get_dash_video_id | ||||
|  | ||||
|   Invidious::Routing.get "/api/manifest/dash/id/videoplayback", Invidious::Routes::APIManifest, :get_dash_video_playback | ||||
|   Invidious::Routing.get "/api/manifest/dash/id/videoplayback/*", Invidious::Routes::APIManifest, :get_dash_video_playback_greedy | ||||
|  | ||||
|   Invidious::Routing.options "/api/manifest/dash/id/videoplayback", Invidious::Routes::APIManifest, :options_dash_video_playback | ||||
|   Invidious::Routing.options "/api/manifest/dash/id/videoplayback/*", Invidious::Routes::APIManifest, :options_dash_video_playback | ||||
|  | ||||
|   Invidious::Routing.get "/api/manifest/hls_playlist/*", Invidious::Routes::APIManifest, :get_hls_playlist | ||||
|   Invidious::Routing.get "/api/manifest/hls_variant/*", Invidious::Routes::APIManifest, :get_hls_variant | ||||
| end | ||||
|   | ||||
| @@ -1,4 +1,7 @@ | ||||
| module Invidious::Routes::APIv1::Authenticated | ||||
| module Invidious::Routes::API::V1::Authenticated | ||||
|   # The notification APIs cannot be extracted yet! | ||||
|   # They require the *local* notifications constant defined in invidious.cr | ||||
|   # | ||||
|   # def self.notifications(env) | ||||
|   #   env.response.content_type = "text/event-stream" | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| module Invidious::Routes::APIv1::Channels | ||||
| module Invidious::Routes::API::V1::Channels | ||||
|   def self.home(env) | ||||
|     locale = LOCALES[env.get("preferences").as(Preferences).locale]? | ||||
|  | ||||
| @@ -241,7 +241,7 @@ module Invidious::Routes::APIv1::Channels | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def self.channel_search(env) | ||||
|   def self.search(env) | ||||
|     locale = LOCALES[env.get("preferences").as(Preferences).locale]? | ||||
|  | ||||
|     env.response.content_type = "application/json" | ||||
| @@ -263,4 +263,15 @@ module Invidious::Routes::APIv1::Channels | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   # 301 redirect from /api/v1/channels/comments/:ucid | ||||
|   # and /api/v1/channels/:ucid/comments to new /api/v1/channels/:ucid/community and | ||||
|   # corresponding equivalent URL structure of the other one. | ||||
|   def self.channel_comments_redirect(env) | ||||
|     env.response.content_type = "application/json" | ||||
|     ucid = env.params.url["ucid"] | ||||
|  | ||||
|     env.response.headers["Location"] = "/api/v1/channels/#{ucid}/community?#{env.params.query}" | ||||
|     haltf env, status_code: 301 | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| module Invidious::Routes::APIv1::Feeds | ||||
| module Invidious::Routes::API::V1::Feeds | ||||
|   def self.trending(env) | ||||
|     locale = LOCALES[env.get("preferences").as(Preferences).locale]? | ||||
|  | ||||
| @@ -31,8 +31,7 @@ module Invidious::Routes::APIv1::Feeds | ||||
|  | ||||
|     if !CONFIG.popular_enabled | ||||
|       error_message = {"error" => "Administrator has disabled this endpoint."}.to_json | ||||
|       env.response.status_code = 400 | ||||
|       return error_message | ||||
|       haltf env, 400, error_message | ||||
|     end | ||||
|  | ||||
|     JSON.build do |json| | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| module Invidious::Routes::APIv1::Misc | ||||
| module Invidious::Routes::API::V1::Misc | ||||
|   # Stats API endpoint for Invidious | ||||
|   def self.stats(env) | ||||
|     locale = LOCALES[env.get("preferences").as(Preferences).locale]? | ||||
|   | ||||
| @@ -1,67 +0,0 @@ | ||||
| # There is far too many API routes to define in invidious.cr | ||||
| # so we'll just do it here instead with a macro. | ||||
| macro define_v1_api_routes(base_url = "/api/v1") | ||||
|   # Videos | ||||
|   Invidious::Routing.get "#{{{base_url}}}/videos/:id", Invidious::Routes::APIv1::Videos, :videos | ||||
|   Invidious::Routing.get "#{{{base_url}}}/storyboards/:id", Invidious::Routes::APIv1::Videos, :storyboards | ||||
|   Invidious::Routing.get "#{{{base_url}}}/captions/:id", Invidious::Routes::APIv1::Videos, :captions | ||||
|   Invidious::Routing.get "#{{{base_url}}}/annotations/:id", Invidious::Routes::APIv1::Videos, :annotations | ||||
|   Invidious::Routing.get "#{{{base_url}}}/comments/:id", Invidious::Routes::APIv1::Videos, :comments | ||||
|  | ||||
|   # Feeds | ||||
|   Invidious::Routing.get "#{{{base_url}}}/trending", Invidious::Routes::APIv1::Feeds, :trending | ||||
|   Invidious::Routing.get "#{{{base_url}}}/popular", Invidious::Routes::APIv1::Feeds, :popular | ||||
|  | ||||
|   # Channels | ||||
|   Invidious::Routing.get "#{{{base_url}}}/channels/:ucid", Invidious::Routes::APIv1::Channels, :home | ||||
|   {% for route in { | ||||
|                     {"home", "home"}, | ||||
|                     {"videos", "videos"}, | ||||
|                     {"latest", "latest"}, | ||||
|                     {"playlists", "playlists"}, | ||||
|                     {"comments", "community"}, # Why is the route for the community API `comments`?, | ||||
|                     {"search", "channel_search"}, | ||||
|                   } %} | ||||
|  | ||||
|   Invidious::Routing.get "#{{{base_url}}}/channels/#{{{route[0]}}}/:ucid", Invidious::Routes::APIv1::Channels, :{{route[1]}} | ||||
|   Invidious::Routing.get "#{{{base_url}}}/channels/:ucid/#{{{route[0]}}}", Invidious::Routes::APIv1::Channels, :{{route[1]}} | ||||
|   {% end %} | ||||
|  | ||||
|   # Search | ||||
|   Invidious::Routing.get "#{{{base_url}}}/search", Invidious::Routes::APIv1::Search, :search | ||||
|   Invidious::Routing.get "#{{{base_url}}}/search/suggestions/:id", Invidious::Routes::APIv1::Search, :search_suggestions | ||||
|  | ||||
|   # Authenticated | ||||
|   # Invidious::Routing.get "#{{{base_url}}}/auth/notifications", Invidious::Routes::APIv1::Authenticated, :notifications | ||||
|   # Invidious::Routing.post "#{{{base_url}}}/auth/notifications", Invidious::Routes::APIv1::Authenticated, :notifications | ||||
|  | ||||
|   Invidious::Routing.get "#{{{base_url}}}/auth/preferences", Invidious::Routes::APIv1::Authenticated, :get_preferences | ||||
|   Invidious::Routing.post "#{{{base_url}}}/auth/preferences", Invidious::Routes::APIv1::Authenticated, :set_preferences | ||||
|  | ||||
|   Invidious::Routing.get "#{{{base_url}}}/auth/feed", Invidious::Routes::APIv1::Authenticated, :feed | ||||
|  | ||||
|   Invidious::Routing.get "#{{{base_url}}}/auth/subscriptions", Invidious::Routes::APIv1::Authenticated, :get_subscriptions | ||||
|   Invidious::Routing.post "#{{{base_url}}}/auth/subscriptions/:ucid", Invidious::Routes::APIv1::Authenticated, :subscribe_channel | ||||
|   Invidious::Routing.delete "#{{{base_url}}}/auth/subscriptions/:ucid", Invidious::Routes::APIv1::Authenticated, :unsubscribe_channel | ||||
|  | ||||
|  | ||||
|   Invidious::Routing.get "#{{{base_url}}}/auth/playlists", Invidious::Routes::APIv1::Authenticated, :list_playlists | ||||
|   Invidious::Routing.post "#{{{base_url}}}/auth/playlists", Invidious::Routes::APIv1::Authenticated, :create_playlist | ||||
|   Invidious::Routing.patch "#{{{base_url}}}/auth/playlists/:ucid", Invidious::Routes::APIv1::Authenticated, :update_playlist_attribute | ||||
|   Invidious::Routing.delete "#{{{base_url}}}/auth/playlists/:ucid", Invidious::Routes::APIv1::Authenticated, :delete_playlist | ||||
|  | ||||
|  | ||||
|   Invidious::Routing.post "#{{{base_url}}}/auth/playlists/:ucid/videos", Invidious::Routes::APIv1::Authenticated, :insert_video_into_playlist | ||||
|   Invidious::Routing.delete "#{{{base_url}}}/auth/playlists/:ucid/videos/:index", Invidious::Routes::APIv1::Authenticated, :delete_video_in_playlist | ||||
|  | ||||
|   Invidious::Routing.get "#{{{base_url}}}/auth/tokens", Invidious::Routes::APIv1::Authenticated, :get_tokens | ||||
|   Invidious::Routing.post "#{{{base_url}}}/auth/tokens/register", Invidious::Routes::APIv1::Authenticated, :register_token | ||||
|   Invidious::Routing.post "#{{{base_url}}}/auth/tokens/unregister", Invidious::Routes::APIv1::Authenticated, :unregister_token | ||||
|  | ||||
|   # Misc | ||||
|   Invidious::Routing.get "#{{{base_url}}}/stats", Invidious::Routes::APIv1::Misc, :stats | ||||
|   Invidious::Routing.get "#{{{base_url}}}/playlists/:plid", Invidious::Routes::APIv1::Misc, :get_playlist | ||||
|   Invidious::Routing.get "#{{{base_url}}}/auth/playlists/:plid", Invidious::Routes::APIv1::Misc, :get_playlist | ||||
|   Invidious::Routing.get "#{{{base_url}}}//mixes/:rdid", Invidious::Routes::APIv1::Misc, :mixes | ||||
|  | ||||
| end | ||||
| @@ -1,4 +1,4 @@ | ||||
| module Invidious::Routes::APIv1::Search | ||||
| module Invidious::Routes::API::V1::Search | ||||
|   def self.search(env) | ||||
|     locale = LOCALES[env.get("preferences").as(Preferences).locale]? | ||||
|     region = env.params.query["region"]? | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| module Invidious::Routes::APIv1::Videos | ||||
| module Invidious::Routes::API::V1::Videos | ||||
|   def self.videos(env) | ||||
|     locale = LOCALES[env.get("preferences").as(Preferences).locale]? | ||||
|  | ||||
| @@ -41,8 +41,7 @@ module Invidious::Routes::APIv1::Videos | ||||
|       env.response.headers["Location"] = env.request.resource.gsub(id, ex.video_id) | ||||
|       return error_json(302, "Video is unavailable", {"videoId" => ex.video_id}) | ||||
|     rescue ex | ||||
|       env.response.status_code = 500 | ||||
|       return | ||||
|       haltf env, 500 | ||||
|     end | ||||
|  | ||||
|     captions = video.captions | ||||
| @@ -80,8 +79,7 @@ module Invidious::Routes::APIv1::Videos | ||||
|     end | ||||
|  | ||||
|     if caption.empty? | ||||
|       env.response.status_code = 404 | ||||
|       return | ||||
|       haltf env, 404 | ||||
|     else | ||||
|       caption = caption[0] | ||||
|     end | ||||
| @@ -164,8 +162,7 @@ module Invidious::Routes::APIv1::Videos | ||||
|       env.response.headers["Location"] = env.request.resource.gsub(id, ex.video_id) | ||||
|       return error_json(302, "Video is unavailable", {"videoId" => ex.video_id}) | ||||
|     rescue ex | ||||
|       env.response.status_code = 500 | ||||
|       return | ||||
|       haltf env, 500 | ||||
|     end | ||||
|  | ||||
|     storyboards = video.storyboards | ||||
| @@ -189,8 +186,7 @@ module Invidious::Routes::APIv1::Videos | ||||
|     storyboard = storyboards.select { |storyboard| width == "#{storyboard[:width]}" || height == "#{storyboard[:height]}" } | ||||
|  | ||||
|     if storyboard.empty? | ||||
|       env.response.status_code = 404 | ||||
|       return | ||||
|       haltf env, 404 | ||||
|     else | ||||
|       storyboard = storyboard[0] | ||||
|     end | ||||
| @@ -236,8 +232,7 @@ module Invidious::Routes::APIv1::Videos | ||||
|     source ||= "archive" | ||||
|  | ||||
|     if !id.match(/[a-zA-Z0-9_-]{11}/) | ||||
|       env.response.status_code = 400 | ||||
|       return | ||||
|       haltf env, 400 | ||||
|     end | ||||
|  | ||||
|     annotations = "" | ||||
| @@ -267,13 +262,11 @@ module Invidious::Routes::APIv1::Videos | ||||
|         response = make_client(URI.parse(location.headers["Location"]), &.get(location.headers["Location"])) | ||||
|  | ||||
|         if response.body.empty? | ||||
|           env.response.status_code = 404 | ||||
|           return | ||||
|           haltf env, 404 | ||||
|         end | ||||
|  | ||||
|         if response.status_code != 200 | ||||
|           env.response.status_code = response.status_code | ||||
|           return | ||||
|           haltf env, response.status_code | ||||
|         end | ||||
|  | ||||
|         annotations = response.body | ||||
| @@ -284,8 +277,7 @@ module Invidious::Routes::APIv1::Videos | ||||
|       response = YT_POOL.client &.get("/annotations_invideo?video_id=#{id}") | ||||
|  | ||||
|       if response.status_code != 200 | ||||
|         env.response.status_code = response.status_code | ||||
|         return | ||||
|         haltf env, response.status_code | ||||
|       end | ||||
|  | ||||
|       annotations = response.body | ||||
| @@ -293,7 +285,7 @@ module Invidious::Routes::APIv1::Videos | ||||
|  | ||||
|     etag = sha256(annotations)[0, 16] | ||||
|     if env.request.headers["If-None-Match"]?.try &.== etag | ||||
|       env.response.status_code = 304 | ||||
|       haltf env, 304 | ||||
|     else | ||||
|       env.response.headers["ETag"] = etag | ||||
|       annotations | ||||
| @@ -349,8 +341,7 @@ module Invidious::Routes::APIv1::Videos | ||||
|       end | ||||
|  | ||||
|       if !reddit_thread || !comments | ||||
|         env.response.status_code = 404 | ||||
|         return | ||||
|         haltf env, 404 | ||||
|       end | ||||
|  | ||||
|       if format == "json" | ||||
|   | ||||
| @@ -278,13 +278,3 @@ module Invidious::Routes::VideoPlayback | ||||
|     return env.redirect url | ||||
|   end | ||||
| 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 | ||||
|   | ||||
| @@ -9,3 +9,92 @@ module Invidious::Routing | ||||
|  | ||||
|   {% 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 | ||||
|  | ||||
|   # Feeds | ||||
|   Invidious::Routing.get "/api/v1/trending", {{namespace}}::Feeds, :trending | ||||
|   Invidious::Routing.get "/api/v1/popular", {{namespace}}::Feeds, :popular | ||||
|  | ||||
|   # 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 %} | ||||
|  | ||||
|   # 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 | ||||
|  | ||||
|  | ||||
|   # Search | ||||
|   Invidious::Routing.get "/api/v1/search", {{namespace}}::Search, :search | ||||
|   Invidious::Routing.get "/api/v1/search/suggestions/:id", {{namespace}}::Search, :search_suggestions | ||||
|  | ||||
|   # Authenticated | ||||
|  | ||||
|   # 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/preferences", {{namespace}}::Authenticated, :get_preferences | ||||
|   Invidious::Routing.post "/api/v1/auth/preferences", {{namespace}}::Authenticated, :set_preferences | ||||
|  | ||||
|   Invidious::Routing.get "/api/v1/auth/feed", {{namespace}}::Authenticated, :feed | ||||
|  | ||||
|   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 | ||||
|  | ||||
|  | ||||
|   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 | ||||
|  | ||||
|  | ||||
|   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 | ||||
|  | ||||
|   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 | ||||
|  | ||||
|   # 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 | ||||
| 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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user