forked from midou/invidious
Merge pull request #2257 from diogorac/fix-only-second-vid
This commit is contained in:
commit
39c27f0c66
@ -149,6 +149,8 @@ function get_playlist(plid, retries) {
|
|||||||
if (xhr.readyState == 4) {
|
if (xhr.readyState == 4) {
|
||||||
if (xhr.status == 200) {
|
if (xhr.status == 200) {
|
||||||
playlist.innerHTML = xhr.response.playlistHtml;
|
playlist.innerHTML = xhr.response.playlistHtml;
|
||||||
|
var nextVideo = document.getElementById(xhr.response.nextVideo);
|
||||||
|
nextVideo.parentNode.parentNode.scrollTop = nextVideo.offsetTop;
|
||||||
|
|
||||||
if (xhr.response.nextVideo) {
|
if (xhr.response.nextVideo) {
|
||||||
player.on('ended', function () {
|
player.on('ended', function () {
|
||||||
|
@ -107,7 +107,7 @@ struct Playlist
|
|||||||
property updated : Time
|
property updated : Time
|
||||||
property thumbnail : String?
|
property thumbnail : String?
|
||||||
|
|
||||||
def to_json(offset, locale, json : JSON::Builder, continuation : String? = nil)
|
def to_json(offset, locale, json : JSON::Builder, video_id : String? = nil)
|
||||||
json.object do
|
json.object do
|
||||||
json.field "type", "playlist"
|
json.field "type", "playlist"
|
||||||
json.field "title", self.title
|
json.field "title", self.title
|
||||||
@ -142,7 +142,7 @@ struct Playlist
|
|||||||
|
|
||||||
json.field "videos" do
|
json.field "videos" do
|
||||||
json.array do
|
json.array do
|
||||||
videos = get_playlist_videos(PG_DB, self, offset: offset, locale: locale, continuation: continuation)
|
videos = get_playlist_videos(PG_DB, self, offset: offset, locale: locale, video_id: video_id)
|
||||||
videos.each_with_index do |video, index|
|
videos.each_with_index do |video, index|
|
||||||
video.to_json(locale, json)
|
video.to_json(locale, json)
|
||||||
end
|
end
|
||||||
@ -151,12 +151,12 @@ struct Playlist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_json(offset, locale, json : JSON::Builder? = nil, continuation : String? = nil)
|
def to_json(offset, locale, json : JSON::Builder? = nil, video_id : String? = nil)
|
||||||
if json
|
if json
|
||||||
to_json(offset, locale, json, continuation: continuation)
|
to_json(offset, locale, json, video_id: video_id)
|
||||||
else
|
else
|
||||||
JSON.build do |json|
|
JSON.build do |json|
|
||||||
to_json(offset, locale, json, continuation: continuation)
|
to_json(offset, locale, json, video_id: video_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -196,7 +196,7 @@ struct InvidiousPlaylist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_json(offset, locale, json : JSON::Builder, continuation : String? = nil)
|
def to_json(offset, locale, json : JSON::Builder, video_id : String? = nil)
|
||||||
json.object do
|
json.object do
|
||||||
json.field "type", "invidiousPlaylist"
|
json.field "type", "invidiousPlaylist"
|
||||||
json.field "title", self.title
|
json.field "title", self.title
|
||||||
@ -218,11 +218,11 @@ struct InvidiousPlaylist
|
|||||||
json.field "videos" do
|
json.field "videos" do
|
||||||
json.array do
|
json.array do
|
||||||
if !offset || offset == 0
|
if !offset || offset == 0
|
||||||
index = PG_DB.query_one?("SELECT index FROM playlist_videos WHERE plid = $1 AND id = $2 LIMIT 1", self.id, continuation, as: Int64)
|
index = PG_DB.query_one?("SELECT index FROM playlist_videos WHERE plid = $1 AND id = $2 LIMIT 1", self.id, video_id, as: Int64)
|
||||||
offset = self.index.index(index) || 0
|
offset = self.index.index(index) || 0
|
||||||
end
|
end
|
||||||
|
|
||||||
videos = get_playlist_videos(PG_DB, self, offset: offset, locale: locale, continuation: continuation)
|
videos = get_playlist_videos(PG_DB, self, offset: offset, locale: locale, video_id: video_id)
|
||||||
videos.each_with_index do |video, index|
|
videos.each_with_index do |video, index|
|
||||||
video.to_json(locale, json, offset + index)
|
video.to_json(locale, json, offset + index)
|
||||||
end
|
end
|
||||||
@ -231,12 +231,12 @@ struct InvidiousPlaylist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_json(offset, locale, json : JSON::Builder? = nil, continuation : String? = nil)
|
def to_json(offset, locale, json : JSON::Builder? = nil, video_id : String? = nil)
|
||||||
if json
|
if json
|
||||||
to_json(offset, locale, json, continuation: continuation)
|
to_json(offset, locale, json, video_id: video_id)
|
||||||
else
|
else
|
||||||
JSON.build do |json|
|
JSON.build do |json|
|
||||||
to_json(offset, locale, json, continuation: continuation)
|
to_json(offset, locale, json, video_id: video_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -426,7 +426,7 @@ def fetch_playlist(plid, locale)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_playlist_videos(db, playlist, offset, locale = nil, continuation = nil)
|
def get_playlist_videos(db, playlist, offset, locale = nil, video_id = nil)
|
||||||
# Show empy playlist if requested page is out of range
|
# Show empy playlist if requested page is out of range
|
||||||
# (e.g, when a new playlist has been created, offset will be negative)
|
# (e.g, when a new playlist has been created, offset will be negative)
|
||||||
if offset >= playlist.video_count || offset < 0
|
if offset >= playlist.video_count || offset < 0
|
||||||
@ -437,17 +437,26 @@ def get_playlist_videos(db, playlist, offset, locale = nil, continuation = nil)
|
|||||||
db.query_all("SELECT * FROM playlist_videos WHERE plid = $1 ORDER BY array_position($2, index) LIMIT 100 OFFSET $3",
|
db.query_all("SELECT * FROM playlist_videos WHERE plid = $1 ORDER BY array_position($2, index) LIMIT 100 OFFSET $3",
|
||||||
playlist.id, playlist.index, offset, as: PlaylistVideo)
|
playlist.id, playlist.index, offset, as: PlaylistVideo)
|
||||||
else
|
else
|
||||||
if offset >= 100
|
if video_id
|
||||||
# Normalize offset to match youtube's behavior (100 videos chunck per request)
|
initial_data = YoutubeAPI.next({
|
||||||
offset = (offset / 100).to_i64 * 100_i64
|
"videoId" => video_id,
|
||||||
|
"playlistId" => playlist.id,
|
||||||
ctoken = produce_playlist_continuation(playlist.id, offset)
|
})
|
||||||
initial_data = YoutubeAPI.browse(ctoken)
|
offset = initial_data.dig?("contents", "twoColumnWatchNextResults", "playlist", "playlist", "currentIndex").try &.as_i || offset
|
||||||
else
|
|
||||||
initial_data = YoutubeAPI.browse("VL" + playlist.id, params: "")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return extract_playlist_videos(initial_data)
|
videos = [] of PlaylistVideo
|
||||||
|
|
||||||
|
until videos.size >= 200 || videos.size == playlist.video_count || offset >= playlist.video_count
|
||||||
|
# 100 videos per request
|
||||||
|
ctoken = produce_playlist_continuation(playlist.id, offset)
|
||||||
|
initial_data = YoutubeAPI.browse(ctoken)
|
||||||
|
videos += extract_playlist_videos(initial_data)
|
||||||
|
|
||||||
|
offset += 100
|
||||||
|
end
|
||||||
|
|
||||||
|
return videos
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -523,8 +532,8 @@ def template_playlist(playlist)
|
|||||||
|
|
||||||
playlist["videos"].as_a.each do |video|
|
playlist["videos"].as_a.each do |video|
|
||||||
html += <<-END_HTML
|
html += <<-END_HTML
|
||||||
<li class="pure-menu-item">
|
<li class="pure-menu-item" id="#{video["videoId"]}">
|
||||||
<a href="/watch?v=#{video["videoId"]}&list=#{playlist["playlistId"]}">
|
<a href="/watch?v=#{video["videoId"]}&list=#{playlist["playlistId"]}&index=#{video["index"]}">
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
<img class="thumbnail" src="/vi/#{video["videoId"]}/mqdefault.jpg">
|
<img class="thumbnail" src="/vi/#{video["videoId"]}/mqdefault.jpg">
|
||||||
<p class="length">#{recode_length_seconds(video["lengthSeconds"].as_i)}</p>
|
<p class="length">#{recode_length_seconds(video["lengthSeconds"].as_i)}</p>
|
||||||
|
@ -24,7 +24,7 @@ module Invidious::Routes::API::V1::Misc
|
|||||||
offset ||= env.params.query["page"]?.try &.to_i?.try { |page| (page - 1) * 100 }
|
offset ||= env.params.query["page"]?.try &.to_i?.try { |page| (page - 1) * 100 }
|
||||||
offset ||= 0
|
offset ||= 0
|
||||||
|
|
||||||
continuation = env.params.query["continuation"]?
|
video_id = env.params.query["continuation"]?
|
||||||
|
|
||||||
format = env.params.query["format"]?
|
format = env.params.query["format"]?
|
||||||
format ||= "json"
|
format ||= "json"
|
||||||
@ -46,12 +46,32 @@ module Invidious::Routes::API::V1::Misc
|
|||||||
return error_json(404, "Playlist does not exist.")
|
return error_json(404, "Playlist does not exist.")
|
||||||
end
|
end
|
||||||
|
|
||||||
response = playlist.to_json(offset, locale, continuation: continuation)
|
# includes into the playlist a maximum of 20 videos, before the offset
|
||||||
|
if offset > 0
|
||||||
|
lookback = offset < 50 ? offset : 50
|
||||||
|
response = playlist.to_json(offset - lookback, locale)
|
||||||
|
json_response = JSON.parse(response)
|
||||||
|
else
|
||||||
|
# Unless the continuation is really the offset 0, it becomes expensive.
|
||||||
|
# It happens when the offset is not set.
|
||||||
|
# First we find the actual offset, and then we lookback
|
||||||
|
# it shouldn't happen often though
|
||||||
|
|
||||||
|
lookback = 0
|
||||||
|
response = playlist.to_json(offset, locale, video_id: video_id)
|
||||||
|
json_response = JSON.parse(response)
|
||||||
|
|
||||||
|
if json_response["videos"].as_a[0]["index"] != offset
|
||||||
|
offset = json_response["videos"].as_a[0]["index"].as_i
|
||||||
|
lookback = offset < 50 ? offset : 50
|
||||||
|
response = playlist.to_json(offset - lookback, locale)
|
||||||
|
json_response = JSON.parse(response)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if format == "html"
|
if format == "html"
|
||||||
response = JSON.parse(response)
|
playlist_html = template_playlist(json_response)
|
||||||
playlist_html = template_playlist(response)
|
index, next_video = json_response["videos"].as_a.skip(1 + lookback).select { |video| !video["author"].as_s.empty? }[0]?.try { |v| {v["index"], v["videoId"]} } || {nil, nil}
|
||||||
index, next_video = response["videos"].as_a.skip(1).select { |video| !video["author"].as_s.empty? }[0]?.try { |v| {v["index"], v["videoId"]} } || {nil, nil}
|
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
"playlistHtml" => playlist_html,
|
"playlistHtml" => playlist_html,
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
<p dir="auto"><b><%= HTML.escape(item.author) %></b></p>
|
<p dir="auto"><b><%= HTML.escape(item.author) %></b></p>
|
||||||
</a>
|
</a>
|
||||||
<% when PlaylistVideo %>
|
<% when PlaylistVideo %>
|
||||||
<a style="width:100%" href="/watch?v=<%= item.id %>&list=<%= item.plid %>">
|
<a style="width:100%" href="/watch?v=<%= item.id %>&list=<%= item.plid %>&index=<%= item.index %>">
|
||||||
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
<img class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/>
|
<img class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/>
|
||||||
|
Loading…
Reference in New Issue
Block a user