// async due to await calls so can't be inside the above lambda expression without farmimg it out to a seperate function private async void UpdateHistoryInternal() { bool canRun = false; lock (historyLock) { if (!isUpdatingHistory) { isUpdatingHistory = true; canRun = true; } } if (!canRun) { return; } Logger.Current.Log(new CallerInfo(), LogLevel.Info, "Updating history items"); List <HistoryTable> historyItems = DatabaseManager.Current.FetchHistoryItems(); // Process everything first so we don't have to wait for scrobbles to see those updates foreach (HistoryTable historyItem in historyItems) { SongModel song = LibraryModel.Current.LookupSongById(historyItem.SongId); if (song != null) { if (!historyItem.Processed) { await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { song.PlayCount++; if (song.LastPlayed < historyItem.DatePlayed) { song.LastPlayed = historyItem.DatePlayed; } }); historyItem.Processed = true; DatabaseManager.Current.Update(historyItem); } } } Logger.Current.Log(new CallerInfo(), LogLevel.Info, "Scrobbling history items"); // TODO: #3 can batch scrobbles foreach (HistoryTable historyItem in historyItems) { if (!historyItem.Scrobbled) { LastfmStatusCode scrobbleResult = await LastFMManager.Current.ScrobbleTrack(historyItem.SongName, historyItem.ArtistName, new DateTime(historyItem.DatePlayed)); Logger.Current.Log(new CallerInfo(), LogLevel.Info, "Scrobbling row {0} result {1}", historyItem.RowId, scrobbleResult); // "Failure" is non-recoverable, so actually mark it as scrobbled so we don't retry later if (scrobbleResult == LastfmStatusCode.Success || scrobbleResult == LastfmStatusCode.Failure) { historyItem.Scrobbled = true; } } if (historyItem.Processed && historyItem.Scrobbled) { DatabaseManager.Current.DeleteHistoryItem(historyItem.RowId); } else { DatabaseManager.Current.Update(historyItem); } } Logger.Current.Log(new CallerInfo(), LogLevel.Info, "Done updating history items"); lock (historyLock) { isUpdatingHistory = false; } }
public async Task <LastfmStatusCode> ScrobbleTrack(string trackName, string artistName, DateTime time, bool retry = false) { bool isScrobblingOn = ApplicationSettings.GetSettingsValue <bool>(ApplicationSettings.SETTING_IS_LASTFM_SCROBBLING_ENABLED, false); if (!isScrobblingOn) { return(LastfmStatusCode.Success); } string sessionKey = ApplicationSettings.GetSettingsValue <string>(ApplicationSettings.SETTING_LASTFM_SESSION_TOKEN, string.Empty); if (sessionKey == string.Empty) { await UpdateScrobbleSession(); sessionKey = ApplicationSettings.GetSettingsValue <string>(ApplicationSettings.SETTING_LASTFM_SESSION_TOKEN, string.Empty); if (sessionKey == string.Empty) { return(LastfmStatusCode.Failure); } } int totalSeconds = (int)(time - UnixTimeZero).TotalSeconds; JObject result = await getInfo("track.scrobble", new Dictionary <string, string>() { { "track", trackName }, { "artist", artistName }, { "timestamp", totalSeconds.ToString() }, { "sk", sessionKey } }, true); if (result["error"] != null) { int r = Int32.Parse(result["error"].ToString()); // bad session key if (r == 9 && !retry) { Logger.Current.Log(new CallerInfo(), LogLevel.Warning, "Got an invalid session response when scrobbling, retrying"); await UpdateScrobbleSession(); LastfmStatusCode secondSuccess = await ScrobbleTrack(trackName, artistName, time, true); return(secondSuccess); } else if (r == 8 || r == 11 || r == 16 || r == 29) { Logger.Current.Log(new CallerInfo(), LogLevel.Warning, "Got an retryable response {0} when scrobbling, retrying later", r); return(LastfmStatusCode.RetryableFailure); } Logger.Current.Log(new CallerInfo(), LogLevel.Warning, "Got an failure response {0} when scrobbling, giving up", r); return(LastfmStatusCode.Failure); } else if (result["scrobbles"] != null) { return(LastfmStatusCode.Success); } else { return(LastfmStatusCode.Failure); } }