summaryrefslogtreecommitdiffstats
path: root/src/invidious.cr
diff options
context:
space:
mode:
Diffstat (limited to 'src/invidious.cr')
-rw-r--r--src/invidious.cr98
1 files changed, 55 insertions, 43 deletions
diff --git a/src/invidious.cr b/src/invidious.cr
index 1b8be67e..deb24ac3 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -106,34 +106,30 @@ LOCALES = {
YT_POOL = QUICPool.new(YT_URL, capacity: CONFIG.pool_size, timeout: 2.0)
-config = CONFIG
-output = STDOUT
-loglvl = LogLevel::Debug
-
+# CLI
Kemal.config.extra_options do |parser|
parser.banner = "Usage: invidious [arguments]"
- parser.on("-c THREADS", "--channel-threads=THREADS", "Number of threads for refreshing channels (default: #{config.channel_threads})") do |number|
+ parser.on("-c THREADS", "--channel-threads=THREADS", "Number of threads for refreshing channels (default: #{CONFIG.channel_threads})") do |number|
begin
- config.channel_threads = number.to_i
+ CONFIG.channel_threads = number.to_i
rescue ex
puts "THREADS must be integer"
exit
end
end
- parser.on("-f THREADS", "--feed-threads=THREADS", "Number of threads for refreshing feeds (default: #{config.feed_threads})") do |number|
+ parser.on("-f THREADS", "--feed-threads=THREADS", "Number of threads for refreshing feeds (default: #{CONFIG.feed_threads})") do |number|
begin
- config.feed_threads = number.to_i
+ CONFIG.feed_threads = number.to_i
rescue ex
puts "THREADS must be integer"
exit
end
end
- parser.on("-o OUTPUT", "--output=OUTPUT", "Redirect output (default: STDOUT)") do |output_arg|
- FileUtils.mkdir_p(File.dirname(output_arg))
- output = File.open(output_arg, mode: "a")
+ parser.on("-o OUTPUT", "--output=OUTPUT", "Redirect output (default: #{CONFIG.output})") do |output|
+ CONFIG.output = output
end
- parser.on("-l LEVEL", "--log-level=LEVEL", "Log level, one of #{LogLevel.values} (default: #{loglvl})") do |loglvl_arg|
- loglvl = LogLevel.parse(loglvl_arg)
+ parser.on("-l LEVEL", "--log-level=LEVEL", "Log level, one of #{LogLevel.values} (default: #{CONFIG.log_level})") do |log_level|
+ CONFIG.log_level = LogLevel.parse(log_level)
end
parser.on("-v", "--version", "Print version") do
puts SOFTWARE.to_pretty_json
@@ -143,43 +139,56 @@ end
Kemal::CLI.new ARGV
-logger = Invidious::LogHandler.new(output, loglvl)
+if CONFIG.output.upcase != "STDOUT"
+ FileUtils.mkdir_p(File.dirname(CONFIG.output))
+end
+OUTPUT = CONFIG.output.upcase == "STDOUT" ? STDOUT : File.open(CONFIG.output, mode: "a")
+LOGGER = Invidious::LogHandler.new(OUTPUT, CONFIG.log_level)
+
+config = CONFIG
# Check table integrity
if CONFIG.check_tables
- check_enum(PG_DB, logger, "privacy", PlaylistPrivacy)
+ check_enum(PG_DB, "privacy", PlaylistPrivacy)
- check_table(PG_DB, logger, "channels", InvidiousChannel)
- check_table(PG_DB, logger, "channel_videos", ChannelVideo)
- check_table(PG_DB, logger, "playlists", InvidiousPlaylist)
- check_table(PG_DB, logger, "playlist_videos", PlaylistVideo)
- check_table(PG_DB, logger, "nonces", Nonce)
- check_table(PG_DB, logger, "session_ids", SessionId)
- check_table(PG_DB, logger, "users", User)
- check_table(PG_DB, logger, "videos", Video)
+ check_table(PG_DB, "channels", InvidiousChannel)
+ check_table(PG_DB, "channel_videos", ChannelVideo)
+ check_table(PG_DB, "playlists", InvidiousPlaylist)
+ check_table(PG_DB, "playlist_videos", PlaylistVideo)
+ check_table(PG_DB, "nonces", Nonce)
+ check_table(PG_DB, "session_ids", SessionId)
+ check_table(PG_DB, "users", User)
+ check_table(PG_DB, "videos", Video)
if CONFIG.cache_annotations
- check_table(PG_DB, logger, "annotations", Annotation)
+ check_table(PG_DB, "annotations", Annotation)
end
end
# Start jobs
-Invidious::Jobs.register Invidious::Jobs::RefreshChannelsJob.new(PG_DB, logger, config)
-Invidious::Jobs.register Invidious::Jobs::RefreshFeedsJob.new(PG_DB, logger, config)
-Invidious::Jobs.register Invidious::Jobs::SubscribeToFeedsJob.new(PG_DB, logger, config, HMAC_KEY)
-Invidious::Jobs.register Invidious::Jobs::UpdateDecryptFunctionJob.new
+Invidious::Jobs.register Invidious::Jobs::RefreshChannelsJob.new(PG_DB, config)
+Invidious::Jobs.register Invidious::Jobs::RefreshFeedsJob.new(PG_DB, config)
+
+DECRYPT_FUNCTION = DecryptFunction.new(CONFIG.decrypt_polling)
+if config.decrypt_polling
+ Invidious::Jobs.register Invidious::Jobs::UpdateDecryptFunctionJob.new
+end
if config.statistics_enabled
Invidious::Jobs.register Invidious::Jobs::StatisticsRefreshJob.new(PG_DB, config, SOFTWARE)
end
+if (config.use_pubsub_feeds.is_a?(Bool) && config.use_pubsub_feeds.as(Bool)) || (config.use_pubsub_feeds.is_a?(Int32) && config.use_pubsub_feeds.as(Int32) > 0)
+ Invidious::Jobs.register Invidious::Jobs::SubscribeToFeedsJob.new(PG_DB, config, HMAC_KEY)
+end
+
if config.popular_enabled
Invidious::Jobs.register Invidious::Jobs::PullPopularVideosJob.new(PG_DB)
end
if config.captcha_key
- Invidious::Jobs.register Invidious::Jobs::BypassCaptchaJob.new(logger, config)
+ Invidious::Jobs.register Invidious::Jobs::BypassCaptchaJob.new(config)
end
connection_channel = Channel({Bool, Channel(PQ::Notification)}).new(32)
@@ -191,8 +200,6 @@ def popular_videos
Invidious::Jobs::PullPopularVideosJob::POPULAR_VIDEOS.get
end
-DECRYPT_FUNCTION = Invidious::Jobs::UpdateDecryptFunctionJob::DECRYPT_FUNCTION
-
before_all do |env|
preferences = begin
Preferences.from_json(env.request.cookies["PREFS"]?.try &.value || "{}")
@@ -1511,7 +1518,7 @@ post "/feed/webhook/:token" do |env|
signature = env.request.headers["X-Hub-Signature"].lchop("sha1=")
if signature != OpenSSL::HMAC.hexdigest(:sha1, HMAC_KEY, body)
- logger.error("/feed/webhook/#{token} : Invalid signature")
+ LOGGER.error("/feed/webhook/#{token} : Invalid signature")
env.response.status_code = 200
next
end
@@ -2133,14 +2140,13 @@ get "/api/v1/annotations/:id" do |env|
file = URI.encode_www_form("#{id[0, 3]}/#{id}.xml")
- client = make_client(ARCHIVE_URL)
- location = client.get("/download/youtubeannotations_#{index}/#{id[0, 2]}.tar/#{file}")
+ location = make_client(ARCHIVE_URL, &.get("/download/youtubeannotations_#{index}/#{id[0, 2]}.tar/#{file}"))
if !location.headers["Location"]?
env.response.status_code = location.status_code
end
- response = make_client(URI.parse(location.headers["Location"])).get(location.headers["Location"])
+ response = make_client(URI.parse(location.headers["Location"]), &.get(location.headers["Location"]))
if response.body.empty?
env.response.status_code = 404
@@ -2622,6 +2628,8 @@ end
begin
playlist = get_playlist(PG_DB, plid, locale)
+ rescue ex : InfoException
+ next error_json(404, ex)
rescue ex
next error_json(404, "Playlist does not exist.")
end
@@ -3182,7 +3190,8 @@ get "/api/manifest/dash/id/:id" do |env|
url = url.rchop("</BaseURL>")
if local
- url = URI.parse(url).full_path
+ uri = URI.parse(url)
+ url = "#{uri.full_path}host/#{uri.host}/"
end
"<BaseURL>#{url}</BaseURL>"
@@ -3364,7 +3373,7 @@ get "/latest_version" do |env|
env.redirect "/api/v1/captions/#{id}?label=#{label}&title=#{title}"
next
else
- itag = download_widget["itag"].as_s
+ itag = download_widget["itag"].as_s.to_i
local = "true"
end
end
@@ -3498,8 +3507,12 @@ get "/videoplayback" do |env|
location = URI.parse(response.headers["Location"])
env.response.headers["Access-Control-Allow-Origin"] = "*"
- host = "#{location.scheme}://#{location.host}"
- client = make_client(URI.parse(host), region)
+ new_host = "#{location.scheme}://#{location.host}"
+ if new_host != host
+ host = new_host
+ client.close
+ client = make_client(URI.parse(new_host), region)
+ end
url = "#{location.full_path}&host=#{location.host}#{region ? "&region=#{region}" : ""}"
else
@@ -3530,7 +3543,6 @@ get "/videoplayback" do |env|
end
begin
- client = make_client(URI.parse(host), region)
client.get(url, headers) do |response|
response.headers.each do |key, value|
if !RESPONSE_HEADERS_BLACKLIST.includes?(key.downcase)
@@ -3571,8 +3583,6 @@ get "/videoplayback" do |env|
chunk_end = chunk_start + HTTP_CHUNK_SIZE - 1
end
- client = make_client(URI.parse(host), region)
-
# TODO: Record bytes written so we can restart after a chunk fails
while true
if !range_end && content_length
@@ -3636,6 +3646,7 @@ get "/videoplayback" do |env|
if ex.message != "Error reading socket: Connection reset by peer"
break
else
+ client.close
client = make_client(URI.parse(host), region)
end
end
@@ -3645,6 +3656,7 @@ get "/videoplayback" do |env|
first_chunk = false
end
end
+ client.close
end
get "/ggpht/*" do |env|
@@ -3919,7 +3931,7 @@ add_context_storage_type(Array(String))
add_context_storage_type(Preferences)
add_context_storage_type(User)
-Kemal.config.logger = logger
+Kemal.config.logger = LOGGER
Kemal.config.host_binding = Kemal.config.host_binding != "0.0.0.0" ? Kemal.config.host_binding : CONFIG.host_binding
Kemal.config.port = Kemal.config.port != 3000 ? Kemal.config.port : CONFIG.port
Kemal.run