forked from midou/invidious
		
	User: Allow CSV Youtube playlists to be imported (#3595)
This commit is contained in:
		| @@ -33,6 +33,7 @@ | ||||
|     "Import": "Import", | ||||
|     "Import Invidious data": "Import Invidious JSON data", | ||||
|     "Import YouTube subscriptions": "Import YouTube/OPML subscriptions", | ||||
|     "Import YouTube playlist (.csv)": "Import YouTube playlist (.csv)", | ||||
|     "Import FreeTube subscriptions (.db)": "Import FreeTube subscriptions (.db)", | ||||
|     "Import NewPipe subscriptions (.json)": "Import NewPipe subscriptions (.json)", | ||||
|     "Import NewPipe data (.zip)": "Import NewPipe data (.zip)", | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -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 | ||||
|     # ------------------- | ||||
|   | ||||
| @@ -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> | ||||
|   | ||||
| @@ -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> | ||||
|  | ||||
| @@ -21,6 +21,11 @@ | ||||
|                 <input type="file" id="import_youtube" name="import_youtube"> | ||||
|             </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"> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user