2021-10-02 20:04:02 +00:00
|
|
|
{% skip_file if flag?(:api_only) %}
|
|
|
|
|
2021-08-11 03:36:25 -07:00
|
|
|
module Invidious::Routes::Embed
|
|
|
|
def self.redirect(env)
|
2022-08-06 13:14:35 +02:00
|
|
|
locale = env.get("preferences").as(Preferences).locale
|
2021-02-02 06:18:16 +01:00
|
|
|
if plid = env.params.query["list"]?.try &.gsub(/[^a-zA-Z0-9_-]/, "")
|
|
|
|
begin
|
2022-01-19 18:34:35 +01:00
|
|
|
playlist = get_playlist(plid)
|
2021-02-02 06:18:16 +01:00
|
|
|
offset = env.params.query["index"]?.try &.to_i? || 0
|
2022-01-19 18:34:35 +01:00
|
|
|
videos = get_playlist_videos(playlist, offset: offset)
|
2022-08-06 13:14:35 +02:00
|
|
|
if videos.empty?
|
|
|
|
url = "/playlist?list=#{plid}"
|
2022-09-02 20:20:43 +02:00
|
|
|
raise NotFoundException.new(translate(locale, "error_video_not_in_playlist", url))
|
2022-08-06 13:14:35 +02:00
|
|
|
end
|
2022-05-27 13:36:13 +00:00
|
|
|
rescue ex : NotFoundException
|
|
|
|
return error_template(404, ex)
|
2021-02-02 06:18:16 +01:00
|
|
|
rescue ex
|
|
|
|
return error_template(500, ex)
|
|
|
|
end
|
|
|
|
|
|
|
|
url = "/embed/#{videos[0].id}?#{env.params.query}"
|
|
|
|
|
|
|
|
if env.params.query.size > 0
|
|
|
|
url += "?#{env.params.query}"
|
|
|
|
end
|
|
|
|
else
|
|
|
|
url = "/"
|
|
|
|
end
|
|
|
|
|
|
|
|
env.redirect url
|
|
|
|
end
|
|
|
|
|
2021-08-11 03:36:25 -07:00
|
|
|
def self.show(env)
|
2022-08-06 13:14:35 +02:00
|
|
|
locale = env.get("preferences").as(Preferences).locale
|
2020-11-06 16:44:36 -06:00
|
|
|
id = env.params.url["id"]
|
|
|
|
|
|
|
|
plid = env.params.query["list"]?.try &.gsub(/[^a-zA-Z0-9_-]/, "")
|
2021-12-07 02:55:43 +01:00
|
|
|
continuation = process_continuation(env.params.query, plid, id)
|
2020-11-06 16:44:36 -06:00
|
|
|
|
|
|
|
if md = env.params.query["playlist"]?
|
2020-11-07 08:22:44 -06:00
|
|
|
.try &.match(/[a-zA-Z0-9_-]{11}(,[a-zA-Z0-9_-]{11})*/)
|
2020-11-06 16:44:36 -06:00
|
|
|
video_series = md[0].split(",")
|
|
|
|
env.params.query.delete("playlist")
|
|
|
|
end
|
|
|
|
|
|
|
|
preferences = env.get("preferences").as(Preferences)
|
|
|
|
|
|
|
|
if id.includes?("%20") || id.includes?("+") || env.params.query.to_s.includes?("%20") || env.params.query.to_s.includes?("+")
|
|
|
|
id = env.params.url["id"].gsub("%20", "").delete("+")
|
|
|
|
|
|
|
|
url = "/embed/#{id}"
|
|
|
|
|
|
|
|
if env.params.query.size > 0
|
|
|
|
url += "?#{env.params.query.to_s.gsub("%20", "").delete("+")}"
|
|
|
|
end
|
|
|
|
|
|
|
|
return env.redirect url
|
|
|
|
end
|
|
|
|
|
|
|
|
# YouTube embed supports `videoseries` with either `list=PLID`
|
|
|
|
# or `playlist=VIDEO_ID,VIDEO_ID`
|
|
|
|
case id
|
|
|
|
when "videoseries"
|
|
|
|
url = ""
|
|
|
|
|
|
|
|
if plid
|
|
|
|
begin
|
2022-01-19 18:34:35 +01:00
|
|
|
playlist = get_playlist(plid)
|
2020-11-06 16:44:36 -06:00
|
|
|
offset = env.params.query["index"]?.try &.to_i? || 0
|
2022-01-19 18:34:35 +01:00
|
|
|
videos = get_playlist_videos(playlist, offset: offset)
|
2022-08-06 13:14:35 +02:00
|
|
|
if videos.empty?
|
|
|
|
url = "/playlist?list=#{plid}"
|
2022-09-02 20:20:43 +02:00
|
|
|
raise NotFoundException.new(translate(locale, "error_video_not_in_playlist", url))
|
2022-08-06 13:14:35 +02:00
|
|
|
end
|
2022-05-27 13:36:13 +00:00
|
|
|
rescue ex : NotFoundException
|
|
|
|
return error_template(404, ex)
|
2020-11-06 16:44:36 -06:00
|
|
|
rescue ex
|
2020-11-30 10:59:21 +01:00
|
|
|
return error_template(500, ex)
|
2020-11-06 16:44:36 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
url = "/embed/#{videos[0].id}"
|
|
|
|
elsif video_series
|
|
|
|
url = "/embed/#{video_series.shift}"
|
|
|
|
env.params.query["playlist"] = video_series.join(",")
|
|
|
|
else
|
|
|
|
return env.redirect "/"
|
|
|
|
end
|
|
|
|
|
|
|
|
if env.params.query.size > 0
|
|
|
|
url += "?#{env.params.query}"
|
|
|
|
end
|
|
|
|
|
|
|
|
return env.redirect url
|
|
|
|
when "live_stream"
|
|
|
|
response = YT_POOL.client &.get("/embed/live_stream?channel=#{env.params.query["channel"]? || ""}")
|
|
|
|
video_id = response.body.match(/"video_id":"(?<video_id>[a-zA-Z0-9_-]{11})"/).try &.["video_id"]
|
|
|
|
|
|
|
|
env.params.query.delete_all("channel")
|
|
|
|
|
|
|
|
if !video_id || video_id == "live_stream"
|
2020-11-30 10:59:21 +01:00
|
|
|
return error_template(500, "Video is unavailable.")
|
2020-11-06 16:44:36 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
url = "/embed/#{video_id}"
|
|
|
|
|
|
|
|
if env.params.query.size > 0
|
|
|
|
url += "?#{env.params.query}"
|
|
|
|
end
|
|
|
|
|
|
|
|
return env.redirect url
|
|
|
|
when id.size > 11
|
|
|
|
url = "/embed/#{id[0, 11]}"
|
|
|
|
|
|
|
|
if env.params.query.size > 0
|
|
|
|
url += "?#{env.params.query}"
|
|
|
|
end
|
|
|
|
|
|
|
|
return env.redirect url
|
|
|
|
else nil # Continue
|
|
|
|
end
|
|
|
|
|
|
|
|
params = process_video_params(env.params.query, preferences)
|
|
|
|
|
|
|
|
user = env.get?("user").try &.as(User)
|
|
|
|
if user
|
|
|
|
subscriptions = user.subscriptions
|
|
|
|
watched = user.watched
|
|
|
|
notifications = user.notifications
|
|
|
|
end
|
|
|
|
subscriptions ||= [] of String
|
|
|
|
|
|
|
|
begin
|
2021-12-07 02:55:43 +01:00
|
|
|
video = get_video(id, region: params.region)
|
2022-05-27 13:36:13 +00:00
|
|
|
rescue ex : NotFoundException
|
|
|
|
return error_template(404, ex)
|
2020-11-06 16:44:36 -06:00
|
|
|
rescue ex
|
2020-11-30 10:59:21 +01:00
|
|
|
return error_template(500, ex)
|
2020-11-06 16:44:36 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
if preferences.annotations_subscribed &&
|
2020-11-07 08:22:44 -06:00
|
|
|
subscriptions.includes?(video.ucid) &&
|
|
|
|
(env.params.query["iv_load_policy"]? || "1") == "1"
|
2020-11-06 16:44:36 -06:00
|
|
|
params.annotations = true
|
|
|
|
end
|
|
|
|
|
|
|
|
# if watched && !watched.includes? id
|
|
|
|
# PG_DB.exec("UPDATE users SET watched = array_append(watched, $1) WHERE email = $2", id, user.as(User).email)
|
|
|
|
# end
|
|
|
|
|
2023-01-05 23:08:05 +00:00
|
|
|
if CONFIG.enable_user_notifications && notifications && notifications.includes? id
|
2021-12-03 03:29:52 +01:00
|
|
|
Invidious::Database::Users.remove_notification(user.as(User), id)
|
2020-11-06 16:44:36 -06:00
|
|
|
env.get("user").as(User).notifications.delete(id)
|
|
|
|
notifications.delete(id)
|
|
|
|
end
|
|
|
|
|
|
|
|
fmt_stream = video.fmt_stream
|
|
|
|
adaptive_fmts = video.adaptive_fmts
|
|
|
|
|
|
|
|
if params.local
|
2021-01-31 19:52:32 +01:00
|
|
|
fmt_stream.each { |fmt| fmt["url"] = JSON::Any.new(URI.parse(fmt["url"].as_s).request_target) }
|
|
|
|
adaptive_fmts.each { |fmt| fmt["url"] = JSON::Any.new(URI.parse(fmt["url"].as_s).request_target) }
|
2020-11-06 16:44:36 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
video_streams = video.video_streams
|
|
|
|
audio_streams = video.audio_streams
|
|
|
|
|
|
|
|
if audio_streams.empty? && !video.live_now
|
|
|
|
if params.quality == "dash"
|
|
|
|
env.params.query.delete_all("quality")
|
|
|
|
return env.redirect "/embed/#{id}?#{env.params.query}"
|
|
|
|
elsif params.listen
|
|
|
|
env.params.query.delete_all("listen")
|
|
|
|
env.params.query["listen"] = "0"
|
|
|
|
return env.redirect "/embed/#{id}?#{env.params.query}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
captions = video.captions
|
|
|
|
|
|
|
|
preferred_captions = captions.select { |caption|
|
2021-06-27 07:18:16 -07:00
|
|
|
params.preferred_captions.includes?(caption.name) ||
|
2021-09-24 19:15:23 -07:00
|
|
|
params.preferred_captions.includes?(caption.language_code.split("-")[0])
|
2020-11-06 16:44:36 -06:00
|
|
|
}
|
|
|
|
preferred_captions.sort_by! { |caption|
|
2021-06-27 07:18:16 -07:00
|
|
|
(params.preferred_captions.index(caption.name) ||
|
2021-09-24 19:15:23 -07:00
|
|
|
params.preferred_captions.index(caption.language_code.split("-")[0])).not_nil!
|
2020-11-06 16:44:36 -06:00
|
|
|
}
|
|
|
|
captions = captions - preferred_captions
|
|
|
|
|
|
|
|
aspect_ratio = nil
|
|
|
|
|
|
|
|
thumbnail = "/vi/#{video.id}/maxres.jpg"
|
|
|
|
|
|
|
|
if params.raw
|
|
|
|
url = fmt_stream[0]["url"].as_s
|
|
|
|
|
|
|
|
fmt_stream.each do |fmt|
|
|
|
|
url = fmt["url"].as_s if fmt["quality"].as_s == params.quality
|
|
|
|
end
|
|
|
|
|
|
|
|
return env.redirect url
|
|
|
|
end
|
|
|
|
|
|
|
|
rendered "embed"
|
|
|
|
end
|
|
|
|
end
|