using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; using xCommons.Extensions; using xExceptions.Constants; using xPushService.Base; using xPushService.Extensions; using xWebinarService.Constants; using xWebinarService.Interfaces; using xWebinarService.Models.Entities; namespace xWebinarService.Hubs { public class XWebinarHub : XBaseWebRTCHub { // #region Props ... public readonly IXWebinarProvider webinarProvider; private readonly IXWebinarGroupStore webinarGroupStore; #endregion // #region Constructor ... public XWebinarHub( ILogger logger, IXWebinarProvider webinarProvider, IXWebinarGroupStore webinarGroupStore ) : base(logger) { this.webinarProvider = webinarProvider; this.webinarGroupStore = webinarGroupStore; } #endregion // #region Actions ... /// /// a Webinar Owner Open Webinar for Broadcasting ... /// /// /// [Authorize] public async Task WebinarOpened(Guid webinarId) { // // Validate Arg ... var isValid = !webinarId.IsNull() && !webinarId.IsDefaultGuid(); if (!isValid) { // logger.LogError($"Invalid Webinar Provider ..."); return; } // // Reading and Validate Requirements ... var userInfo = Context.GetUserInfo(); var connectionId = Context.ConnectionId; isValid = !userInfo.IsNullOrDefault() && !connectionId.IsNullOrEmpty(); if (!isValid) { // logger.LogError($"Invaid User Info ..."); return; } // // Retrieve Webinar Model and Validate it Exists ... try { // // Retrieve Webinar ... var webinar = await webinarProvider.GetWebinar(webinarId); // // Validate Webinar ... isValid = !webinar.IsNullOrDefault(); if (!isValid) { // XException.NotFound.Throw(); logger.LogError($"Webinar Not Found ..."); } // // Validate User is Webinar Owner ... isValid = !userInfo.UserId.IsNullOrEmpty() && userInfo.UserId == webinar.OwnerId; if (!isValid) { // XException.NotAllowed.Throw(); logger.LogError($"Not Allowed to Present Webinar ..."); } // // Now try to Enable Webinar and Notify Webinars Client Which it's Open ... webinar.Enabled = true; webinar = await webinarProvider.UpdateWebinar(webinar); await Clients.AllExcept(connectionId).SendAsync(XWebinarHubAction.WebinarOpened.GetStringValue(), webinarId); // // Create a Group and Put User on it ... await Groups.AddToGroupAsync(connectionId, webinarId.ToString()); // // Check Exists or not ... var connection = new XHubConnectionDto { UserId = userInfo.UserId, ConnectionId = connectionId, Username = userInfo.UserName, }; var groupEntity = await webinarGroupStore.FindOneAsync(x => x.WebinarId == webinarId); if (!groupEntity.IsNullOrDefault()) { // // Update ... groupEntity.Connections.Clear(); groupEntity.Connections.Add(connection); await webinarGroupStore.UpdateAsync(groupEntity.Id, groupEntity); } else { // // Add ... groupEntity = new XWebinarGroupEntity { WebinarId = webinarId }; groupEntity.Connections.Add(connection); await webinarGroupStore.AddAsync(groupEntity); } } catch { } } /// /// Close a Webinar by it's Owner ... /// /// /// [Authorize] public async Task WebinarClosed(Guid webinarId) { // // Validate Arg ... var isValid = !webinarId.IsNull() && !webinarId.IsDefaultGuid(); if (!isValid) { // logger.LogError($"Invalid Webinar Provider ..."); return; } // // Reading and Validate Requirements ... var userInfo = Context.GetUserInfo(); var connectionId = Context.ConnectionId; isValid = !userInfo.IsNullOrDefault() && !connectionId.IsNullOrEmpty(); if (!isValid) { // logger.LogError($"Invaid User Info ..."); return; } // // Retrieve Webinar Model and Validate it Exists ... try { // // Retrieve Webinar ... var webinar = await webinarProvider.GetWebinar(webinarId); // // Validate Webinar ... isValid = !webinar.IsNullOrDefault(); if (!isValid) { // XException.NotFound.Throw(); logger.LogError($"Webinar Not Found ..."); } // // Validate User is Webinar Owner ... isValid = !userInfo.UserId.IsNullOrEmpty() && userInfo.UserId == webinar.OwnerId; if (!isValid) { // XException.NotAllowed.Throw(); logger.LogError($"Not Allowed to Present Webinar ..."); } // // Now try to Enable Webinar and Notify Webinars Client Which it's Open ... webinar.Enabled = false; webinar = await webinarProvider.UpdateWebinar(webinar); await Clients.AllExcept(connectionId).SendAsync(XWebinarHubAction.WebinarClosed.GetStringValue(), webinarId); // var webinarName = webinarId.ToString(); await Clients.OthersInGroup(webinarName).SendAsync(XWebinarHubAction.WebinarClosed.ToString()); await Groups.RemoveFromGroupAsync(connectionId, webinarName); // // Check Exists or not ... var groupEntity = await webinarGroupStore.FindOneAsync(x => x.WebinarId == webinarId); if (!groupEntity.IsNullOrDefault()) { await webinarGroupStore.RemoveAsync(groupEntity.Id); } } catch { } } /// /// a Webinar Subscriber Joined to Opened Webinar ... /// /// /// [Authorize] public async Task ViewerJoined(Guid webinarId) { // // Validate ... var isValid = !webinarId.IsNull() && !webinarId.IsDefaultGuid(); if (!isValid) { // logger.LogError($"Invalid Webinar Provider ..."); return; } // // Retrieve requirements ... var userInfo = Context.GetUserInfo(); var connectionId = Context.ConnectionId; isValid = !userInfo.IsNullOrDefault() && !connectionId.IsNullOrEmpty(); if (!isValid) { // logger.LogError($"Invaid User Info ..."); return; } // try { // // Reading Webinar ... var webinar = await webinarProvider.GetWebinar(webinarId); isValid = !webinar.IsNullOrDefault(); if (!isValid) { // logger.LogError($"Webinar Not Found ..."); XException.NotFound.Throw(); } // // Validate User is Webinar Subscriber ... // Or Webinar is Open ... if (webinar.Type != XWebinarType.Public) { // isValid = await webinarProvider.IsSubscribed( webinarId: webinarId, subscriberId: userInfo.UserId ); if (!isValid) { // logger.LogError("User Not Have Permission to Join Webinar ..."); XException.NotAllowed.Throw(); } } // var webinarName = webinarId.ToString(); // // Add User to Webinar ... await Groups.AddToGroupAsync(connectionId, webinarName); // // Notify Other Users which a Viewer Joined ... await Clients.OthersInGroup(webinarName).SendAsync(XWebinarHubAction.ViewerJoined.GetStringValue(), connectionId, webinarId, userInfo.UserId, userInfo.UserName ); // // Check Exists or not ... var connection = new XHubConnectionDto { UserId = userInfo.UserId, ConnectionId = connectionId, Username = userInfo.UserName, }; var groupEntity = await webinarGroupStore.FindOneAsync(x => x.WebinarId == webinarId); if (!groupEntity.IsNullOrDefault()) { // // Check Current User ID Exists ... var userConnection = groupEntity.Connections.FirstOrDefault(c => c.UserId == userInfo.UserId); if (!userConnection.IsNullOrDefault()) { userConnection.ConnectionId = connectionId; } else { groupEntity.Connections.Add(connection); } // await webinarGroupStore.UpdateAsync(groupEntity.Id, groupEntity); } } catch { } } /// /// a Webina Subscriber Lefts Group ... /// /// /// [Authorize] public async Task ViewerLeaved(Guid webinarId) { // // Validate ... var isValid = !webinarId.IsNull() && !webinarId.IsDefaultGuid(); if (!isValid) { // logger.LogError($"Invalid Webinar Provider ..."); return; } // // Retrieve requirements ... var userInfo = Context.GetUserInfo(); var connectionId = Context.ConnectionId; isValid = !userInfo.IsNullOrDefault() && !connectionId.IsNullOrEmpty(); if (!isValid) { // logger.LogError($"Invaid User Info ..."); return; } // try { // // Reading Webinar ... var webinar = await webinarProvider.GetWebinar(webinarId); isValid = !webinar.IsNullOrDefault(); if (!isValid) { // logger.LogError($"Webinar Not Found ..."); XException.NotFound.Throw(); } // // Validate User is Webinar Subscriber ... // Or Webinar is Open ... if (webinar.Type != XWebinarType.Public) { // isValid = await webinarProvider.IsSubscribed( webinarId: webinarId, subscriberId: userInfo.UserId ); if (!isValid) { // logger.LogError("User Not Have Permission to Join Webinar ..."); XException.NotAllowed.Throw(); } } // var webinarName = webinarId.ToString(); // // Add User to Webinar ... await Groups.RemoveFromGroupAsync(connectionId, webinarName); // // Notify Other Users which a Viewer Leaved ... await Clients.OthersInGroup(webinarName).SendAsync(XWebinarHubAction.ViewerLeaved.GetStringValue(), connectionId, webinarId, userInfo.UserId, userInfo.UserName ); // // Check Exists or not ... var groupEntity = await webinarGroupStore.FindOneAsync(x => x.WebinarId == webinarId); if (!groupEntity.IsNullOrDefault()) { // // Check Current User ID Exists ... var userConnection = groupEntity.Connections.FirstOrDefault(c => c.ConnectionId == connectionId); if (!userConnection.IsNullOrDefault()) { groupEntity.Connections.Remove(userConnection); } // await webinarGroupStore.UpdateAsync(groupEntity.Id, groupEntity); } } catch { } } /// /// Return a Collection of Webinars Visitors ... /// /// /// [Authorize] public async Task> WebinarVisitors(Guid webinarId) { // var result = new List(); // // Reading and Validate Requirements ... var userInfo = Context.GetUserInfo(); var connectionId = Context.ConnectionId; // // Check Group Exists ... var groupEntity = await webinarGroupStore.FindOneAsync(x => x.WebinarId == webinarId); if (!groupEntity.IsNullOrDefault()) { // // Validate Requester is a Viewer ... var connection = groupEntity.Connections.FirstOrDefault(c => c.ConnectionId == connectionId || c.UserId == userInfo.UserId ); if (!connection.IsNullOrDefault()) { result = groupEntity.Connections; } } // return result; } /// /// Send a Message to Specified Webinar ... /// /// /// /// [Authorize] public async Task Message(Guid webinarId, string message) { // // Validate ... var isValid = !webinarId.IsNull() && !webinarId.IsDefaultGuid(); if (!isValid) { // logger.LogError($"Invalid Webinar Provider ..."); return; } // // Retrieve requirements ... var userInfo = Context.GetUserInfo(); var connectionId = Context.ConnectionId; isValid = !userInfo.IsNullOrDefault() && !connectionId.IsNullOrEmpty(); if (!isValid) { // logger.LogError($"Invaid User Info ..."); return; } // try { // // Reading Webinar ... var webinar = await webinarProvider.GetWebinar(webinarId); isValid = !webinar.IsNullOrDefault(); if (!isValid) { // logger.LogError($"Webinar Not Found ..."); XException.NotFound.Throw(); } // // Validate User is Webinar Owner or Subscriber ... // Or Webinar is Open ... if (webinar.Type != XWebinarType.Public) { // isValid = userInfo.UserId == webinar.OwnerId || (await webinarProvider.IsSubscribed( webinarId: webinarId, subscriberId: userInfo.UserId )); if (!isValid) { // logger.LogError("User Not Have Permission to Join Webinar ..."); XException.NotAllowed.Throw(); } } // var webinarName = webinarId.ToString(); // // Notify Other Users which a Viewer Leaved ... await Clients.OthersInGroup(webinarName).SendAsync(XWebinarHubAction.Message.GetStringValue(), connectionId, userInfo.UserId, userInfo.UserName, message ); } catch { } } #endregion } }