using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR; using xCommons.Extensions; using xModels.Dtos; using xPushService.Constants; using xPushService.Interfaces; using xPushService.Models; namespace xPushService.Base { /// /// a base class for implementing Hubs ... /// public abstract class XBaseHub : Hub, IXBaseHub { // #region Props ... protected readonly IXPushGroupStore groupStore; protected readonly IXPushConnectionStore connectionStore; #endregion // #region Constructor ... public XBaseHub( IXPushGroupStore groupStore, IXPushConnectionStore connectionStore ) : base() { // this.groupStore = groupStore; this.connectionStore = connectionStore; } #endregion // #region Abstract ... public abstract XPushConnectionDto GetConnection(); #endregion // #region EnevtHandlers ... #endregion // #region Overrides ... public override Task OnConnectedAsync() { // var connection = GetConnection(); if (!connection.IsNull()) { // connectionStore .Add(connection) .RunTask(); // var count = connectionStore .Count() .RunTask(); // Console.WriteLine($"Count After Coonected: {count}"); } // return base.OnConnectedAsync(); } public override Task OnDisconnectedAsync(Exception exception) { // var connection = GetConnection(); if (!connection.IsNull()) { // connectionStore .RemoveByConnectionId(connection.Id) .RunTask(); // var count = connectionStore .Count() .RunTask(); // Console.WriteLine($"Count After DisCoonected: {count}"); } // return base.OnDisconnectedAsync(exception); } #endregion // #region Actions ... /// /// Notify to all Other Clients which a new Connection is established ... /// /// public Task NotifyNewConnection(string connectionId) { // var actor = Context.User.Identity.Name; var authType = Context.User.Identity.AuthenticationType; var actorRole = Context?.User?.FindFirst("role")?.Value; // var pushMessage = new XPushMessage { // Actor = actor, Payload = connectionId, TimeStamp = DateTime.UtcNow, Type = XPushType.System.GetStringValue(), Topic = XPushType.System.GetStringValue(), Action = XBasePushAction.NotifyNewConnection.GetStringValue(), Message = $"a new connection stablished by {connectionId} ...", }; // Console.WriteLine($"XPushServiceLog => "); Console.WriteLine($"XPushServiceLog => NotifyNewConnection: User: {actor}/Role: {actorRole}/AuthType: {authType}/ConnectionId: {connectionId}/ConnectedAt: {DateTime.UtcNow}"); Console.WriteLine($"XPushServiceLog => "); // return Clients.Others.SendAsync( XBasePushAction.PushMessage.GetStringValue(), pushMessage ); } /// /// Update Last Seen ... /// public Task UpdateLastSeen() { var connectionId = Context.ConnectionId; return connectionStore .UpdateLastSeen(connectionId) .ContinueWith(updateLastSeenTask => { // var updateLastSeen = updateLastSeenTask .RunTask(); if (updateLastSeen) { // var updatedConnection = connectionStore .GetByConnectionId(connectionId) .RunTask(); // var count = connectionStore .Count() .RunTask(); // Console.WriteLine($"Connection Last Seen Updated: {connectionId}: {updatedConnection.LastSeen}, Connection Count: {count} ..."); } }); } /// /// publicly Push a Message to Other Clients ... /// /// /// public Task PushMessageAsync(XPushMessage message) { // if (message.IsNull()) { message = GetPushMessage(); } else { message.TimeStamp = DateTime.UtcNow; } // return Clients.Others.SendAsync(XBasePushAction.PushMessage.GetStringValue(), message); } /// /// publicly Push a Message to Other Clients ... /// /// /// [Authorize] public Task AuthorizedMessageAsync(XPushMessage message) { // if (message.IsNull()) { message = GetPushMessage(); } else { message.TimeStamp = DateTime.UtcNow; } // return Clients.Others.SendAsync(XBasePushAction.PushMessage.GetStringValue(), message); } /// /// push message to All connections ... /// /// /// public Task PushMessageToAll(XPushMessage message) { // // Normalize Message ... if (message.IsNull()) { message = GetPushMessage(); } else { message.TimeStamp = DateTime.UtcNow; } // return Clients .All .SendAsync( XBasePushAction.PushMessage.GetStringValue(), message ); } /// /// push message to specific connection ... /// /// /// /// public Task PushMessageToConnection( string connectionId, XPushMessage message ) { // // Validate Args ... if (connectionId.IsNullOrEmpty()) { return Task.CompletedTask; } // // Normalize Message ... if (message.IsNull()) { message = GetPushMessage(); } else { message.TimeStamp = DateTime.UtcNow; } // return Clients .Client(connectionId) .SendAsync( XBasePushAction.PushMessage.GetStringValue(), message ); } /// /// push message to specific connections ... /// /// /// /// public Task PushMessageToConnections( IEnumerable connectionIds, XPushMessage message ) { // // Validate Args ... if (!connectionIds.HasChild()) { return Task.CompletedTask; } // // Normalize Message ... if (message.IsNull()) { message = GetPushMessage(); } else { message.TimeStamp = DateTime.UtcNow; } // return Clients .Clients( connectionIds .ToList() .AsReadOnly() ) .SendAsync( XBasePushAction.PushMessage.GetStringValue(), message ); } #endregion // #region Protected ... /// /// retrieve connected user name ... /// /// protected string GetUserName() { return Context?.User?.Identity?.Name; } /// /// retrieve connected user role ... /// /// protected string GetUserRole() { return Context?.User?.FindFirst("role")?.Value; } /// /// Retrieve Empty Message ... /// /// protected XPushMessage GetPushMessage() { // var timeStamp = DateTime.UtcNow; var actor = Context.User.Identity.Name; var connectionId = Context.ConnectionId; // var result = new XPushMessage { Actor = actor, TimeStamp = timeStamp, Payload = connectionId, }; // return result; } /// /// retrieve current connection id ... /// /// protected string GetConnectionId() { return Context.ConnectionId; } /// /// Retrieve Connection Model from Context ... /// /// protected XPushConnectionDto GetBaseConnection() { // var connectionId = Context.ConnectionId; var userName = Context.User.Identity.Name; var authenticationType = Context.User.Identity.AuthenticationType; // var httpContext = Context.GetHttpContext(); var deviceJson = httpContext.Request.Query["Option"].ToString(); var device = deviceJson.FromJSON(); // var result = new XPushConnectionDto { User = userName, Device = device, Id = connectionId, LastSeen = DateTime.UtcNow }; // return result; } #endregion // #region Private ... #endregion } }