mirror of
https://github.com/iv-org/invidious.git
synced 2025-08-13 08:08:31 +00:00
actual fix large playlists
This commit is contained in:
parent
3286328de4
commit
35219a34a7
@ -47,19 +47,19 @@ describe "Helper" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#produce_playlist_url" do
|
describe "#produce_playlist_continuation" do
|
||||||
it "correctly produces url for requesting index `x` of a playlist" do
|
it "correctly produces url for requesting index `x` of a playlist" do
|
||||||
produce_playlist_url("UUCla9fZca4I7KagBtgRGnOw", 0).should eq("/browse_ajax?continuation=4qmFsgIqEhpWTFVVQ2xhOWZaY2E0STdLYWdCdGdSR25PdxoMZWdaUVZEcERRVUU9&gl=US&hl=en")
|
produce_playlist_continuation("UUCla9fZca4I7KagBtgRGnOw", 0).should eq("4qmFsgIqEhpWTFVVQ2xhOWZaY2E0STdLYWdCdGdSR25PdxoMZWdaUVZEcERRVUU9")
|
||||||
|
|
||||||
produce_playlist_url("UCCla9fZca4I7KagBtgRGnOw", 0).should eq("/browse_ajax?continuation=4qmFsgIqEhpWTFVVQ2xhOWZaY2E0STdLYWdCdGdSR25PdxoMZWdaUVZEcERRVUU9&gl=US&hl=en")
|
produce_playlist_continuation("UCCla9fZca4I7KagBtgRGnOw", 0).should eq("4qmFsgIqEhpWTFVVQ2xhOWZaY2E0STdLYWdCdGdSR25PdxoMZWdaUVZEcERRVUU9")
|
||||||
|
|
||||||
produce_playlist_url("PLt5AfwLFPxWLNVixpe1w3fi6lE2OTq0ET", 0).should eq("/browse_ajax?continuation=4qmFsgI0EiRWTFBMdDVBZndMRlB4V0xOVml4cGUxdzNmaTZsRTJPVHEwRVQaDGVnWlFWRHBEUVVFPQ%3D%3D&gl=US&hl=en")
|
produce_playlist_continuation("PLt5AfwLFPxWLNVixpe1w3fi6lE2OTq0ET", 0).should eq("4qmFsgI0EiRWTFBMdDVBZndMRlB4V0xOVml4cGUxdzNmaTZsRTJPVHEwRVQaDGVnWlFWRHBEUVVFPQ%3D%3D")
|
||||||
|
|
||||||
produce_playlist_url("PLt5AfwLFPxWLNVixpe1w3fi6lE2OTq0ET", 10000).should eq("/browse_ajax?continuation=4qmFsgI0EiRWTFBMdDVBZndMRlB4V0xOVml4cGUxdzNmaTZsRTJPVHEwRVQaDGVnZFFWRHBEU2tKUA%3D%3D&gl=US&hl=en")
|
produce_playlist_continuation("PLt5AfwLFPxWLNVixpe1w3fi6lE2OTq0ET", 10000).should eq("4qmFsgI0EiRWTFBMdDVBZndMRlB4V0xOVml4cGUxdzNmaTZsRTJPVHEwRVQaDGVnZFFWRHBEU2tKUA%3D%3D")
|
||||||
|
|
||||||
produce_playlist_url("PL55713C70BA91BD6E", 0).should eq("/browse_ajax?continuation=4qmFsgIkEhRWTFBMNTU3MTNDNzBCQTkxQkQ2RRoMZWdaUVZEcERRVUU9&gl=US&hl=en")
|
produce_playlist_continuation("PL55713C70BA91BD6E", 0).should eq("4qmFsgIkEhRWTFBMNTU3MTNDNzBCQTkxQkQ2RRoMZWdaUVZEcERRVUU9")
|
||||||
|
|
||||||
produce_playlist_url("PL55713C70BA91BD6E", 10000).should eq("/browse_ajax?continuation=4qmFsgIkEhRWTFBMNTU3MTNDNzBCQTkxQkQ2RRoMZWdkUVZEcERTa0pQ&gl=US&hl=en")
|
produce_playlist_continuation("PL55713C70BA91BD6E", 10000).should eq("4qmFsgIkEhRWTFBMNTU3MTNDNzBCQTkxQkQ2RRoMZWdkUVZEcERTa0pQ")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -937,23 +937,27 @@ def get_about_info(ucid, locale)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fetch_youtubei(continuation)
|
||||||
|
data = {
|
||||||
|
"context": {
|
||||||
|
"client": {
|
||||||
|
"clientName": "WEB",
|
||||||
|
"clientVersion": "2.20201021.03.00",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"continuation": continuation,
|
||||||
|
}.to_json
|
||||||
|
return YT_POOL.client &.post(
|
||||||
|
"/youtubei/v1/browse?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8",
|
||||||
|
headers: HTTP::Headers{"content-type" => "application/json"},
|
||||||
|
body: data
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
def get_channel_videos_response(ucid, page = 1, auto_generated = nil, sort_by = "newest", youtubei_browse = true)
|
def get_channel_videos_response(ucid, page = 1, auto_generated = nil, sort_by = "newest", youtubei_browse = true)
|
||||||
if youtubei_browse
|
if youtubei_browse
|
||||||
continuation = produce_channel_videos_continuation(ucid, page, auto_generated: auto_generated, sort_by: sort_by, v2: true)
|
continuation = produce_channel_videos_continuation(ucid, page, auto_generated: auto_generated, sort_by: sort_by, v2: true)
|
||||||
data = {
|
return fetch_youtubei(continuation)
|
||||||
"context": {
|
|
||||||
"client": {
|
|
||||||
"clientName": "WEB",
|
|
||||||
"clientVersion": "2.20201021.03.00",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"continuation": continuation,
|
|
||||||
}.to_json
|
|
||||||
return YT_POOL.client &.post(
|
|
||||||
"/youtubei/v1/browse?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8",
|
|
||||||
headers: HTTP::Headers{"content-type" => "application/json"},
|
|
||||||
body: data
|
|
||||||
)
|
|
||||||
else
|
else
|
||||||
url = produce_channel_videos_url(ucid, page, auto_generated: auto_generated, sort_by: sort_by, v2: true)
|
url = produce_channel_videos_url(ucid, page, auto_generated: auto_generated, sort_by: sort_by, v2: true)
|
||||||
return YT_POOL.client &.get(url)
|
return YT_POOL.client &.get(url)
|
||||||
|
@ -307,7 +307,7 @@ def subscribe_playlist(db, user, playlist)
|
|||||||
return playlist
|
return playlist
|
||||||
end
|
end
|
||||||
|
|
||||||
def produce_playlist_url(id, index)
|
def produce_playlist_continuation(id, index)
|
||||||
if id.starts_with? "UC"
|
if id.starts_with? "UC"
|
||||||
id = "UU" + id.lchop("UC")
|
id = "UU" + id.lchop("UC")
|
||||||
end
|
end
|
||||||
@ -332,7 +332,7 @@ def produce_playlist_url(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 "/browse_ajax?continuation=#{continuation}&gl=US&hl=en"
|
return continuation
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_playlist(db, plid, locale, refresh = true, force_refresh = false)
|
def get_playlist(db, plid, locale, refresh = true, force_refresh = false)
|
||||||
@ -435,17 +435,12 @@ def get_playlist_videos(db, playlist, offset, locale = nil, continuation = nil)
|
|||||||
end
|
end
|
||||||
|
|
||||||
def fetch_playlist_videos(plid, video_count, offset = 0, locale = nil, continuation = nil)
|
def fetch_playlist_videos(plid, video_count, offset = 0, locale = nil, continuation = nil)
|
||||||
if continuation
|
if !continuation && video_count > 100
|
||||||
response = YT_POOL.client &.get("/watch?v=#{continuation}&list=#{plid}&gl=US&hl=en")
|
continuation = produce_playlist_continuation(plid, offset)
|
||||||
initial_data = extract_initial_data(response.body)
|
|
||||||
offset = initial_data["currentVideoEndpoint"]?.try &.["watchEndpoint"]?.try &.["index"]?.try &.as_i64 || offset
|
|
||||||
end
|
end
|
||||||
|
if continuation
|
||||||
if video_count > 100
|
response = fetch_youtubei(continuation)
|
||||||
url = produce_playlist_url(plid, offset)
|
initial_data = JSON.parse(response.body).as_h
|
||||||
|
|
||||||
response = YT_POOL.client &.get(url)
|
|
||||||
initial_data = JSON.parse(response.body).as_a.find(&.as_h.["response"]?).try &.as_h
|
|
||||||
elsif offset > 100
|
elsif offset > 100
|
||||||
return [] of PlaylistVideo
|
return [] of PlaylistVideo
|
||||||
else # Extract first page of videos
|
else # Extract first page of videos
|
||||||
@ -465,9 +460,9 @@ end
|
|||||||
|
|
||||||
def extract_playlist_videos(initial_data : Hash(String, JSON::Any))
|
def extract_playlist_videos(initial_data : Hash(String, JSON::Any))
|
||||||
videos = [] of PlaylistVideo
|
videos = [] of PlaylistVideo
|
||||||
|
(initial_data["contents"]?.try &.["twoColumnBrowseResultsRenderer"]["tabs"].as_a.select(&.["tabRenderer"]["selected"]?.try &.as_bool)[0]["tabRenderer"]["content"]?.try &.["sectionListRenderer"]["contents"][0]["itemSectionRenderer"]["contents"][0]["playlistVideoListRenderer"]["contents"].as_a ||
|
||||||
(initial_data["contents"]?.try &.["twoColumnBrowseResultsRenderer"]["tabs"].as_a.select(&.["tabRenderer"]["selected"]?.try &.as_bool)[0]["tabRenderer"]["content"]["sectionListRenderer"]["contents"][0]["itemSectionRenderer"]["contents"][0]["playlistVideoListRenderer"]["contents"].as_a ||
|
initial_data["response"]?.try &.["continuationContents"]["playlistVideoListContinuation"]["contents"].as_a ||
|
||||||
initial_data["response"]?.try &.["continuationContents"]["playlistVideoListContinuation"]["contents"].as_a).try &.each do |item|
|
initial_data["continuationContents"]["playlistVideoListContinuation"]["contents"].as_a).try &.each do |item|
|
||||||
if i = item["playlistVideoRenderer"]?
|
if i = item["playlistVideoRenderer"]?
|
||||||
video_id = i["navigationEndpoint"]["watchEndpoint"]["videoId"].as_s
|
video_id = i["navigationEndpoint"]["watchEndpoint"]["videoId"].as_s
|
||||||
plid = i["navigationEndpoint"]["watchEndpoint"]["playlistId"].as_s
|
plid = i["navigationEndpoint"]["watchEndpoint"]["playlistId"].as_s
|
||||||
|
Loading…
Reference in New Issue
Block a user