sharp-chat/SharpChat.SockChat/Commands/KickBanCommand.cs
2024-05-29 20:51:41 +00:00

87 lines
3.6 KiB
C#

using SharpChat.Events;
using SharpChat.Misuzu;
using SharpChat.SockChat.PacketsS2C;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace SharpChat.SockChat.Commands {
public class KickBanCommand : ISockChatClientCommand {
private readonly MisuzuClient Misuzu;
public KickBanCommand(MisuzuClient msz) {
Misuzu = msz;
}
public bool IsMatch(SockChatClientCommandContext ctx) {
return ctx.NameEquals("kick")
|| ctx.NameEquals("ban");
}
public void Dispatch(SockChatClientCommandContext ctx) {
bool isBanning = ctx.NameEquals("ban");
if(!ctx.User.Permissions.HasFlag(isBanning ? UserPermissions.BanUser : UserPermissions.KickUser)) {
ctx.Chat.SendTo(ctx.User, new CommandNotAllowedErrorS2CPacket(ctx.Name));
return;
}
string banUserTarget = ctx.Args.ElementAtOrDefault(0) ?? string.Empty;
string? banDurationStr = ctx.Args.ElementAtOrDefault(1);
int banReasonIndex = 1;
UserInfo? banUser = null;
(string name, UsersContext.NameTarget target) = SockChatUtility.ExplodeUserName(banUserTarget);
if(string.IsNullOrEmpty(name) || (banUser = ctx.Chat.Users.Get(name: name, nameTarget: target)) == null) {
ctx.Chat.SendTo(ctx.User, new UserNotFoundErrorS2CPacket(banUserTarget));
return;
}
if(!ctx.User.IsSuper && banUser.Rank >= ctx.User.Rank && banUser != ctx.User) {
ctx.Chat.SendTo(ctx.User, new KickBanNotAllowedErrorS2CPacket(SockChatUtility.GetUserName(banUser)));
return;
}
TimeSpan duration = isBanning ? TimeSpan.MaxValue : TimeSpan.Zero;
if(!string.IsNullOrWhiteSpace(banDurationStr) && double.TryParse(banDurationStr, out double durationSeconds)) {
if(durationSeconds < 0) {
ctx.Chat.SendTo(ctx.User, new CommandFormatErrorS2CPacket());
return;
}
duration = TimeSpan.FromSeconds(durationSeconds);
++banReasonIndex;
}
if(duration <= TimeSpan.Zero) {
ctx.Chat.Events.Dispatch("user:kickban", banUser, UserKickBanEventData.OfDuration(UserDisconnectReason.Kicked, TimeSpan.Zero));
return;
}
string banReason = string.Join(' ', ctx.Args.Skip(banReasonIndex));
Task.Run(async () => {
string userId = banUser.UserId.ToString();
MisuzuBanInfo? fbi = await Misuzu.CheckBanAsync(userId);
if(fbi != null && fbi.IsBanned && !fbi.HasExpired) {
ctx.Chat.SendTo(ctx.User, new KickBanNotAllowedErrorS2CPacket(SockChatUtility.GetUserName(banUser)));
return;
}
string[] userRemoteAddrs = ctx.Chat.Connections.GetUserRemoteAddresses(banUser);
string userRemoteAddr = string.Format(", ", userRemoteAddrs);
// Misuzu only stores the IP address in private comment and doesn't do any checking, so this is fine.
await Misuzu.CreateBanAsync(
userId, userRemoteAddr,
ctx.User.UserId.ToString(), ctx.Connection.RemoteAddress,
duration, banReason
);
ctx.Chat.Events.Dispatch("user:kickban", banUser, UserKickBanEventData.OfDuration(UserDisconnectReason.Kicked, duration));
}).Wait();
}
}
}