diff --git a/src/components/PlaylistsPage.vue b/src/components/PlaylistsPage.vue
index 716524b5..02353d73 100644
--- a/src/components/PlaylistsPage.vue
+++ b/src/components/PlaylistsPage.vue
@@ -3,7 +3,19 @@
@@ -94,22 +106,90 @@ export default {
else this.playlists = this.playlists.filter(playlist => playlist.id !== id);
});
},
- createPlaylist() {
+ onCreatePlaylist() {
const name = prompt(this.$t("actions.create_playlist"));
- if (name)
- this.fetchJson(this.authApiUrl() + "/user/playlists/create", null, {
- method: "POST",
- body: JSON.stringify({
- name: name,
- }),
- headers: {
- Authorization: this.getAuthToken(),
- "Content-Type": "application/json",
- },
- }).then(json => {
- if (json.error) alert(json.error);
- else this.fetchPlaylists();
- });
+ if (!name) return;
+ this.createPlaylist(name).then(json => {
+ if (json.error) alert(json.error);
+ else this.fetchPlaylists();
+ });
+ },
+ async createPlaylist(name) {
+ let json = await this.fetchJson(this.authApiUrl() + "/user/playlists/create", null, {
+ method: "POST",
+ body: JSON.stringify({
+ name: name,
+ }),
+ headers: {
+ Authorization: this.getAuthToken(),
+ "Content-Type": "application/json",
+ },
+ });
+ return json;
+ },
+ async exportPlaylists() {
+ if (!this.playlists) return;
+ let json = {
+ format: "Piped",
+ version: 1,
+ playlists: [],
+ };
+ let tasks = [];
+ for (var i = 0; i < this.playlists.length; i++) {
+ tasks.push(this.fetchPlaylistJson(this.playlists[i].id));
+ }
+ json.playlists = await Promise.all(tasks);
+ this.download(JSON.stringify(json), "playlists.json", "application/json");
+ },
+ async fetchPlaylistJson(playlistId) {
+ let playlist = await this.fetchJson(this.authApiUrl() + "/playlists/" + playlistId);
+ let playlistJson = {
+ name: playlist.name,
+ // possible other types: history, watch later, ...
+ type: "playlist",
+ // as Invidious supports public and private playlists
+ visibility: "private",
+ // list of the videos, starting with "https://youtube.com" to clarify that those are YT videos
+ videos: [],
+ };
+ for (var i = 0; i < playlist.relatedStreams.length; i++) {
+ playlistJson.videos.push("https://youtube.com" + playlist.relatedStreams[i].url);
+ }
+ return playlistJson;
+ },
+ async importPlaylists() {
+ const file = this.$refs.fileSelector.files[0];
+ let text = await file.text();
+ let playlists = JSON.parse(text).playlists;
+ if (!playlists.length) {
+ alert(this.$t("actions.no_valid_playlists"));
+ return;
+ }
+ let tasks = [];
+ for (var i = 0; i < playlists.length; i++) {
+ tasks.push(this.createPlaylistWithVideos(playlists[i]));
+ }
+ await Promise.all(tasks);
+ window.location.reload();
+ },
+ async createPlaylistWithVideos(playlist) {
+ let newPlaylist = await this.createPlaylist(playlist.name);
+ console.log(newPlaylist);
+ let videoIds = playlist.videos.map(url => url.substr(-11));
+ await this.addVideosToPlaylist(newPlaylist.playlistId, videoIds);
+ },
+ async addVideosToPlaylist(playlistId, videoIds) {
+ await this.fetchJson(this.authApiUrl() + "/user/playlists/add", null, {
+ method: "POST",
+ body: JSON.stringify({
+ playlistId: playlistId,
+ videoIds: videoIds,
+ }),
+ headers: {
+ Authorization: this.getAuthToken(),
+ "Content-Type": "application/json",
+ },
+ });
},
},
};
diff --git a/src/locales/en.json b/src/locales/en.json
index fab0ced3..8d3782a1 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -118,7 +118,8 @@
"status_page": "Status",
"source_code": "Source code",
"instance_donations": "Instance donations",
- "reply_count": "{count} replies"
+ "reply_count": "{count} replies",
+ "no_valid_playlists": "The file doesn't contain valid playlists!"
},
"comment": {
"pinned_by": "Pinned by {author}",