public async Task NowPlaying(Audio item, LastfmUser user) { var request = new NowPlayingRequest { Track = item.Name, Album = item.Album, Artist = item.Artists.First(), ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.NowPlaying, SessionKey = user.SessionKey }; //Add duration if (item.RunTimeTicks != null) request.Duration = Convert.ToInt32(TimeSpan.FromTicks((long)item.RunTimeTicks).TotalSeconds); var response = await Post<NowPlayingRequest, ScrobbleResponse>(request); if (response != null && !response.IsError()) { Plugin.Logger.Info("{0} is now playing '{1}' - {2} - {3}", user.Username, request.Track, request.Album, request.Artist); return; } Plugin.Logger.Error("Failed to send now playing for track: {0}", item.Name); }
public async Task NowPlaying(Audio item, LastfmUser user) { var request = new NowPlayingRequest { Track = item.Name, Album = item.Album, Artist = item.Artists.First(), ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.NowPlaying, SessionKey = user.SessionKey }; //Add duration if (item.RunTimeTicks != null) { request.Duration = Convert.ToInt32(TimeSpan.FromTicks((long)item.RunTimeTicks).TotalSeconds); } var response = await Post <NowPlayingRequest, ScrobbleResponse>(request); if (response != null && !response.IsError()) { Plugin.Logger.Info("{0} is now playing '{1}' - {2} - {3}", user.Username, request.Track, request.Album, request.Artist); return; } Plugin.Logger.Error("Failed to send now playing for track: {0}", item.Name); }
/// <summary> /// Returns a list of a target user's loved tracks from the Last.FM API. See https://www.last.fm/api/show/user.getLovedTracks /// </summary> /// <param name="lastfmUser"></param> /// <param name="progress"></param> /// <param name="cancellationToken"></param> /// <param name="maxProgress"></param> /// <param name="progressOffset"></param> private async Task <List <LastfmLovedTrack> > GetLovedTracksLibrary(LastfmUser lastfmUser, IProgress <double> progress, CancellationToken cancellationToken, double maxProgress, double progressOffset) { var tracks = new List <LastfmLovedTrack>(); int page = 1; bool moreTracks; do { cancellationToken.ThrowIfCancellationRequested(); var response = await _apiClient.GetLovedTracks(lastfmUser, cancellationToken, page ++).ConfigureAwait(false); if (response == null || !response.HasLovedTracks()) { break; } tracks.AddRange(response.LovedTracks.Tracks); moreTracks = !response.LovedTracks.Metadata.IsLastPage(); // Only report progress in download because it will be 90% of the time taken var currentProgress = ((double)response.LovedTracks.Metadata.Page / response.LovedTracks.Metadata.TotalPages) * (maxProgress - progressOffset) + progressOffset; _logger.LogDebug("Progress: " + currentProgress * 100); progress.Report(currentProgress * 100); } while (moreTracks); _logger.LogInformation("Retrieved {0} lovedTracks from LastFM for user {1}", tracks.Count(), lastfmUser.Username); return(tracks); }
private async Task <List <LastfmTrack> > GetUsersLibrary(LastfmUser lastfmUser, IProgress <double> progress, CancellationToken cancellationToken, double maxProgress, double progressOffset) { var tracks = new List <LastfmTrack>(); var page = 1; //Page 0 = 1 bool moreTracks; do { cancellationToken.ThrowIfCancellationRequested(); var response = await _apiClient.GetTracks(lastfmUser, cancellationToken, page ++).ConfigureAwait(false); if (response == null || !response.HasTracks()) { break; } tracks.AddRange(response.Tracks.Tracks); moreTracks = !response.Tracks.Metadata.IsLastPage(); //Only report progress in download because it will be 90% of the time taken var currentProgress = ((double)response.Tracks.Metadata.Page / response.Tracks.Metadata.TotalPages) * (maxProgress - progressOffset) + progressOffset; Plugin.Logger.Debug("Progress: " + currentProgress * 100); progress.Report(currentProgress * 100); } while (moreTracks); return(tracks); }
/// <summary> /// Loves or unloves a track /// </summary> /// <param name="item">The track</param> /// <param name="user">The Lastfm User</param> /// <param name="love">If the track is loved or not</param> /// <returns></returns> public async Task <bool> LoveTrack(Audio item, LastfmUser user, bool love = true) { var request = new TrackLoveRequest { Artist = item.Artists.FirstOrDefault(), Track = item.Name, ApiKey = Strings.Keys.LastfmApiKey, Method = love ? Strings.Methods.TrackLove : Strings.Methods.TrackUnlove, SessionKey = user.SessionKey, }; try { //Send the request var response = await Post <TrackLoveRequest, BaseResponse>(request); if (response != null && !response.IsError()) { _logger.LogInformation("{0} {2}loved track '{1}'", user.Username, item.Name, (love ? "" : "un")); return(true); } _logger.LogError("{0} Failed to love = {3} track '{1}' - {2}", user.Username, item.Name, response.Message, love); return(false); } catch (Exception ex) { _logger.LogError("{0} Failed to love = {2} track '{1}'", ex, user.Username, item.Name, love); return(false); } }
public async Task Scrobble(Audio item, LastfmUser user) { if (string.IsNullOrWhiteSpace(item.Name)) { Plugin.Logger.Error("Cannot scrobble track: {0}, no name", item.Id); return; } var artist = item.Artists?.FirstOrDefault(); if (string.IsNullOrWhiteSpace(artist)) { Plugin.Logger.Error("Cannot scrobble track: {0} ({1}), no artist found", item.Id, item.Name); return; } var request = new ScrobbleRequest { Track = item.Name, Album = item.Album, Artist = artist, Timestamp = Helpers.CurrentTimestamp(), SessionKey = user.SessionKey }; var response = await Post <ScrobbleRequest, ScrobbleResponse>(request).ConfigureAwait(false); if (response != null && !response.IsError()) { Plugin.Logger.Info("{0} played '{1}' - {2} - {3}", user.Username, request.Track, request.Album, request.Artist); return; } Plugin.Logger.Error("Failed to Scrobble track: {0}", item.Name); }
public async Task <LovedTracksResponse> GetLovedTracks(LastfmUser user) { var request = new GetLovedTracksRequest { User = user.Username, ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.GetLovedTracks }; return(await Get <GetLovedTracksRequest, LovedTracksResponse>(request)); }
public async Task <GetTracksResponse> GetTracks(LastfmUser user, MusicArtist artist, CancellationToken cancellationToken) { var request = new GetTracksRequest { User = user.Username, Artist = artist.Name, ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.GetTracks, Limit = 1000 }; return(await Get <GetTracksRequest, GetTracksResponse>(request, cancellationToken)); }
public async Task <GetTracksResponse> GetTracks(LastfmUser user, CancellationToken cancellationToken, int page = 0, int limit = 200) { var request = new GetTracksRequest { User = user.Username, ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.GetTracks, Limit = limit, Page = page }; return(await Get <GetTracksRequest, GetTracksResponse>(request, cancellationToken)); }
public async Task <LovedTracksResponse> GetLovedTracks(LastfmUser user, CancellationToken cancellationToken, int page) { var request = new GetLovedTracksRequest { User = user.Username, ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.GetLovedTracks, Limit = 1000, // {"error":6,"message":"limit param out of bounds (1-1000)"} Page = page, Secure = true }; return(await Get <GetLovedTracksRequest, LovedTracksResponse>(request, cancellationToken)); }
public async Task NowPlaying(Audio item, LastfmUser user) { var request = new NowPlayingRequest { Track = item.Name, Artist = item.Artists.First(), ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.NowPlaying, SessionKey = user.SessionKey, Secure = true }; if (!string.IsNullOrWhiteSpace(item.Album)) { request.Album = item.Album; } if (item.ProviderIds.ContainsKey("MusicBrainzTrack")) { request.MbId = item.ProviderIds["MusicBrainzTrack"]; } // Add duration if (item.RunTimeTicks != null) { request.Duration = Convert.ToInt32(TimeSpan.FromTicks((long)item.RunTimeTicks).TotalSeconds); } try { var response = await Post <NowPlayingRequest, ScrobbleResponse>(request); if (response != null && !response.IsError()) { _logger.LogInformation("{0} is now playing artist={1}, track={2}, album={3}", user.Username, request.Artist, request.Track, request.Album); return; } _logger.LogError("Failed to send now playing for track: {0}", item.Name); } catch (Exception ex) { _logger.LogError("Failed to send now playing for track: ex={0}, name={1}, track={2}, artist={3}, album={4}, mbid={5}", ex, item.Name, request.Track, request.Artist, request.Album, request.MbId); } }
public async Task Scrobble(Audio item, LastfmUser user) { // API docs -> https://www.last.fm/api/show/track.scrobble var request = new ScrobbleRequest { Track = item.Name, Artist = item.Artists.First(), Timestamp = Helpers.CurrentTimestamp(), ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.Scrobble, SessionKey = user.SessionKey, Secure = true }; if (!string.IsNullOrWhiteSpace(item.Album)) { request.Album = item.Album; } if (item.ProviderIds.ContainsKey("MusicBrainzTrack")) { request.MbId = item.ProviderIds["MusicBrainzTrack"]; } try { // Send the request var response = await Post <ScrobbleRequest, ScrobbleResponse>(request); if (response != null && !response.IsError()) { _logger.LogInformation("{0} played artist={1}, track={2}, album={3}", user.Username, request.Artist, request.Track, request.Album); return; } _logger.LogError("Failed to Scrobble track: {0}", item.Name); } catch (Exception ex) { _logger.LogError("Failed to Scrobble track: track: ex={0}, name={1}, track={2}, artist={3}, album={4}, mbid={5}", ex, item.Name, request.Track, request.Artist, request.Album, request.MbId); } }
public async Task Scrobble(Audio item, LastfmUser user) { var request = new ScrobbleRequest { Track = item.Name, Artist = item.Artists.FirstOrDefault(), Timestamp = Helpers.CurrentTimestamp(), ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.Scrobble, SessionKey = user.SessionKey }; if (!string.IsNullOrWhiteSpace(item.Album)) { request.Album = item.Album; } if (item.ProviderIds.ContainsKey("MusicBrainzTrack")) { request.MbId = item.ProviderIds["MusicBrainzTrack"]; } try { //Send the request var response = await Post <ScrobbleRequest, ScrobbleResponse>(request); if (response != null && !response.IsError()) { Plugin.Logger.Info("{0} played '{1}' - {2} - {3}", user.Username, request.Track, request.Album, request.Artist); return; } Plugin.Logger.Error("Failed to Scrobble track: {0}", item.Name); } catch (Exception ex) { Plugin.Logger.ErrorException("Failed to Scrobble track: {0}", ex, item.Name); } }
/// <summary> /// Loves or unloves a track /// </summary> /// <param name="item">The track</param> /// <param name="user">The Lastfm User</param> /// <param name="love">If the track is loved or not</param> /// <returns></returns> public async Task <bool> LoveTrack(Audio item, LastfmUser user, bool love = true) { var request = new TrackLoveRequest(love) { Artist = item.Artists.First(), Track = item.Name, SessionKey = user.SessionKey, }; //Send the request var response = await Post <TrackLoveRequest, BaseResponse>(request).ConfigureAwait(false); if (response == null || response.IsError()) { Plugin.Logger.Error("{0} Failed to love = {3} track '{1}' - {2}", user.Username, item.Name, response?.Message ?? "empty response", love); return(false); } Plugin.Logger.Info("{0} {2}loved track '{1}'", user.Username, item.Name, love ? "" : "un"); return(true); }
public async Task NowPlaying(Audio item, LastfmUser user) { if (string.IsNullOrWhiteSpace(item.Name)) { Plugin.Logger.Error("Cannot set now playing for track: {0}, no name", item.Id); return; } var artist = item.Artists?.FirstOrDefault(); if (string.IsNullOrWhiteSpace(artist)) { Plugin.Logger.Error("Cannot set now playing for track: {0} ({1}), no artist found", item.Id, item.Name); return; } var request = new NowPlayingRequest { Track = item.Name, Artist = artist, Album = item.Album, SessionKey = user.SessionKey }; //Add duration if (item.RunTimeTicks != null) { request.Duration = Convert.ToInt32(TimeSpan.FromTicks((long)item.RunTimeTicks).TotalSeconds); } var response = await Post <NowPlayingRequest, ScrobbleResponse>(request).ConfigureAwait(false); if (response != null && !response.IsError()) { Plugin.Logger.Info("{0} is now playing '{1}' - {2} - {3}", user.Username, request.Track, request.Album, request.Artist); return; } Plugin.Logger.Error("Failed to send now playing for track: {0}", item.Name); }
public async Task Scrobble(Audio item, LastfmUser user) { var request = new ScrobbleRequest { Track = item.Name, Album = item.Album, Artist = item.Artists.First(), Timestamp = Helpers.CurrentTimestamp(), ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.Scrobble, SessionKey = user.SessionKey }; var response = await Post <ScrobbleRequest, ScrobbleResponse>(request); if (response != null && !response.IsError()) { Plugin.Logger.Info("{0} played '{1}' - {2} - {3}", user.Username, request.Track, request.Album, request.Artist); return; } Plugin.Logger.Error("Failed to Scrobble track: {0}", item.Name); }
private async Task <List <LastfmArtistTrack> > GetArtistTracks(LastfmUser lastfmUser, MusicArtist artist, IProgress <double> progress, CancellationToken cancellationToken, double maxProgress, double progressOffset) { var tracks = new List <LastfmArtistTrack>(); var page = 1; //Page 0 = 1 bool moreTracks; do { cancellationToken.ThrowIfCancellationRequested(); var response = await _apiClient.GetArtistTracks(lastfmUser, artist, cancellationToken, page ++).ConfigureAwait(false); if (response == null || !response.HasTracks()) { break; } tracks.AddRange(response.ArtistTracks.Tracks); moreTracks = !response.ArtistTracks.Metadata.IsLastPage(); } while (moreTracks); return(tracks); }
public async Task Scrobble(Audio item, LastfmUser user) { var request = new ScrobbleRequest { Track = item.Name, Album = item.Album, Artist = item.Artists.First(), Timestamp = Helpers.CurrentTimestamp(), ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.Scrobble, SessionKey = user.SessionKey }; var response = await Post<ScrobbleRequest, ScrobbleResponse>(request); if (response != null && !response.IsError()) { Plugin.Logger.Info("{0} played '{1}' - {2} - {3}", user.Username, request.Track, request.Album, request.Artist); return; } Plugin.Logger.Error("Failed to Scrobble track: {0}", item.Name); }
/// <summary> /// Loves or unloves a track /// </summary> /// <param name="item">The track</param> /// <param name="user">The Lastfm User</param> /// <param name="love">If the track is loved or not</param> /// <returns></returns> public async Task<bool> LoveTrack(Audio item, LastfmUser user, bool love = true) { var request = new TrackLoveRequest { Artist = item.Artists.First(), Track = item.Name, ApiKey = Strings.Keys.LastfmApiKey, Method = love ? Strings.Methods.TrackLove : Strings.Methods.TrackUnlove, SessionKey = user.SessionKey, }; //Send the request var response = await Post<TrackLoveRequest, BaseResponse>(request); if (response != null && !response.IsError()) { Plugin.Logger.Info("{0} {2}loved track '{1}'", user.Username, item.Name, (love ? "" : "un")); return true; } Plugin.Logger.Error("{0} Failed to love = {3} track '{1}' - {2}", user.Username, item.Name, response.Message, love); return false; }
/// <summary> /// Unlove a track. This is the same as LoveTrack with love as false /// </summary> /// <param name="item">The track</param> /// <param name="user">The Lastfm User</param> /// <returns></returns> public async Task <bool> UnloveTrack(Audio item, LastfmUser user) { return(await LoveTrack(item, user, false)); }
/// <summary> /// Unlove a track. This is the same as LoveTrack with love as false /// </summary> /// <param name="item">The track</param> /// <param name="user">The Lastfm User</param> /// <returns></returns> public async Task<bool> UnloveTrack(Audio item, LastfmUser user) { return await LoveTrack(item, user, false); }
private async Task SyncDataforUserByArtistBulk(User user, IProgress <double> progress, CancellationToken cancellationToken, double maxProgress, double progressOffset) { LastfmUser lastFmUser = UserHelpers.GetUser(user); if (!lastFmUser.Options.SyncFavourites) { return; } _logger.LogInformation("Syncing LastFM favourties for {0}", user.Username); List <MusicArtist> artists = _libraryManager.GetArtists(new InternalItemsQuery(user)) .Items .Select(i => i.Item1) .Cast <MusicArtist>() .ToList(); int matchedSongs = 0; // Fetch the user's loved tracks from LastFM API. List <LastfmLovedTrack> lovedTracks = await GetLovedTracksLibrary(lastFmUser, progress, cancellationToken, maxProgress, progressOffset); if (lovedTracks.Count == 0) { _logger.LogInformation("User {0} has no loved tracks in last.fm", user.Username); return; } // Group the list of loved tracks by artist List <IGrouping <string, LastfmLovedTrack> > groupedLovedTracks = lovedTracks.GroupBy(t => t.Artist.MusicBrainzId).ToList(); // Iterate over each artist in user's library // iterate over each song by artist // for each song, compare against the list of song/track in the lastfm loved track list foreach (MusicArtist artist in artists) { cancellationToken.ThrowIfCancellationRequested(); string artistMBid = Helpers.GetMusicBrainzArtistId(artist); if (artistMBid == null) { continue; } if (groupedLovedTracks.FirstOrDefault(t => t.Key.Equals(artistMBid)) == null || !groupedLovedTracks.FirstOrDefault(t => t.Key.Equals(artistMBid)).Any()) { continue; } _logger.LogDebug("Found {0} LastFM lovedtracks for {1}", groupedLovedTracks.FirstOrDefault(t => t.Key.Equals(artistMBid)).ToList().Count, artist.Name); // Loop through each song foreach (Audio song in artist.GetTaggedItems(new InternalItemsQuery(user) { IncludeItemTypes = new[] { "Audio" }, EnableTotalRecordCount = false }).OfType <Audio>().ToList()) { LastfmLovedTrack matchedSong = Helpers.FindMatchedLastfmSong(groupedLovedTracks.FirstOrDefault(t => t.Key.Equals(artistMBid)).ToList(), song); if (matchedSong == null) { continue; } // We have found a match matchedSongs++; var userData = _userDataManager.GetUserData(user, song); userData.IsFavorite = true; _userDataManager.SaveUserData(user, song, userData, UserDataSaveReason.UpdateUserRating, cancellationToken); _logger.LogDebug("Found library match for {0} = {1}", song.Name, matchedSong.Name); } } _logger.LogInformation("Finished Last.fm lovedTracks sync for {0}. Matched Songs: {2}", user.Username, matchedSongs); }
public async Task<LovedTracksResponse> GetLovedTracks(LastfmUser user) { var request = new GetLovedTracksRequest { User = user.Username, ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.GetLovedTracks }; return await Get<GetLovedTracksRequest, LovedTracksResponse>(request); }
public async Task<GetTracksResponse> GetTracks(LastfmUser user, MusicArtist artist, CancellationToken cancellationToken) { var request = new GetTracksRequest { User = user.Username, Artist = artist.Name, ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.GetTracks, Limit = 1000 }; return await Get<GetTracksRequest, GetTracksResponse>(request, cancellationToken); }
public async Task<GetTracksResponse> GetTracks(LastfmUser user, CancellationToken cancellationToken, int page = 0, int limit = 200) { var request = new GetTracksRequest { User = user.Username, ApiKey = Strings.Keys.LastfmApiKey, Method = Strings.Methods.GetTracks, Limit = limit, Page = page }; return await Get<GetTracksRequest, GetTracksResponse>(request, cancellationToken); }
/// <summary> /// Initializes a new instance of the <see cref="PluginConfiguration" /> class. /// </summary> public PluginConfiguration() { LastfmUsers = new LastfmUser[] { }; }
private async Task<List<LastfmTrack>> GetUsersLibrary(LastfmUser lastfmUser, IProgress<double> progress, CancellationToken cancellationToken, double maxProgress, double progressOffset) { var tracks = new List<LastfmTrack>(); var page = 1; //Page 0 = 1 bool moreTracks; do { cancellationToken.ThrowIfCancellationRequested(); var response = await _apiClient.GetTracks(lastfmUser, cancellationToken, page++).ConfigureAwait(false); if (response == null || !response.HasTracks()) break; tracks.AddRange(response.Tracks.Tracks); moreTracks = !response.Tracks.Metadata.IsLastPage(); //Only report progress in download because it will be 90% of the time taken var currentProgress = ((double)response.Tracks.Metadata.Page / response.Tracks.Metadata.TotalPages) * (maxProgress - progressOffset) + progressOffset; Plugin.Logger.Debug("Progress: " + currentProgress * 100); progress.Report(currentProgress * 100); } while (moreTracks); return tracks; }