Fix Style/RedundantReturn type of Ameba issues

This commit is contained in:
Sijawusz Pur Rahnama 2026-01-11 23:17:53 +01:00
parent 9f96682783
commit 9aec157453
73 changed files with 376 additions and 379 deletions

View File

@ -31,9 +31,6 @@ Lint/SpecFilename:
# Style # Style
# #
Style/RedundantReturn:
Enabled: false
Style/RedundantNext: Style/RedundantNext:
Enabled: false Enabled: false

View File

@ -14,7 +14,7 @@ require "spectator"
require "../../../src/invidious/http_server/static_assets_handler.cr" require "../../../src/invidious/http_server/static_assets_handler.cr"
private def get_static_assets_handler private def get_static_assets_handler
return Invidious::HttpServer::StaticAssetsHandler.new "spec/http_server/handlers/static_assets_handler", directory_listing: false Invidious::HttpServer::StaticAssetsHandler.new "spec/http_server/handlers/static_assets_handler", directory_listing: false
end end
# Slightly modified version of `handle` function from # Slightly modified version of `handle` function from
@ -125,7 +125,7 @@ Spectator.describe StaticAssetsHandler do
gzip.gets_to_end gzip.gets_to_end
end end
return expect(decompressed) expect(decompressed)
end end
it "For full file requests" do it "For full file requests" do

View File

@ -7,7 +7,7 @@ Spectator.configure do |config|
end end
def csv_sample def csv_sample
return <<-CSV <<-CSV
Kanal-ID,Kanal-URL,Kanaltitel Kanal-ID,Kanal-URL,Kanaltitel
UC0hHW5Y08ggq-9kbrGgWj0A,http://www.youtube.com/channel/UC0hHW5Y08ggq-9kbrGgWj0A,Matias Marolla UC0hHW5Y08ggq-9kbrGgWj0A,http://www.youtube.com/channel/UC0hHW5Y08ggq-9kbrGgWj0A,Matias Marolla
UC0vBXGSyV14uvJ4hECDOl0Q,http://www.youtube.com/channel/UC0vBXGSyV14uvJ4hECDOl0Q,Techquickie UC0vBXGSyV14uvJ4hECDOl0Q,http://www.youtube.com/channel/UC0vBXGSyV14uvJ4hECDOl0Q,Techquickie

View File

@ -26,7 +26,7 @@ def load_mock(file) : Hash(String, JSON::Any)
file = File.join(__DIR__, "..", "mocks", file + ".json") file = File.join(__DIR__, "..", "mocks", file + ".json")
content = File.read(file) content = File.read(file)
return JSON.parse(content).as_h JSON.parse(content).as_h
end end
Spectator.configure do |config| Spectator.configure do |config|

View File

@ -141,7 +141,7 @@ def get_batch_channels(channels)
end end
end end
return final final
end end
def get_channel(id) : InvidiousChannel def get_channel(id) : InvidiousChannel
@ -152,7 +152,7 @@ def get_channel(id) : InvidiousChannel
Invidious::Database::Channels.insert(channel, update_on_conflict: true) Invidious::Database::Channels.insert(channel, update_on_conflict: true)
end end
return channel channel
end end
def fetch_channel(ucid, pull_all_videos : Bool) def fetch_channel(ucid, pull_all_videos : Bool)
@ -292,5 +292,5 @@ def fetch_channel(ucid, pull_all_videos : Bool)
end end
channel.updated = Time.utc channel.updated = Time.utc
return channel channel
end end

View File

@ -21,7 +21,7 @@ def fetch_channel_community(ucid, cursor, locale, format, thin_mode)
items = container.as_a items = container.as_a
end end
return extract_channel_community(items, ucid: ucid, locale: locale, format: format, thin_mode: thin_mode) extract_channel_community(items, ucid: ucid, locale: locale, format: format, thin_mode: thin_mode)
end end
def decode_ucid_from_post_protobuf(params) def decode_ucid_from_post_protobuf(params)
@ -30,7 +30,7 @@ def decode_ucid_from_post_protobuf(params)
.try { |i| IO::Memory.new(i) } .try { |i| IO::Memory.new(i) }
.try { |i| Protodec::Any.parse(i) } .try { |i| Protodec::Any.parse(i) }
return decoded_protobuf.try(&.["56:0:embedded"]["2:0:string"].as_s) decoded_protobuf.try(&.["56:0:embedded"]["2:0:string"].as_s)
end end
def fetch_channel_community_post(ucid, post_id, locale, format, thin_mode) def fetch_channel_community_post(ucid, post_id, locale, format, thin_mode)
@ -53,7 +53,7 @@ def fetch_channel_community_post(ucid, post_id, locale, format, thin_mode)
items << item items << item
end end
return extract_channel_community(items, ucid: ucid, locale: locale, format: format, thin_mode: thin_mode, is_single_post: true) extract_channel_community(items, ucid: ucid, locale: locale, format: format, thin_mode: thin_mode, is_single_post: true)
end end
def extract_channel_community(items, *, ucid, locale, format, thin_mode, is_single_post : Bool = false) def extract_channel_community(items, *, ucid, locale, format, thin_mode, is_single_post : Bool = false)
@ -294,7 +294,7 @@ def extract_channel_community(items, *, ucid, locale, format, thin_mode, is_sing
end end
end end
return response response
end end
def produce_channel_community_continuation(ucid, cursor) def produce_channel_community_continuation(ucid, cursor)
@ -310,7 +310,7 @@ def produce_channel_community_continuation(ucid, cursor)
.try { |i| Base64.urlsafe_encode(i) } .try { |i| Base64.urlsafe_encode(i) }
.try { |i| URI.encode_www_form(i) } .try { |i| URI.encode_www_form(i) }
return continuation continuation
end end
def extract_channel_community_cursor(continuation) def extract_channel_community_cursor(continuation)

View File

@ -24,7 +24,7 @@ def fetch_channel_playlists(ucid, author, continuation, sort_by)
initial_data = YoutubeAPI.browse(ucid, params: params || "") initial_data = YoutubeAPI.browse(ucid, params: params || "")
end end
return extract_items(initial_data, author, ucid) extract_items(initial_data, author, ucid)
end end
def fetch_channel_podcasts(ucid, author, continuation) def fetch_channel_podcasts(ucid, author, continuation)
@ -33,7 +33,7 @@ def fetch_channel_podcasts(ucid, author, continuation)
else else
initial_data = YoutubeAPI.browse(ucid, params: "Eghwb2RjYXN0c_IGBQoDugEA") initial_data = YoutubeAPI.browse(ucid, params: "Eghwb2RjYXN0c_IGBQoDugEA")
end end
return extract_items(initial_data, author, ucid) extract_items(initial_data, author, ucid)
end end
def fetch_channel_releases(ucid, author, continuation) def fetch_channel_releases(ucid, author, continuation)
@ -42,7 +42,7 @@ def fetch_channel_releases(ucid, author, continuation)
else else
initial_data = YoutubeAPI.browse(ucid, params: "EghyZWxlYXNlc_IGBQoDsgEA") initial_data = YoutubeAPI.browse(ucid, params: "EghyZWxlYXNlc_IGBQoDsgEA")
end end
return extract_items(initial_data, author, ucid) extract_items(initial_data, author, ucid)
end end
def fetch_channel_courses(ucid, author, continuation) def fetch_channel_courses(ucid, author, continuation)
@ -51,5 +51,5 @@ def fetch_channel_courses(ucid, author, continuation)
else else
initial_data = YoutubeAPI.browse(ucid, params: "Egdjb3Vyc2Vz8gYFCgPCAQA%3D") initial_data = YoutubeAPI.browse(ucid, params: "Egdjb3Vyc2Vz8gYFCgPCAQA%3D")
end end
return extract_items(initial_data, author, ucid) extract_items(initial_data, author, ucid)
end end

View File

@ -9,7 +9,7 @@ module Invidious::Channel::Tabs
# an author name and ucid directly (e.g in RSS feeds). # an author name and ucid directly (e.g in RSS feeds).
# TODO: figure out how to get rid of that # TODO: figure out how to get rid of that
def get_videos(channel : AboutChannel, *, continuation : String? = nil, sort_by = "newest") def get_videos(channel : AboutChannel, *, continuation : String? = nil, sort_by = "newest")
return get_videos( get_videos(
channel.author, channel.ucid, channel.author, channel.ucid,
continuation: continuation, sort_by: sort_by continuation: continuation, sort_by: sort_by
) )
@ -19,7 +19,7 @@ module Invidious::Channel::Tabs
# an author name and ucid directly (e.g in RSS feeds). # an author name and ucid directly (e.g in RSS feeds).
# TODO: figure out how to get rid of that # TODO: figure out how to get rid of that
def get_videos(channel : InvidiousChannel, *, continuation : String? = nil, sort_by = "newest") def get_videos(channel : InvidiousChannel, *, continuation : String? = nil, sort_by = "newest")
return get_videos( get_videos(
channel.author, channel.id, channel.author, channel.id,
continuation: continuation, sort_by: sort_by continuation: continuation, sort_by: sort_by
) )
@ -29,7 +29,7 @@ module Invidious::Channel::Tabs
continuation ||= make_initial_videos_ctoken(ucid, sort_by) continuation ||= make_initial_videos_ctoken(ucid, sort_by)
initial_data = YoutubeAPI.browse(continuation: continuation) initial_data = YoutubeAPI.browse(continuation: continuation)
return extract_items(initial_data, author, ucid) extract_items(initial_data, author, ucid)
end end
def get_60_videos(channel : AboutChannel, *, continuation : String? = nil, sort_by = "newest") def get_60_videos(channel : AboutChannel, *, continuation : String? = nil, sort_by = "newest")
@ -59,7 +59,7 @@ module Invidious::Channel::Tabs
continuation ||= make_initial_shorts_ctoken(channel.ucid, sort_by) continuation ||= make_initial_shorts_ctoken(channel.ucid, sort_by)
initial_data = YoutubeAPI.browse(continuation: continuation) initial_data = YoutubeAPI.browse(continuation: continuation)
return extract_items(initial_data, channel.author, channel.ucid) extract_items(initial_data, channel.author, channel.ucid)
end end
# ------------------- # -------------------
@ -70,7 +70,7 @@ module Invidious::Channel::Tabs
continuation ||= make_initial_livestreams_ctoken(channel.ucid, sort_by) continuation ||= make_initial_livestreams_ctoken(channel.ucid, sort_by)
initial_data = YoutubeAPI.browse(continuation: continuation) initial_data = YoutubeAPI.browse(continuation: continuation)
return extract_items(initial_data, channel.author, channel.ucid) extract_items(initial_data, channel.author, channel.ucid)
end end
def get_60_livestreams(channel : AboutChannel, *, continuation : String? = nil, sort_by = "newest") def get_60_livestreams(channel : AboutChannel, *, continuation : String? = nil, sort_by = "newest")
@ -98,10 +98,10 @@ module Invidious::Channel::Tabs
private def sort_options_videos_short(sort_by : String) private def sort_options_videos_short(sort_by : String)
case sort_by case sort_by
when "newest" then return 4_i64 when "newest" then 4_i64
when "popular" then return 2_i64 when "popular" then 2_i64
when "oldest" then return 5_i64 when "oldest" then 5_i64
else return 4_i64 # Fallback to "newest" else 4_i64 # Fallback to "newest"
end end
end end
@ -118,7 +118,7 @@ module Invidious::Channel::Tabs
}, },
} }
return channel_ctoken_wrap(ucid, object) channel_ctoken_wrap(ucid, object)
end end
# Generate the initial "continuation token" to get the first page of the # Generate the initial "continuation token" to get the first page of the
@ -134,7 +134,7 @@ module Invidious::Channel::Tabs
}, },
} }
return channel_ctoken_wrap(ucid, object) channel_ctoken_wrap(ucid, object)
end end
# Generate the initial "continuation token" to get the first page of the # Generate the initial "continuation token" to get the first page of the
@ -158,7 +158,7 @@ module Invidious::Channel::Tabs
}, },
} }
return channel_ctoken_wrap(ucid, object) channel_ctoken_wrap(ucid, object)
end end
# The protobuf structure common between videos/shorts/livestreams # The protobuf structure common between videos/shorts/livestreams
@ -187,6 +187,6 @@ module Invidious::Channel::Tabs
.try { |i| Base64.urlsafe_encode(i) } .try { |i| Base64.urlsafe_encode(i) }
.try { |i| URI.encode_www_form(i) } .try { |i| URI.encode_www_form(i) }
return continuation continuation
end end
end end

View File

@ -37,7 +37,7 @@ def text_to_parsed_content(text : String) : JSON::Any
nodes << (node) nodes << (node)
end end
end end
return JSON.parse({"runs" => nodes}.to_json) JSON.parse({"runs" => nodes}.to_json)
end end
def parse_content(content : JSON::Any, video_id : String? = "") : String def parse_content(content : JSON::Any, video_id : String? = "") : String
@ -85,5 +85,5 @@ def content_to_comment_html(content, video_id : String? = "")
text text
end end
return html_array.join("").delete('\ufeff') html_array.join("").delete('\ufeff')
end end

View File

