diff --git a/src/invidious/playlists.cr b/src/invidious/playlists.cr index 568f3e2e6..a4ef212fc 100644 --- a/src/invidious/playlists.cr +++ b/src/invidious/playlists.cr @@ -439,7 +439,8 @@ def get_playlist_videos(db, playlist, offset, locale = nil, continuation = nil) else videos = [] of PlaylistVideo - until videos.size >= 50 || videos.size == playlist.video_count || offset >= playlist.video_count + original_offset = offset + until videos.size >= 100 || videos.size == playlist.video_count || offset >= playlist.video_count if offset >= 100 # Normalize offset to match youtube's behavior (100 videos chunck per request) normalized_offset = (offset / 100).to_i64 * 100_i64 @@ -459,7 +460,7 @@ def get_playlist_videos(db, playlist, offset, locale = nil, continuation = nil) end end else - until videos[0].index == offset + until videos[0].index == original_offset videos.shift if videos.size == 0 break @@ -550,7 +551,7 @@ def template_playlist(playlist) playlist["videos"].as_a.each do |video| html += <<-END_HTML -
  • +
  • diff --git a/src/invidious/routes/api/v1/misc.cr b/src/invidious/routes/api/v1/misc.cr index cf95bd9ba..9aa75e09e 100644 --- a/src/invidious/routes/api/v1/misc.cr +++ b/src/invidious/routes/api/v1/misc.cr @@ -24,7 +24,7 @@ module Invidious::Routes::API::V1::Misc offset ||= env.params.query["page"]?.try &.to_i?.try { |page| (page - 1) * 100 } offset ||= 0 - continuation = env.params.query["continuation"]? + video_id = env.params.query["continuation"]? format = env.params.query["format"]? format ||= "json" @@ -46,12 +46,32 @@ module Invidious::Routes::API::V1::Misc return error_json(404, "Playlist does not exist.") end - response = playlist.to_json(offset, locale, continuation: continuation) + # includes into the playlist a maximum of 20 videos, before the offset + lookback = 20 + if offset > 0 + lookback = offset < lookback ? offset : lookback + 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 + + response = playlist.to_json(offset, locale, continuation: continuation) + 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" - response = JSON.parse(response) - playlist_html = template_playlist(response) - 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} + playlist_html = template_playlist(json_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} response = { "playlistHtml" => playlist_html,