diff --git a/Selector.Web/Pages/Now.cs b/Selector.Web/Pages/Now.cs new file mode 100644 index 0000000..b38c158 --- /dev/null +++ b/Selector.Web/Pages/Now.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Logging; +using Microsoft.AspNetCore.SignalR; +using Microsoft.AspNetCore.Identity; + +using Selector.Web.Hubs; +using Selector.Web.Service; +using Selector.Model; + +namespace Selector.Web.Pages +{ + public class NowModel : PageModel + { + private readonly ILogger Logger; + private readonly INowPlayingMappingFactory MappingFactory; + private readonly CacheHubProxy HubProxy; + private readonly UserManager UserManager; + + public NowModel(ILogger logger, + INowPlayingMappingFactory mappingFactory, + CacheHubProxy hubProxy, + UserManager userManager) + { + Logger = logger; + MappingFactory = mappingFactory; + HubProxy = hubProxy; + UserManager = userManager; + } + + public void OnGet() + { + HubProxy.FormMapping(MappingFactory.Get(UserManager.GetUserId(User))); + } + } +} diff --git a/Selector.Web/Pages/Now.cshtml b/Selector.Web/Pages/Now.cshtml new file mode 100644 index 0000000..6366216 --- /dev/null +++ b/Selector.Web/Pages/Now.cshtml @@ -0,0 +1,13 @@ +@page +@model NowModel +@{ + ViewData["Title"] = "Now"; +} + +
+

Now

+
+ +@section Scripts { + +} \ No newline at end of file diff --git a/Selector.Web/Services/CacheHubProxy.cs b/Selector.Web/Services/CacheHubProxy.cs new file mode 100644 index 0000000..a6a181d --- /dev/null +++ b/Selector.Web/Services/CacheHubProxy.cs @@ -0,0 +1,71 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.SignalR; + +using StackExchange.Redis; +using Selector.Web.Hubs; + +namespace Selector.Web.Service +{ + public class CacheHubProxy + { + private readonly ILogger Logger; + private readonly ISubscriber Subscriber; + private readonly ServiceProvider Services; + + public CacheHubProxy(ILogger logger, + ISubscriber subscriber, + ServiceProvider services + ) + { + Logger = logger; + Subscriber = subscriber; + Services = services; + } + + public void FormMapping(ICacheHubMapping mapping) where THub: Hub where T: class + { + var context = Services.GetService>(); + mapping.ConstructMapping(Subscriber, context); + } + } + + // public class CacheHubProxy + // where THub: Hub + // where T: class + // { + // private readonly ILogger> Logger; + // private readonly ISubscriber Subscriber; + // private readonly IHubContext HubContext; + // private readonly List> Mappings; + + // public CacheHubProxy(ILogger> logger, + // ISubscriber subscriber, + // IHubContext hubContext, + // IEnumerable> mappings + // ) + // { + // Logger = logger; + // Subscriber = subscriber; + // HubContext = hubContext; + // Mappings = mappings.ToList(); + // } + + // public void FormMapping(ICacheHubMapping mapping) + // { + // mapping.ConstructMapping(Subscriber, HubContext); + // } + + // public void AddMapping(ICacheHubMapping mapping) + // { + // Mappings.Add(mapping); + // FormMapping(mapping); + // } + // } +} \ No newline at end of file diff --git a/Selector.Web/Services/CacheHubProxyService.cs b/Selector.Web/Services/CacheHubProxyService.cs new file mode 100644 index 0000000..11aa828 --- /dev/null +++ b/Selector.Web/Services/CacheHubProxyService.cs @@ -0,0 +1,35 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace Selector.Web.Service +{ + public class CacheHubProxyService: IHostedService + { + private readonly ILogger Logger; + private readonly CacheHubProxy Proxy; + + public CacheHubProxyService( + ILogger logger, + CacheHubProxy proxy + ) + { + Logger = logger; + Proxy = proxy; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + Logger.LogInformation("Starting cache hub proxy"); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + Logger.LogInformation("Stopping cache hub proxy"); + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/Selector.Web/Services/Mappings/ICacheHubMapping.cs b/Selector.Web/Services/Mappings/ICacheHubMapping.cs new file mode 100644 index 0000000..7505aa6 --- /dev/null +++ b/Selector.Web/Services/Mappings/ICacheHubMapping.cs @@ -0,0 +1,16 @@ +using System; +using System.Threading.Tasks; + +using Microsoft.AspNetCore.SignalR; +using StackExchange.Redis; + +namespace Selector.Web.Service +{ + public interface ICacheHubMapping + where THub : Hub + where T : class + { + public Task ConstructMapping(ISubscriber subscriber, IHubContext hub); + // public Task RemoveMapping(ISubscriber subscriber, THub hub); + } +} \ No newline at end of file diff --git a/Selector.Web/Services/Mappings/MappingFactory.cs b/Selector.Web/Services/Mappings/MappingFactory.cs new file mode 100644 index 0000000..9518fa1 --- /dev/null +++ b/Selector.Web/Services/Mappings/MappingFactory.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using SpotifyAPI.Web; + +namespace Selector.Web.Service +{ + public interface INowPlayingMappingFactory { + public NowPlayingMapping Get(string userId); + } + + public class NowPlayingMappingFactory : INowPlayingMappingFactory { + + private readonly ILoggerFactory LoggerFactory; + + public NowPlayingMappingFactory(ILoggerFactory loggerFactory) + { + LoggerFactory = loggerFactory; + } + + public NowPlayingMapping Get(string userId) + { + return new NowPlayingMapping( + LoggerFactory?.CreateLogger(), + userId + ); + } + } +} diff --git a/Selector.Web/Services/Mappings/NowPlayingMapping.cs b/Selector.Web/Services/Mappings/NowPlayingMapping.cs new file mode 100644 index 0000000..c73c7dc --- /dev/null +++ b/Selector.Web/Services/Mappings/NowPlayingMapping.cs @@ -0,0 +1,33 @@ +using System; +using System.Text.Json; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging; + +using StackExchange.Redis; + +using Selector.Web.Hubs; +using Selector.Cache; + +namespace Selector.Web.Service +{ + public class NowPlayingMapping : ICacheHubMapping + { + private readonly string UserId; + + public NowPlayingMapping(ILogger logger, string userId) + { + UserId = userId; + } + + public async Task ConstructMapping(ISubscriber subscriber, IHubContext hub) + { + (await subscriber.SubscribeAsync(Key.CurrentlyPlaying(UserId))).OnMessage(async message => { + + var deserialised = JsonSerializer.Deserialize(message.ToString()); + await hub.Clients.User(UserId).OnNewPlaying(deserialised); + }); + } + } +} \ No newline at end of file diff --git a/Selector.Web/Startup.cs b/Selector.Web/Startup.cs index 319a5c3..edc70fd 100644 --- a/Selector.Web/Startup.cs +++ b/Selector.Web/Startup.cs @@ -15,6 +15,7 @@ using Microsoft.EntityFrameworkCore; using StackExchange.Redis; +using Selector.Web.Service; using Selector.Web.Hubs; using Selector.Model; using Selector.Model.Authorisation; @@ -115,6 +116,10 @@ namespace Selector.Web services.AddTransient(services => services.GetService().GetDatabase()); services.AddTransient(services => services.GetService().GetSubscriber()); } + + // HOSTED + services.AddSingleton(); + services.AddSingleton(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.