diff --git a/Constants/XWebinarHubAction.cs b/Constants/XWebinarHubAction.cs
new file mode 100644
index 0000000..3d75696
--- /dev/null
+++ b/Constants/XWebinarHubAction.cs
@@ -0,0 +1,37 @@
+using xExceptions.Attributes;
+
+namespace xWebinarService.Constants
+{
+ public enum XWebinarHubAction
+ {
+ ///
+ /// When a Webinar is Available to Join ...
+ ///
+ [StringValue("WebinarOpened")]
+ WebinarOpened,
+
+ ///
+ /// When a Webinar Closed ...
+ ///
+ [StringValue("WebinarClosed")]
+ WebinarClosed,
+
+ ///
+ /// When a Viewer is Joined to Webinar ...
+ ///
+ [StringValue("ViewerJoined")]
+ ViewerJoined,
+
+ ///
+ /// When a Webinar Subscriber Leaved a Webinar ...
+ ///
+ [StringValue("ViewerLeaved")]
+ ViewerLeaved,
+
+ ///
+ /// Send a Message to Webinar ...
+ ///
+ [StringValue("Message")]
+ Message,
+ }
+}
\ No newline at end of file
diff --git a/Hub/XWebinarHub.cs b/Hub/XWebinarHub.cs
index 4b873ac..7760d7e 100644
--- a/Hub/XWebinarHub.cs
+++ b/Hub/XWebinarHub.cs
@@ -1,30 +1,435 @@
+using System;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Linq;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.SignalR;
+using Microsoft.Extensions.Logging;
+using xCommons.Extensions;
+using xExceptions.Constants;
+using xIdentityModels.Models;
using xPushService.Base;
-using xPushService.Interfaces;
-using xPushService.Models;
+using xPushService.Extensions;
+using xWebinarService.Constants;
+using xWebinarService.Models.Dtos;
+using xWebinarService.Providers;
namespace xWebinarService.Hub
{
public class XWebinarHub : XBaseWebRTCHub
{
- protected XWebinarHub(
- IXPushGroupStore groupStore,
- IXPushConnectionStore connectionStore,
- IXWebRTCConnectionStore webRTCConnectionStore
- ) : base(
- groupStore,
- connectionStore,
- webRTCConnectionStore
- )
- { }
+ //
+ #region Props ...
+ public readonly XWebinarProvider webinarProvider;
+ #endregion
- public override XPushConnectionDto GetConnection()
+ //
+ #region Constructor ...
+ public XWebinarHub(
+ ILogger logger,
+ XWebinarProvider webinarProvider
+ ) : base(logger)
+ {
+ this.webinarProvider = webinarProvider;
+ }
+ #endregion
+
+ //
+ #region Actions ...
+ ///
+ /// a Webinar Owner Open Webinar for Broadcasting ...
+ ///
+ ///
+ ///
+ [Authorize]
+ public async Task WebinarOpened(Guid webinarId)
{
//
- var result = GetBaseConnection();
- result.Type = GetType().Name;
+ // Validate Arg ...
+ var isValid = !webinarId.IsNull() &&
+ !webinarId.IsDefaultGuid();
+ if (!isValid)
+ {
+ //
+ logger.LogError($"Invalid Webinar Provider ...");
+ return;
+ }
//
- return result;
+ // 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());
+ }
+ 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);
+ }
+ 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, userInfo.UserId, userInfo.UserName);
+ }
+ 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,
+ userInfo.UserId,
+ userInfo.UserName
+ );
+ }
+ catch
+ { }
+ }
+
+ ///
+ /// 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
}
}
\ No newline at end of file