2021-10-11 01:06:43 +01:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
2021-11-29 21:04:15 +00:00
|
|
|
|
|
2021-10-12 23:29:05 +01:00
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
2021-10-11 01:06:43 +01:00
|
|
|
|
using Microsoft.Extensions.Hosting;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
2021-10-11 18:17:36 +01:00
|
|
|
|
using Microsoft.Extensions.Options;
|
2021-10-11 01:06:43 +01:00
|
|
|
|
|
2021-10-28 23:05:07 +01:00
|
|
|
|
using Selector.Cache;
|
|
|
|
|
|
2021-10-11 01:06:43 +01:00
|
|
|
|
namespace Selector.CLI
|
|
|
|
|
{
|
2021-11-25 18:26:20 +00:00
|
|
|
|
class LocalWatcherService : IHostedService
|
2021-10-11 01:06:43 +01:00
|
|
|
|
{
|
2021-10-12 23:29:05 +01:00
|
|
|
|
private const string ConfigInstanceKey = "localconfig";
|
|
|
|
|
|
2021-11-25 18:26:20 +00:00
|
|
|
|
private readonly ILogger<LocalWatcherService> Logger;
|
2021-10-11 18:17:36 +01:00
|
|
|
|
private readonly RootOptions Config;
|
2021-10-12 23:29:05 +01:00
|
|
|
|
private readonly IWatcherFactory WatcherFactory;
|
|
|
|
|
private readonly IWatcherCollectionFactory WatcherCollectionFactory;
|
|
|
|
|
private readonly IRefreshTokenFactoryProvider SpotifyFactory;
|
2021-11-29 21:04:15 +00:00
|
|
|
|
|
|
|
|
|
private readonly IServiceProvider ServiceProvider;
|
2021-10-11 01:06:43 +01:00
|
|
|
|
|
2021-10-11 23:19:19 +01:00
|
|
|
|
private Dictionary<string, IWatcherCollection> Watchers { get; set; } = new();
|
|
|
|
|
|
2021-11-25 18:26:20 +00:00
|
|
|
|
public LocalWatcherService(
|
2021-10-12 23:29:05 +01:00
|
|
|
|
IWatcherFactory watcherFactory,
|
|
|
|
|
IWatcherCollectionFactory watcherCollectionFactory,
|
|
|
|
|
IRefreshTokenFactoryProvider spotifyFactory,
|
2021-11-29 21:04:15 +00:00
|
|
|
|
|
|
|
|
|
IServiceProvider serviceProvider,
|
|
|
|
|
|
|
|
|
|
ILogger<LocalWatcherService> logger,
|
|
|
|
|
IOptions<RootOptions> config
|
2021-10-12 23:29:05 +01:00
|
|
|
|
) {
|
2021-11-29 21:04:15 +00:00
|
|
|
|
Logger = logger;
|
2021-10-11 18:17:36 +01:00
|
|
|
|
Config = config.Value;
|
2021-11-29 21:04:15 +00:00
|
|
|
|
|
2021-10-12 23:29:05 +01:00
|
|
|
|
WatcherFactory = watcherFactory;
|
|
|
|
|
WatcherCollectionFactory = watcherCollectionFactory;
|
|
|
|
|
SpotifyFactory = spotifyFactory;
|
2021-11-29 21:04:15 +00:00
|
|
|
|
|
|
|
|
|
ServiceProvider = serviceProvider;
|
2021-10-11 01:06:43 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-12 23:29:05 +01:00
|
|
|
|
public async Task StartAsync(CancellationToken cancellationToken)
|
2021-10-11 01:06:43 +01:00
|
|
|
|
{
|
2021-11-25 18:26:20 +00:00
|
|
|
|
Logger.LogInformation("Starting local watcher service...");
|
2021-10-11 01:06:43 +01:00
|
|
|
|
|
2021-11-25 18:26:20 +00:00
|
|
|
|
var watcherIndices = await InitInstances();
|
2021-10-11 23:19:19 +01:00
|
|
|
|
|
2021-12-18 17:45:34 +00:00
|
|
|
|
Logger.LogInformation("Starting {count} affected watcher collection(s)...", watcherIndices.Count());
|
2021-10-12 23:29:05 +01:00
|
|
|
|
StartWatcherCollections(watcherIndices);
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-25 18:26:20 +00:00
|
|
|
|
private async Task<IEnumerable<string>> InitInstances()
|
2021-10-12 23:29:05 +01:00
|
|
|
|
{
|
|
|
|
|
var indices = new HashSet<string>();
|
|
|
|
|
|
|
|
|
|
foreach (var watcherOption in Config.WatcherOptions.Instances)
|
|
|
|
|
{
|
|
|
|
|
var logMsg = new StringBuilder();
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(watcherOption.Name))
|
|
|
|
|
{
|
2021-10-13 23:19:47 +01:00
|
|
|
|
logMsg.Append($"Creating [{watcherOption.Name}] watcher [{watcherOption.Type}]");
|
2021-10-12 23:29:05 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-10-13 23:19:47 +01:00
|
|
|
|
logMsg.Append($"Creating new [{watcherOption.Type}] watcher");
|
2021-10-12 23:29:05 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(watcherOption.PlaylistUri)) logMsg.Append($" [{ watcherOption.PlaylistUri}]");
|
|
|
|
|
Logger.LogInformation(logMsg.ToString());
|
|
|
|
|
|
|
|
|
|
var watcherCollectionIdx = watcherOption.WatcherCollection ?? ConfigInstanceKey;
|
|
|
|
|
indices.Add(watcherCollectionIdx);
|
|
|
|
|
|
|
|
|
|
if (!Watchers.ContainsKey(watcherCollectionIdx))
|
|
|
|
|
Watchers[watcherCollectionIdx] = WatcherCollectionFactory.Get();
|
|
|
|
|
|
|
|
|
|
var watcherCollection = Watchers[watcherCollectionIdx];
|
|
|
|
|
|
|
|
|
|
Logger.LogDebug("Getting Spotify factory");
|
|
|
|
|
var spotifyFactory = await SpotifyFactory.GetFactory(watcherOption.RefreshKey);
|
|
|
|
|
|
|
|
|
|
IWatcher watcher = null;
|
|
|
|
|
switch(watcherOption.Type)
|
|
|
|
|
{
|
|
|
|
|
case WatcherType.Player:
|
2021-11-05 18:41:45 +00:00
|
|
|
|
watcher = await WatcherFactory.Get<PlayerWatcher>(spotifyFactory, id: watcherOption.Name, pollPeriod: watcherOption.PollPeriod);
|
2021-10-12 23:29:05 +01:00
|
|
|
|
break;
|
|
|
|
|
case WatcherType.Playlist:
|
|
|
|
|
throw new NotImplementedException("Playlist watchers not implemented");
|
2021-10-31 09:19:48 +00:00
|
|
|
|
// break;
|
2021-10-12 23:29:05 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-13 23:19:47 +01:00
|
|
|
|
List<IConsumer> consumers = new();
|
|
|
|
|
foreach(var consumer in watcherOption.Consumers)
|
|
|
|
|
{
|
|
|
|
|
switch(consumer)
|
|
|
|
|
{
|
|
|
|
|
case Consumers.AudioFeatures:
|
2021-11-29 21:04:15 +00:00
|
|
|
|
consumers.Add(await ServiceProvider.GetService<AudioFeatureInjectorFactory>().Get(spotifyFactory));
|
2021-10-28 23:05:07 +01:00
|
|
|
|
break;
|
|
|
|
|
|
2021-10-29 22:35:34 +01:00
|
|
|
|
case Consumers.AudioFeaturesCache:
|
2021-11-29 21:04:15 +00:00
|
|
|
|
consumers.Add(await ServiceProvider.GetService<CachingAudioFeatureInjectorFactory>().Get(spotifyFactory));
|
2021-10-29 22:35:34 +01:00
|
|
|
|
break;
|
|
|
|
|
|
2021-10-28 23:05:07 +01:00
|
|
|
|
case Consumers.CacheWriter:
|
2021-11-29 21:04:15 +00:00
|
|
|
|
consumers.Add(await ServiceProvider.GetService<CacheWriterFactory>().Get());
|
2021-10-28 23:05:07 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Consumers.Publisher:
|
2021-11-29 21:04:15 +00:00
|
|
|
|
consumers.Add(await ServiceProvider.GetService<PublisherFactory>().Get());
|
2021-10-13 23:19:47 +01:00
|
|
|
|
break;
|
2021-10-31 08:54:11 +00:00
|
|
|
|
|
|
|
|
|
case Consumers.PlayCounter:
|
|
|
|
|
if(!string.IsNullOrWhiteSpace(watcherOption.LastFmUsername))
|
|
|
|
|
{
|
2021-12-04 12:49:09 +00:00
|
|
|
|
consumers.Add(await ServiceProvider.GetService<PlayCounterFactory>().Get(creds: new() { Username = watcherOption.LastFmUsername }));
|
2021-10-31 08:54:11 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-11-25 18:26:20 +00:00
|
|
|
|
Logger.LogError("No Last.fm username provided, skipping play counter");
|
2021-10-31 08:54:11 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2021-10-13 23:19:47 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
watcherCollection.Add(watcher, consumers);
|
2021-10-12 23:29:05 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return indices;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void StartWatcherCollections(IEnumerable<string> indices)
|
|
|
|
|
{
|
|
|
|
|
foreach (var index in indices)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2021-12-18 17:45:34 +00:00
|
|
|
|
Logger.LogInformation("Starting watcher collection [{index}]", index);
|
2021-10-12 23:29:05 +01:00
|
|
|
|
Watchers[index].Start();
|
|
|
|
|
}
|
|
|
|
|
catch (KeyNotFoundException)
|
|
|
|
|
{
|
2021-12-18 17:45:34 +00:00
|
|
|
|
Logger.LogError("Unable to retrieve watcher collection [{index}] when starting", index);
|
2021-10-12 23:29:05 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-10-11 01:06:43 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Task StopAsync(CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
Logger.LogInformation("Shutting down");
|
2021-10-11 23:19:19 +01:00
|
|
|
|
|
|
|
|
|
foreach((var key, var watcher) in Watchers)
|
|
|
|
|
{
|
2021-12-18 17:45:34 +00:00
|
|
|
|
Logger.LogInformation("Stopping watcher collection [{key}]", key);
|
2021-10-11 23:19:19 +01:00
|
|
|
|
watcher.Stop();
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-11 01:06:43 +01:00
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|