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 LegacyCommandResponse(LCR.COMMAND_NOT_ALLOWED, true, $"/{ctx.Name}")); return; } string banUserTarget = ctx.Args.ElementAtOrDefault(0); string banDurationStr = ctx.Args.ElementAtOrDefault(1); int banReasonIndex = 1; ChatUser banUser = null; if(banUserTarget == null || (banUser = ctx.Chat.Users.FirstOrDefault(u => u.NameEquals(banUserTarget))) == null) { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.USER_NOT_FOUND, true, banUser == null ? "User" : banUserTarget)); return; } if(banUser == ctx.User || banUser.Rank >= ctx.User.Rank) { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.KICK_NOT_ALLOWED, true, 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 LegacyCommandResponse(LCR.COMMAND_FORMAT_ERROR)); 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.IsBanned && !fbi.HasExpired) { ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.KICK_NOT_ALLOWED, true, banUser.LegacyName)); return; } await Misuzu.CreateBanAsync( userId, userIp, ctx.User.UserId.ToString(), ctx.Connection.RemoteAddress.ToString(), duration, banReason ); ctx.Chat.BanUser(banUser, duration); }).Wait(); } } }