summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSamantaz Fox <coding@samantaz.fr>2023-05-23 19:34:24 +0200
committerSamantaz Fox <coding@samantaz.fr>2023-05-23 19:34:24 +0200
commit8d434ac06af32e5c714867379baa180e16d340fc (patch)
treead657ab4d7e46dd0ee5a036061675e90b1c82c7a /src
parent1333e6db264b39516ec2f6897cf8410db368bf9e (diff)
parentc421f1f205eba08ca38b70833a9cc3aec72df36f (diff)
downloadinvidious-8d434ac06af32e5c714867379baa180e16d340fc.tar.gz
invidious-8d434ac06af32e5c714867379baa180e16d340fc.tar.bz2
invidious-8d434ac06af32e5c714867379baa180e16d340fc.zip
User: Allow CSV Youtube playlists to be imported (#3595)
Diffstat (limited to 'src')
-rw-r--r--src/invidious/routes/preferences.cr9
-rw-r--r--src/invidious/user/imports.cr69
-rw-r--r--src/invidious/views/feeds/playlists.ecr15
-rw-r--r--src/invidious/views/user/data_control.ecr7
4 files changed, 95 insertions, 5 deletions
diff --git a/src/invidious/routes/preferences.cr b/src/invidious/routes/preferences.cr
index 570cba69..abe0f34e 100644
--- a/src/invidious/routes/preferences.cr
+++ b/src/invidious/routes/preferences.cr
@@ -310,6 +310,15 @@ module Invidious::Routes::PreferencesRoute
response: error_template(415, "Invalid subscription file uploaded")
)
end
+ when "import_youtube_pl"
+ filename = part.filename || ""
+ success = Invidious::User::Import.from_youtube_pl(user, body, filename, type)
+
+ if !success
+ haltf(env, status_code: 415,
+ response: error_template(415, "Invalid playlist file uploaded")
+ )
+ end
when "import_freetube"
Invidious::User::Import.from_freetube(user, body)
when "import_newpipe_subscriptions"
diff --git a/src/invidious/user/imports.cr b/src/invidious/user/imports.cr
index aa947456..e4b25156 100644
--- a/src/invidious/user/imports.cr
+++ b/src/invidious/user/imports.cr
@@ -30,6 +30,60 @@ struct Invidious::User
return subscriptions
end
+ def parse_playlist_export_csv(user : User, raw_input : String)
+ # Split the input into head and body content
+ raw_head, raw_body = raw_input.split("\n\n", limit: 2, remove_empty: true)
+
+ # Create the playlist from the head content
+ csv_head = CSV.new(raw_head, headers: true)
+ csv_head.next
+ title = csv_head[4]
+ description = csv_head[5]
+ visibility = csv_head[6]
+
+ if visibility.compare("Public", case_insensitive: true) == 0
+ privacy = PlaylistPrivacy::Public
+ else
+ privacy = PlaylistPrivacy::Private
+ end
+
+ playlist = create_playlist(title, privacy, user)
+ Invidious::Database::Playlists.update_description(playlist.id, description)
+
+ # Add each video to the playlist from the body content
+ csv_body = CSV.new(raw_body, headers: true)
+ csv_body.each do |row|
+ video_id = row[0]
+ if playlist
+ next if !video_id
+ next if video_id == "Video Id"
+
+ begin
+ video = get_video(video_id)
+ rescue ex
+ next
+ end
+
+ playlist_video = PlaylistVideo.new({
+ title: video.title,
+ id: video.id,
+ author: video.author,
+ ucid: video.ucid,
+ length_seconds: video.length_seconds,
+ published: video.published,
+ plid: playlist.id,
+ live_now: video.live_now,
+ index: Random::Secure.rand(0_i64..Int64::MAX),
+ })
+
+ Invidious::Database::PlaylistVideos.insert(playlist_video)
+ Invidious::Database::Playlists.update_video_added(playlist.id, playlist_video.index)
+ end
+ end
+
+ return playlist
+ end
+
# -------------------
# Invidious
# -------------------
@@ -149,6 +203,21 @@ struct Invidious::User
return true
end
+ def from_youtube_pl(user : User, body : String, filename : String, type : String) : Bool
+ extension = filename.split(".").last
+
+ if extension == "csv" || type == "text/csv"
+ playlist = parse_playlist_export_csv(user, body)
+ if playlist
+ return true
+ else
+ return false
+ end
+ else
+ return false
+ end
+ end
+
# -------------------
# Freetube
# -------------------
diff --git a/src/invidious/views/feeds/playlists.ecr b/src/invidious/views/feeds/playlists.ecr
index e52a7707..2a4b6edd 100644
--- a/src/invidious/views/feeds/playlists.ecr
+++ b/src/invidious/views/feeds/playlists.ecr
@@ -5,12 +5,19 @@
<%= rendered "components/feed_menu" %>
<div class="pure-g h-box">
- <div class="pure-u-2-3">
+ <div class="pure-u-1-3">
<h3><%= translate(locale, "user_created_playlists", %(<span id="count">#{items_created.size}</span>)) %></h3>
</div>
- <div class="pure-u-1-3" style="text-align:right">
- <h3>
- <a href="/create_playlist?referer=<%= URI.encode_www_form(referer) %>"><%= translate(locale, "Create playlist") %></a>
+ <div class="pure-u-1-3">
+ <h3 style="text-align:center">
+ <a href="/create_playlist?referer=<%= URI.encode_www_form("/feed/playlists") %>"><%= translate(locale, "Create playlist") %></a>
+ </h3>
+ </div>
+ <div class="pure-u-1-3">
+ <h3 style="text-align:right">
+ <a href="/data_control?referer=<%= URI.encode_www_form("/feed/playlists") %>">
+ <%= translate(locale, "Import/export") %>
+ </a>
</h3>
</div>
</div>
diff --git a/src/invidious/views/user/data_control.ecr b/src/invidious/views/user/data_control.ecr
index a451159f..27654b40 100644
--- a/src/invidious/views/user/data_control.ecr
+++ b/src/invidious/views/user/data_control.ecr
@@ -8,7 +8,7 @@
<legend><%= translate(locale, "Import") %></legend>
<div class="pure-control-group">
- <label for="import_youtube"><%= translate(locale, "Import Invidious data") %></label>
+ <label for="import_invidious"><%= translate(locale, "Import Invidious data") %></label>
<input type="file" id="import_invidious" name="import_invidious">
</div>
@@ -22,6 +22,11 @@
</div>
<div class="pure-control-group">
+ <label for="import_youtube_pl"><%= translate(locale, "Import YouTube playlist (.csv)") %></label>
+ <input type="file" id="import_youtube_pl" name="import_youtube_pl">
+ </div>
+
+ <div class="pure-control-group">
<label for="import_freetube"><%= translate(locale, "Import FreeTube subscriptions (.db)") %></label>
<input type="file" id="import_freetube" name="import_freetube">
</div>