WGShare.API/WGShare.API/Controllers/Frontend/RoomController.cs

411 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AgoraIO.Media;
using Hangfire.MemoryStorage.Database;
using Mapster;
using Masuit.Tools;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Microsoft.IdentityModel.Tokens;
using SqlSugar;
using SqlSugar.Extensions;
using WGShare.API.Controllers.Basic;
using WGShare.API.Helpers;
using WGShare.API.Hubs;
using WGShare.Domain.Constant;
using WGShare.Domain.DTOs.File;
using WGShare.Domain.DTOs.Room;
using WGShare.Domain.DTOs.User;
using WGShare.Domain.Entities;
using WGShare.Domain.FriendlyException;
using WGShare.Domain.GeneralModel;
using Yitter.IdGenerator;
namespace WGShare.API.Controllers.Frontend
{
/// <summary>
/// 会议室接口
/// </summary>
[ApiExplorerSettings(GroupName = "frontend")]
[Route("room")]
public class RoomController : BasicController
{
private readonly ISqlSugarClient _sqlSugar;
private readonly IConfiguration _configuration;
private readonly OssHelper _ossHelper;
private readonly AgoraHelper _agoraHelper;
private readonly IHubContext<SessionManageHub, IMessageClient> _hubContext;
private readonly ILogger<RoomController> _logger;
public RoomController(ISqlSugarClient sqlSugar,
IConfiguration configuration,
OssHelper ossHelper,
AgoraHelper agoraHelper,
IHubContext<SessionManageHub, IMessageClient> hubContext,
ILogger<RoomController> logger)
{
this._sqlSugar = sqlSugar;
this._configuration = configuration;
this._ossHelper = ossHelper;
this._agoraHelper = agoraHelper;
this._hubContext = hubContext;
this._logger = logger;
}
///// <summary>
///// 获取会议室管理员
///// </summary>
///// <returns></returns>
//[HttpGet("manager")]
//public async Task<List<string>> GetRoomManager([FromQuery] string roomId)
//{
// return await _sqlSugar.Queryable<RoomManager>()
// .Where(x => x.RoomId == roomId)
// .Select(x => x.UserId)
// .ToListAsync();
//}
/// <summary>
/// 设置房间管理员
/// </summary>
/// <returns></returns>
[HttpPost("manager")]
public async Task<bool> SetRoomManager([FromQuery] string roomId, [FromBody] List<string> userIds)
{
var entities = userIds.ConvertAll(x => new RoomManager
{
RoomId = roomId,
UserId = x
});
return await _sqlSugar.Insertable(entities).ExecuteCommandAsync() > 0;
}
/// <summary>
/// 取消房间管理员
/// </summary>
/// <returns></returns>
[HttpDelete("manager")]
public async Task<bool> DelRoomManager([FromQuery] string roomId, [FromBody] List<string> userIds)
{
return await _sqlSugar.Deleteable<RoomManager>()
.Where(x => x.RoomId == roomId && userIds.Contains(x.UserId))
.ExecuteCommandAsync() > 0;
}
/// <summary>
/// 查询用户信息
/// </summary>
/// <returns></returns>
[HttpGet("user")]
public async Task<List<UserOutputDTO>> GetUsers([FromQuery] string roomNum)
{
var channelUsers = RedisHelper.Instance.HVals<ChannelUserInfo>(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum));
if (channelUsers.IsNullOrEmpty())
{
return new List<UserOutputDTO>();
}
var uids = channelUsers.Select(x => x.UID);
var users = await _sqlSugar.Queryable<User>()
.Where(x => uids.Contains(x.Id))
.ToListAsync();
var managerIds = await _sqlSugar.Queryable<RoomManager>()
.InnerJoin<Room>((rm, r) => r.Id == rm.RoomId)
.Where((rm, r) => r.RoomNum == roomNum)
.Select((rm, r) => rm.UserId)
.ToListAsync();
var result = users.Adapt<List<UserOutputDTO>>();
result.ForEach(x =>
{
x.IsManager = managerIds.Contains(x.Id);
var info = channelUsers.FirstOrDefault(q => q.UID == x.Id);
if (info != null)
{
x.EnableMicr = info.EnableMicr;
x.EnableCamera = info.EnableCamera;
}
});
return result;
#region
//var data = await _agoraHelper.GetChannelUserList(roomNum);
//if (data == null)
//{
// throw Oops.Oh("请求失败");
//}
//if (!data.channel_exist)
//{
// throw Oops.Oh("频道不存在");
//}
//if (data.broadcasters.IsNullOrEmpty())
//{
// return new List<UserOutputDTO>();
//}
//var accounts = data.broadcasters.ConvertAll(x => x.ToString());
//var users = await _sqlSugar.Queryable<User>()
// .Where(x => accounts.Contains(x.Account))
// .ToListAsync();
//var managerIds = await _sqlSugar.Queryable<RoomManager>()
// .InnerJoin<Room>((rm, r) => r.Id == rm.RoomId)
// .Where((rm, r) => r.RoomNum == roomNum)
// .Select((rm, r) => rm.UserId)
// .ToListAsync();
//var result = users.Adapt<List<UserOutputDTO>>();
//result.ForEach(x => x.IsManager = managerIds.Contains(x.Id));
//return result;
#endregion
}
/// <summary>
/// 检验房间是否存在
/// </summary>
/// <returns></returns>
[HttpGet("checkout"), AllowAnonymous]
public async Task<bool> ExistsRoom([FromQuery] string roomNum)
{
return await _sqlSugar.Queryable<Room>().AnyAsync(x => x.RoomNum == roomNum && x.IsDelete == false);
}
/// <summary>
/// 获取单个会议室信息
/// </summary>
/// <returns></returns>
[HttpGet("{roomNum}")]
public async Task<RoomOutputDTO> GetRoom([FromRoute] string roomNum)
{
var room = await _sqlSugar.Queryable<Room>().FirstAsync(x => x.RoomNum == roomNum && x.IsDelete == false);
if (room == null)
{
throw Oops.Oh("会议号无效");
}
return room.Adapt<RoomOutputDTO>();
}
/// <summary>
/// 获取房间rtc token
/// </summary>
/// <returns></returns>
[HttpGet("tk/rtc")]
public async Task<string> GetRTCToken([FromQuery] string roomNum)
{
//var privilegeExpiredTs = _configuration["Agora:tokenExpireTimeInSecond"].ToInt32() + Utils.getTimestamp();
return new RtcTokenBuilder2().buildTokenWithUserAccount(
_configuration["Agora:appId"],
_configuration["Agora:appSecret"],
roomNum,
Account,
RtcTokenBuilder2.Role.ROLE_PUBLISHER,
_configuration["Agora:tokenExpireTimeInSecond"].ToInt32(),
_configuration["Agora:tokenExpireTimeInSecond"].ToInt32());
}
/// <summary>
/// 邀请用户
/// </summary>
/// <returns></returns>
[HttpPost("invite")]
public async Task InviteUser([FromQuery] string roomId, [FromBody] string[] inviteeUids)
{
var room = await _sqlSugar.Queryable<Room>().FirstAsync(x => x.Id == roomId);
var connectIds = RedisHelper.Instance.HMGet(RedisKeyConstant.SessionManage.GetOnlineUserKey(TenantId), inviteeUids);
connectIds.RemoveWhere(x => string.IsNullOrWhiteSpace(x));
await _hubContext.Clients.Clients(connectIds).Invitation(room.RoomNum, room.RoomName, UserName);
}
/// <summary>
/// 踢出房间
/// </summary>
/// <returns></returns>
[HttpGet("kickout")]
public async Task KickOut([FromQuery] string roomNum, [FromQuery] string kickUid)
{
var connectId = RedisHelper.Instance.HGet(RedisKeyConstant.SessionManage.GetOnlineUserKey(TenantId), kickUid);
if (!string.IsNullOrWhiteSpace(connectId))
{
await _hubContext.Clients.Client(connectId).ForceExitRoom(roomNum);
}
}
/// <summary>
/// 开闭麦
/// </summary>
/// <returns></returns>
[HttpGet("oper-micr")]
public async Task Mute([FromQuery] string roomNum, [FromQuery] bool enableMicr, [FromQuery] string? uid, [FromQuery] bool? isAll = false)
{
if (isAll.HasValue && isAll.Value)
{
// 全员静音
var allUsers = RedisHelper.Instance.HGetAll<ChannelUserInfo>(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum));
if (!allUsers.Any())
{
return;
}
allUsers.ForEach(x => x.Value.EnableMicr = enableMicr);
RedisHelper.Instance.HMSet(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum), allUsers);
await _hubContext.Clients.Group(roomNum).OperMicr(enableMicr);
await _hubContext.Clients.Group(roomNum).RefreshUserList();
return;
}
var userInfo = RedisHelper.Instance.HGet<ChannelUserInfo>(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum), uid);
if (userInfo == null || string.IsNullOrWhiteSpace(userInfo.ConnectId))
{
_logger.LogError($"闭麦操作,用户不存在频道rediskey:{RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum)} uid" + uid);
return;
}
userInfo.EnableMicr = enableMicr;
RedisHelper.Instance.HSet(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum), uid, userInfo);
await _hubContext.Clients.Clients(userInfo.ConnectId).OperMicr(enableMicr);
await _hubContext.Clients.Group(roomNum).RefreshUserList();
}
/// <summary>
/// 开关闭摄像头
/// </summary>
/// <returns></returns>
[HttpGet("oper-camera")]
public async Task CloseCamera([FromQuery] string roomNum, [FromQuery] bool enableCamera, [FromQuery] string? uid, [FromQuery] bool? isAll = false)
{
if (isAll.HasValue && isAll.Value)
{
var allUsers = RedisHelper.Instance.HGetAll<ChannelUserInfo>(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum));
if (!allUsers.Any())
{
return;
}
allUsers.ForEach(x => x.Value.EnableCamera = enableCamera);
RedisHelper.Instance.HMSet(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum), allUsers);
// 全员开关闭摄像头
await _hubContext.Clients.Group(roomNum).OperCamera(enableCamera);
await _hubContext.Clients.Group(roomNum).RefreshUserList();
return;
}
var userInfo = RedisHelper.Instance.HGet<ChannelUserInfo>(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum), uid);
if (userInfo == null || string.IsNullOrWhiteSpace(userInfo.ConnectId))
{
_logger.LogError($"关闭摄像头操作,用户不存在频道rediskey:{RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum)} uid" + uid);
return;
}
userInfo.EnableCamera = enableCamera;
RedisHelper.Instance.HSet(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum), uid, userInfo);
await _hubContext.Clients.Clients(userInfo.ConnectId).OperCamera(enableCamera);
await _hubContext.Clients.Group(roomNum).RefreshUserList();
}
#region
/// <summary>
/// 分享上传文件
/// </summary>
/// <param name="inputDTO"></param>
/// <returns></returns>
[HttpPost("file")]
public async Task<bool> AddFile([FromBody] ShareFileInputDTO inputDTO)
{
var entity = inputDTO.Adapt<ShareFile>();
entity.Id = YitIdHelper.NextId().ToString();
entity.UserId = UId;
return await _sqlSugar.Insertable(entity).ExecuteCommandAsync() > 0;
}
/// <summary>
/// 删除文件
/// </summary>
/// <returns></returns>
[HttpDelete("file")]
public async Task<bool> DeleteFile([FromBody] List<string> ids)
{
return await _sqlSugar.Updateable<ShareFile>()
.SetColumns(x => x.IsDelete == true)
.Where(x => ids.Contains(x.Id))
.ExecuteCommandHasChangeAsync();
}
/// <summary>
/// 获取分享文件列表
/// </summary>
/// <param name="roomId">房间Id</param>
/// <param name="pagedBaseDto"></param>
/// <returns></returns>
[HttpGet("file")]
public async Task<PagedResult<ShareFileOutputDTO>> GetFilesList([FromQuery] string roomId, [FromQuery] string? keyword, [FromQuery] PagedBaseDto pagedBaseDto)
{
RefAsync<int> total = 0;
var list = await _sqlSugar.Queryable<ShareFile>()
.LeftJoin<User>((sf, u) => sf.UserId == u.Id)
.Where((sf, u) => sf.IsDelete == false && sf.RoomId == roomId)
.WhereIF(!string.IsNullOrWhiteSpace(keyword), (sf, u) => sf.FileName.Contains(keyword))
.Select((sf, u) => new ShareFileOutputDTO
{
Id = sf.Id,
UserId = u.Id,
UserName = u.UserName,
FileName = sf.FileName,
FileUrl = sf.FileUrl,
RoomId = sf.RoomId,
Size = sf.Size,
ModifyTime = sf.ModifyTime,
DownloadCount = sf.DownloadCount,
}).ToPageListAsync(pagedBaseDto.PageIndex, pagedBaseDto.PageSize, total);
return PagedResult<ShareFileOutputDTO>.Create(list, total.Value);
}
/// <summary>
/// 获取文件上传url
/// </summary>
/// <returns></returns>
[HttpGet("up-fileurl")]
public async Task<IActionResult> GetUploadUrl([FromQuery] string roomNum, [FromQuery] string fileSuffix)
{
return Ok(_ossHelper.GetUploadUrl($@"share_file/{TenantId}/{roomNum}", Guid.NewGuid().ToString("N") + "." + fileSuffix));
}
/// <summary>
/// 获取文件下载地址
/// </summary>
/// <param name="fileUrl"></param>
/// <param name="fileId">文件Id</param>
/// <returns></returns>
[HttpGet("file-dw-url")]
public async Task<string> GetDownloadUrl([FromQuery] string fileUrl, [FromQuery] string fileId)
{
await _sqlSugar.Updateable<ShareFile>()
.SetColumns(x => x.DownloadCount == x.DownloadCount + 1)
.Where(x => x.Id == fileId).ExecuteCommandAsync();
return _ossHelper.GetAccessFileUrl(fileUrl);
}
#endregion
}
}