using SharpChat.Misuzu; using SharpChat.Packet; using System; using System.Linq; using System.Threading.Tasks; namespace SharpChat.Commands { public class KickBanCommand : IChatCommand { private readonly MisuzuClient Misuzu; public KickBanCommand(MisuzuClient msz) { Misuzu = msz ?? throw new ArgumentNullException(nameof(msz)); } public bool IsMatch(ChatCommandContext ctx) { return ctx.NameEquals("kick") || ctx.NameEquals("ban"); } public void Dispatch(ChatCommandContext ctx) { bool isBanning = ctx.NameEquals("ban"); if(!ctx.User.Can(isBanning ? ChatUserPermissions.BanUser : ChatUserPermissions.KickUser)) { ctx.Chat.SendTo(ctx.User, new CommandNotAllowedErrorPacket(ctx.Name)); return; } string banUserTarget = ctx.Args.ElementAtOrDefault(0) ?? string.Empty; string? banDurationStr = ctx.Args.ElementAtOrDefault(1); int banReasonIndex = 1; ChatUser? banUser = null; if(string.IsNullOrEmpty(banUserTarget) || (banUser = ctx.Chat.Users.FirstOrDefault(u => u.NameEquals(banUserTarget))) == null) { ctx.Chat.SendTo(ctx.User, new UserNotFoundErrorPacket(banUserTarget)); return; } if(!ctx.User.IsSuper && banUser.Rank >= ctx.User.Rank && banUser != ctx.User) { ctx.Chat.SendTo(ctx.User, new KickBanNotAllowedErrorPacket(banUser.LegacyName)); 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 CommandFormatErrorPacket()); return; } duration = TimeSpan.FromSeconds(durationSeconds); ++banReasonIndex; } if(duration <= TimeSpan.Zero) { ctx.Chat.BanUser(banUser, duration); return; } string banReason = string.Join(' ', ctx.Args.Skip(banReasonIndex)); Task.Run(async () => { string userId = banUser.UserId.ToString(); string userIp = ctx.Chat.GetRemoteAddresses(banUser).FirstOrDefault()?.ToString() ?? string.Empty; // obviously it makes no sense to only check for one ip address but that's current misuzu limitations MisuzuBanInfo? fbi = await Misuzu.CheckBanAsync(userId, userIp); if(fbi != null && fbi.IsBanned && !fbi.HasExpired) { ctx.Chat.SendTo(ctx.User, new KickBanNotAllowedErrorPacket(banUser.LegacyName)); return; } await Misuzu.CreateBanAsync( userId, userIp, ctx.User.UserId.ToString(), ctx.Connection.RemoteAddress.ToString(), duration, banReason ); ctx.Chat.BanUser(banUser, duration); }).Wait(); } } }