From 88430a6fc0b19ce4a3946e307821d73127034995 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sun, 7 Oct 2018 21:11:33 -0500 Subject: [PATCH] Add playlist playback support --- assets/css/default.css | 5 +++ src/invidious.cr | 34 +++++++++++++++++- src/invidious/mixes.cr | 38 ++++++++++++++++++++ src/invidious/playlists.cr | 50 ++++++++++++++++++++++++-- src/invidious/views/watch.ecr | 68 +++++++++++++++++++++++++++++++++-- 5 files changed, 190 insertions(+), 5 deletions(-) diff --git a/assets/css/default.css b/assets/css/default.css index 15cd1d4e..e60b9da8 100644 --- a/assets/css/default.css +++ b/assets/css/default.css @@ -17,6 +17,11 @@ div { animation: spin 2s linear infinite; } +.playlist-restricted { + height: 20em; + padding-right: 10px; +} + /* * Navbar */ diff --git a/src/invidious.cr b/src/invidious.cr index 9be7fd85..a6b77c54 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -217,6 +217,8 @@ get "/watch" do |env| next env.redirect "/" end + plid = env.params.query["list"]? + user = env.get? "user" if user user = user.as(User) @@ -2939,6 +2941,11 @@ get "/api/v1/playlists/:plid" do |env| page = env.params.query["page"]?.try &.to_i? page ||= 1 + format = env.params.query["format"]? + format ||= "json" + + continuation = env.params.query["continuation"]? + if plid.starts_with? "RD" next env.redirect "/api/v1/mixes/#{plid}" end @@ -2951,7 +2958,7 @@ get "/api/v1/playlists/:plid" do |env| end begin - videos = fetch_playlist_videos(plid, page, playlist.video_count) + videos = fetch_playlist_videos(plid, page, playlist.video_count, continuation) rescue ex videos = [] of PlaylistVideo end @@ -3010,6 +3017,17 @@ get "/api/v1/playlists/:plid" do |env| end end + if format == "html" + response = JSON.parse(response) + playlist_html = template_playlist(response) + next_video = response["videos"].as_a[1]?.try &.["videoId"] + + response = { + "playlistHtml" => playlist_html, + "nextVideo" => next_video, + }.to_json + end + response end @@ -3021,6 +3039,9 @@ get "/api/v1/mixes/:rdid" do |env| continuation = env.params.query["continuation"]? continuation ||= rdid.lchop("RD") + format = env.params.query["format"]? + format ||= "json" + begin mix = fetch_mix(rdid, continuation) rescue ex @@ -3059,6 +3080,17 @@ get "/api/v1/mixes/:rdid" do |env| end end + if format == "html" + response = JSON.parse(response) + playlist_html = template_mix(response) + next_video = response["videos"].as_a[1]?.try &.["videoId"] + + response = { + "playlistHtml" => playlist_html, + "nextVideo" => next_video, + }.to_json + end + response end diff --git a/src/invidious/mixes.cr b/src/invidious/mixes.cr index ef53ad4d..69a2d67d 100644 --- a/src/invidious/mixes.cr +++ b/src/invidious/mixes.cr @@ -35,6 +35,10 @@ def fetch_mix(rdid, video_id, cookies = nil) raise "Could not create mix." end + if !yt_data["contents"]["twoColumnWatchNextResults"]["playlist"] + raise "Could not create mix." + end + playlist = yt_data["contents"]["twoColumnWatchNextResults"]["playlist"]["playlist"] mix_title = playlist["title"].as_s @@ -74,3 +78,37 @@ def fetch_mix(rdid, video_id, cookies = nil) videos = videos.first(50) return Mix.new(mix_title, rdid, videos) end + +def template_mix(mix) + html = <<-END_HTML +

+ + #{mix["title"]} + +

+
+
    + END_HTML + + mix["videos"].as_a.each do |video| + html += <<-END_HTML +
  1. + + +

    #{video["title"]}

    +

    + #{video["author"]} +

    +
    +
  2. + END_HTML + end + + html += <<-END_HTML +
+
+
+ END_HTML + + html +end diff --git a/src/invidious/playlists.cr b/src/invidious/playlists.cr index 32fcd016..b75a3293 100644 --- a/src/invidious/playlists.cr +++ b/src/invidious/playlists.cr @@ -26,11 +26,23 @@ class Playlist }) end -def fetch_playlist_videos(plid, page, video_count) +def fetch_playlist_videos(plid, page, video_count, continuation = nil) client = make_client(YT_URL) - if video_count > 100 + if continuation + html = client.get("/watch?v=#{continuation}&list=#{plid}&bpctr=#{Time.new.epoch + 2000}&gl=US&hl=en&disable_polymer=1") + html = XML.parse_html(html.body) + + index = html.xpath_node(%q(//span[@id="playlist-current-index"])).try &.content.to_i? + if index + index -= 1 + end + index ||= 0 + else index = (page - 1) * 100 + end + + if video_count > 100 url = produce_playlist_url(plid, index) response = client.get(url) @@ -199,3 +211,37 @@ def fetch_playlist(plid) return playlist end + +def template_playlist(playlist) + html = <<-END_HTML +

+ + #{playlist["title"]} + +

+
+
    + END_HTML + + playlist["videos"].as_a.each do |video| + html += <<-END_HTML +
  1. + + +

    #{video["title"]}

    +

    + #{video["author"]} +

    +
    +
  2. + END_HTML + end + + html += <<-END_HTML +
+
+
+ END_HTML + + html +end diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index 4eaaf9a6..7df3794b 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -123,6 +123,13 @@
+ <% if plid %> +
+

+
+
+ <% end %> + <% if !preferences || preferences && preferences.related_videos %>
<% rvs.each do |rv| %> @@ -145,6 +152,61 @@