diff --git a/Selector.CLI/WatcherService.cs b/Selector.CLI/WatcherService.cs index 8e15cdc..9ca5226 100644 --- a/Selector.CLI/WatcherService.cs +++ b/Selector.CLI/WatcherService.cs @@ -101,7 +101,7 @@ namespace Selector.CLI switch(watcherOption.Type) { case WatcherType.Player: - watcher = await WatcherFactory.Get(spotifyFactory, watcherOption.PollPeriod); + watcher = await WatcherFactory.Get(spotifyFactory, id: watcherOption.Name, pollPeriod: watcherOption.PollPeriod); break; case WatcherType.Playlist: throw new NotImplementedException("Playlist watchers not implemented"); diff --git a/Selector.Cache/Consumer/CacheWriterConsumer.cs b/Selector.Cache/Consumer/CacheWriterConsumer.cs index 5ee713c..b12d1e1 100644 --- a/Selector.Cache/Consumer/CacheWriterConsumer.cs +++ b/Selector.Cache/Consumer/CacheWriterConsumer.cs @@ -41,11 +41,11 @@ namespace Selector.Cache { var payload = JsonSerializer.Serialize((CurrentlyPlayingDTO) e); - Logger.LogTrace($"Caching current for [{e.Username}]"); + Logger.LogTrace($"Caching current for [{e.Id}/{e.SpotifyUsername}]"); - var resp = await Db.StringSetAsync(Key.CurrentlyPlaying(e.Username), payload); + var resp = await Db.StringSetAsync(Key.CurrentlyPlaying(e.Id), payload); - Logger.LogDebug($"Cached current for [{e.Username}], {(resp ? "value set" : "value NOT set")}"); + Logger.LogDebug($"Cached current for [{e.Id}/{e.SpotifyUsername}], {(resp ? "value set" : "value NOT set")}"); } diff --git a/Selector.Cache/Consumer/PublisherConsumer.cs b/Selector.Cache/Consumer/PublisherConsumer.cs index 6330679..2a99bd5 100644 --- a/Selector.Cache/Consumer/PublisherConsumer.cs +++ b/Selector.Cache/Consumer/PublisherConsumer.cs @@ -41,12 +41,12 @@ namespace Selector.Cache { var payload = JsonSerializer.Serialize((CurrentlyPlayingDTO) e); - Logger.LogTrace($"Publishing current for [{e.Username}]"); + Logger.LogTrace($"Publishing current for [{e.Id}/{e.SpotifyUsername}]"); // TODO: currently using spotify username for cache key, use db username - var receivers = await Subscriber.PublishAsync(Key.CurrentlyPlaying(e.Username), payload); + var receivers = await Subscriber.PublishAsync(Key.CurrentlyPlaying(e.Id), payload); - Logger.LogDebug($"Published current for [{e.Username}], {receivers} receivers"); + Logger.LogDebug($"Published current for [{e.Id}/{e.SpotifyUsername}], {receivers} receivers"); } public void Subscribe(IWatcher watch = null) diff --git a/Selector.Cache/DTO.cs b/Selector.Cache/DTO.cs index fea13f9..85bcd50 100644 --- a/Selector.Cache/DTO.cs +++ b/Selector.Cache/DTO.cs @@ -18,7 +18,7 @@ namespace Selector.Cache { return new() { Context = e.Current, - Username = e.Username, + Username = e.SpotifyUsername, Track = track }; } @@ -27,7 +27,7 @@ namespace Selector.Cache { return new() { Context = e.Current, - Username = e.Username, + Username = e.SpotifyUsername, Episode = episode }; } diff --git a/Selector.Cache/Key.cs b/Selector.Cache/Key.cs index a1fdab1..5c46f4d 100644 --- a/Selector.Cache/Key.cs +++ b/Selector.Cache/Key.cs @@ -7,14 +7,28 @@ namespace Selector.Cache public class Key { public const string CurrentlyPlayingName = "CurrentlyPlaying"; + public const string TrackName = "Track"; + public const string AlbumName = "Album"; + public const string ArtistName = "Artist"; + public const string AudioFeatureName = "AudioFeature"; + public const string PlayCountName = "PlayCount"; public const string WorkerName = "Worker"; - public static string CurrentlyPlaying(string user) => Namespace(new[] { user, CurrentlyPlayingName }); - public static string AudioFeature(string trackId) => Namespace(new[] { TrackName, trackId, AudioFeatureName }); + /// + /// Current playback for a user + /// + /// User's database Id (Guid) + /// + public static string CurrentlyPlaying(string user) => Namespace(user, CurrentlyPlayingName); + public static string AudioFeature(string trackId) => Namespace(TrackName, trackId, AudioFeatureName); - public static string Namespace(string[] args) => string.Join(":", args); + public static string TrackPlayCount(string name, string artist) => Namespace(TrackName, artist, name, PlayCountName); + public static string AlbumPlayCount(string name, string artist) => Namespace(AlbumName, artist, name, PlayCountName); + public static string ArtistPlayCount(string name) => Namespace(ArtistName, name, PlayCountName); + + public static string Namespace(params string[] args) => string.Join(":", args); } } diff --git a/Selector.Model/ApplicationUser.cs b/Selector.Model/ApplicationUser.cs index 6feadc9..211908d 100644 --- a/Selector.Model/ApplicationUser.cs +++ b/Selector.Model/ApplicationUser.cs @@ -22,9 +22,11 @@ namespace Selector.Model public class ApplicationUserDTO { + public string Id { get; set; } public string UserName { get; set; } public string Email { get; set; } public string PhoneNumber { get; set; } + public bool LockoutEnabled { get; set; } public bool SpotifyIsLinked { get; set; } public DateTime SpotifyLastRefresh { get; set; } @@ -35,9 +37,11 @@ namespace Selector.Model public string LastFmUsername { get; set; } public static explicit operator ApplicationUserDTO(ApplicationUser user) => new() { + Id = user.Id, UserName = user.UserName, Email = user.Email, PhoneNumber = user.PhoneNumber, + LockoutEnabled = user.LockoutEnabled, SpotifyIsLinked = user.SpotifyIsLinked, SpotifyLastRefresh = user.SpotifyLastRefresh, diff --git a/Selector.Web/Services/Mappings/NowPlayingMapping.cs b/Selector.Web/Services/Mappings/NowPlayingMapping.cs index c93e713..9eb8830 100644 --- a/Selector.Web/Services/Mappings/NowPlayingMapping.cs +++ b/Selector.Web/Services/Mappings/NowPlayingMapping.cs @@ -27,7 +27,7 @@ namespace Selector.Web.Service public async Task ConstructMapping(ISubscriber subscriber, IHubContext hub) { - var key = Key.CurrentlyPlaying(Username); + var key = Key.CurrentlyPlaying(UserId); (await subscriber.SubscribeAsync(key)).OnMessage(async message => { try{ diff --git a/Selector/Consumers/PlayCounter.cs b/Selector/Consumers/PlayCounter.cs index 73627c2..0ed7bd7 100644 --- a/Selector/Consumers/PlayCounter.cs +++ b/Selector/Consumers/PlayCounter.cs @@ -79,12 +79,12 @@ namespace Selector } else { - Logger.LogDebug($"Track info error [{e.Username}] [{trackInfo.Result.Status}]"); + Logger.LogDebug($"Track info error [{e.Id}/{e.SpotifyUsername}] [{trackInfo.Result.Status}]"); } } else { - Logger.LogError(trackInfo.Exception, $"Track info task faulted, [{e.Username}] [{e.Current.DisplayString()}]"); + Logger.LogError(trackInfo.Exception, $"Track info task faulted, [{e.Id}/{e.SpotifyUsername}] [{e.Current.DisplayString()}]"); } if (albumInfo.IsCompletedSuccessfully) @@ -95,12 +95,12 @@ namespace Selector } else { - Logger.LogDebug($"Album info error [{e.Username}] [{albumInfo.Result.Status}]"); + Logger.LogDebug($"Album info error [{e.Id}/{e.SpotifyUsername}] [{albumInfo.Result.Status}]"); } } else { - Logger.LogError(albumInfo.Exception, $"Album info task faulted, [{e.Username}] [{e.Current.DisplayString()}]"); + Logger.LogError(albumInfo.Exception, $"Album info task faulted, [{e.Id}/{e.SpotifyUsername}] [{e.Current.DisplayString()}]"); } //TODO: Add artist count @@ -113,15 +113,15 @@ namespace Selector } else { - Logger.LogDebug($"User info error [{e.Username}] [{userInfo.Result.Status}]"); + Logger.LogDebug($"User info error [{e.Id}/{e.SpotifyUsername}] [{userInfo.Result.Status}]"); } } else { - Logger.LogError(userInfo.Exception, $"User info task faulted, [{e.Username}] [{e.Current.DisplayString()}]"); + Logger.LogError(userInfo.Exception, $"User info task faulted, [{e.Id}/{e.SpotifyUsername}] [{e.Current.DisplayString()}]"); } - Logger.LogDebug($"Adding Last.fm data [{Credentials.Username}/{e.Username}] [{track.DisplayString()}], track: {trackCount}, album: {albumCount}, artist: {artistCount}, user: {userCount}"); + Logger.LogDebug($"Adding Last.fm data [{e.Id}/{e.SpotifyUsername}/{Credentials.Username}] [{track.DisplayString()}], track: {trackCount}, album: {albumCount}, artist: {artistCount}, user: {userCount}"); OnNewPlayCount(new() { diff --git a/Selector/Watcher/BaseWatcher.cs b/Selector/Watcher/BaseWatcher.cs index fd0197f..706588b 100644 --- a/Selector/Watcher/BaseWatcher.cs +++ b/Selector/Watcher/BaseWatcher.cs @@ -13,7 +13,8 @@ namespace Selector public abstract class BaseWatcher: IWatcher { protected readonly ILogger Logger; - public string Username { get; set; } + public string Id { get; set; } + public string SpotifyUsername { get; set; } public BaseWatcher(ILogger logger = null) { diff --git a/Selector/Watcher/Interfaces/Events.cs b/Selector/Watcher/Interfaces/Events.cs index 78544a3..54a38b2 100644 --- a/Selector/Watcher/Interfaces/Events.cs +++ b/Selector/Watcher/Interfaces/Events.cs @@ -9,17 +9,23 @@ namespace Selector /// /// Spotify Username /// - public string Username { get; set; } + public string SpotifyUsername { get; set; } + /// + /// String Id for watcher, used to hold user Db Id + /// + /// + public string Id { get; set; } PlayerTimeline Timeline { get; set; } - public static ListeningChangeEventArgs From(CurrentlyPlayingContext previous, CurrentlyPlayingContext current, PlayerTimeline timeline, string username = null) + public static ListeningChangeEventArgs From(CurrentlyPlayingContext previous, CurrentlyPlayingContext current, PlayerTimeline timeline, string id = null, string username = null) { return new ListeningChangeEventArgs() { Previous = previous, Current = current, Timeline = timeline, - Username = username + Id = id, + SpotifyUsername = username }; } } diff --git a/Selector/Watcher/Interfaces/IWatcherFactory.cs b/Selector/Watcher/Interfaces/IWatcherFactory.cs index b60e3d2..8bbe1cd 100644 --- a/Selector/Watcher/Interfaces/IWatcherFactory.cs +++ b/Selector/Watcher/Interfaces/IWatcherFactory.cs @@ -7,7 +7,7 @@ namespace Selector { public interface IWatcherFactory { - public Task Get(ISpotifyConfigFactory spotifyFactory, int pollPeriod) + public Task Get(ISpotifyConfigFactory spotifyFactory, string id, int pollPeriod) where T : class, IWatcher; } } diff --git a/Selector/Watcher/PlayerWatcher.cs b/Selector/Watcher/PlayerWatcher.cs index 1c9ab9a..30fd7a1 100644 --- a/Selector/Watcher/PlayerWatcher.cs +++ b/Selector/Watcher/PlayerWatcher.cs @@ -74,14 +74,14 @@ namespace Selector && (Live.Item is FullTrack || Live.Item is FullEpisode)) { Logger.LogDebug($"Playback started: {Live.DisplayString()}"); - OnPlayingChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); + OnPlayingChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername)); } // STOPPED PLAYBACK else if((previous.Item is FullTrack || previous.Item is FullEpisode) && Live is null) { Logger.LogDebug($"Playback stopped: {previous.DisplayString()}"); - OnPlayingChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); + OnPlayingChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername)); } // CONTINUING PLAYBACK else { @@ -92,17 +92,17 @@ namespace Selector { if(!eq.IsEqual(previousTrack, currentTrack)) { Logger.LogDebug($"Track changed: {previousTrack.DisplayString()} -> {currentTrack.DisplayString()}"); - OnItemChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); + OnItemChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername)); } if(!eq.IsEqual(previousTrack.Album, currentTrack.Album)) { Logger.LogDebug($"Album changed: {previousTrack.Album.DisplayString()} -> {currentTrack.Album.DisplayString()}"); - OnAlbumChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); + OnAlbumChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername)); } if(!eq.IsEqual(previousTrack.Artists[0], currentTrack.Artists[0])) { Logger.LogDebug($"Artist changed: {previousTrack.Artists.DisplayString()} -> {currentTrack.Artists.DisplayString()}"); - OnArtistChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); + OnArtistChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername)); } } // CHANGED CONTENT @@ -110,8 +110,8 @@ namespace Selector || (previous.Item is FullEpisode && Live.Item is FullTrack)) { Logger.LogDebug($"Media type changed: {previous.Item}, {previous.Item}"); - OnContentChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); - OnItemChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); + OnContentChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername)); + OnItemChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername)); } // PODCASTS else if(previous.Item is FullEpisode previousEp @@ -119,7 +119,7 @@ namespace Selector { if(!eq.IsEqual(previousEp, currentEp)) { Logger.LogDebug($"Podcast changed: {previousEp.DisplayString()} -> {currentEp.DisplayString()}"); - OnItemChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); + OnItemChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername)); } } else { @@ -129,25 +129,25 @@ namespace Selector // CONTEXT if(!eq.IsEqual(previous.Context, Live.Context)) { Logger.LogDebug($"Context changed: {previous.Context.DisplayString()} -> {Live.Context.DisplayString()}"); - OnContextChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); + OnContextChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername)); } // DEVICE if(!eq.IsEqual(previous?.Device, Live?.Device)) { Logger.LogDebug($"Device changed: {previous?.Device.DisplayString()} -> {Live?.Device.DisplayString()}"); - OnDeviceChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); + OnDeviceChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername)); } // IS PLAYING if(previous.IsPlaying != Live.IsPlaying) { Logger.LogDebug($"Playing state changed: {previous.IsPlaying} -> {Live.IsPlaying}"); - OnPlayingChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); + OnPlayingChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername)); } // VOLUME if(previous.Device.VolumePercent != Live.Device.VolumePercent) { Logger.LogDebug($"Volume changed: {previous.Device.VolumePercent}% -> {Live.Device.VolumePercent}%"); - OnVolumeChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); + OnVolumeChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername)); } } } diff --git a/Selector/Watcher/WatcherFactory.cs b/Selector/Watcher/WatcherFactory.cs index 1f2bb6c..c665554 100644 --- a/Selector/Watcher/WatcherFactory.cs +++ b/Selector/Watcher/WatcherFactory.cs @@ -19,7 +19,7 @@ namespace Selector Equal = equal; } - public async Task Get(ISpotifyConfigFactory spotifyFactory, int pollPeriod = 3000) + public async Task Get(ISpotifyConfigFactory spotifyFactory, string id = null, int pollPeriod = 3000) where T : class, IWatcher { if(typeof(T).IsAssignableFrom(typeof(PlayerWatcher))) @@ -35,7 +35,8 @@ namespace Selector LoggerFactory?.CreateLogger() ?? NullLogger.Instance, pollPeriod: pollPeriod ) { - Username = user.DisplayName + SpotifyUsername = user.DisplayName, + Id = id }; } //else if (typeof(T).IsAssignableFrom(typeof(PlaylistWatcher)))