From 5d8de5fde2dee11ee8feb63f0bce74d373eec56f Mon Sep 17 00:00:00 2001
From: Dmitry Sandalov <dmitry@sandalov.org>
Date: Sun, 17 May 2020 14:28:00 +0300
Subject: [PATCH] Allow user to subscribe to playlist (#17)

---
 src/invidious.cr                           | 33 ++++++++++++++++++----
 src/invidious/playlists.cr                 | 21 ++++++++++++++
 src/invidious/views/playlist.ecr           |  6 ++++
 src/invidious/views/view_all_playlists.ecr | 18 ++++++++++--
 src/invidious/views/watch.ecr              |  2 +-
 5 files changed, 71 insertions(+), 9 deletions(-)

diff --git a/src/invidious.cr b/src/invidious.cr
index 6a197795..56722b7e 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -846,8 +846,14 @@ get "/view_all_playlists" do |env|
 
   user = user.as(User)
 
-  items = PG_DB.query_all("SELECT * FROM playlists WHERE author = $1 ORDER BY created", user.email, as: InvidiousPlaylist)
-  items.map! do |item|
+  items_created = PG_DB.query_all("SELECT * FROM playlists WHERE author = $1 AND id LIKE 'IV%' ORDER BY created", user.email, as: InvidiousPlaylist)
+  items_created.map! do |item|
+    item.author = ""
+    item
+  end
+
+  items_saved = PG_DB.query_all("SELECT * FROM playlists WHERE author = $1 AND id NOT LIKE 'IV%' ORDER BY created", user.email, as: InvidiousPlaylist)
+  items_saved.map! do |item|
     item.author = ""
     item
   end
@@ -918,6 +924,25 @@ post "/create_playlist" do |env|
   env.redirect "/playlist?list=#{playlist.id}"
 end
 
+get "/subscribe_playlist" do |env|
+  locale = LOCALES[env.get("preferences").as(Preferences).locale]?
+
+  user = env.get? "user"
+  referer = get_referer(env)
+
+  if !user
+    next env.redirect "/"
+  end
+
+  user = user.as(User)
+
+  playlist_id = env.params.query["list"]
+  playlist = get_playlist(PG_DB, playlist_id, locale)
+  subscribe_playlist(PG_DB, user, playlist)
+
+  env.redirect "/playlist?list=#{playlist.id}"
+end
+
 get "/delete_playlist" do |env|
   locale = LOCALES[env.get("preferences").as(Preferences).locale]?
 
@@ -933,10 +958,6 @@ get "/delete_playlist" do |env|
   sid = sid.as(String)
 
   plid = env.params.query["list"]?
-  if !plid || !plid.starts_with?("IV")
-    next env.redirect referer
-  end
-
   playlist = PG_DB.query_one?("SELECT * FROM playlists WHERE id = $1", plid, as: InvidiousPlaylist)
   if !playlist || playlist.author != user.email
     next env.redirect referer
diff --git a/src/invidious/playlists.cr b/src/invidious/playlists.cr
index 9c8afd3c..184329dc 100644
--- a/src/invidious/playlists.cr
+++ b/src/invidious/playlists.cr
@@ -277,6 +277,27 @@ def create_playlist(db, title, privacy, user)
   return playlist
 end
 
+def subscribe_playlist(db, user, playlist)
+  playlist = InvidiousPlaylist.new(
+    title: playlist.title.byte_slice(0, 150),
+    id: playlist.id,
+    author: user.email,
+    description: "", # Max 5000 characters
+    video_count: playlist.video_count,
+    created: Time.utc,
+    updated: playlist.updated,
+    privacy: PlaylistPrivacy::Private,
+    index: [] of Int64,
+  )
+
+  playlist_array = playlist.to_a
+  args = arg_array(playlist_array)
+
+  db.exec("INSERT INTO playlists VALUES (#{args})", args: playlist_array)
+
+  return playlist
+end
+
 def extract_playlist(plid, nodeset, index)
   videos = [] of PlaylistVideo
 
diff --git a/src/invidious/views/playlist.ecr b/src/invidious/views/playlist.ecr
index 7316af14..bb721c3a 100644
--- a/src/invidious/views/playlist.ecr
+++ b/src/invidious/views/playlist.ecr
@@ -45,6 +45,12 @@
                 <% if playlist.is_a?(InvidiousPlaylist) && playlist.author == user.try &.email %>
                     <div class="pure-u-1-3"><a href="/edit_playlist?list=<%= plid %>"><i class="icon ion-md-create"></i></a></div>
                     <div class="pure-u-1-3"><a href="/delete_playlist?list=<%= plid %>"><i class="icon ion-md-trash"></i></a></div>
+                <% else %>
+                    <% if PG_DB.query_one?("SELECT id FROM playlists WHERE id = $1", playlist.id, as: String).nil? %>
+                        <div class="pure-u-1-3"><a href="/subscribe_playlist?list=<%= plid %>"><i class="icon ion-md-add"></i></a></div>
+                    <% else %>
+                        <div class="pure-u-1-3"><a href="/delete_playlist?list=<%= plid %>"><i class="icon ion-md-trash"></i></a></div>
+                    <% end %>
                 <% end %>
                 <div class="pure-u-1-3"><a href="/feed/playlist/<%= plid %>"><i class="icon ion-logo-rss"></i></a></div>
             </div>
diff --git a/src/invidious/views/view_all_playlists.ecr b/src/invidious/views/view_all_playlists.ecr
index 0fa7a325..5ec6aa31 100644
--- a/src/invidious/views/view_all_playlists.ecr
+++ b/src/invidious/views/view_all_playlists.ecr
@@ -6,7 +6,7 @@
 
 <div class="pure-g h-box">
     <div class="pure-u-2-3">
-        <h3><%= translate(locale, "`x` playlists", %(<span id="count">#{items.size}</span>)) %></h3>
+        <h3><%= translate(locale, "`x` created playlists", %(<span id="count">#{items_created.size}</span>)) %></h3>
     </div>
     <div class="pure-u-1-3" style="text-align:right">
         <h3>
@@ -16,7 +16,21 @@
 </div>
 
 <div class="pure-g">
-    <% items.each_slice(4) do |slice| %>
+    <% items_created.each_slice(4) do |slice| %>
+        <% slice.each do |item| %>
+            <%= rendered "components/item" %>
+        <% end %>
+    <% end %>
+</div>
+
+<div class="pure-g h-box">
+    <div class="pure-u-1">
+        <h3><%= translate(locale, "`x` saved playlists", %(<span id="count">#{items_saved.size}</span>)) %></h3>
+    </div>
+</div>
+
+<div class="pure-g">
+    <% items_saved.each_slice(4) do |slice| %>
         <% slice.each do |item| %>
             <%= rendered "components/item" %>
         <% end %>
diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr
index 7c9acb14..61c3b7dc 100644
--- a/src/invidious/views/watch.ecr
+++ b/src/invidious/views/watch.ecr
@@ -102,7 +102,7 @@
             </p>
 
             <% if user %>
-                <% playlists = PG_DB.query_all("SELECT id,title FROM playlists WHERE author = $1", user.email, as: {String, String}) %>
+                <% playlists = PG_DB.query_all("SELECT id,title FROM playlists WHERE author = $1 AND id LIKE 'IV%'", user.email, as: {String, String}) %>
                 <% if !playlists.empty? %>
                     <form data-onsubmit="return_false" class="pure-form pure-form-stacked" action="/playlist_ajax" method="post">
                         <div class="pure-control-group">