Exemplo n.º 1
0
        public async Task <List <IPlaylistSyncError> > SyncToSpotify(MusicBeeSyncHelper mb, List <MusicBeePlaylist> mbPlaylistsToSync,
                                                                     bool includeFoldersInPlaylistName = false, bool includeZAtStartOfDatePlaylistName = true)
        {
            List <IPlaylistSyncError> errors = new List <IPlaylistSyncError>();

            foreach (MusicBeePlaylist playlist in mbPlaylistsToSync)
            {
                // Use LINQ to check for a playlist with the same name
                // If there is one, clear it's contents, otherwise create one
                // Unless it's been deleted, in which case pretend it doesn't exist.
                // I'm not sure how to undelete a playlist, or even if you can
                string spotifyPlaylistName = null;
                if (includeFoldersInPlaylistName)
                {
                    spotifyPlaylistName = playlist.Name;
                }
                else
                {
                    spotifyPlaylistName = playlist.Name.Split('\\').Last();
                }

                if (includeZAtStartOfDatePlaylistName)
                {
                    // if it starts with a 2, it's a date playlist
                    if (spotifyPlaylistName.StartsWith("2"))
                    {
                        spotifyPlaylistName = $"Z {spotifyPlaylistName}";
                    }
                }

                // If Spotify playlist with same name already exists, clear it.
                // Otherwise create one
                SimplePlaylist thisPlaylist = Playlists.FirstOrDefault(p => p.Name == spotifyPlaylistName);
                string         thisPlaylistId;
                if (thisPlaylist != null)
                {
                    var request = new PlaylistReplaceItemsRequest(new List <string>()
                    {
                    });
                    var success = await Spotify.Playlists.ReplaceItems(thisPlaylist.Id, request);

                    if (!success)
                    {
                        Log("Error while trying to clear playlist before syncing new tracks");
                        return(errors);
                    }
                    thisPlaylistId = thisPlaylist.Id;
                }
                else
                {
                    var          request     = new PlaylistCreateRequest(spotifyPlaylistName);
                    FullPlaylist newPlaylist = await Spotify.Playlists.Create(Profile.Id, request);

                    thisPlaylistId = newPlaylist.Id;
                }


                List <FullTrack> songsToAdd = new List <FullTrack>();
                // And get the title and artist of each file, and add it to the GMusic playlist
                foreach (var song in playlist.Songs)
                {
                    string title  = song.Title;
                    string artist = song.Artist;
                    string album  = song.Album;

                    string         artistEsc = EscapeChar(artist.ToLower());
                    string         titleEsc  = EscapeChar(title.ToLower());
                    string         searchStr = $"artist:{artistEsc} track:{titleEsc}";
                    var            request   = new SearchRequest(SearchRequest.Types.Track, searchStr);
                    SearchResponse search    = await Spotify.Search.Item(request);

                    if (search.Tracks == null || search.Tracks.Items == null)
                    {
                        Log($"Could not find track on Spotify '{searchStr}' for '{title}' by '{artist}'");
                        continue;
                    }

                    if (search.Tracks.Items.Count == 0)
                    {
                        Log($"Found 0 results on Spotify for: {searchStr} for '{title}' by '{artist}'");
                        continue;
                    }

                    // try to find track matching artist and title
                    FullTrack trackToAdd = null;
                    foreach (FullTrack track in search.Tracks.Items)
                    {
                        bool titleMatches  = (track.Name.ToLower() == title.ToLower());
                        bool artistMatches = (track.Artists.Exists(a => a.Name.ToLower() == artist.ToLower()));
                        bool albumMatches  = (track.Album.Name.ToLower() == album.ToLower());
                        if (titleMatches && artistMatches && albumMatches)
                        {
                            trackToAdd = track;
                            break;
                        }
                        else if ((titleMatches && artistMatches) || (titleMatches && albumMatches) || (artistMatches && albumMatches))
                        {
                            // if two of them match, guessing this track is correct is
                            // probably better than just using the firstordefault, but keep looping hoping for a better track
                            trackToAdd = track;
                        }
                        else if (artistMatches && trackToAdd == null)
                        {
                            // if just the artist matches and we haven't found anything yet... this might be our best guess
                            trackToAdd = track;
                        }
                    }

                    if (trackToAdd == null)
                    {
                        trackToAdd = search.Tracks.Items.FirstOrDefault();
                        Log($"Didn't find a perfect match for {searchStr} for '{title}' by '{artist}', so using '{trackToAdd.Name}' by '{trackToAdd.Artists.FirstOrDefault().Name}' instead");
                    }

                    songsToAdd.Add(trackToAdd);
                }

                List <string> uris = songsToAdd.ConvertAll(x => x.Uri);
                while (uris.Count > 0)
                {
                    List <string> currUris = uris.Take(75).ToList();
                    if (currUris.Count == 0)
                    {
                        break;
                    }

                    uris.RemoveRange(0, currUris.Count);
                    var request = new PlaylistAddItemsRequest(currUris);
                    var resp    = await Spotify.Playlists.AddItems(thisPlaylistId, request);

                    if (resp == null)
                    {
                        Log("Error while trying to update playlist with track uris");
                        return(errors);
                    }
                }
            }

            return(errors);
        }
