mirror of
https://github.com/RedWizardsLab/EchoHub.git
synced 2026-09-04 08:36:11 +02:00
feat: implement notification sound functionality with user customization options
This commit is contained in:
@@ -72,13 +72,17 @@ public class ModerationController : ControllerBase
|
||||
if (target.Role >= caller!.Role)
|
||||
return BadRequest(new ErrorResponse("Cannot kick a user with equal or higher role."));
|
||||
|
||||
// Broadcast kick to all channels the user is in
|
||||
// Broadcast kick to all channels the user is in, then clean up presence
|
||||
var channels = _presenceTracker.GetChannelsForUser(target.Username);
|
||||
foreach (var channel in channels)
|
||||
{
|
||||
await BroadcastToAllAsync(b => b.SendUserKickedAsync(channel, target.Username, request?.Reason));
|
||||
}
|
||||
|
||||
// Remove from presence tracker and force disconnect all connections
|
||||
var reason = request?.Reason ?? "You have been kicked from the server.";
|
||||
await ForceDisconnectAndCleanupAsync(target.Username, reason);
|
||||
|
||||
return Ok(new { Message = $"{target.Username} has been kicked." });
|
||||
}
|
||||
|
||||
@@ -98,8 +102,12 @@ public class ModerationController : ControllerBase
|
||||
target.IsBanned = true;
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
// Broadcast ban notification, then force disconnect
|
||||
await BroadcastToAllAsync(b => b.SendUserBannedAsync(target.Username, request?.Reason));
|
||||
|
||||
var reason = request?.Reason ?? "You have been banned from this server.";
|
||||
await ForceDisconnectAndCleanupAsync(target.Username, reason);
|
||||
|
||||
return Ok(new { Message = $"{target.Username} has been banned." });
|
||||
}
|
||||
|
||||
@@ -217,6 +225,36 @@ public class ModerationController : ControllerBase
|
||||
return (caller, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove user from presence tracking, broadcast their departure from all channels,
|
||||
/// send a ForceDisconnect signal, and update their DB status.
|
||||
/// </summary>
|
||||
private async Task ForceDisconnectAndCleanupAsync(string username, string reason)
|
||||
{
|
||||
var (connectionIds, channels) = _presenceTracker.ForceRemoveUser(username);
|
||||
|
||||
// Notify remaining users that this person left each channel
|
||||
foreach (var channel in channels)
|
||||
{
|
||||
await BroadcastToAllAsync(b => b.SendUserLeftAsync(channel, username));
|
||||
}
|
||||
|
||||
// Signal the user's clients to disconnect
|
||||
if (connectionIds.Count > 0)
|
||||
{
|
||||
await BroadcastToAllAsync(b => b.ForceDisconnectUserAsync(connectionIds, reason));
|
||||
}
|
||||
|
||||
// Mark user offline in DB
|
||||
var user = await _db.Users.FirstOrDefaultAsync(u => u.Username == username);
|
||||
if (user is not null)
|
||||
{
|
||||
user.Status = UserStatus.Invisible;
|
||||
user.LastSeenAt = DateTimeOffset.UtcNow;
|
||||
await _db.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task BroadcastToAllAsync(Func<IChatBroadcaster, Task> action)
|
||||
{
|
||||
foreach (var broadcaster in _broadcasters)
|
||||
|
||||
@@ -151,4 +151,27 @@ public class PresenceTracker
|
||||
{
|
||||
return _userConnections.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forcibly remove a user from all tracking. Returns their connection IDs and channels
|
||||
/// so the caller can broadcast departures and force-disconnect connections.
|
||||
/// </summary>
|
||||
public (List<string> ConnectionIds, List<string> Channels) ForceRemoveUser(string username)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
var channels = _userChannels.TryRemove(username, out var ch)
|
||||
? ch.ToList()
|
||||
: [];
|
||||
|
||||
var connectionIds = _userConnections.TryRemove(username, out var conns)
|
||||
? conns.ToList()
|
||||
: [];
|
||||
|
||||
foreach (var connId in connectionIds)
|
||||
_connections.TryRemove(connId, out _);
|
||||
|
||||
return (connectionIds, channels);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,4 +73,13 @@ public class SignalRBroadcaster : IChatBroadcaster
|
||||
|
||||
return HubContext.Clients.Client(connectionId).Error(message);
|
||||
}
|
||||
|
||||
public Task ForceDisconnectUserAsync(List<string> connectionIds, string reason)
|
||||
{
|
||||
var signalRIds = connectionIds.Where(c => !c.StartsWith("irc-")).ToList();
|
||||
if (signalRIds.Count == 0)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return HubContext.Clients.Clients(signalRIds).ForceDisconnect(reason);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user