audio feature pushing to web frontend working
This commit is contained in:
parent
a3628182c9
commit
b75920867b
@ -6,7 +6,6 @@
|
|||||||
"Watcher": {
|
"Watcher": {
|
||||||
"Instances": [
|
"Instances": [
|
||||||
{
|
{
|
||||||
"name": "Player Watcher",
|
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"lastfmusername": "sarsoo",
|
"lastfmusername": "sarsoo",
|
||||||
"pollperiod": 2000,
|
"pollperiod": 2000,
|
||||||
|
@ -20,14 +20,25 @@ namespace Selector.Cache
|
|||||||
Cache = cache;
|
Cache = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TrackAudioFeatures> Get(string userId, string trackId)
|
public async Task<TrackAudioFeatures> Get(string refreshToken, string trackId)
|
||||||
{
|
{
|
||||||
|
if(string.IsNullOrWhiteSpace(trackId)) throw new ArgumentNullException("No track Id provided");
|
||||||
|
|
||||||
var track = await Cache.StringGetAsync(Key.AudioFeature(trackId));
|
var track = await Cache.StringGetAsync(Key.AudioFeature(trackId));
|
||||||
if (track == RedisValue.Null)
|
if (track == RedisValue.Null)
|
||||||
{
|
{
|
||||||
// TODO: finish implementing network pull
|
if(!string.IsNullOrWhiteSpace(refreshToken))
|
||||||
// return await SpotifyClient.GetAudioFeatures(trackId);
|
{
|
||||||
throw new NotImplementedException("Can't pull over network yet");
|
var factory = await SpotifyFactory.GetFactory(refreshToken);
|
||||||
|
var spotifyClient = new SpotifyClient(await factory.GetConfig());
|
||||||
|
|
||||||
|
// TODO: Error checking
|
||||||
|
return await spotifyClient.Tracks.GetAudioFeatures(trackId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,6 @@ using System.Text.Json;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
|
||||||
|
|
||||||
using SpotifyAPI.Web;
|
using SpotifyAPI.Web;
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
@ -36,7 +35,7 @@ namespace Selector.Cache
|
|||||||
|
|
||||||
public async Task AsyncCacheCallback(AnalysedTrack e)
|
public async Task AsyncCacheCallback(AnalysedTrack e)
|
||||||
{
|
{
|
||||||
var payload = JsonSerializer.Serialize(e);
|
var payload = JsonSerializer.Serialize(e.Features);
|
||||||
|
|
||||||
Logger.LogTrace($"Caching current for [{e.Track.DisplayString()}]");
|
Logger.LogTrace($"Caching current for [{e.Track.DisplayString()}]");
|
||||||
|
|
||||||
|
@ -1,29 +1,36 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Data.SqlTypes;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
using SpotifyAPI.Web;
|
using SpotifyAPI.Web;
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
|
|
||||||
using Selector.Cache;
|
using Selector.Cache;
|
||||||
using System.Text.Json;
|
using Selector.Model;
|
||||||
|
|
||||||
namespace Selector.Web.Hubs
|
namespace Selector.Web.Hubs
|
||||||
{
|
{
|
||||||
public interface INowPlayingHubClient
|
public interface INowPlayingHubClient
|
||||||
{
|
{
|
||||||
public Task OnNewPlaying(CurrentlyPlayingDTO context);
|
public Task OnNewPlaying(CurrentlyPlayingDTO context);
|
||||||
// public Task OnNewAudioFeature(TrackAudioFeatures features);
|
public Task OnNewAudioFeature(TrackAudioFeatures features);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NowPlayingHub: Hub<INowPlayingHubClient>
|
public class NowPlayingHub: Hub<INowPlayingHubClient>
|
||||||
{
|
{
|
||||||
private readonly IDatabaseAsync Cache;
|
private readonly IDatabaseAsync Cache;
|
||||||
// private readonly AudioFeaturePuller AudioFeaturePuller;
|
private readonly AudioFeaturePuller AudioFeaturePuller;
|
||||||
|
private readonly ApplicationDbContext Db;
|
||||||
|
|
||||||
public NowPlayingHub(IDatabaseAsync cache)
|
public NowPlayingHub(IDatabaseAsync cache, AudioFeaturePuller puller, ApplicationDbContext db)
|
||||||
{
|
{
|
||||||
Cache = cache;
|
Cache = cache;
|
||||||
|
AudioFeaturePuller = puller;
|
||||||
|
Db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task OnConnected()
|
public async Task OnConnected()
|
||||||
@ -34,13 +41,33 @@ namespace Selector.Web.Hubs
|
|||||||
public async Task SendNewPlaying()
|
public async Task SendNewPlaying()
|
||||||
{
|
{
|
||||||
var nowPlaying = await Cache.StringGetAsync(Key.CurrentlyPlaying(Context.UserIdentifier));
|
var nowPlaying = await Cache.StringGetAsync(Key.CurrentlyPlaying(Context.UserIdentifier));
|
||||||
var deserialised = JsonSerializer.Deserialize<CurrentlyPlayingDTO>(nowPlaying);
|
if (nowPlaying != RedisValue.Null)
|
||||||
await Clients.Caller.OnNewPlaying(deserialised);
|
{
|
||||||
|
var deserialised = JsonSerializer.Deserialize<CurrentlyPlayingDTO>(nowPlaying);
|
||||||
|
await Clients.Caller.OnNewPlaying(deserialised);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// public async Task SendAudioFeatures(string trackId)
|
public async Task SendAudioFeatures(string trackId)
|
||||||
// {
|
{
|
||||||
// await Clients.Caller.OnNewAudioFeature(await AudioFeaturePuller.Get(trackId));
|
var user = Db.Users
|
||||||
// }
|
.AsNoTracking()
|
||||||
|
.Where(u => u.Id == Context.UserIdentifier)
|
||||||
|
.SingleOrDefault()
|
||||||
|
?? throw new SqlNullValueException("No user returned");
|
||||||
|
var watcher = Db.Watcher
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(w => w.UserId == Context.UserIdentifier
|
||||||
|
&& w.Type == WatcherType.Player)
|
||||||
|
.SingleOrDefault()
|
||||||
|
?? throw new SqlNullValueException($"No player watcher found for [{user.UserName}]");
|
||||||
|
|
||||||
|
var feature = await AudioFeaturePuller.Get(user.SpotifyRefreshToken, trackId);
|
||||||
|
|
||||||
|
if (feature is not null)
|
||||||
|
{
|
||||||
|
await Clients.Caller.OnNewAudioFeature(feature);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
47
Selector.Web/Services/SpotifyInitialiser.cs
Normal file
47
Selector.Web/Services/SpotifyInitialiser.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace Selector.Web.Service {
|
||||||
|
public class SpotifyInitialiser : IHostedService
|
||||||
|
{
|
||||||
|
private readonly ILogger<SpotifyInitialiser> Logger;
|
||||||
|
private readonly IRefreshTokenFactoryProvider FactoryProvider;
|
||||||
|
private readonly RootOptions Config;
|
||||||
|
|
||||||
|
public SpotifyInitialiser(
|
||||||
|
ILogger<SpotifyInitialiser> logger,
|
||||||
|
IRefreshTokenFactoryProvider factoryProvider,
|
||||||
|
IOptions<RootOptions> config
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Logger = logger;
|
||||||
|
FactoryProvider = factoryProvider;
|
||||||
|
Config = config.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Logger.LogInformation("Initialising Spotify Factory");
|
||||||
|
|
||||||
|
if(string.IsNullOrEmpty(Config.ClientId) || string.IsNullOrEmpty(Config.ClientSecret))
|
||||||
|
{
|
||||||
|
Logger.LogError("Unable to initialise Spotify factory, null client id or secret");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FactoryProvider.Initialise(Config.ClientId, Config.ClientSecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -43,7 +43,7 @@ namespace Selector.Web
|
|||||||
|
|
||||||
services.AddRazorPages().AddRazorRuntimeCompilation();
|
services.AddRazorPages().AddRazorRuntimeCompilation();
|
||||||
services.AddControllers();
|
services.AddControllers();
|
||||||
services.AddSignalR();
|
services.AddSignalR(o => o.EnableDetailedErrors = true);
|
||||||
|
|
||||||
services.AddDbContext<ApplicationDbContext>(options =>
|
services.AddDbContext<ApplicationDbContext>(options =>
|
||||||
options.UseNpgsql(Configuration.GetConnectionString("Default"))
|
options.UseNpgsql(Configuration.GetConnectionString("Default"))
|
||||||
@ -117,7 +117,9 @@ namespace Selector.Web
|
|||||||
services.AddTransient<ISubscriber>(services => services.GetService<ConnectionMultiplexer>().GetSubscriber());
|
services.AddTransient<ISubscriber>(services => services.GetService<ConnectionMultiplexer>().GetSubscriber());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
services.AddHostedService<SpotifyInitialiser>();
|
||||||
services.AddSingleton<IRefreshTokenFactoryProvider, CachingRefreshTokenFactoryProvider>();
|
services.AddSingleton<IRefreshTokenFactoryProvider, CachingRefreshTokenFactoryProvider>();
|
||||||
|
services.AddSingleton<AudioFeaturePuller>();
|
||||||
|
|
||||||
services.AddSingleton<CacheHubProxy>();
|
services.AddSingleton<CacheHubProxy>();
|
||||||
services.AddHostedService<CacheHubProxyService>();
|
services.AddHostedService<CacheHubProxyService>();
|
||||||
|
@ -40,17 +40,17 @@ const app = Vue.createApp({
|
|||||||
this.currentlyPlaying = context;
|
this.currentlyPlaying = context;
|
||||||
this.cards = [];
|
this.cards = [];
|
||||||
|
|
||||||
// if(context.track !== null && context.track !== undefined)
|
if(context.track !== null && context.track !== undefined)
|
||||||
// {
|
{
|
||||||
// connection.invoke("SendAudioFeatures", context.track.id);
|
connection.invoke("SendAudioFeatures", context.track.id);
|
||||||
// }
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// connection.on("OnNewAudioFeature", (feature: TrackAudioFeatures) =>
|
connection.on("OnNewAudioFeature", (feature: TrackAudioFeatures) =>
|
||||||
// {
|
{
|
||||||
// console.log(feature);
|
console.log(feature);
|
||||||
// this.trackFeatures = feature;
|
this.trackFeatures = feature;
|
||||||
// });
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user