add some new implementation of Webinar Hub ...

This commit is contained in:
2025-11-14 16:40:00 +03:30
parent d57e8f7f0b
commit 70c61ac3b8
2 changed files with 458 additions and 16 deletions
+37
View File
@@ -0,0 +1,37 @@
using xExceptions.Attributes;
namespace xWebinarService.Constants
{
public enum XWebinarHubAction
{
/// <summary>
/// When a Webinar is Available to Join ...
/// </summary>
[StringValue("WebinarOpened")]
WebinarOpened,
/// <summary>
/// When a Webinar Closed ...
/// </summary>
[StringValue("WebinarClosed")]
WebinarClosed,
/// <summary>
/// When a Viewer is Joined to Webinar ...
/// </summary>
[StringValue("ViewerJoined")]
ViewerJoined,
/// <summary>
/// When a Webinar Subscriber Leaved a Webinar ...
/// </summary>
[StringValue("ViewerLeaved")]
ViewerLeaved,
/// <summary>
/// Send a Message to Webinar ...
/// </summary>
[StringValue("Message")]
Message,
}
}
+421 -16
View File
@@ -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<XWebinarHub> logger,
XWebinarProvider webinarProvider
) : base(logger)
{
this.webinarProvider = webinarProvider;
}
#endregion
//
#region Actions ...
/// <summary>
/// a Webinar Owner Open Webinar for Broadcasting ...
/// </summary>
/// <param name="webinarId"></param>
/// <returns></returns>
[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 { }
}
/// <summary>
/// Close a Webinar by it's Owner ...
/// </summary>
/// <param name="webinarId"></param>
/// <returns></returns>
[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 { }
}
/// <summary>
/// a Webinar Subscriber Joined to Opened Webinar ...
/// </summary>
/// <param name="webinarId"></param>
/// <returns></returns>
[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
{ }
}
/// <summary>
/// a Webina Subscriber Lefts Group ...
/// </summary>
/// <param name="webinarId"></param>
/// <returns></returns>
[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
{ }
}
/// <summary>
/// Send a Message to Specified Webinar ...
/// </summary>
/// <param name="webinarId"></param>
/// <param name="message"></param>
/// <returns></returns>
[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
}
}