Restructure API route organisation

This commit is contained in:
syeopite 2021-08-12 11:46:03 -07:00
parent cbf3d75087
commit 66becbf46f
No known key found for this signature in database
GPG Key ID: 6FA616E5A5294A82
8 changed files with 166 additions and 163 deletions

View File

@ -1,116 +0,0 @@
class Invidious::Routes::V1Api < Invidious::Routes::BaseRoute
def comments(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]?
region = env.params.query["region"]?
env.response.content_type = "application/json"
id = env.params.url["id"]
source = env.params.query["source"]?
source ||= "youtube"
thin_mode = env.params.query["thin_mode"]?
thin_mode = thin_mode == "true"
format = env.params.query["format"]?
format ||= "json"
action = env.params.query["action"]?
action ||= "action_get_comments"
continuation = env.params.query["continuation"]?
sort_by = env.params.query["sort_by"]?.try &.downcase
if source == "youtube"
sort_by ||= "top"
begin
comments = fetch_youtube_comments(id, PG_DB, continuation, format, locale, thin_mode, region, sort_by: sort_by, action: action)
rescue ex
return error_json(500, ex)
end
return comments
elsif source == "reddit"
sort_by ||= "confidence"
begin
comments, reddit_thread = fetch_reddit_comments(id, sort_by: sort_by)
content_html = template_reddit_comments(comments, locale)
content_html = fill_links(content_html, "https", "www.reddit.com")
content_html = replace_links(content_html)
rescue ex
comments = nil
reddit_thread = nil
content_html = ""
end
if !reddit_thread || !comments
env.response.status_code = 404
return
end
if format == "json"
reddit_thread = JSON.parse(reddit_thread.to_json).as_h
reddit_thread["comments"] = JSON.parse(comments.to_json)
return reddit_thread.to_json
else
response = {
"title" => reddit_thread.title,
"permalink" => reddit_thread.permalink,
"contentHtml" => content_html,
}
return response.to_json
end
end
end
def trending(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json"
region = env.params.query["region"]?
trending_type = env.params.query["type"]?
begin
trending, plid = fetch_trending(trending_type, region, locale)
rescue ex
return error_json(500, ex)
end
videos = JSON.build do |json|
json.array do
trending.each do |video|
video.to_json(locale, json)
end
end
end
videos
end
def popular(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json"
if !CONFIG.popular_enabled
error_message = {"error" => "Administrator has disabled this endpoint."}.to_json
env.response.status_code = 400
return error_message
end
JSON.build do |json|
json.array do
popular_videos.each do |video|
video.to_json(locale, json)
end
end
end
end
end

View File

@ -1,5 +1,5 @@
class Invidious::Routes::V1Api < Invidious::Routes::BaseRoute module Invidious::Routes::APIv1
def home(env) def self.home(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]? locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json" env.response.content_type = "application/json"
@ -124,7 +124,7 @@ class Invidious::Routes::V1Api < Invidious::Routes::BaseRoute
end end
end end
def latest(env) def self.latest(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]? locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json" env.response.content_type = "application/json"
@ -146,7 +146,7 @@ class Invidious::Routes::V1Api < Invidious::Routes::BaseRoute
end end
end end
def videos(env) def self.videos(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]? locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json" env.response.content_type = "application/json"
@ -182,7 +182,7 @@ class Invidious::Routes::V1Api < Invidious::Routes::BaseRoute
end end
end end
def playlists(env) def self.playlists(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]? locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json" env.response.content_type = "application/json"
@ -219,7 +219,7 @@ class Invidious::Routes::V1Api < Invidious::Routes::BaseRoute
end end
end end
def community(env) def self.community(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]? locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json" env.response.content_type = "application/json"
@ -241,27 +241,4 @@ class Invidious::Routes::V1Api < Invidious::Routes::BaseRoute
return error_json(500, ex) return error_json(500, ex)
end end
end end
def channel_search(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json"
ucid = env.params.url["ucid"]
query = env.params.query["q"]?
query ||= ""
page = env.params.query["page"]?.try &.to_i?
page ||= 1
count, search_results = channel_search(query, page, ucid)
JSON.build do |json|
json.array do
search_results.each do |item|
item.to_json(locale, json)
end
end
end
end
end end

View File

@ -0,0 +1,46 @@
module Invidious::Routes::APIv1
def self.trending(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json"
region = env.params.query["region"]?
trending_type = env.params.query["type"]?
begin
trending, plid = fetch_trending(trending_type, region, locale)
rescue ex
return error_json(500, ex)
end
videos = JSON.build do |json|
json.array do
trending.each do |video|
video.to_json(locale, json)
end
end
end
videos
end
def self.popular(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json"
if !CONFIG.popular_enabled
error_message = {"error" => "Administrator has disabled this endpoint."}.to_json
env.response.status_code = 400
return error_message
end
JSON.build do |json|
json.array do
popular_videos.each do |video|
video.to_json(locale, json)
end
end
end
end
end

View File

@ -1,6 +1,6 @@
class Invidious::Routes::V1Api < Invidious::Routes::BaseRoute module Invidious::Routes::APIv1
# Stats API endpoint for Invidious # Stats API endpoint for Invidious
def stats(env) def self.stats(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]? locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json" env.response.content_type = "application/json"

View File

@ -1,18 +1,18 @@
# There is far too many API routes to define in invidious.cr # There is far too many API routes to define in invidious.cr
# so we'll just do it here instead with a macro. # so we'll just do it here instead with a macro.
macro define_v1_api_routes(base_url = "/api/v1") macro define_v1_api_routes(base_url = "/api/v1")
Invidious::Routing.get "#{{{base_url}}}/stats", Invidious::Routes::V1Api, :stats Invidious::Routing.get "#{{{base_url}}}/stats", Invidious::Routes::APIv1, :stats
Invidious::Routing.get "#{{{base_url}}}/storyboards/:id", Invidious::Routes::V1Api, :storyboards Invidious::Routing.get "#{{{base_url}}}/storyboards/:id", Invidious::Routes::APIv1, :storyboards
Invidious::Routing.get "#{{{base_url}}}/captions/:id", Invidious::Routes::V1Api, :captions Invidious::Routing.get "#{{{base_url}}}/captions/:id", Invidious::Routes::APIv1, :captions
Invidious::Routing.get "#{{{base_url}}}/annotations/:id", Invidious::Routes::V1Api, :annotations Invidious::Routing.get "#{{{base_url}}}/annotations/:id", Invidious::Routes::APIv1, :annotations
Invidious::Routing.get "#{{{base_url}}}/search/suggestions/:id", Invidious::Routes::V1Api, :search_suggestions Invidious::Routing.get "#{{{base_url}}}/search/suggestions/:id", Invidious::Routes::APIv1, :search_suggestions
Invidious::Routing.get "#{{{base_url}}}/comments/:id", Invidious::Routes::V1Api, :comments Invidious::Routing.get "#{{{base_url}}}/comments/:id", Invidious::Routes::APIv1, :comments
Invidious::Routing.get "#{{{base_url}}}/trending", Invidious::Routes::V1Api, :trending Invidious::Routing.get "#{{{base_url}}}/trending", Invidious::Routes::APIv1, :trending
Invidious::Routing.get "#{{{base_url}}}/popular", Invidious::Routes::V1Api, :popular Invidious::Routing.get "#{{{base_url}}}/popular", Invidious::Routes::APIv1, :popular
Invidious::Routing.get "#{{{base_url}}}/channels/:ucid", Invidious::Routes::V1Api, :home Invidious::Routing.get "#{{{base_url}}}/channels/:ucid", Invidious::Routes::APIv1, :home
{% for route in { {% for route in {
{"home", "home"}, {"home", "home"},
@ -23,8 +23,8 @@ macro define_v1_api_routes(base_url = "/api/v1")
{"search", "channel_search"}, {"search", "channel_search"},
} %} } %}
Invidious::Routing.get "#{{{base_url}}}/channels/#{{{route[0]}}}/:ucid", Invidious::Routes::V1Api, :{{route[1]}} Invidious::Routing.get "#{{{base_url}}}/channels/#{{{route[0]}}}/:ucid", Invidious::Routes::APIv1, :{{route[1]}}
Invidious::Routing.get "#{{{base_url}}}/channels/:ucid/#{{{route[0]}}}", Invidious::Routes::V1Api, :{{route[1]}} Invidious::Routing.get "#{{{base_url}}}/channels/:ucid/#{{{route[0]}}}", Invidious::Routes::APIv1, :{{route[1]}}
{% end %} {% end %}
end end

View File

@ -0,0 +1,24 @@
module Invidious::Routes::APIv1
def self.channel_search(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json"
ucid = env.params.url["ucid"]
query = env.params.query["q"]?
query ||= ""
page = env.params.query["page"]?.try &.to_i?
page ||= 1
count, search_results = channel_search(query, page, ucid)
JSON.build do |json|
json.array do
search_results.each do |item|
item.to_json(locale, json)
end
end
end
end
end

View File

@ -0,0 +1,2 @@
module Invidious::Routes::APIv1
end

View File

@ -1,10 +1,10 @@
class Invidious::Routes::V1Api < Invidious::Routes::BaseRoute module Invidious::Routes::APIv1
# Fetches YouTube storyboards # Fetches YouTube storyboards
# #
# Which are sprites containing x * y preview # Which are sprites containing x * y preview
# thumbnails for individual scenes in a video. # thumbnails for individual scenes in a video.
# See https://support.jwplayer.com/articles/how-to-add-preview-thumbnails # See https://support.jwplayer.com/articles/how-to-add-preview-thumbnails
def storyboards(env) def self.storyboards(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]? locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json" env.response.content_type = "application/json"
@ -80,7 +80,7 @@ class Invidious::Routes::V1Api < Invidious::Routes::BaseRoute
end end
end end
def captions(env) def self.captions(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]? locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "application/json" env.response.content_type = "application/json"
@ -206,7 +206,7 @@ class Invidious::Routes::V1Api < Invidious::Routes::BaseRoute
webvtt webvtt
end end
def annotations(env) def self.annotations(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]? locale = LOCALES[env.get("preferences").as(Preferences).locale]?
env.response.content_type = "text/xml" env.response.content_type = "text/xml"
@ -280,7 +280,7 @@ class Invidious::Routes::V1Api < Invidious::Routes::BaseRoute
end end
end end
def search_suggestions(env) def self.search_suggestions(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]? locale = LOCALES[env.get("preferences").as(Preferences).locale]?
region = env.params.query["region"]? region = env.params.query["region"]?
@ -313,4 +313,74 @@ class Invidious::Routes::V1Api < Invidious::Routes::BaseRoute
return error_json(500, ex) return error_json(500, ex)
end end
end end
def self.comments(env)
locale = LOCALES[env.get("preferences").as(Preferences).locale]?
region = env.params.query["region"]?
env.response.content_type = "application/json"
id = env.params.url["id"]
source = env.params.query["source"]?
source ||= "youtube"
thin_mode = env.params.query["thin_mode"]?
thin_mode = thin_mode == "true"
format = env.params.query["format"]?
format ||= "json"
action = env.params.query["action"]?
action ||= "action_get_comments"
continuation = env.params.query["continuation"]?
sort_by = env.params.query["sort_by"]?.try &.downcase
if source == "youtube"
sort_by ||= "top"
begin
comments = fetch_youtube_comments(id, continuation, format, locale, thin_mode, region, sort_by: sort_by)
rescue ex
return error_json(500, ex)
end
return comments
elsif source == "reddit"
sort_by ||= "confidence"
begin
comments, reddit_thread = fetch_reddit_comments(id, sort_by: sort_by)
content_html = template_reddit_comments(comments, locale)
content_html = fill_links(content_html, "https", "www.reddit.com")
content_html = replace_links(content_html)
rescue ex
comments = nil
reddit_thread = nil
content_html = ""
end
if !reddit_thread || !comments
env.response.status_code = 404
return
end
if format == "json"
reddit_thread = JSON.parse(reddit_thread.to_json).as_h
reddit_thread["comments"] = JSON.parse(comments.to_json)
return reddit_thread.to_json
else
response = {
"title" => reddit_thread.title,
"permalink" => reddit_thread.permalink,
"contentHtml" => content_html,
}
return response.to_json
end
end
end
end end