From 344ccf3b03f640fa65504d45a1fa8df87e1c744c Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Tue, 13 Apr 2021 19:33:37 +0200 Subject: [PATCH] Use '/youtubei/v1/browse' endpoint for playlists --- src/invidious/helpers/youtube_api.cr | 36 ++++++++++++++++++++++++---- src/invidious/playlists.cr | 20 +++------------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/invidious/helpers/youtube_api.cr b/src/invidious/helpers/youtube_api.cr index dc3a7eb5..1b8f6dae 100644 --- a/src/invidious/helpers/youtube_api.cr +++ b/src/invidious/helpers/youtube_api.cr @@ -8,15 +8,20 @@ HARDCODED_CLIENT_VERS = "2.20210330.08.00" #################################################################### # request_youtube_api_browse(continuation) +# request_youtube_api_browse(browse_id, params) # # Requests the youtubei/vi/browse endpoint with the required headers # to get JSON in en-US (english US). # -# The requested data is a continuation token (ctoken). Depending on -# this token's contents, the returned data can be comments, playlist -# videos, search results, channel community tab, ... +# The requested data can either be: # -def request_youtube_api_browse(continuation) +# - A continuation token (ctoken). Depending on this token's +# contents, the returned data can be comments, playlist videos, +# search results, channel community tab, ... +# +# - A playlist ID (parameters MUST be an empty string) +# +def request_youtube_api_browse(continuation : String) # JSON Request data, required by the API data = { "context": { @@ -33,6 +38,29 @@ def request_youtube_api_browse(continuation) return _youtube_api_post_json("/youtubei/v1/browse", data) end +def request_youtube_api_browse(browse_id : String, params : String) + # JSON Request data, required by the API + data = { + "browseId" => browse_id, + "context" => { + "client" => { + "hl" => "en", + "gl" => "US", + "clientName" => "WEB", + "clientVersion" => HARDCODED_CLIENT_VERS, + }, + }, + } + + # Append the additionnal parameters if those were provided + # (this is required for channel info, playlist and community, e.g) + if params != "" + data["params"] = params + end + + return _youtube_api_post_json("/youtubei/v1/browse", data) +end + #################################################################### # request_youtube_api_search(search_query, params, region) # diff --git a/src/invidious/playlists.cr b/src/invidious/playlists.cr index 150f1c15..fe7f82f3 100644 --- a/src/invidious/playlists.cr +++ b/src/invidious/playlists.cr @@ -361,16 +361,7 @@ def fetch_playlist(plid, locale) plid = "UU#{plid.lchop("UC")}" end - response = YT_POOL.client &.get("/playlist?list=#{plid}&hl=en") - if response.status_code != 200 - if response.headers["location"]?.try &.includes? "/sorry/index" - raise InfoException.new("Could not extract playlist info. Instance is likely blocked.") - else - raise InfoException.new("Not a playlist.") - end - end - - initial_data = extract_initial_data(response.body) + initial_data = request_youtube_api_browse("VL" + plid, params: "") playlist_sidebar_renderer = initial_data["sidebar"]?.try &.["playlistSidebarRenderer"]?.try &.["items"]? raise InfoException.new("Could not extract playlistSidebarRenderer.") if !playlist_sidebar_renderer @@ -453,15 +444,10 @@ def get_playlist_videos(db, playlist, offset, locale = nil, continuation = nil) ctoken = produce_playlist_continuation(playlist.id, offset) initial_data = request_youtube_api_browse(ctoken) else - response = YT_POOL.client &.get("/playlist?list=#{playlist.id}&gl=US&hl=en") - initial_data = extract_initial_data(response.body) + initial_data = request_youtube_api_browse("VL" + playlist.id, params: "") end - if initial_data - return extract_playlist_videos(initial_data) - else - return [] of PlaylistVideo - end + return extract_playlist_videos(initial_data) end end