Exemplo n.º 2
0
        public async Task <List <IPlaylistSyncError> > SyncToMusicBee(MusicBeeSyncHelper mb, List <SimplePlaylist> playlists)
        {
            List <IPlaylistSyncError> errors = new List <IPlaylistSyncError>();

            // Go through each playlist we want to sync in turn
            foreach (SimplePlaylist playlist in playlists)
            {
                // Create an empty list for this playlist's local songs
                List <MusicBeeSong> mbPlaylistSongs = new List <MusicBeeSong>();

                // Get all tracks for playlist
                var fp = await Spotify.Playlists.Get(playlist.Id);

                var allTracks = await Spotify.PaginateAll(fp.Tracks);

                var tracks = new List <FullTrack>();
                foreach (var t in allTracks)
                {
                    if (t.Track is FullTrack track)
                    {
                        tracks.Add(track);
                    }
                }

                foreach (FullTrack track in tracks)
                {
                    string       artistStr  = track.Artists.FirstOrDefault().Name.ToLower();
                    string       titleStr   = track.Name.ToLower();
                    MusicBeeSong thisMbSong = mb.Songs.FirstOrDefault(s => s.Artist.ToLower() == artistStr && s.Title.ToLower() == titleStr);
                    if (thisMbSong != null)
                    {
                        mbPlaylistSongs.Add(thisMbSong);
                    }
                    else
                    {
                        errors.Add(new UnableToFindSpotifyTrackError()
                        {
                            AlbumName       = track.Album.Name,
                            ArtistName      = track.Artists.FirstOrDefault().Name,
                            PlaylistName    = playlist.Name,
                            TrackName       = track.Name,
                            SearchedService = false
                        });
                    }
                }

                //mbAPI expects a string array of song filenames to create a playlist
                string[] mbPlaylistSongFiles = new string[mbPlaylistSongs.Count];
                int      i = 0;
                foreach (MusicBeeSong song in mbPlaylistSongs)
                {
                    mbPlaylistSongFiles[i] = song.Filename;
                    i++;
                }

                // Now we need to delete any existing playlist with matching name
                MusicBeePlaylist localPlaylist = mb.Playlists.FirstOrDefault(p => p.Name == playlist.Name);
                if (localPlaylist != null)
                {
                    mb.MbApiInterface.Playlist_DeletePlaylist(localPlaylist.mbName);
                }

                // Create the playlist locally
                string playlistRelativeDir = "";
                string playlistName        = playlist.Name;

                // if it's a date playlist, remove first Z
                if (playlistName.StartsWith("Z "))
                {
                    playlistName = playlistName.Skip(2).ToString();
                }

                string[] itemsInPath = playlist.Name.Split('\\');
                if (itemsInPath.Length > 1)
                {
                    // Creates a playlist at top level directory
                    mb.MbApiInterface.Playlist_CreatePlaylist("", playlistName, mbPlaylistSongFiles);
                }

                mb.MbApiInterface.Playlist_CreatePlaylist(playlistRelativeDir, playlistName, mbPlaylistSongFiles);
            }

            // Get the local playlists again
            mb.RefreshMusicBeePlaylists();

            return(errors);
        }