@ -45,7 +45,7 @@ module Invidious::Comments
html = node html = node
end end
return html.to_xml(options: XML::SaveOptions::NO_DECL) html.to_xml(options: XML::SaveOptions::NO_DECL)
end end
def fill_links(html, scheme, host) def fill_links(html, scheme, host)
@ -71,6 +71,6 @@ module Invidious::Comments
html = html.xpath_node(%q(//body/p)).not_nil! html = html.xpath_node(%q(//body/p)).not_nil!
end end
return html.to_xml(options: XML::SaveOptions::NO_DECL) html.to_xml(options: XML::SaveOptions::NO_DECL)
end end
end end

View File

@ -13,7 +13,7 @@ module Invidious::Comments
client_config = YoutubeAPI::ClientConfig.new(region: region) client_config = YoutubeAPI::ClientConfig.new(region: region)
response = YoutubeAPI.next(continuation: ctoken, client_config: client_config) response = YoutubeAPI.next(continuation: ctoken, client_config: client_config)
return parse_youtube(id, response, format, locale, thin_mode, sort_by) parse_youtube(id, response, format, locale, thin_mode, sort_by)
end end
def fetch_community_post_comments(ucid, post_id, sort_by = "top") def fetch_community_post_comments(ucid, post_id, sort_by = "top")
@ -58,7 +58,7 @@ module Invidious::Comments
.try { |i| URI.encode_www_form(i) } .try { |i| URI.encode_www_form(i) }
initial_data = YoutubeAPI.browse(continuation: continuation) initial_data = YoutubeAPI.browse(continuation: continuation)
return initial_data initial_data
end end
def parse_youtube(id, response, format, locale, thin_mode, sort_by = "top", is_post = false) def parse_youtube(id, response, format, locale, thin_mode, sort_by = "top", is_post = false)
@ -320,7 +320,7 @@ module Invidious::Comments
end end
end end
return response response
end end
def produce_continuation(video_id, cursor = "", sort_by = "top") def produce_continuation(video_id, cursor = "", sort_by = "top")
@ -364,6 +364,6 @@ module Invidious::Comments
.try { |i| Base64.urlsafe_encode(i) } .try { |i| Base64.urlsafe_encode(i) }
.try { |i| URI.encode_www_form(i) } .try { |i| URI.encode_www_form(i) }
return continuation continuation
end end
end end

View File

@ -183,15 +183,15 @@ class Config
def disabled?(option) def disabled?(option)
case disabled = CONFIG.disable_proxy case disabled = CONFIG.disable_proxy
when Bool when Bool
return disabled disabled
when Array when Array
if disabled.includes? option if disabled.includes? option
return true true
else else
return false false
end end
else else
return false false
end end
end end
@ -318,6 +318,6 @@ class Config
end end
end end
return config config
end end
end end

View File

@ -19,6 +19,6 @@ module Invidious::Database::Annotations
WHERE id = $1 WHERE id = $1
SQL SQL
return PG_DB.query_one?(request, id, as: Annotation) PG_DB.query_one?(request, id, as: Annotation)
end end
end end

View File

@ -132,6 +132,6 @@ module Invidious::Database
end end
end end
return column_array column_array
end end
end end

View File

@ -72,7 +72,7 @@ module Invidious::Database::Channels
WHERE id = $1 WHERE id = $1
SQL SQL
return PG_DB.query_one?(request, id, as: InvidiousChannel) PG_DB.query_one?(request, id, as: InvidiousChannel)
end end
def select(ids : Array(String)) : Array(InvidiousChannel)? def select(ids : Array(String)) : Array(InvidiousChannel)?
@ -83,7 +83,7 @@ module Invidious::Database::Channels
WHERE id = ANY($1) WHERE id = ANY($1)
SQL SQL
return PG_DB.query_all(request, ids, as: InvidiousChannel) PG_DB.query_all(request, ids, as: InvidiousChannel)
end end
end end
@ -114,7 +114,7 @@ module Invidious::Database::ChannelVideos
RETURNING (xmax=0) AS was_insert RETURNING (xmax=0) AS was_insert
SQL SQL
return PG_DB.query_one(request, *video.to_tuple, as: Bool) PG_DB.query_one(request, *video.to_tuple, as: Bool)
end end
# ------------------- # -------------------
@ -130,7 +130,7 @@ module Invidious::Database::ChannelVideos
ORDER BY published DESC ORDER BY published DESC
SQL SQL
return PG_DB.query_all(request, ids, as: ChannelVideo) PG_DB.query_all(request, ids, as: ChannelVideo)
end end
def select_notfications(ucid : String, since : Time) : Array(ChannelVideo) def select_notfications(ucid : String, since : Time) : Array(ChannelVideo)
@ -141,7 +141,7 @@ module Invidious::Database::ChannelVideos
LIMIT 15 LIMIT 15
SQL SQL
return PG_DB.query_all(request, ucid, since, as: ChannelVideo) PG_DB.query_all(request, ucid, since, as: ChannelVideo)
end end
def select_popular_videos : Array(ChannelVideo) def select_popular_videos : Array(ChannelVideo)

View File

@ -50,6 +50,6 @@ module Invidious::Database::Nonces
WHERE nonce = $1 WHERE nonce = $1
SQL SQL
return PG_DB.query_one?(request, nonce, as: {String, Time}) PG_DB.query_one?(request, nonce, as: {String, Time})
end end
end end

View File

@ -100,7 +100,7 @@ module Invidious::Database::Playlists
WHERE id = $1 WHERE id = $1
SQL SQL
return PG_DB.query_one?(request, id, as: InvidiousPlaylist) PG_DB.query_one?(request, id, as: InvidiousPlaylist)
end end
def select_all(*, author : String) : Array(InvidiousPlaylist) def select_all(*, author : String) : Array(InvidiousPlaylist)
@ -109,7 +109,7 @@ module Invidious::Database::Playlists
WHERE author = $1 WHERE author = $1
SQL SQL
return PG_DB.query_all(request, author, as: InvidiousPlaylist) PG_DB.query_all(request, author, as: InvidiousPlaylist)
end end
# ------------------- # -------------------
@ -157,7 +157,7 @@ module Invidious::Database::Playlists
WHERE id = $1 WHERE id = $1
SQL SQL
return PG_DB.query_one?(request, id, as: String).nil? PG_DB.query_one?(request, id, as: String).nil?
end end
# Count how many playlist a user has created. # Count how many playlist a user has created.
@ -167,7 +167,7 @@ module Invidious::Database::Playlists
WHERE author = $1 WHERE author = $1
SQL SQL
return PG_DB.query_one?(request, author, as: Int64) || 0_i64 PG_DB.query_one?(request, author, as: Int64) || 0_i64
end end
end end
@ -225,7 +225,7 @@ module Invidious::Database::PlaylistVideos
OFFSET $4 OFFSET $4
SQL SQL
return PG_DB.query_all(request, plid, index, limit, offset, as: PlaylistVideo) PG_DB.query_all(request, plid, index, limit, offset, as: PlaylistVideo)
end end
def select_index(plid : String, vid : String) : Int64? def select_index(plid : String, vid : String) : Int64?
@ -235,7 +235,7 @@ module Invidious::Database::PlaylistVideos
LIMIT 1 LIMIT 1
SQL SQL
return PG_DB.query_one?(request, plid, vid, as: Int64) PG_DB.query_one?(request, plid, vid, as: Int64)
end end
def select_one_id(plid : String, index : VideoIndex) : String? def select_one_id(plid : String, index : VideoIndex) : String?
@ -246,7 +246,7 @@ module Invidious::Database::PlaylistVideos
LIMIT 1 LIMIT 1
SQL SQL
return PG_DB.query_one?(request, plid, index, as: String) PG_DB.query_one?(request, plid, index, as: String)
end end
def select_ids(plid : String, index : VideoIndex, limit = 500) : Array(String) def select_ids(plid : String, index : VideoIndex, limit = 500) : Array(String)
@ -257,6 +257,6 @@ module Invidious::Database::PlaylistVideos
LIMIT $3 LIMIT $3
SQL SQL
return PG_DB.query_all(request, plid, index, limit, as: String) PG_DB.query_all(request, plid, index, limit, as: String)
end end
end end

View File

@ -194,7 +194,7 @@ module Invidious::Database::Users
WHERE email = $1 WHERE email = $1
SQL SQL
return PG_DB.query_one?(request, email, as: User) PG_DB.query_one?(request, email, as: User)
end end
# Same as select, but can raise an exception # Same as select, but can raise an exception
@ -204,7 +204,7 @@ module Invidious::Database::Users
WHERE email = $1 WHERE email = $1
SQL SQL
return PG_DB.query_one(request, email, as: User) PG_DB.query_one(request, email, as: User)
end end
def select(*, token : String) : User? def select(*, token : String) : User?
@ -213,7 +213,7 @@ module Invidious::Database::Users
WHERE token = $1 WHERE token = $1
SQL SQL
return PG_DB.query_one?(request, token, as: User) PG_DB.query_one?(request, token, as: User)
end end
def select_notifications(user : User) : Array(String) def select_notifications(user : User) : Array(String)
@ -223,6 +223,6 @@ module Invidious::Database::Users
WHERE email = $1 WHERE email = $1
SQL SQL
return PG_DB.query_one(request, user.email, as: Array(String)) PG_DB.query_one(request, user.email, as: Array(String))
end end
end end

View File

@ -47,6 +47,6 @@ module Invidious::Database::Videos
WHERE id = $1 WHERE id = $1
SQL SQL
return PG_DB.query_one?(request, id, as: Video) PG_DB.query_one?(request, id, as: Video)
end end
end end

View File

@ -23,7 +23,7 @@ class BrokenTubeException < Exception
end end
def message def message
return "Missing JSON element \"#{@element}\"" "Missing JSON element \"#{@element}\""
end end
end end

View File

@ -14,7 +14,7 @@ module Invidious::Frontend::ChannelPage
end end
def generate_tabs_links(locale : String, channel : AboutChannel, selected_tab : TabsAvailable) def generate_tabs_links(locale : String, channel : AboutChannel, selected_tab : TabsAvailable)
return String.build(1500) do |str| String.build(1500) do |str|
base_url = "/channel/#{channel.ucid}" base_url = "/channel/#{channel.ucid}"
TabsAvailable.each do |tab| TabsAvailable.each do |tab|

View File

@ -6,9 +6,9 @@ module Invidious::Frontend::Misc
if preferences.automatic_instance_redirect if preferences.automatic_instance_redirect
current_page = env.get?("current_page").as(String) current_page = env.get?("current_page").as(String)
return "/redirect?referer=#{current_page}" "/redirect?referer=#{current_page}"
else else
return "https://redirect.invidious.io#{env.request.resource}" "https://redirect.invidious.io#{env.request.resource}"
end end
end end
end end

View File

@ -60,7 +60,7 @@ module Invidious::Frontend::Pagination
end end
def nav_numeric(locale : String?, *, base_url : String | URI, current_page : Int, show_next : Bool = true) def nav_numeric(locale : String?, *, base_url : String | URI, current_page : Int, show_next : Bool = true)
return String.build do |str| String.build do |str|
str << %(<div class="h-box">\n) str << %(<div class="h-box">\n)
str << %(<div class="page-nav-container flexible">\n) str << %(<div class="page-nav-container flexible">\n)
@ -91,7 +91,7 @@ module Invidious::Frontend::Pagination
end end
def nav_ctoken(locale : String?, *, base_url : String | URI, ctoken : String?, first_page : Bool, params : URI::Params) def nav_ctoken(locale : String?, *, base_url : String | URI, ctoken : String?, first_page : Bool, params : URI::Params)
return String.build do |str| String.build do |str|
str << %(<div class="h-box">\n) str << %(<div class="h-box">\n)
str << %(<div class="page-nav-container flexible">\n) str << %(<div class="page-nav-container flexible">\n)

View File

@ -3,7 +3,7 @@ module Invidious::Frontend::SearchFilters
# Generate the search filters collapsable widget. # Generate the search filters collapsable widget.
def generate(filters : Search::Filters, query : String, page : Int, locale : String) : String def generate(filters : Search::Filters, query : String, page : Int, locale : String) : String
return String.build(8000) do |str| String.build(8000) do |str|
str << "<div id='filters'>\n" str << "<div id='filters'>\n"
str << "\t<details id='filters-collapse'>" str << "\t<details id='filters-collapse'>"
str << "\t\t<summary>" << translate(locale, "search_filters_title") << "</summary>\n" str << "\t\t<summary>" << translate(locale, "search_filters_title") << "</summary>\n"

View File

@ -33,7 +33,7 @@ module Invidious::Frontend::WatchPage
url = "#{invidious_companion.public_url}/download?check=#{invidious_companion_encrypt(video.id)}" url = "#{invidious_companion.public_url}/download?check=#{invidious_companion_encrypt(video.id)}"
end end
return String.build(4000) do |str| String.build(4000) do |str|
str << "<form" str << "<form"
str << " class=\"pure-form pure-form-stacked\"" str << " class=\"pure-form pure-form-stacked\""
str << " action='#{url}'" str << " action='#{url}'"

View File

@ -9,7 +9,7 @@ module Invidious::Hashtag
response = YoutubeAPI.browse(continuation: ctoken, client_config: client_config) response = YoutubeAPI.browse(continuation: ctoken, client_config: client_config)
items, _ = extract_items(response) items, _ = extract_items(response)
return items items
end end
def generate_continuation(hashtag : String, cursor : Int) def generate_continuation(hashtag : String, cursor : Int)
@ -37,6 +37,6 @@ module Invidious::Hashtag
.try { |i| Base64.urlsafe_encode(i) } .try { |i| Base64.urlsafe_encode(i) }
.try { |i| URI.encode_www_form(i) } .try { |i| URI.encode_www_form(i) }
return continuation continuation
end end
end end

View File

@ -15,7 +15,7 @@ def github_details(summary : String, content : String)
details += %(\n```) details += %(\n```)
details += %(\n</p>) details += %(\n</p>)
details += %(\n</details>) details += %(\n</details>)
return HTML.escape(details) HTML.escape(details)
end end
def get_issue_template(env : HTTP::Server::Context, exception : Exception) : Tuple(String, String) def get_issue_template(env : HTTP::Server::Context, exception : Exception) : Tuple(String, String)
@ -86,7 +86,7 @@ def error_template_helper(env : HTTP::Server::Context, status_code : Int32, exce
# proposed above the error message, just worded differently. # proposed above the error message, just worded differently.
next_steps = "" next_steps = ""
return templated "error" templated "error"
end end
def error_template_helper(env : HTTP::Server::Context, status_code : Int32, message : String) def error_template_helper(env : HTTP::Server::Context, status_code : Int32, message : String)
@ -98,7 +98,7 @@ def error_template_helper(env : HTTP::Server::Context, status_code : Int32, mess
error_message = translate(locale, message) error_message = translate(locale, message)
next_steps = error_redirect_helper(env) next_steps = error_redirect_helper(env)
return templated "error" templated "error"
end end
# ------------------- # -------------------
@ -117,14 +117,14 @@ def error_atom_helper(env : HTTP::Server::Context, status_code : Int32, exceptio
env.response.content_type = "application/atom+xml" env.response.content_type = "application/atom+xml"
env.response.status_code = status_code env.response.status_code = status_code
return "<error>#{exception.inspect_with_backtrace}</error>" "<error>#{exception.inspect_with_backtrace}</error>"
end end
def error_atom_helper(env : HTTP::Server::Context, status_code : Int32, message : String) def error_atom_helper(env : HTTP::Server::Context, status_code : Int32, message : String)
env.response.content_type = "application/atom+xml" env.response.content_type = "application/atom+xml"
env.response.status_code = status_code env.response.status_code = status_code
return "<error>#{message}</error>" "<error>#{message}</error>"
end end
# ------------------- # -------------------
@ -154,7 +154,7 @@ def error_json_helper(
error_message = error_message.merge(additional_fields) error_message = error_message.merge(additional_fields)
end end
return error_message.to_json error_message.to_json
end end
def error_json_helper( def error_json_helper(
@ -172,7 +172,7 @@ def error_json_helper(
error_message = error_message.merge(additional_fields) error_message = error_message.merge(additional_fields)
end end
return error_message.to_json error_message.to_json
end end
# ------------------- # -------------------
@ -191,7 +191,7 @@ def error_redirect_helper(env : HTTP::Server::Context)
go_to_youtube = translate(locale, "next_steps_error_message_go_to_youtube") go_to_youtube = translate(locale, "next_steps_error_message_go_to_youtube")
switch_instance = translate(locale, "Switch Invidious Instance") switch_instance = translate(locale, "Switch Invidious Instance")
return <<-HTML <<-HTML
<p style="margin-bottom: 4px;">#{next_steps_text}</p> <p style="margin-bottom: 4px;">#{next_steps_text}</p>
<ul> <ul>
<li> <li>
@ -206,6 +206,6 @@ def error_redirect_helper(env : HTTP::Server::Context)
</ul> </ul>
HTML HTML
else else
return "" ""
end end
end end

View File

@ -32,7 +32,7 @@ def html_to_content(description_html : String)
description = XML.parse_html(description).content.strip("\n ") description = XML.parse_html(description).content.strip("\n ")
end end
return description description
end end
def cache_annotation(id, annotations) def cache_annotation(id, annotations)
@ -165,7 +165,7 @@ def create_notification_stream(env, topics, connection_channel)
end end
def extract_initial_data(body) : Hash(String, JSON::Any) def extract_initial_data(body) : Hash(String, JSON::Any)
return JSON.parse(body.match(/(window\["ytInitialData"\]|var\s*ytInitialData)\s*=\s*(?<info>{.*?});<\/script>/mx).try &.["info"] || "{}").as_h JSON.parse(body.match(/(window\["ytInitialData"\]|var\s*ytInitialData)\s*=\s*(?<info>{.*?});<\/script>/mx).try &.["info"] || "{}").as_h
end end
def proxy_file(response, env) def proxy_file(response, env)
@ -196,5 +196,5 @@ def get_playback_statistic
Invidious::Jobs::StatisticsRefreshJob::STATISTICS["playback"] = tracker Invidious::Jobs::StatisticsRefreshJob::STATISTICS["playback"] = tracker
end end
return tracker.as(Hash(String, Int64 | Float64)) tracker.as(Hash(String, Int64 | Float64))
end end

View File

@ -91,7 +91,7 @@ def load_all_locales
locales[name] = JSON.parse(File.read("locales/#{name}.json")).as_h locales[name] = JSON.parse(File.read("locales/#{name}.json")).as_h
end end
return locales locales
end end
def translate(locale : String?, key : String, text : String | Hash(String, String)? = nil) : String def translate(locale : String?, key : String, text : String | Hash(String, String)? = nil) : String
@ -141,7 +141,7 @@ def translate(locale : String?, key : String, text : String | Hash(String, Strin
end end
end end
return translation translation
end end
def translate_count(locale : String, key : String, count : Int, format = NumberFormatting::None) : String def translate_count(locale : String, key : String, count : Int, format = NumberFormatting::None) : String
@ -177,15 +177,15 @@ def translate_count(locale : String, key : String, count : Int, format = NumberF
else count_txt = count.to_s else count_txt = count.to_s
end end
return translation.gsub("{{count}}", count_txt) translation.gsub("{{count}}", count_txt)
end end
def translate_bool(locale : String?, translation : Bool) def translate_bool(locale : String?, translation : Bool)
case translation case translation
when true when true
return translate(locale, "Yes") translate(locale, "Yes")
when false when false
return translate(locale, "No") translate(locale, "No")
end end
end end
@ -195,5 +195,5 @@ def locale_is_rtl?(locale : String?)
# Arabic, Persian, Hebrew # Arabic, Persian, Hebrew
# See https://en.wikipedia.org/wiki/Right-to-left_script#List_of_RTL_scripts # See https://en.wikipedia.org/wiki/Right-to-left_script#List_of_RTL_scripts
return {"ar", "fa", "he"}.includes? locale {"ar", "fa", "he"}.includes? locale
end end

View File

@ -175,7 +175,7 @@ module I18next::Plurals
# If nothing was found, then use the most common form, i.e # If nothing was found, then use the most common form, i.e
# one singular and one plural, as in english. Not perfect, # one singular and one plural, as in english. Not perfect,
# but better than yielding an exception at the user. # but better than yielding an exception at the user.
return PluralForms::Single_not_one PluralForms::Single_not_one
end end
def get_suffix(locale : String, count : Int) : String def get_suffix(locale : String, count : Int) : String
@ -183,19 +183,19 @@ module I18next::Plurals
# determine if comparison should be done on a signed or unsigned integer, # determine if comparison should be done on a signed or unsigned integer,
# but this variable is never set, resulting in the comparison always # but this variable is never set, resulting in the comparison always
# being done on absolute numbers. # being done on absolute numbers.
return get_suffix_retrocompat(locale, count.abs) get_suffix_retrocompat(locale, count.abs)
end end
# Emulate the `rule.numbers.size == 2 && rule.numbers[0] == 1` check # Emulate the `rule.numbers.size == 2 && rule.numbers[0] == 1` check
# from original i18next code # from original i18next code
private def simple_plural?(form : PluralForms) : Bool private def simple_plural?(form : PluralForms) : Bool
case form case form
when .single_gt_one? then return true when .single_gt_one? then true
when .single_not_one? then return true when .single_not_one? then true
when .special_icelandic? then return true when .special_icelandic? then true
when .special_macedonian? then return true when .special_macedonian? then true
else else
return false false
end end
end end
@ -226,7 +226,7 @@ module I18next::Plurals
# when 2 # when 2
# return "_#{suffix}" # return "_#{suffix}"
# else # v3 # else # v3
return "_#{idx}" "_#{idx}"
# end # end
end end
end end
@ -238,35 +238,35 @@ module I18next::Plurals
module SuffixIndex module SuffixIndex
def self.get_index(plural_form : PluralForms, count : Int) : UInt8 def self.get_index(plural_form : PluralForms, count : Int) : UInt8
case plural_form case plural_form
when .single_gt_one? then return (count > 1) ? 1_u8 : 0_u8 when .single_gt_one? then (count > 1) ? 1_u8 : 0_u8
when .single_not_one? then return (count != 1) ? 1_u8 : 0_u8 when .single_not_one? then (count != 1) ? 1_u8 : 0_u8
when .none? then return 0_u8 when .none? then 0_u8
when .dual_slavic? then return dual_slavic(count) when .dual_slavic? then dual_slavic(count)
when .special_arabic? then return special_arabic(count) when .special_arabic? then special_arabic(count)
when .special_czech_slovak? then return special_czech_slovak(count) when .special_czech_slovak? then special_czech_slovak(count)
when .special_polish_kashubian? then return special_polish_kashubian(count) when .special_polish_kashubian? then special_polish_kashubian(count)
when .special_welsh? then return special_welsh(count) when .special_welsh? then special_welsh(count)
when .special_irish? then return special_irish(count) when .special_irish? then special_irish(count)
when .special_scottish_gaelic? then return special_scottish_gaelic(count) when .special_scottish_gaelic? then special_scottish_gaelic(count)
when .special_icelandic? then return special_icelandic(count) when .special_icelandic? then special_icelandic(count)
when .special_javanese? then return special_javanese(count) when .special_javanese? then special_javanese(count)
when .special_cornish? then return special_cornish(count) when .special_cornish? then special_cornish(count)
when .special_lithuanian? then return special_lithuanian(count) when .special_lithuanian? then special_lithuanian(count)
when .special_latvian? then return special_latvian(count) when .special_latvian? then special_latvian(count)
when .special_macedonian? then return special_macedonian(count) when .special_macedonian? then special_macedonian(count)
when .special_mandinka? then return special_mandinka(count) when .special_mandinka? then special_mandinka(count)
when .special_maltese? then return special_maltese(count) when .special_maltese? then special_maltese(count)
when .special_romanian? then return special_romanian(count) when .special_romanian? then special_romanian(count)
when .special_slovenian? then return special_slovenian(count) when .special_slovenian? then special_slovenian(count)
when .special_hebrew? then return special_hebrew(count) when .special_hebrew? then special_hebrew(count)
when .special_odia? then return special_odia(count) when .special_odia? then special_odia(count)
# Mixed v3/v4 forms # Mixed v3/v4 forms
when .special_spanish_italian? then return special_cldr_spanish_italian(count) when .special_spanish_italian? then special_cldr_spanish_italian(count)
when .special_french_portuguese? then return special_cldr_french_portuguese(count) when .special_french_portuguese? then special_cldr_french_portuguese(count)
when .special_hungarian_serbian? then return special_cldr_hungarian_serbian(count) when .special_hungarian_serbian? then special_cldr_hungarian_serbian(count)
else else
# default, if nothing matched above # default, if nothing matched above
return 0_u8 0_u8
end end
end end
@ -280,11 +280,11 @@ module I18next::Plurals
n_mod_100 = count % 100 n_mod_100 = count % 100
if n_mod_10 == 1 && n_mod_100 != 11 if n_mod_10 == 1 && n_mod_100 != 11
return 0_u8 0_u8
elsif n_mod_10 >= 2 && n_mod_10 <= 4 && (n_mod_100 < 10 || n_mod_100 >= 20) elsif n_mod_10 >= 2 && n_mod_10 <= 4 && (n_mod_100 < 10 || n_mod_100 >= 20)
return 1_u8 1_u8
else else
return 2_u8 2_u8
end end
end end
@ -300,7 +300,7 @@ module I18next::Plurals
return 3_u8 if (n_mod_100 >= 3 && n_mod_100 <= 10) return 3_u8 if (n_mod_100 >= 3 && n_mod_100 <= 10)
return 4_u8 if (n_mod_100 >= 11) return 4_u8 if (n_mod_100 >= 11)
return 5_u8 5_u8
end end
# Plural form for Czech and Slovak languages # Plural form for Czech and Slovak languages
@ -311,7 +311,7 @@ module I18next::Plurals
def self.special_czech_slovak(count : Int) : UInt8 def self.special_czech_slovak(count : Int) : UInt8
return 0_u8 if (count == 1) return 0_u8 if (count == 1)
return 1_u8 if (count >= 2 && count <= 4) return 1_u8 if (count >= 2 && count <= 4)
return 2_u8 2_u8
end end
# Plural form for Polish and Kashubian languages # Plural form for Polish and Kashubian languages
@ -326,9 +326,9 @@ module I18next::Plurals
n_mod_100 = count % 100 n_mod_100 = count % 100
if n_mod_10 >= 2 && n_mod_10 <= 4 && (n_mod_100 < 10 || n_mod_100 >= 20) if n_mod_10 >= 2 && n_mod_10 <= 4 && (n_mod_100 < 10 || n_mod_100 >= 20)
return 1_u8 1_u8
else else
return 2_u8 2_u8
end end
end end
@ -341,7 +341,7 @@ module I18next::Plurals
return 0_u8 if (count == 1) return 0_u8 if (count == 1)
return 1_u8 if (count == 2) return 1_u8 if (count == 2)
return 2_u8 if (count != 8 && count != 11) return 2_u8 if (count != 8 && count != 11)
return 3_u8 3_u8
end end
# Plural form for Irish language # Plural form for Irish language
@ -354,7 +354,7 @@ module I18next::Plurals
return 1_u8 if (count == 2) return 1_u8 if (count == 2)
return 2_u8 if (count < 7) return 2_u8 if (count < 7)
return 3_u8 if (count < 11) return 3_u8 if (count < 11)
return 4_u8 4_u8
end end
# Plural form for Gaelic language # Plural form for Gaelic language
@ -366,7 +366,7 @@ module I18next::Plurals
return 0_u8 if (count == 1 || count == 11) return 0_u8 if (count == 1 || count == 11)
return 1_u8 if (count == 2 || count == 12) return 1_u8 if (count == 2 || count == 12)
return 2_u8 if (count > 2 && count < 20) return 2_u8 if (count > 2 && count < 20)
return 3_u8 3_u8
end end
# Plural form for Icelandic language # Plural form for Icelandic language
@ -376,9 +376,9 @@ module I18next::Plurals
# #
def self.special_icelandic(count : Int) : UInt8 def self.special_icelandic(count : Int) : UInt8
if (count % 10) != 1 || (count % 100) == 11 if (count % 10) != 1 || (count % 100) == 11
return 1_u8 1_u8
else else
return 0_u8 0_u8
end end
end end
@ -388,7 +388,7 @@ module I18next::Plurals
# Rule: (n !== 0) # Rule: (n !== 0)
# #
def self.special_javanese(count : Int) : UInt8 def self.special_javanese(count : Int) : UInt8
return (count != 0) ? 1_u8 : 0_u8 (count != 0) ? 1_u8 : 0_u8
end end
# Plural form for Cornish language # Plural form for Cornish language
@ -400,7 +400,7 @@ module I18next::Plurals
return 0_u8 if count == 1 return 0_u8 if count == 1
return 1_u8 if count == 2 return 1_u8 if count == 2
return 2_u8 if count == 3 return 2_u8 if count == 3
return 3_u8 3_u8
end end
# Plural form for Lithuanian language # Plural form for Lithuanian language
@ -413,11 +413,11 @@ module I18next::Plurals
n_mod_100 = count % 100 n_mod_100 = count % 100
if n_mod_10 == 1 && n_mod_100 != 11 if n_mod_10 == 1 && n_mod_100 != 11
return 0_u8 0_u8
elsif n_mod_10 >= 2 && (n_mod_100 < 10 || n_mod_100 >= 20) elsif n_mod_10 >= 2 && (n_mod_100 < 10 || n_mod_100 >= 20)
return 1_u8 1_u8
else else
return 2_u8 2_u8
end end
end end
@ -428,11 +428,11 @@ module I18next::Plurals
# #
def self.special_latvian(count : Int) : UInt8 def self.special_latvian(count : Int) : UInt8
if (count % 10) == 1 && (count % 100) != 11 if (count % 10) == 1 && (count % 100) != 11
return 0_u8 0_u8
elsif count != 0 elsif count != 0
return 1_u8 1_u8
else else
return 2_u8 2_u8
end end
end end
@ -443,9 +443,9 @@ module I18next::Plurals
# #
def self.special_macedonian(count : Int) : UInt8 def self.special_macedonian(count : Int) : UInt8
if count == 1 || ((count % 10) == 1 && (count % 100) != 11) if count == 1 || ((count % 10) == 1 && (count % 100) != 11)
return 0_u8 0_u8
else else
return 1_u8 1_u8
end end
end end
@ -455,7 +455,7 @@ module I18next::Plurals
# Rule: (n==0 ? 0 : n==1 ? 1 : 2) # Rule: (n==0 ? 0 : n==1 ? 1 : 2)
# #
def self.special_mandinka(count : Int) : UInt8 def self.special_mandinka(count : Int) : UInt8
return (count == 0 || count == 1) ? count.to_u8 : 2_u8 (count == 0 || count == 1) ? count.to_u8 : 2_u8
end end
# Plural form for Maltese language # Plural form for Maltese language
@ -470,7 +470,7 @@ module I18next::Plurals
n_mod_100 = count % 100 n_mod_100 = count % 100
return 1_u8 if (n_mod_100 > 1 && n_mod_100 < 11) return 1_u8 if (n_mod_100 > 1 && n_mod_100 < 11)
return 2_u8 if (n_mod_100 > 10 && n_mod_100 < 20) return 2_u8 if (n_mod_100 > 10 && n_mod_100 < 20)
return 3_u8 3_u8
end end
# Plural form for Romanian language # Plural form for Romanian language
@ -484,7 +484,7 @@ module I18next::Plurals
n_mod_100 = count % 100 n_mod_100 = count % 100
return 1_u8 if (n_mod_100 > 0 && n_mod_100 < 20) return 1_u8 if (n_mod_100 > 0 && n_mod_100 < 20)
return 2_u8 2_u8
end end
# Plural form for Slovenian language # Plural form for Slovenian language
@ -497,7 +497,7 @@ module I18next::Plurals
return 1_u8 if (n_mod_100 == 1) return 1_u8 if (n_mod_100 == 1)
return 2_u8 if (n_mod_100 == 2) return 2_u8 if (n_mod_100 == 2)
return 3_u8 if (n_mod_100 == 3 || n_mod_100 == 4) return 3_u8 if (n_mod_100 == 3 || n_mod_100 == 4)
return 0_u8 0_u8
end end
# Plural form for Hebrew language # Plural form for Hebrew language
@ -510,9 +510,9 @@ module I18next::Plurals
return 1_u8 if (count == 2) return 1_u8 if (count == 2)
if (count < 0 || count > 10) && (count % 10) == 0 if (count < 0 || count > 10) && (count % 10) == 0
return 2_u8 2_u8
else else
return 3_u8 3_u8
end end
end end
@ -523,7 +523,7 @@ module I18next::Plurals
# special rule for it. # special rule for it.
# #
def self.special_odia(count : Int) : UInt8 def self.special_odia(count : Int) : UInt8
return (count == 1) ? 0_u8 : 1_u8 (count == 1) ? 0_u8 : 1_u8
end end
# ------------------- # -------------------
@ -537,7 +537,7 @@ module I18next::Plurals
def self.special_cldr_spanish_italian(count : Int) : UInt8 def self.special_cldr_spanish_italian(count : Int) : UInt8
return 0_u8 if (count == 1) # one return 0_u8 if (count == 1) # one
return 1_u8 if (count != 0 && count % 1_000_000 == 0) # many return 1_u8 if (count != 0 && count % 1_000_000 == 0) # many
return 2_u8 # other 2_u8 # other
end end
# Plural form for French and Portuguese # Plural form for French and Portuguese
@ -547,7 +547,7 @@ module I18next::Plurals
def self.special_cldr_french_portuguese(count : Int) : UInt8 def self.special_cldr_french_portuguese(count : Int) : UInt8
return 0_u8 if (count == 0 || count == 1) # one return 0_u8 if (count == 0 || count == 1) # one
return 1_u8 if (count % 1_000_000 == 0) # many return 1_u8 if (count % 1_000_000 == 0) # many
return 2_u8 # other 2_u8 # other
end end
# Plural form for Hungarian and Serbian # Plural form for Hungarian and Serbian
@ -560,7 +560,7 @@ module I18next::Plurals
return 0_u8 if (n_mod_10 == 1 && n_mod_100 != 11) # one return 0_u8 if (n_mod_10 == 1 && n_mod_100 != 11) # one
return 1_u8 if (2 <= n_mod_10 <= 4 && (n_mod_100 < 12 || 14 < n_mod_100)) # few return 1_u8 if (2 <= n_mod_10 <= 4 && (n_mod_100 < 12 || 14 < n_mod_100)) # few
return 2_u8 # other 2_u8 # other
end end
end end
end end

View File

@ -315,7 +315,7 @@ struct ProblematicTimelineItem
# Provides compatibility with PlaylistVideo # Provides compatibility with PlaylistVideo
def to_json(json : JSON::Builder, *args, **kwargs) def to_json(json : JSON::Builder, *args, **kwargs)
return to_json("", json) to_json("", json)
end end
def to_xml(env, locale, xml : XML::Builder) def to_xml(env, locale, xml : XML::Builder)

View File

@ -16,7 +16,7 @@ def generate_token(email, scopes, expire, key)
token["signature"] = sign_token(key, token) token["signature"] = sign_token(key, token)
return token.to_json token.to_json
end end
def generate_response(session, scopes, key, expire = 6.hours, use_nonce = false) def generate_response(session, scopes, key, expire = 6.hours, use_nonce = false)
@ -36,7 +36,7 @@ def generate_response(session, scopes, key, expire = 6.hours, use_nonce = false)
token["signature"] = sign_token(key, token) token["signature"] = sign_token(key, token)
return token.to_json token.to_json
end end
def sign_token(key, hash) def sign_token(key, hash)
@ -63,7 +63,7 @@ def sign_token(key, hash)
end end
string_to_sign = string_to_sign.sort.join("\n") string_to_sign = string_to_sign.sort.join("\n")
return Base64.urlsafe_encode(OpenSSL::HMAC.digest(:sha256, key, string_to_sign)).strip Base64.urlsafe_encode(OpenSSL::HMAC.digest(:sha256, key, string_to_sign)).strip
end end
def validate_request(token, session, request, key, locale = nil) def validate_request(token, session, request, key, locale = nil)
@ -131,7 +131,7 @@ def scope_includes_scope(scope, subset)
return false return false
end end
return true true
end end
def scopes_include_scope(scopes, subset) def scopes_include_scope(scopes, subset)
@ -141,5 +141,5 @@ def scopes_include_scope(scopes, subset)
end end
end end
return false false
end end

View File

@ -8,7 +8,7 @@ def ci_lower_bound(pos, n)
z = 1.96 z = 1.96
phat = 1.0*pos/n phat = 1.0*pos/n
return (phat + z*z/(2*n) - z * Math.sqrt((phat*(1 - phat) + z*z/(4*n))/n))/(1 + z*z/n) (phat + z*z/(2*n) - z * Math.sqrt((phat*(1 - phat) + z*z/(4*n))/n))/(1 + z*z/n)
end end
def elapsed_text(elapsed) def elapsed_text(elapsed)
@ -31,12 +31,12 @@ def decode_length_seconds(string)
seconds: length_seconds[2] seconds: length_seconds[2]
).total_seconds.to_i32 ).total_seconds.to_i32
return length_seconds length_seconds
end end
def recode_length_seconds(time) def recode_length_seconds(time)
if time <= 0 if time <= 0
return "" ""
else else
time = time.seconds time = time.seconds
text = "#{time.minutes.to_s.rjust(2, '0')}:#{time.seconds.to_s.rjust(2, '0')}" text = "#{time.minutes.to_s.rjust(2, '0')}:#{time.seconds.to_s.rjust(2, '0')}"
@ -47,7 +47,7 @@ def recode_length_seconds(time)
text = text.lchop('0') text = text.lchop('0')
return text text
end end
end end
@ -66,7 +66,7 @@ def decode_interval(string : String) : Time::Span
time = Time::Span.new(minutes: raw_minutes) time = Time::Span.new(minutes: raw_minutes)
end end
return time time
end end
def decode_time(string) def decode_time(string)
@ -88,7 +88,7 @@ def decode_time(string)
time = hours * 3600 + minutes * 60 + seconds + millis // 1000 time = hours * 3600 + minutes * 60 + seconds + millis // 1000
end end
return time time
end end
def decode_date(string : String) def decode_date(string : String)
@ -136,26 +136,26 @@ def decode_date(string : String)
raise "Could not parse #{string}" raise "Could not parse #{string}"
end end
return Time.utc - delta Time.utc - delta
end end
def recode_date(time : Time, locale) def recode_date(time : Time, locale)
span = Time.utc - time span = Time.utc - time
if span.total_days > 365.0 if span.total_days > 365.0
return translate_count(locale, "generic_count_years", span.total_days.to_i // 365) translate_count(locale, "generic_count_years", span.total_days.to_i // 365)
elsif span.total_days > 30.0 elsif span.total_days > 30.0
return translate_count(locale, "generic_count_months", span.total_days.to_i // 30) translate_count(locale, "generic_count_months", span.total_days.to_i // 30)
elsif span.total_days > 7.0 elsif span.total_days > 7.0
return translate_count(locale, "generic_count_weeks", span.total_days.to_i // 7) translate_count(locale, "generic_count_weeks", span.total_days.to_i // 7)
elsif span.total_hours > 24.0 elsif span.total_hours > 24.0
return translate_count(locale, "generic_count_days", span.total_days.to_i) translate_count(locale, "generic_count_days", span.total_days.to_i)
elsif span.total_minutes > 60.0 elsif span.total_minutes > 60.0
return translate_count(locale, "generic_count_hours", span.total_hours.to_i) translate_count(locale, "generic_count_hours", span.total_hours.to_i)
elsif span.total_seconds > 60.0 elsif span.total_seconds > 60.0
return translate_count(locale, "generic_count_minutes", span.total_minutes.to_i) translate_count(locale, "generic_count_minutes", span.total_minutes.to_i)
else else
return translate_count(locale, "generic_count_seconds", span.total_seconds.to_i) translate_count(locale, "generic_count_seconds", span.total_seconds.to_i)
end end
end end
@ -173,9 +173,9 @@ def short_text_to_number(short_text : String) : Int64
when "b" then number *= 1_000_000_000 when "b" then number *= 1_000_000_000
end end
return number.to_i64 number.to_i64
rescue ex rescue ex
return 0_i64 0_i64
end end
def number_to_short_text(number) def number_to_short_text(number)
@ -208,7 +208,7 @@ def arg_array(array, start = 1)
args = args.join(",") args = args.join(",")
end end
return args args
end end
def make_host_url(kemal_config) def make_host_url(kemal_config)
@ -234,7 +234,7 @@ def make_host_url(kemal_config)
host = CONFIG.domain.not_nil!.lchop(".") host = CONFIG.domain.not_nil!.lchop(".")
return "#{scheme}#{host}#{port}" "#{scheme}#{host}#{port}"
end end
def get_referer(env, fallback = "/", unroll = true) def get_referer(env, fallback = "/", unroll = true)
@ -267,13 +267,13 @@ def get_referer(env, fallback = "/", unroll = true)
referer = fallback referer = fallback
end end
return referer referer
end end
def sha256(text) def sha256(text)
digest = OpenSSL::Digest.new("SHA256") digest = OpenSSL::Digest.new("SHA256")
digest << text digest << text
return digest.final.hexstring digest.final.hexstring
end end
def subscribe_pubsub(topic, key) def subscribe_pubsub(topic, key)
@ -301,7 +301,7 @@ def subscribe_pubsub(topic, key)
"hub.secret" => key.to_s, "hub.secret" => key.to_s,
} }
return make_client(PUBSUB_URL, &.post("/subscribe", form: body)) make_client(PUBSUB_URL, &.post("/subscribe", form: body))
end end
def parse_range(range) def parse_range(range)
@ -327,7 +327,7 @@ def reduce_uri(uri : URI | String, max_length : Int32 = 50, suffix : String = "
if str.size > max_length if str.size > max_length
str = "#{str[0, max_length]}#{suffix}" str = "#{str[0, max_length]}#{suffix}"
end end
return str str
end end
# Get the html link from a NavigationEndpoint or an innertubeCommand # Get the html link from a NavigationEndpoint or an innertubeCommand
@ -380,7 +380,7 @@ def parse_link_endpoint(endpoint : JSON::Any, text : String, video_id : String)
text = %(<a href="#{url}">#{reduce_uri(text)}</a>) text = %(<a href="#{url}">#{reduce_uri(text)}</a>)
end end
end end
return text text
end end
def encrypt_ecb_without_salt(data, key) def encrypt_ecb_without_salt(data, key)
@ -393,11 +393,11 @@ def encrypt_ecb_without_salt(data, key)
io.write(cipher.final) io.write(cipher.final)
io.rewind io.rewind
return io io
end end
def invidious_companion_encrypt(data) def invidious_companion_encrypt(data)
timestamp = Time.utc.to_unix timestamp = Time.utc.to_unix
encrypted_data = encrypt_ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key) encrypted_data = encrypt_ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key)
return Base64.urlsafe_encode(encrypted_data) Base64.urlsafe_encode(encrypted_data)
end end

View File

@ -40,7 +40,7 @@ module WebVTT
end end
private def escape(text : String) : String private def escape(text : String) : String
return text.gsub(ESCAPE_SUBSTITUTIONS) text.gsub(ESCAPE_SUBSTITUTIONS)
end end
def document(setting_fields : Hash(String, String)? = nil, &) def document(setting_fields : Hash(String, String)? = nil, &)

View File

@ -68,7 +68,7 @@ module Invidious::HttpServer
end end
end end
return flush_io_to_cache(retrieve_bytes_from, file_path, file_info) flush_io_to_cache(retrieve_bytes_from, file_path, file_info)
end end
# Writes file data to the cache # Writes file data to the cache
@ -114,7 +114,7 @@ module Invidious::HttpServer
# This is only used in the specs to clear the cache before each handler test # This is only used in the specs to clear the cache before each handler test
def self.clear_cache def self.clear_cache
@@current_cache_size = 0 @@current_cache_size = 0
return @@cached_files.clear @@cached_files.clear
end end
end end
end end

View File

@ -14,9 +14,9 @@ module Invidious::HttpServer
url.query_params = params url.query_params = params
if absolute if absolute
return "#{HOST_URL}#{url.request_target}" "#{HOST_URL}#{url.request_target}"
else else
return url.request_target url.request_target
end end
end end
@ -35,7 +35,7 @@ module Invidious::HttpServer
str << params str << params
end end
return url url
end end
end end
end end

View File

@ -73,7 +73,7 @@ class Invidious::Jobs::InstanceListRefreshJob < Invidious::Jobs::BaseJob
raw_instance_list = [] of JSON::Any raw_instance_list = [] of JSON::Any
end end
return raw_instance_list raw_instance_list
end end
# Checks if the given target instance is outdated # Checks if the given target instance is outdated
@ -84,7 +84,7 @@ class Invidious::Jobs::InstanceListRefreshJob < Invidious::Jobs::BaseJob
remote_commit_date = Time.parse(remote_commit_date[0], "%Y.%m.%d", Time::Location::UTC) remote_commit_date = Time.parse(remote_commit_date[0], "%Y.%m.%d", Time::Location::UTC)
local_commit_date = Time.parse(CURRENT_VERSION, "%Y.%m.%d", Time::Location::UTC) local_commit_date = Time.parse(CURRENT_VERSION, "%Y.%m.%d", Time::Location::UTC)
return (remote_commit_date - local_commit_date).abs.days > 30 (remote_commit_date - local_commit_date).abs.days > 30
end end
# Checks if the uptime of the target instance is greater than 90% over a 30 day period # Checks if the uptime of the target instance is greater than 90% over a 30 day period
@ -92,6 +92,6 @@ class Invidious::Jobs::InstanceListRefreshJob < Invidious::Jobs::BaseJob
return true if !target_instance_health_monitor["down"].as_bool == false return true if !target_instance_health_monitor["down"].as_bool == false
return true if target_instance_health_monitor["uptime"].as_f < 90 return true if target_instance_health_monitor["uptime"].as_f < 90
return false false
end end
end end

View File

@ -74,7 +74,7 @@ def fetch_mix(rdid, video_id, cookies = nil, locale = nil)
videos.uniq!(&.id) videos.uniq!(&.id)
videos = videos.first(50) videos = videos.first(50)
return Mix.new({ Mix.new({
title: mix_title, title: mix_title,
id: rdid, id: rdid,
videos: videos, videos: videos,

View File

@ -180,7 +180,7 @@ struct InvidiousPlaylist
module PlaylistPrivacyConverter module PlaylistPrivacyConverter
def self.from_rs(rs) def self.from_rs(rs)
return PlaylistPrivacy.parse(String.new(rs.read(Slice(UInt8)))) PlaylistPrivacy.parse(String.new(rs.read(Slice(UInt8))))
end end
end end
@ -265,7 +265,7 @@ def create_playlist(title, privacy, user)
Invidious::Database::Playlists.insert(playlist) Invidious::Database::Playlists.insert(playlist)
return playlist playlist
end end
def subscribe_playlist(user, playlist) def subscribe_playlist(user, playlist)
@ -283,7 +283,7 @@ def subscribe_playlist(user, playlist)
Invidious::Database::Playlists.insert(playlist) Invidious::Database::Playlists.insert(playlist)
return playlist playlist
end end
def produce_playlist_continuation(id, index) def produce_playlist_continuation(id, index)
@ -318,18 +318,18 @@ def produce_playlist_continuation(id, index)
.try { |i| Base64.urlsafe_encode(i) } .try { |i| Base64.urlsafe_encode(i) }
.try { |i| URI.encode_www_form(i) } .try { |i| URI.encode_www_form(i) }
return continuation continuation
end end
def get_playlist(plid : String) def get_playlist(plid : String)
if plid.starts_with? "IV" if plid.starts_with? "IV"
if playlist = Invidious::Database::Playlists.select(id: plid) if playlist = Invidious::Database::Playlists.select(id: plid)
return playlist playlist
else else
raise NotFoundException.new("Playlist does not exist.") raise NotFoundException.new("Playlist does not exist.")
end end
else else
return fetch_playlist(plid) fetch_playlist(plid)
end end
end end
@ -398,7 +398,7 @@ def fetch_playlist(plid : String)
ucid = author_info.dig?("title", "runs", 0, "navigationEndpoint", "browseEndpoint", "browseId").try &.as_s || "" ucid = author_info.dig?("title", "runs", 0, "navigationEndpoint", "browseEndpoint", "browseId").try &.as_s || ""
end end
return Playlist.new({ Playlist.new({
title: title, title: title,
id: plid, id: plid,
author: author, author: author,
@ -443,7 +443,7 @@ def get_playlist_videos(playlist : InvidiousPlaylist | Playlist, offset : Int32,
offset += 100 offset += 100
end end
return videos videos
end end
end end
@ -504,7 +504,7 @@ def extract_playlist_videos(initial_data : Hash(String, JSON::Any))
videos << ProblematicTimelineItem.new(parse_exception: ex) videos << ProblematicTimelineItem.new(parse_exception: ex)
end end
return videos videos
end end
def template_playlist(playlist, listen) def template_playlist(playlist, listen)

View File

@ -337,10 +337,10 @@ module Invidious::Routes::Account
end end
if redirect if redirect
return env.redirect referer env.redirect referer
else else
env.response.content_type = "application/json" env.response.content_type = "application/json"
return "{}" "{}"
end end
end end
end end

View File

@ -140,7 +140,7 @@ module Invidious::Routes::API::Manifest
end end
end end
return manifest manifest
end end
# /api/manifest/dash/id/videoplayback # /api/manifest/dash/id/videoplayback

View File

@ -35,7 +35,7 @@ module Invidious::Routes::API::V1::Authenticated
env.response.content_type = "application/json" env.response.content_type = "application/json"
user = env.get("user").as(User) user = env.get("user").as(User)
return Invidious::User::Export.to_invidious(user) Invidious::User::Export.to_invidious(user)
end end
def self.import_invidious(env) def self.import_invidious(env)
@ -71,7 +71,7 @@ module Invidious::Routes::API::V1::Authenticated
end end
watched ||= [] of String watched ||= [] of String
return watched.to_json watched.to_json
end end
def self.mark_watched(env) def self.mark_watched(env)
@ -423,7 +423,7 @@ module Invidious::Routes::API::V1::Authenticated
env.response.content_type = "text/html" env.response.content_type = "text/html"
csrf_token = generate_response(sid, {":authorize_token"}, HMAC_KEY, use_nonce: true) csrf_token = generate_response(sid, {":authorize_token"}, HMAC_KEY, use_nonce: true)
return templated "user/authorize_token" templated "user/authorize_token"
else else
env.response.content_type = "application/json" env.response.content_type = "application/json"

View File

@ -137,7 +137,7 @@ module Invidious::Routes::API::V1::Channels
env.params.query.delete("sort_by") if env.params.query.has_key?("sort_by") env.params.query.delete("sort_by") if env.params.query.has_key?("sort_by")
env.params.query.delete("continuation") if env.params.query.has_key?("continuation") env.params.query.delete("continuation") if env.params.query.has_key?("continuation")
return videos(env) videos(env)
end end
def self.videos(env) def self.videos(env)
@ -173,7 +173,7 @@ module Invidious::Routes::API::V1::Channels
end end
end end
return JSON.build do |json| JSON.build do |json|
json.object do json.object do
json.field "videos" do json.field "videos" do
json.array do json.array do
@ -219,7 +219,7 @@ module Invidious::Routes::API::V1::Channels
end end
end end
return JSON.build do |json| JSON.build do |json|
json.object do json.object do
json.field "videos" do json.field "videos" do
json.array do json.array do
@ -265,7 +265,7 @@ module Invidious::Routes::API::V1::Channels
end end
end end
return JSON.build do |json| JSON.build do |json|
json.object do json.object do
json.field "videos" do json.field "videos" do
json.array do json.array do
@ -416,7 +416,7 @@ module Invidious::Routes::API::V1::Channels
begin begin
fetch_channel_community(ucid, continuation, locale, format, thin_mode) fetch_channel_community(ucid, continuation, locale, format, thin_mode)
rescue ex rescue ex
return error_json(500, ex) error_json(500, ex)
end end
end end
@ -444,7 +444,7 @@ module Invidious::Routes::API::V1::Channels
begin begin
fetch_channel_community_post(ucid, id, locale, format, thin_mode) fetch_channel_community_post(ucid, id, locale, format, thin_mode)
rescue ex rescue ex
return error_json(500, ex) error_json(500, ex)
end end
end end
@ -472,7 +472,7 @@ module Invidious::Routes::API::V1::Channels
else else
comments = YoutubeAPI.browse(continuation: continuation) comments = YoutubeAPI.browse(continuation: continuation)
end end
return Comments.parse_youtube(id, comments, format, locale, thin_mode, is_post: true) Comments.parse_youtube(id, comments, format, locale, thin_mode, is_post: true)
end end
def self.channels(env) def self.channels(env)

View File

@ -4,7 +4,7 @@ module Invidious::Routes::API::V1::Misc
env.response.content_type = "application/json" env.response.content_type = "application/json"
if !CONFIG.statistics_enabled if !CONFIG.statistics_enabled
return {"software" => SOFTWARE}.to_json {"software" => SOFTWARE}.to_json
else else
# Calculate playback success rate # Calculate playback success rate
if (tracker = Invidious::Jobs::StatisticsRefreshJob::STATISTICS["playback"]?) if (tracker = Invidious::Jobs::StatisticsRefreshJob::STATISTICS["playback"]?)
@ -22,7 +22,7 @@ module Invidious::Routes::API::V1::Misc
end end
end end
return Invidious::Jobs::StatisticsRefreshJob::STATISTICS.to_json Invidious::Jobs::StatisticsRefreshJob::STATISTICS.to_json
end end
end end

View File

@ -53,7 +53,7 @@ module Invidious::Routes::API::V1::Search
end end
end end
rescue ex rescue ex
return error_json(500, ex) error_json(500, ex)
end end
end end

View File

@ -18,7 +18,7 @@ module Invidious::Routes::API::V1::Videos
return error_json(500, ex) return error_json(500, ex)
end end
return JSON.build do |json| JSON.build do |json|
Invidious::JSONify::APIv1.video(video, json, locale: locale, proxy: proxy) Invidious::JSONify::APIv1.video(video, json, locale: locale, proxy: proxy)
end end
end end
@ -247,7 +247,7 @@ module Invidious::Routes::API::V1::Videos
# videojs-vtt-thumbnails is not compliant to the VTT specification, it # videojs-vtt-thumbnails is not compliant to the VTT specification, it
# doesn't unescape the HTML entities, so we have to do it here: # doesn't unescape the HTML entities, so we have to do it here:
# TODO: remove this when we migrate to VideoJS 8 # TODO: remove this when we migrate to VideoJS 8
return HTML.unescape(vtt_file) HTML.unescape(vtt_file)
end end
def self.annotations(env) def self.annotations(env)
@ -352,7 +352,7 @@ module Invidious::Routes::API::V1::Videos
return error_json(500, ex) return error_json(500, ex)
end end
return comments comments
elsif source == "reddit" elsif source == "reddit"
sort_by ||= "confidence" sort_by ||= "confidence"
@ -418,7 +418,7 @@ module Invidious::Routes::API::V1::Videos
return error_json(500, ex) return error_json(500, ex)
end end
return JSON.build do |json| JSON.build do |json|
json.object do json.object do
json.field "startTime", start_time json.field "startTime", start_time
json.field "endTime", end_time json.field "endTime", end_time
@ -513,6 +513,6 @@ module Invidious::Routes::API::V1::Videos
return error_json(500, ex) return error_json(500, ex)
end end
return transcript.to_json transcript.to_json
end end
end end

View File

@ -4,7 +4,7 @@ module Invidious::Routes::Channels
# Redirection for unsupported routes ("tabs") # Redirection for unsupported routes ("tabs")
def self.redirect_home(env) def self.redirect_home(env)
ucid = env.params.url["ucid"] ucid = env.params.url["ucid"]
return env.redirect "/channel/#{URI.encode_www_form(ucid)}" env.redirect "/channel/#{URI.encode_www_form(ucid)}"
end end
def self.home(env) def self.home(env)
@ -365,7 +365,7 @@ module Invidious::Routes::Channels
url += "?#{invidious_url_params}" if !invidious_url_params.empty? url += "?#{invidious_url_params}" if !invidious_url_params.empty?
return env.redirect url env.redirect url
end end
# Handles redirects for the /profile endpoint # Handles redirects for the /profile endpoint
@ -378,7 +378,7 @@ module Invidious::Routes::Channels
user = env.params.query["user"]? user = env.params.query["user"]?
if !user if !user
return error_template(404, "This channel does not exist.") error_template(404, "This channel does not exist.")
else else
env.redirect "/user/#{user}#{uri_params}" env.redirect "/user/#{user}#{uri_params}"
end end

View File

@ -55,6 +55,6 @@ module Invidious::Routes::Companion
env.response.headers[key] = value env.response.headers[key] = value
end end
return IO.copy response.body_io, env.response IO.copy response.body_io, env.response
end end
end end

View File

@ -148,6 +148,6 @@ module Invidious::Routes::Images
return env.response.headers.delete("Transfer-Encoding") return env.response.headers.delete("Transfer-Encoding")
end end
return proxy_file(response, env) proxy_file(response, env)
end end
end end

View File

@ -241,7 +241,7 @@ module Invidious::Routes::VideoPlayback
query_params = HTTP::Params.new(raw_params) query_params = HTTP::Params.new(raw_params)
env.response.headers["Access-Control-Allow-Origin"] = "*" env.response.headers["Access-Control-Allow-Origin"] = "*"
return env.redirect "/videoplayback?#{query_params}" env.redirect "/videoplayback?#{query_params}"
end end
# /videoplayback/* && /videoplayback/* # /videoplayback/* && /videoplayback/*
@ -307,6 +307,6 @@ module Invidious::Routes::VideoPlayback
url += "&title=#{URI.encode_www_form(title, space_to_plus: false)}" if title url += "&title=#{URI.encode_www_form(title, space_to_plus: false)}" if title
end end
return env.redirect url env.redirect url
end end
end end

View File

@ -215,7 +215,7 @@ module Invidious::Routes::Watch
url += "&#{env.params.query}" url += "&#{env.params.query}"
end end
return env.redirect url env.redirect url
end end
def self.mark_watched(env) def self.mark_watched(env)
@ -289,9 +289,9 @@ module Invidious::Routes::Watch
env.params.query["end"] = end_time.to_s if end_time != nil env.params.query["end"] = end_time.to_s if end_time != nil
end end
return env.redirect "/watch?v=#{video_id}&#{env.params.query}" env.redirect "/watch?v=#{video_id}&#{env.params.query}"
else else
return error_template(404, "The requested clip doesn't exist") error_template(404, "The requested clip doesn't exist")
end end
end end
@ -330,16 +330,16 @@ module Invidious::Routes::Watch
env.params.query["title"] = filename env.params.query["title"] = filename
env.params.query["label"] = URI.decode_www_form(label.as_s) env.params.query["label"] = URI.decode_www_form(label.as_s)
return Invidious::Routes::API::V1::Videos.captions(env) Invidious::Routes::API::V1::Videos.captions(env)
elsif itag = download_widget["itag"]?.try &.as_i.to_s elsif itag = download_widget["itag"]?.try &.as_i.to_s
# URL params specific to /latest_version # URL params specific to /latest_version
env.params.query["id"] = video_id env.params.query["id"] = video_id
env.params.query["title"] = filename env.params.query["title"] = filename
env.params.query["local"] = "true" env.params.query["local"] = "true"
return Invidious::Routes::VideoPlayback.latest_version(env) Invidious::Routes::VideoPlayback.latest_version(env)
else else
return error_template(400, "Invalid label or itag") error_template(400, "Invalid label or itag")
end end
end end
end end

View File

@ -28,5 +28,5 @@ def produce_channel_search_continuation(ucid, query, page)
.try { |i| Base64.urlsafe_encode(i) } .try { |i| Base64.urlsafe_encode(i) }
.try { |i| URI.encode_www_form(i) } .try { |i| URI.encode_www_form(i) }
return continuation continuation
end end

View File

@ -80,7 +80,7 @@ module Invidious::Search
end end
def default? : Bool def default? : Bool
return @date.none? && @type.all? && @duration.none? && \ @date.none? && @type.all? && @duration.none? && \
@features.none? && @sort.relevance? @features.none? && @sort.relevance?
end end
@ -110,7 +110,7 @@ module Invidious::Search
end end
end end
return features features
end end
def self.format_features(features : Features) : String def self.format_features(features : Features) : String
@ -132,7 +132,7 @@ module Invidious::Search
str << "location" if features.location? str << "location" if features.location?
str << "purchased" if features.purchased? str << "purchased" if features.purchased?
return str.join(',') str.join(',')
end end
def self.from_legacy_filters(str : String) : {Filters, String, String, Bool} def self.from_legacy_filters(str : String) : {Filters, String, String, Bool}
@ -230,7 +230,7 @@ module Invidious::Search
params.delete("sort") params.delete("sort")
end end
return filters filters
end end
def to_iv_params : HTTP::Params def to_iv_params : HTTP::Params
@ -249,7 +249,7 @@ module Invidious::Search
raw_params["features"] = [Filters.format_features(@features)] raw_params["features"] = [Filters.format_features(@features)]
end end
return HTTP::Params.new(raw_params) HTTP::Params.new(raw_params)
end end
# ------------------- # -------------------
@ -304,7 +304,7 @@ module Invidious::Search
# See https://github.com/iv-org/invidious/issues/4398 # See https://github.com/iv-org/invidious/issues/4398
object["30:varint"] = 1.to_i64 object["30:varint"] = 1.to_i64
return object object
.try { |i| Protodec::Any.cast_json(i) } .try { |i| Protodec::Any.cast_json(i) }
.try { |i| Protodec::Any.from_json(i) } .try { |i| Protodec::Any.from_json(i) }
.try { |i| Base64.urlsafe_encode(i) } .try { |i| Base64.urlsafe_encode(i) }
@ -370,7 +370,7 @@ module Invidious::Search
# Remove URL parameter and return result # Remove URL parameter and return result
params.delete("sp") params.delete("sp")
return filters filters
end end
end end
end end

View File

@ -10,7 +10,7 @@ module Invidious::Search
initial_data = YoutubeAPI.search(query.text, search_params, client_config: client_config) initial_data = YoutubeAPI.search(query.text, search_params, client_config: client_config)
items, _ = extract_items(initial_data) items, _ = extract_items(initial_data)
return items.reject!(Category) items.reject!(Category)
end end
# Search a youtube channel # Search a youtube channel
@ -32,14 +32,14 @@ module Invidious::Search
response_json = YoutubeAPI.browse(continuation) response_json = YoutubeAPI.browse(continuation)
items, _ = extract_items(response_json, "", ucid) items, _ = extract_items(response_json, "", ucid)
return items.reject!(Category) items.reject!(Category)
end end
# Search inside of user subscriptions # Search inside of user subscriptions
def subscriptions(query : Query, user : Invidious::User) : Array(ChannelVideo) def subscriptions(query : Query, user : Invidious::User) : Array(ChannelVideo)
view_name = "subscriptions_#{sha256(user.email)}" view_name = "subscriptions_#{sha256(user.email)}"
return PG_DB.query_all(<<-SQL, query.text, (query.page - 1) * 20, as: ChannelVideo) PG_DB.query_all(<<-SQL, query.text, (query.page - 1) * 20, as: ChannelVideo)
SELECT id,title,published,updated,ucid,author,length_seconds SELECT id,title,published,updated,ucid,author,length_seconds
FROM ( FROM (
SELECT *, SELECT *,

View File

@ -25,19 +25,19 @@ module Invidious::Search
# Return true if @raw_query is either `nil` or empty # Return true if @raw_query is either `nil` or empty
private def empty_raw_query? private def empty_raw_query?
return @raw_query.empty? @raw_query.empty?
end end
# Same as `empty_raw_query?`, but named for external use # Same as `empty_raw_query?`, but named for external use
def empty? def empty?
return empty_raw_query? empty_raw_query?
end end
# Getter for the query string. # Getter for the query string.
# It is named `text` to reduce confusion (`search_query.text` makes more # It is named `text` to reduce confusion (`search_query.text` makes more
# sense than `search_query.query`) # sense than `search_query.query`)
def text def text
return @query @query
end end
# Initialize a new search query. # Initialize a new search query.
@ -135,7 +135,7 @@ module Invidious::Search
end end
end end
return items items
end end
# Return the HTTP::Params corresponding to this Query (invidious format) # Return the HTTP::Params corresponding to this Query (invidious format)
@ -145,7 +145,7 @@ module Invidious::Search
params["q"] = @query params["q"] = @query
params["channel"] = @channel if !@channel.empty? params["channel"] = @channel if !@channel.empty?
return params params
end end
# Checks if the query is a standalone URL # Checks if the query is a standalone URL
@ -160,7 +160,7 @@ module Invidious::Search
return false if !@filters.default? return false if !@filters.default?
# Simple heuristics: domain name # Simple heuristics: domain name
return @raw_query.starts_with?( @raw_query.starts_with?(
/(https?:\/\/)?(www\.)?(m\.)?youtu(\.be|be\.com)\// /(https?:\/\/)?(www\.)?(m\.)?youtu(\.be|be\.com)\//
) )
end end

View File

@ -53,7 +53,7 @@ struct Invidious::User
answer = "#{hour}:#{minute.to_s.rjust(2, '0')}:#{second.to_s.rjust(2, '0')}" answer = "#{hour}:#{minute.to_s.rjust(2, '0')}:#{second.to_s.rjust(2, '0')}"
answer = OpenSSL::HMAC.hexdigest(:sha256, key, answer) answer = OpenSSL::HMAC.hexdigest(:sha256, key, answer)
return { {
question: image, question: image,
tokens: {generate_response(answer, {":login"}, key, use_nonce: true)}, tokens: {generate_response(answer, {":login"}, key, use_nonce: true)},
} }

View File

@ -11,7 +11,7 @@ struct Invidious::User
# Session ID (SID) cookie # Session ID (SID) cookie
# Parameter "domain" comes from the global config # Parameter "domain" comes from the global config
def sid(domain : String?, sid) : HTTP::Cookie def sid(domain : String?, sid) : HTTP::Cookie
return HTTP::Cookie.new( HTTP::Cookie.new(
name: "SID", name: "SID",
domain: domain, domain: domain,
value: sid, value: sid,
@ -25,7 +25,7 @@ struct Invidious::User
# Preferences (PREFS) cookie # Preferences (PREFS) cookie
# Parameter "domain" comes from the global config # Parameter "domain" comes from the global config
def prefs(domain : String?, preferences : Preferences) : HTTP::Cookie def prefs(domain : String?, preferences : Preferences) : HTTP::Cookie
return HTTP::Cookie.new( HTTP::Cookie.new(
name: "PREFS", name: "PREFS",
domain: domain, domain: domain,
value: URI.encode_www_form(preferences.to_json), value: URI.encode_www_form(preferences.to_json),

View File

@ -5,7 +5,7 @@ struct Invidious::User
def to_invidious(user : User) def to_invidious(user : User)
playlists = Invidious::Database::Playlists.select_like_iv(user.email) playlists = Invidious::Database::Playlists.select_like_iv(user.email)
return JSON.build do |json| JSON.build do |json|
json.object do json.object do
json.field "subscriptions", user.subscriptions json.field "subscriptions", user.subscriptions
json.field "watch_history", user.watched json.field "watch_history", user.watched

View File

@ -27,7 +27,7 @@ struct Invidious::User
subscriptions << channel_id subscriptions << channel_id
end end
return subscriptions subscriptions
end end
def parse_playlist_export_csv(user : User, raw_input : String) def parse_playlist_export_csv(user : User, raw_input : String)
@ -81,7 +81,7 @@ struct Invidious::User
end end
end end
return playlist playlist
end end
# ------------------- # -------------------
@ -171,7 +171,7 @@ struct Invidious::User
opml_extensions = ["xml", "opml"] opml_extensions = ["xml", "opml"]
return opml_mimetypes.any?(&.== mimetype) || opml_extensions.any?(&.== extension) opml_mimetypes.any?(&.== mimetype) || opml_extensions.any?(&.== extension)
end end
# Import subscribed channels from Youtube # Import subscribed channels from Youtube
@ -200,7 +200,7 @@ struct Invidious::User
user.subscriptions = get_batch_channels(user.subscriptions) user.subscriptions = get_batch_channels(user.subscriptions)
Invidious::Database::Users.update_subscriptions(user) Invidious::Database::Users.update_subscriptions(user)
return true true
end end
def from_youtube_pl(user : User, body : String, filename : String, type : String) : Bool def from_youtube_pl(user : User, body : String, filename : String, type : String) : Bool
@ -209,12 +209,12 @@ struct Invidious::User
if extension == "csv" || type == "text/csv" if extension == "csv" || type == "text/csv"
playlist = parse_playlist_export_csv(user, body) playlist = parse_playlist_export_csv(user, body)
if playlist if playlist
return true true
else else
return false false
end end
else else
return false false
end end
end end
@ -232,9 +232,9 @@ struct Invidious::User
user.watched += watched user.watched += watched
user.watched.uniq! user.watched.uniq!
Invidious::Database::Users.update_watch_history(user) Invidious::Database::Users.update_watch_history(user)
return true true
else else
return false false
end end
end end
@ -328,7 +328,7 @@ struct Invidious::User
end end
# Success! # Success!
return true true
end end
end # module end # module
end end

View File

@ -260,12 +260,12 @@ struct Preferences
module TimeSpanConverter module TimeSpanConverter
def self.to_yaml(value : Time::Span, yaml : YAML::Nodes::Builder) def self.to_yaml(value : Time::Span, yaml : YAML::Nodes::Builder)
return yaml.scalar value.total_minutes.to_i32 yaml.scalar value.total_minutes.to_i32
end end
def self.from_yaml(ctx : YAML::ParseContext, node : YAML::Nodes::Node) : Time::Span def self.from_yaml(ctx : YAML::ParseContext, node : YAML::Nodes::Node) : Time::Span
if node.is_a?(YAML::Nodes::Scalar) if node.is_a?(YAML::Nodes::Scalar)
return decode_interval(node.value) decode_interval(node.value)
else else
node.raise "Expected scalar, not #{node.class}" node.raise "Expected scalar, not #{node.class}"
end end

View File

@ -56,15 +56,15 @@ struct Video
def video_type : VideoType def video_type : VideoType
video_type = info["videoType"]?.try &.as_s || "video" video_type = info["videoType"]?.try &.as_s || "video"
return VideoType.parse?(video_type) || VideoType::Video VideoType.parse?(video_type) || VideoType::Video
end end
def schema_version : Int def schema_version : Int
return info["version"]?.try &.as_i || 1 info["version"]?.try &.as_i || 1
end end
def published : Time def published : Time
return info["published"]? info["published"]?
.try { |t| Time.parse(t.as_s, "%Y-%m-%d", Time::Location::UTC) } || Time.utc .try { |t| Time.parse(t.as_s, "%Y-%m-%d", Time::Location::UTC) } || Time.utc
end end
@ -73,11 +73,11 @@ struct Video
end end
def live_now def live_now
return (video_type == VideoType::Livestream) (video_type == VideoType::Livestream)
end end
def post_live_dvr def post_live_dvr
return info["isPostLiveDvr"].as_bool info["isPostLiveDvr"].as_bool
end end
def premiere_timestamp : Time? def premiere_timestamp : Time?
@ -94,21 +94,21 @@ struct Video
def fmt_stream : Array(Hash(String, JSON::Any)) def fmt_stream : Array(Hash(String, JSON::Any))
if formats = info.dig?("streamingData", "formats") if formats = info.dig?("streamingData", "formats")
return formats formats
.as_a.map(&.as_h) .as_a.map(&.as_h)
.sort_by! { |f| f["width"]?.try &.as_i || 0 } .sort_by! { |f| f["width"]?.try &.as_i || 0 }
else else
return [] of Hash(String, JSON::Any) [] of Hash(String, JSON::Any)
end end
end end
def adaptive_fmts : Array(Hash(String, JSON::Any)) def adaptive_fmts : Array(Hash(String, JSON::Any))
if formats = info.dig?("streamingData", "adaptiveFormats") if formats = info.dig?("streamingData", "adaptiveFormats")
return formats formats
.as_a.map(&.as_h) .as_a.map(&.as_h)
.sort_by! { |f| f["width"]?.try &.as_i || f["audioTrack"]?.try { |a| a["audioIsDefault"]?.try { |v| v.as_bool ? -1 : 0 } } || 0 } .sort_by! { |f| f["width"]?.try &.as_i || f["audioTrack"]?.try { |a| a["audioIsDefault"]?.try { |v| v.as_bool ? -1 : 0 } } || 0 }
else else
return [] of Hash(String, JSON::Any) [] of Hash(String, JSON::Any)
end end
end end
@ -124,11 +124,11 @@ struct Video
def storyboards def storyboards
container = info.dig?("storyboards") || JSON::Any.new("{}") container = info.dig?("storyboards") || JSON::Any.new("{}")
return IV::Videos::Storyboard.from_yt_json(container, length_seconds) IV::Videos::Storyboard.from_yt_json(container, length_seconds)
end end
def paid def paid
return (reason || "").includes? "requires payment" (reason || "").includes? "requires payment"
end end
def premium def premium
@ -140,7 +140,7 @@ struct Video
@captions = Invidious::Videos::Captions::Metadata.from_yt_json(info["captions"]) @captions = Invidious::Videos::Captions::Metadata.from_yt_json(info["captions"])
end end
return @captions @captions
end end
def hls_manifest_url : String? def hls_manifest_url : String?
@ -162,7 +162,7 @@ struct Video
dash_url.query = "#{dash_query}&mpd_version=5" dash_url.query = "#{dash_query}&mpd_version=5"
end end
return dash_url.to_s dash_url.to_s
end end
def genre_url : String? def genre_url : String?
@ -170,11 +170,11 @@ struct Video
end end
def vr? : Bool? def vr? : Bool?
return {"EQUIRECTANGULAR", "MESH"}.includes? projection_type {"EQUIRECTANGULAR", "MESH"}.includes? projection_type
end end
def projection_type : String? def projection_type : String?
return info.dig?("streamingData", "adaptiveFormats", 0, "projectionType").try &.as_s info.dig?("streamingData", "adaptiveFormats", 0, "projectionType").try &.as_s
end end
def reason : String? def reason : String?
@ -197,7 +197,7 @@ struct Video
private macro getset_string(name) private macro getset_string(name)
# Return {{ name.stringify }} from `info` # Return {{ name.stringify }} from `info`
def {{ name.id.underscore }} : String def {{ name.id.underscore }} : String
return info[{{ name.stringify }}]?.try &.as_s || "" info[{{ name.stringify }}]?.try &.as_s || ""
end end
# Update {{ name.stringify }} into `info` # Update {{ name.stringify }} into `info`
@ -211,7 +211,7 @@ struct Video
private macro getset_string_array(name) private macro getset_string_array(name)
# Return {{ name.stringify }} from `info` # Return {{ name.stringify }} from `info`
def {{ name.id.underscore }} : Array(String) def {{ name.id.underscore }} : Array(String)
return info[{{ name.stringify }}]?.try &.as_a.map &.as_s || [] of String info[{{ name.stringify }}]?.try &.as_a.map &.as_s || [] of String
end end
# Update {{ name.stringify }} into `info` # Update {{ name.stringify }} into `info`
@ -225,7 +225,7 @@ struct Video
{% for op, type in {i32: Int32, i64: Int64} %} {% for op, type in {i32: Int32, i64: Int64} %}
private macro getset_{{ op }}(name) private macro getset_{{ op }}(name)
def \{{name.id.underscore}} : {{ type }} def \{{name.id.underscore}} : {{ type }}
return info[\{{name.stringify}}]?.try &.as_i64.to_{{ op }} || 0_{{ op }} info[\{{name.stringify}}]?.try &.as_i64.to_{{ op }} || 0_{{ op }}
end end
def \{{name.id.underscore}}=(value : Int) def \{{name.id.underscore}}=(value : Int)
@ -239,7 +239,7 @@ struct Video
private macro getset_bool(name) private macro getset_bool(name)
# Return {{ name.stringify }} from `info` # Return {{ name.stringify }} from `info`
def {{ name.id.underscore }} : Bool def {{ name.id.underscore }} : Bool
return info[{{ name.stringify }}]?.try &.as_bool || false info[{{ name.stringify }}]?.try &.as_bool || false
end end
# Update {{ name.stringify }} into `info` # Update {{ name.stringify }} into `info`
@ -254,7 +254,7 @@ struct Video
private macro predicate_bool(method_name, name) private macro predicate_bool(method_name, name)
# Return {{ name.stringify }} from `info` # Return {{ name.stringify }} from `info`
def {{ method_name.id.underscore }}? : Bool def {{ method_name.id.underscore }}? : Bool
return info[{{ name.stringify }}]?.try &.as_bool || false info[{{ name.stringify }}]?.try &.as_bool || false
end end
# Update {{ name.stringify }} into `info` # Update {{ name.stringify }} into `info`
@ -316,11 +316,11 @@ def get_video(id, refresh = true, region = nil, force_refresh = false)
Invidious::Database::Videos.insert(video) if !region Invidious::Database::Videos.insert(video) if !region
end end
return video video
rescue DB::Error rescue DB::Error
# Avoid common `DB::PoolRetryAttemptsExceeded` error and friends # Avoid common `DB::PoolRetryAttemptsExceeded` error and friends
# Note: All DB errors inherit from `DB::Error` # Note: All DB errors inherit from `DB::Error`
return fetch_video(id, region) fetch_video(id, region)
end end
def fetch_video(id, region) def fetch_video(id, region)
@ -350,7 +350,7 @@ def fetch_video(id, region)
updated: Time.utc, updated: Time.utc,
}) })
return video video
end end
def process_continuation(query, plid, id) def process_continuation(query, plid, id)

View File

@ -33,7 +33,7 @@ module Invidious::Videos
captions_list << Captions::Metadata.new(name, language_code, base_url, auto_generated) captions_list << Captions::Metadata.new(name, language_code, base_url, auto_generated)
end end
return captions_list captions_list
end end
def timedtext_to_vtt(timedtext : String, tlang = nil) : String def timedtext_to_vtt(timedtext : String, tlang = nil) : String
@ -82,7 +82,7 @@ module Invidious::Videos
end end
end end
return result result
end end
end end

View File

@ -26,7 +26,7 @@ private def copy_string(str : String::Builder, iter : Iterator, count : Int) : I
copied += 1 copied += 1
end end
return copied copied
end end
def parse_description(desc, video_id : String) : String? def parse_description(desc, video_id : String) : String?
@ -52,7 +52,7 @@ def parse_description(desc, video_id : String) : String?
index = 0 index = 0
return String.build do |str| String.build do |str|
commands.each do |command| commands.each do |command|
cmd_start = command["startIndex"].as_i cmd_start = command["startIndex"].as_i
cmd_length = command["length"].as_i cmd_length = command["length"].as_i

View File

@ -1,6 +1,6 @@
module Invidious::Videos::Formats module Invidious::Videos::Formats
def self.itag_to_metadata?(itag : JSON::Any) def self.itag_to_metadata?(itag : JSON::Any)
return FORMATS[itag.to_s]? FORMATS[itag.to_s]?
end end
# See https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/youtube.py#L380-#L476 # See https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/youtube.py#L380-#L476

View File

@ -40,7 +40,7 @@ def parse_related_video(related : JSON::Any) : Hash(String, JSON::Any)?
# TODO: when refactoring video types, make a struct for related videos # TODO: when refactoring video types, make a struct for related videos
# or reuse an existing type, if that fits. # or reuse an existing type, if that fits.
return { {
"id" => related["videoId"], "id" => related["videoId"],
"title" => related["title"]["simpleText"], "title" => related["title"]["simpleText"],
"author" => author || JSON::Any.new(""), "author" => author || JSON::Any.new(""),
@ -128,7 +128,7 @@ def extract_video_info(video_id : String)
# Data structure version, for cache control # Data structure version, for cache control
params["version"] = JSON::Any.new(Video::SCHEMA_VERSION.to_i64) params["version"] = JSON::Any.new(Video::SCHEMA_VERSION.to_i64)
return params params
end end
def try_fetch_streaming_data(id : String, client_config : YoutubeAPI::ClientConfig) : Hash(String, JSON::Any)? def try_fetch_streaming_data(id : String, client_config : YoutubeAPI::ClientConfig) : Hash(String, JSON::Any)?
@ -145,7 +145,7 @@ def try_fetch_streaming_data(id : String, client_config : YoutubeAPI::ClientConf
"The video returned by YouTube isn't the requested one. (#{client_config.client_type} client)" "The video returned by YouTube isn't the requested one. (#{client_config.client_type} client)"
) )
elsif playability_status == "OK" elsif playability_status == "OK"
return response response
else else
return return
end end
@ -440,7 +440,7 @@ def parse_video_info(video_id : String, player_response : Hash(String, JSON::Any
"subCountText" => JSON::Any.new(subs_text || "-"), "subCountText" => JSON::Any.new(subs_text || "-"),
} }
return params params
end end
private def convert_url(fmt) private def convert_url(fmt)
@ -457,9 +457,9 @@ private def convert_url(fmt)
url.query_params = params url.query_params = params
LOGGER.trace("convert_url: new url is '#{url}'") LOGGER.trace("convert_url: new url is '#{url}'")
return url.to_s url.to_s
rescue ex rescue ex
LOGGER.debug("convert_url: Error when parsing video URL") LOGGER.debug("convert_url: Error when parsing video URL")
LOGGER.trace(ex.inspect_with_backtrace) LOGGER.trace(ex.inspect_with_backtrace)
return "" ""
end end

View File

@ -62,7 +62,7 @@ module Invidious::Videos
# The base URL is the first chunk # The base URL is the first chunk
base_url = URI.parse(storyboards.shift) base_url = URI.parse(storyboards.shift)
return storyboards.map_with_index do |sb, i| storyboards.map_with_index do |sb, i|
# Separate the different storyboard parameters: # Separate the different storyboard parameters:
# width/height: respective dimensions, in pixels, of a single thumbnail # width/height: respective dimensions, in pixels, of a single thumbnail
# count: how many thumbnails are displayed across the full video # count: how many thumbnails are displayed across the full video

View File

@ -45,7 +45,7 @@ module Invidious::Videos
.try { |i| Base64.urlsafe_encode(i) } .try { |i| Base64.urlsafe_encode(i) }
.try { |i| URI.encode_www_form(i) } .try { |i| URI.encode_www_form(i) }
return params params
end end
# Constructs a Transcripts struct from the initial YouTube response # Constructs a Transcripts struct from the initial YouTube response
@ -92,7 +92,7 @@ module Invidious::Videos
lines << line_type.new(start_ms, end_ms, text) lines << line_type.new(start_ms, end_ms, text)
end end
return Transcript.new( Transcript.new(
lines: lines, lines: lines,
language_code: language_code, language_code: language_code,
auto_generated: auto_generated, auto_generated: auto_generated,
@ -120,7 +120,7 @@ module Invidious::Videos
end end
end end
return vtt vtt
end end
def to_json(json : JSON::Builder) def to_json(json : JSON::Builder)

View File

@ -158,5 +158,5 @@ def process_video_params(query, preferences)
save_player_pos: save_player_pos, save_player_pos: save_player_pos,
}) })
return params params
end end

View File

@ -133,7 +133,7 @@ def make_client(url : URI, region = nil, force_resolve : Bool = false, force_you
client.read_timeout = 10.seconds client.read_timeout = 10.seconds
client.connect_timeout = 10.seconds client.connect_timeout = 10.seconds
return client client
end end
def make_client(url : URI, region = nil, force_resolve : Bool = false, use_http_proxy : Bool = true, &) def make_client(url : URI, region = nil, force_resolve : Bool = false, use_http_proxy : Bool = true, &)
@ -149,7 +149,7 @@ def make_configured_http_proxy_client
# This method is only called when configuration for an HTTP proxy are set # This method is only called when configuration for an HTTP proxy are set
config_proxy = CONFIG.http_proxy.not_nil! config_proxy = CONFIG.http_proxy.not_nil!
return HTTP::Proxy::Client.new( HTTP::Proxy::Client.new(
config_proxy.host, config_proxy.host,
config_proxy.port, config_proxy.port,
@ -163,12 +163,12 @@ end
# Creates a new one when the specified pool for the subdomain does not exist # Creates a new one when the specified pool for the subdomain does not exist
def get_ytimg_pool(subdomain) def get_ytimg_pool(subdomain)
if pool = YTIMG_POOLS[subdomain]? if pool = YTIMG_POOLS[subdomain]?
return pool pool
else else
LOGGER.info("ytimg_pool: Creating a new HTTP pool for \"https://#{subdomain}.ytimg.com\"") LOGGER.info("ytimg_pool: Creating a new HTTP pool for \"https://#{subdomain}.ytimg.com\"")
pool = YoutubeConnectionPool.new(URI.parse("https://#{subdomain}.ytimg.com"), capacity: CONFIG.pool_size) pool = YoutubeConnectionPool.new(URI.parse("https://#{subdomain}.ytimg.com"), capacity: CONFIG.pool_size)
YTIMG_POOLS[subdomain] = pool YTIMG_POOLS[subdomain] = pool
return pool pool
end end
end end

View File

@ -37,7 +37,7 @@ record AuthorFallback, name : String, id : String
private module Parsers private module Parsers
module BaseParser module BaseParser
def parse(*args) def parse(*args)
return parse_internal(*args) parse_internal(*args)
rescue ex rescue ex
LOGGER.debug("#{{{ @type.name }}}: Failed to render item.") LOGGER.debug("#{{{ @type.name }}}: Failed to render item.")
LOGGER.debug("#{{{ @type.name }}}: Got exception: #{ex.message}") LOGGER.debug("#{{{ @type.name }}}: Got exception: #{ex.message}")
@ -170,7 +170,7 @@ private module Parsers
end end
def self.parser_name def self.parser_name
return {{ @type.name }} {{ @type.name }}
end end
end end
@ -237,7 +237,7 @@ private module Parsers
end end
def self.parser_name def self.parser_name
return {{ @type.name }} {{ @type.name }}
end end
end end
@ -277,7 +277,7 @@ private module Parsers
end end
end end
return SearchHashtag.new({ SearchHashtag.new({
title: title, title: title,
url: url, url: url,
video_count: short_text_to_number(video_count_txt || ""), video_count: short_text_to_number(video_count_txt || ""),
@ -286,7 +286,7 @@ private module Parsers
end end
def self.parser_name def self.parser_name
return {{ @type.name }} {{ @type.name }}
end end
end end
@ -331,7 +331,7 @@ private module Parsers
end end
def self.parser_name def self.parser_name
return {{ @type.name }} {{ @type.name }}
end end
end end
@ -392,7 +392,7 @@ private module Parsers
end end
def self.parser_name def self.parser_name
return {{ @type.name }} {{ @type.name }}
end end
end end
@ -464,7 +464,7 @@ private module Parsers
end end
def self.parser_name def self.parser_name
return {{ @type.name }} {{ @type.name }}
end end
end end
@ -489,11 +489,11 @@ private module Parsers
child = VideoRendererParser.process(item_contents, author_fallback) child = VideoRendererParser.process(item_contents, author_fallback)
child ||= PlaylistRendererParser.process(item_contents, author_fallback) child ||= PlaylistRendererParser.process(item_contents, author_fallback)
return child child
end end
def self.parser_name def self.parser_name
return {{ @type.name }} {{ @type.name }}
end end
end end
@ -520,11 +520,11 @@ private module Parsers
child ||= PlaylistRendererParser.process(item_contents, author_fallback) child ||= PlaylistRendererParser.process(item_contents, author_fallback)
child ||= LockupViewModelParser.process(item_contents, author_fallback) child ||= LockupViewModelParser.process(item_contents, author_fallback)
child ||= ShortsLockupViewModelParser.process(item_contents, author_fallback) child ||= ShortsLockupViewModelParser.process(item_contents, author_fallback)
return child child
end end
def self.parser_name def self.parser_name
return {{ @type.name }} {{ @type.name }}
end end
end end
@ -623,7 +623,7 @@ private module Parsers
end end
def self.parser_name def self.parser_name
return {{ @type.name }} {{ @type.name }}
end end
end end
@ -688,7 +688,7 @@ private module Parsers
# item_contents.dig("rendererContext", "commandContext", "onTap", "innertubeCommand", "watchEndpoint") # item_contents.dig("rendererContext", "commandContext", "onTap", "innertubeCommand", "watchEndpoint")
# Available fields: "videoId", "playlistId", "params" # Available fields: "videoId", "playlistId", "params"
return SearchPlaylist.new({ SearchPlaylist.new({
title: title, title: title,
id: playlist_id, id: playlist_id,
author: author_fallback.name, author: author_fallback.name,
@ -701,7 +701,7 @@ private module Parsers
end end
def self.parser_name def self.parser_name
return {{ @type.name }} {{ @type.name }}
end end
end end
@ -759,7 +759,7 @@ private module Parsers
end end
def self.parser_name def self.parser_name
return {{ @type.name }} {{ @type.name }}
end end
end end
@ -788,7 +788,7 @@ private module Parsers
end end
def self.parser_name def self.parser_name
return {{ @type.name }} {{ @type.name }}
end end
end end
end end
@ -842,7 +842,7 @@ private module Extractors
raw_items = rich_grid_contents.as_a raw_items = rich_grid_contents.as_a
end end
return raw_items raw_items
end end
private def self.unpack_section_list(contents) private def self.unpack_section_list(contents)
@ -856,7 +856,7 @@ private module Extractors
end end
end end
return raw_items raw_items
end end
private def self.unpack_item_section(contents) private def self.unpack_item_section(contents)
@ -871,11 +871,11 @@ private module Extractors
end end
end end
return raw_items raw_items
end end
def self.extractor_name def self.extractor_name
return {{ @type.name }} {{ @type.name }}
end end
end end
@ -912,11 +912,11 @@ private module Extractors
end end
end end
return raw_items.flatten raw_items.flatten
end end
def self.extractor_name def self.extractor_name
return {{ @type.name }} {{ @type.name }}
end end
end end
@ -946,11 +946,11 @@ private module Extractors
content ||= target.dig?("gridContinuation", "items") content ||= target.dig?("gridContinuation", "items")
content ||= target.dig?("richGridContinuation", "contents") content ||= target.dig?("richGridContinuation", "contents")
return content.nil? ? [] of JSON::Any : content.as_a content.nil? ? [] of JSON::Any : content.as_a
end end
def self.extractor_name def self.extractor_name
return {{ @type.name }} {{ @type.name }}
end end
end end
end end
@ -966,14 +966,14 @@ module HelperExtractors
def self.get_video_count(container : JSON::Any) : Int32 def self.get_video_count(container : JSON::Any) : Int32
if box = container["videoCountText"]? if box = container["videoCountText"]?
if (extracted_text = extract_text(box)) && !extracted_text.includes? " subscriber" if (extracted_text = extract_text(box)) && !extracted_text.includes? " subscriber"
return extracted_text.gsub(/\D/, "").to_i extracted_text.gsub(/\D/, "").to_i
else else
return 0 0
end end
elsif box = container["videoCount"]? elsif box = container["videoCount"]?
return box.as_s.to_i box.as_s.to_i
else else
return 0 0
end end
end end
@ -987,7 +987,7 @@ module HelperExtractors
# Simpletext: "4M views" # Simpletext: "4M views"
# runs: {"text": "1.1K"},{"text":" watching"} # runs: {"text": "1.1K"},{"text":" watching"}
return box["simpleText"]?.try &.as_s.sub(" views", "") || box["simpleText"]?.try &.as_s.sub(" views", "") ||
box.dig?("runs", 0, "text").try &.as_s || "0" box.dig?("runs", 0, "text").try &.as_s || "0"
end end
@ -997,7 +997,7 @@ module HelperExtractors
# #
# Raises when it's unable to parse from the given JSON data. # Raises when it's unable to parse from the given JSON data.
def self.get_thumbnails(container : JSON::Any) : String def self.get_thumbnails(container : JSON::Any) : String
return container.dig("thumbnail", "thumbnails", 0, "url").as_s container.dig("thumbnail", "thumbnails", 0, "url").as_s
end end
# ditto # ditto
@ -1005,13 +1005,13 @@ module HelperExtractors
# YouTube sometimes sends the thumbnail as: # YouTube sometimes sends the thumbnail as:
# {"thumbnails": [{"thumbnails": [{"url": "example.com"}, ...]}]} # {"thumbnails": [{"thumbnails": [{"url": "example.com"}, ...]}]}
def self.get_thumbnails_plural(container : JSON::Any) : String def self.get_thumbnails_plural(container : JSON::Any) : String
return container.dig("thumbnails", 0, "thumbnails", 0, "url").as_s container.dig("thumbnails", 0, "thumbnails", 0, "url").as_s
end end
# Retrieves the ID required for querying the InnerTube browse endpoint. # Retrieves the ID required for querying the InnerTube browse endpoint.
# Returns an empty string when it's unable to do so # Returns an empty string when it's unable to do so
def self.get_browse_id(container) def self.get_browse_id(container)
return container.dig?("navigationEndpoint", "browseEndpoint", "browseId").try &.as_s || "" container.dig?("navigationEndpoint", "browseEndpoint", "browseId").try &.as_s || ""
end end
end end

View File

@ -21,7 +21,7 @@ def extract_text(item : JSON::Any?) : String?
end end
if text_container = item["simpleText"]? if text_container = item["simpleText"]?
return text_container.as_s text_container.as_s
elsif text_container = item["runs"]? elsif text_container = item["runs"]?
return text_container.as_a.map(&.["text"].as_s).join("") return text_container.as_a.map(&.["text"].as_s).join("")
end end
@ -58,18 +58,18 @@ def has_verified_badge?(badges : JSON::Any?)
return true if style == "BADGE_STYLE_TYPE_VERIFIED_ARTIST" return true if style == "BADGE_STYLE_TYPE_VERIFIED_ARTIST"
end end
return false false
rescue ex rescue ex
LOGGER.debug("Unable to parse owner badges. Got exception: #{ex.message}") LOGGER.debug("Unable to parse owner badges. Got exception: #{ex.message}")
LOGGER.trace("Owner badges data: #{badges.to_json}") LOGGER.trace("Owner badges data: #{badges.to_json}")
return false false
end end
# This function extracts SearchVideo items from a Category. # This function extracts SearchVideo items from a Category.
# Categories are commonly returned in search results and trending pages. # Categories are commonly returned in search results and trending pages.
def extract_category(category : Category) : Array(SearchVideo) def extract_category(category : Category) : Array(SearchVideo)
return category.contents.select(SearchVideo) category.contents.select(SearchVideo)
end end
# :ditto: # :ditto:
@ -81,5 +81,5 @@ end
def extract_selected_tab(tabs) def extract_selected_tab(tabs)
# Extract the selected tab from the array of tabs Youtube returns # Extract the selected tab from the array of tabs Youtube returns
return tabs.as_a.select(&.["tabRenderer"]?.try &.["selected"]?.try &.as_bool)[0]["tabRenderer"] tabs.as_a.select(&.["tabRenderer"]?.try &.["selected"]?.try &.as_bool)[0]["tabRenderer"]
end end

View File

@ -30,7 +30,7 @@ module UrlSanitizer
return false return false
end end
return true true
end end
# Return which kind of parameters are allowed based on the # Return which kind of parameters are allowed based on the
@ -38,13 +38,13 @@ module UrlSanitizer
private def determine_allowed(path_root : String) private def determine_allowed(path_root : String)
case path_root case path_root
when "watch", "w", "v", "embed", "e", "shorts", "clip" when "watch", "w", "v", "embed", "e", "shorts", "clip"
return :watch :watch
when .starts_with?("@"), "c", "channel", "user", "profile", "attribution_link" when .starts_with?("@"), "c", "channel", "user", "profile", "attribution_link"
return :channel :channel
when "playlist", "mix" when "playlist", "mix"
return :playlist :playlist
when "results", "search" when "results", "search"
return :search :search
else # hashtag, post, trending, brand URLs, etc.. else # hashtag, post, trending, brand URLs, etc..
return return
end end
@ -61,7 +61,7 @@ module UrlSanitizer
end end
end end
return new_params new_params
end end
# Transform any user-supplied youtube URL into something we can trust # Transform any user-supplied youtube URL into something we can trust
@ -116,6 +116,6 @@ module UrlSanitizer
new_uri.query_params = new_params new_uri.query_params = new_params
end end
return new_uri new_uri
end end
end end

View File

@ -267,7 +267,7 @@ module YoutubeAPI
# Convert to string, for logging purposes # Convert to string, for logging purposes
def to_s def to_s
return { {
client_type: name, client_type: name,
region: @region, region: @region,
}.to_s }.to_s
@ -331,7 +331,7 @@ module YoutubeAPI
client_context["client"]["platform"] = platform client_context["client"]["platform"] = platform
end end
return client_context client_context
end end
#################################################################### ####################################################################
@ -360,7 +360,7 @@ module YoutubeAPI
"continuation" => continuation, "continuation" => continuation,
} }
return _post_json("/youtubei/v1/browse", data, client_config) _post_json("/youtubei/v1/browse", data, client_config)
end end
# :ditto: # :ditto:
@ -382,7 +382,7 @@ module YoutubeAPI
data["params"] = params data["params"] = params
end end
return _post_json("/youtubei/v1/browse", data, client_config) _post_json("/youtubei/v1/browse", data, client_config)
end end
#################################################################### ####################################################################
@ -428,7 +428,7 @@ module YoutubeAPI
"continuation" => continuation, "continuation" => continuation,
} }
return _post_json("/youtubei/v1/next", data, client_config) _post_json("/youtubei/v1/next", data, client_config)
end end
# :ditto: # :ditto:
@ -438,12 +438,12 @@ module YoutubeAPI
"context" => make_context(client_config), "context" => make_context(client_config),
}) })
return _post_json("/youtubei/v1/next", data2, client_config) _post_json("/youtubei/v1/next", data2, client_config)
end end
# Allow a NamedTuple to be passed, too. # Allow a NamedTuple to be passed, too.
def next(data : NamedTuple, *, client_config : ClientConfig? = nil) def next(data : NamedTuple, *, client_config : ClientConfig? = nil)
return self.next(data.to_h, client_config: client_config) self.next(data.to_h, client_config: client_config)
end end
#################################################################### ####################################################################
@ -461,7 +461,7 @@ module YoutubeAPI
} }
if CONFIG.invidious_companion.present? if CONFIG.invidious_companion.present?
return _post_invidious_companion("/youtubei/v1/player", data) _post_invidious_companion("/youtubei/v1/player", data)
else else
return return
end end
@ -501,7 +501,7 @@ module YoutubeAPI
"url" => url, "url" => url,
} }
return _post_json("/youtubei/v1/navigation/resolve_url", data, client_config) _post_json("/youtubei/v1/navigation/resolve_url", data, client_config)
end end
#################################################################### ####################################################################
@ -530,7 +530,7 @@ module YoutubeAPI
"params" => params, "params" => params,
} }
return _post_json("/youtubei/v1/search", data, client_config) _post_json("/youtubei/v1/search", data, client_config)
end end
#################################################################### ####################################################################
@ -554,7 +554,7 @@ module YoutubeAPI
"params" => params, "params" => params,
} }
return _post_json("/youtubei/v1/get_transcript", data, client_config) _post_json("/youtubei/v1/get_transcript", data, client_config)
end end
#################################################################### ####################################################################
@ -623,7 +623,7 @@ module YoutubeAPI
error #{code} with message:<br>\"#{message}\"") error #{code} with message:<br>\"#{message}\"")
end end
return initial_data initial_data
end end
#################################################################### ####################################################################
@ -661,7 +661,7 @@ module YoutubeAPI
end end
end end
return response_body response_body
rescue ex rescue ex
raise InfoException.new("Error while communicating with Invidious companion: " + (ex.message || "no extra info found")) raise InfoException.new("Error while communicating with Invidious companion: " + (ex.message || "no extra info found"))
end end
@ -695,6 +695,6 @@ module YoutubeAPI
end end
end end
return body_io.gets_to_end body_io.gets_to_end
end end
end # End of module end # End of module