Exemplo n.º 3
0
        public async Task <List <IPlaylistSyncError> > SyncToGoogle(MusicBeeSyncHelper mb, List <MusicBeePlaylist> mbPlaylistsToSync,
                                                                    bool includeFoldersInPlaylistName = false, bool includeZAtStartOfDatePlaylistName = true)
        {
            List <IPlaylistSyncError> errors = new List <IPlaylistSyncError>();

            foreach (MusicBeePlaylist playlist in mbPlaylistsToSync)
            {
                // Use LINQ to check for a playlist with the same name
                // If there is one, clear it's contents, otherwise create one
                // Unless it's been deleted, in which case pretend it doesn't exist.
                // I'm not sure how to undelete a playlist, or even if you can
                string gpmPlaylistName = null;
                if (includeFoldersInPlaylistName)
                {
                    gpmPlaylistName = playlist.Name;
                }
                else
                {
                    gpmPlaylistName = playlist.Name.Split('\\').Last();
                }

                if (includeZAtStartOfDatePlaylistName)
                {
                    // if it starts with a 2, it's a date playlist
                    if (gpmPlaylistName.StartsWith("2"))
                    {
                        gpmPlaylistName = $"Z {gpmPlaylistName}";
                    }
                }

                Playlist thisPlaylist   = GooglePlaylists.FirstOrDefault(p => p.Name == gpmPlaylistName && p.Deleted == false);
                String   thisPlaylistID = "";
                if (thisPlaylist != null)
                {
                    List <PlaylistEntry> allPlsSongs = thisPlaylist.Songs;

                    if (allPlsSongs.Count > 0)
                    {
                        MutatePlaylistResponse response = await api.RemoveFromPlaylistAsync(allPlsSongs);
                    }
                    thisPlaylistID = thisPlaylist.Id;
                }
                else
                {
                    MutatePlaylistResponse response = await api.CreatePlaylistAsync(gpmPlaylistName);

                    thisPlaylistID = response.MutateResponses.First().ID;
                }

                List <Track> songsToAdd = new List <Track>();
                // And get the title and artist of each file, and add it to the GMusic playlist
                foreach (var song in playlist.Songs)
                {
                    string title  = song.Title;
                    string artist = song.Artist;
                    string album  = song.Album;

                    // First check for matching title, artist, album, if we find nothing, then check for matching title/artist
                    Track gSong = GoogleSongsFetched.FirstOrDefault(item => (item.Artist.ToLower() == artist.ToLower() && item.Title.ToLower() == title.ToLower() && item.Album.ToLower() == album.ToLower()));
                    if (gSong == null)
                    {
                        gSong = GoogleSongsFetched.FirstOrDefault(item => (item.Artist.ToLower() == artist.ToLower() && item.Title.ToLower() == title.ToLower()));
                        if (gSong != null)
                        {
                            songsToAdd.Add(gSong);
                        }
                        else
                        {
                            // Didn't find it in cached library, so query for it
                            Track result = await TryGetTrackAsync(artist, title, album);

                            if (result != null)
                            {
                                GoogleSongsFetched.Add(result);
                                songsToAdd.Add(result);
                            }
                            else
                            {
                                // didn't find it even via querying
                                errors.Add(new UnableToFindGPMTrackError()
                                {
                                    PlaylistName    = gpmPlaylistName,
                                    AlbumName       = album,
                                    ArtistName      = artist,
                                    TrackName       = title,
                                    SearchedService = true,
                                });
                            }
                        }
                    }
                    else
                    {
                        songsToAdd.Add(gSong);
                    }
                }

                await api.AddToPlaylistAsync(thisPlaylistID, songsToAdd);
            }

            return(errors);
        }
Exemplo n.º 4
0
        public async Task <List <IPlaylistSyncError> > SyncToMusicBee(MusicBeeSyncHelper mb, List <Playlist> playlists)
        {
            List <IPlaylistSyncError> errors = new List <IPlaylistSyncError>();

            // Go through each playlist we want to sync in turn
            foreach (Playlist playlist in playlists)
            {
                // Create an empty list for this playlist's local songs
                List <MusicBeeSong> mbPlaylistSongs = new List <MusicBeeSong>();

                // For each entry in the playlist we're syncing, get the song from the GMusic library we've downloaded,
                // Get the song Title and Artist and then look it up in the list of local songs.
                // If we find it, add it to the list of local songs
                foreach (PlaylistEntry entry in playlist.Songs)
                {
                    Track thisSong = GoogleSongsFetched.FirstOrDefault(s => s.Id == entry.TrackID || s.NID == entry.TrackID);

                    // if we couldn't find it, attempt to fetch it by trackID and cache it
                    if (IsTrackInvalid(thisSong))
                    {
                        thisSong = await api.GetTrackAsync(entry.TrackID);

                        if (IsTrackInvalid(thisSong))
                        {
                            errors.Add(new UnableToFindGooglePlaylistEntryError()
                            {
                                GpmPlaylistName     = playlist.Name,
                                GpmPlaylistPosition = entry.AbsolutePosition,
                                GpmTrackId          = entry.TrackID,
                            });
                        }
                        else
                        {
                            GoogleSongsFetched.Add(thisSong);
                        }
                    }

                    if (!IsTrackInvalid(thisSong))
                    {
                        MusicBeeSong thisMbSong = mb.Songs.FirstOrDefault(s => s.Artist == thisSong.Artist && s.Title == thisSong.Title && s.Album == thisSong.Album);
                        if (thisMbSong != null)
                        {
                            mbPlaylistSongs.Add(thisMbSong);
                        }
                        else
                        {
                            errors.Add(new UnableToFindGPMTrackError()
                            {
                                AlbumName       = thisSong.Album,
                                ArtistName      = thisSong.Artist,
                                PlaylistName    = playlist.Name,
                                TrackName       = thisSong.Title,
                                SearchedService = false,
                            });
                        }
                    }
                }

                //mbAPI expects a string array of song filenames to create a playlist
                string[] mbPlaylistSongFiles = new string[mbPlaylistSongs.Count];
                int      i = 0;
                foreach (MusicBeeSong song in mbPlaylistSongs)
                {
                    mbPlaylistSongFiles[i] = song.Filename;
                    i++;
                }

                // Now we need to delete any existing playlist with matching name
                MusicBeePlaylist localPlaylist = mb.Playlists.FirstOrDefault(p => p.Name == playlist.Name);
                if (localPlaylist != null)
                {
                    mb.MbApiInterface.Playlist_DeletePlaylist(localPlaylist.mbName);
                }

                // Create the playlist locally
                string playlistRelativeDir = "";
                string playlistName        = playlist.Name;

                string[] itemsInPath = playlist.Name.Split('\\');
                if (itemsInPath.Length > 1)
                {
                    // Creates a playlist at top level directory
                    mb.MbApiInterface.Playlist_CreatePlaylist("", playlistName, mbPlaylistSongFiles);
                }

                mb.MbApiInterface.Playlist_CreatePlaylist(playlistRelativeDir, playlistName, mbPlaylistSongFiles);
            }

            // Get the local playlists again
            mb.RefreshMusicBeePlaylists();

            return(errors);
        }
        public async Task <List <IPlaylistSyncError> > SyncToYoutubeMusic(MusicBeeSyncHelper mb, List <MusicBeePlaylist> mbPlaylistsToSync,
                                                                          bool includeFoldersInPlaylistName = false, bool includeZAtStartOfDatePlaylistName = true)
        {
            List <IPlaylistSyncError> errors = new List <IPlaylistSyncError>();

            foreach (var playlist in mbPlaylistsToSync)
            {
                string newPlaylistName = null;
                if (includeFoldersInPlaylistName)
                {
                    newPlaylistName = playlist.Name;
                }
                else
                {
                    newPlaylistName = playlist.Name.Split('\\').Last();
                }

                if (includeZAtStartOfDatePlaylistName)
                {
                    // if it starts with a 2, it's a date playlist
                    if (newPlaylistName.StartsWith("2"))
                    {
                        newPlaylistName = $"Z {newPlaylistName}";
                    }
                }


                List <string> videoIds = new List <string>();


                foreach (var song in playlist.Songs)
                {
                    string searchStr = $"{song.Title} {song.Artist} {song.Album}";
                    var    response  = await Ytm.Search(searchStr);

                    var video = FindMatchInSearchResult(searchStr, song, response);

                    if (video == null || !IsPerfectMatch(song, video))
                    {
                        // if we couldn't find it, try searching uploads
                        response = await Ytm.SearchUploads(searchStr);

                        var otherVideo = FindMatchInSearchResult(searchStr, song, response);

                        video = FindBestMatchBetweenTwo(song, video, otherVideo);
                    }

                    if (video == null)
                    {
                        errors.Add(new UnableToFindYTMTrackError()
                        {
                            AlbumName       = song.Album,
                            ArtistName      = song.Artist,
                            PlaylistName    = playlist.Name,
                            SearchedService = true,
                            TrackName       = song.Title,
                        });
                    }
                    else
                    {
                        videoIds.Add(video.VideoId);
                    }
                }

                // If YTM playlist with same name already exists, clear it.
                // Otherwise create one
                var thisPlaylist = Playlists.FirstOrDefault(p => p.Title == newPlaylistName);
                if (thisPlaylist != null)
                {
                    var playlistWithSongs = await Ytm.GetPlaylist(thisPlaylist.PlaylistId, authRequired : true);

                    if (playlistWithSongs.Tracks.Count != 0)
                    {
                        var res = await Ytm.RemovePlaylistItems(playlistWithSongs.PlaylistId, playlistWithSongs.Tracks);

                        if (!res)
                        {
                            Log("Error while trying to clear playlist before syncing new tracks");
                            return(errors);
                        }
                    }

                    await Ytm.AddPlaylistItems(playlistWithSongs.PlaylistId, videoIds);
                }
                else
                {
                    var res = await Ytm.CreatePlaylist(newPlaylistName, "", videoIds : videoIds);
                }
            }

            return(errors);
        }
        public async Task <List <IPlaylistSyncError> > SyncToMusicBee(MusicBeeSyncHelper mb, List <Playlist> playlists)
        {
            List <IPlaylistSyncError> errors = new List <IPlaylistSyncError>();

            return(errors);
        }