public async Task SyncBans(DiscordGuild guild) { var syncedBans = await redis.GetAsync <List <ulong> >(RedisKeyNaming.SyncedInfractions); foreach (var bannedUser in syncedBans) { await guild.BanMemberAsync(bannedUser, 0, "Synced with the database which contains all reported users (banned)"); await Task.Delay(TimeSpan.FromSeconds(3)); } }
private async void Detection_FakeMuteExploitDetected(AbuseTracker detectedUser, DiscordUser user) { if (!resetTask?.IsCompleted ?? false) { return; } await Logger.Warning("Exploit", $"Detected {detectedUser.UserID} speaking while muted for {(DateTime.Now - detectedUser.FirstHit)?.TotalSeconds} seconds."); // We put this on its own thread since it shouldn't interrupt any of this code resetTask = Task.Run(async() => await Cooldown(detectedUser)); if (!config.BanDetectedUsers) { return; } var member = await guild.GetMemberAsync(detectedUser.UserID); try { await member.SendMessageAsync($"You have been banned from {guild.Name} because you were detected using a voice chat exploit.\n\n" + "If you believe this is an error, please contact the server administrators."); } catch (Exception e) { await Logger.Warning("Exploit", $"Unable to send a DM to {member.DisplayName}#{member.Discriminator} [{detectedUser.UserID}]: {e.Message}"); } try { await guild.BanMemberAsync(member, 0, $"{client.CurrentUser.Username}: Detected abuse of the Fake Mute exploit"); } catch (Exception e) { await Logger.Error("Exploit", $"Unable to ban {member.DisplayName}#{member.Discriminator} [{detectedUser.UserID}]: {e.Message}"); } }
public static async Task <bool> BanFromServerAsync(ulong targetUserId, string reason, ulong moderatorId, DiscordGuild guild, int deleteDays = 7, DiscordChannel channel = null, TimeSpan banDuration = default, bool appealable = false) { DiscordUser naughtyUser = await Program.discord.GetUserAsync(targetUserId); bool permaBan = false; DiscordChannel logChannel = await Program.discord.GetChannelAsync(Program.cfgjson.LogChannel); DiscordRole mutedRole = guild.GetRole(Program.cfgjson.MutedRole); DateTime? expireTime = DateTime.Now + banDuration; DiscordMember moderator = await guild.GetMemberAsync(moderatorId); if (banDuration == default) { permaBan = true; expireTime = null; } MemberPunishment newBan = new MemberPunishment() { MemberId = targetUserId, ModId = moderatorId, ServerId = guild.Id, ExpireTime = expireTime }; await Program.db.HashSetAsync("bans", targetUserId, JsonConvert.SerializeObject(newBan)); try { DiscordMember targetMember = await guild.GetMemberAsync(targetUserId); if (permaBan) { if (appealable) { await targetMember.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} You have been banned from **{guild.Name}**!\nReason: **{reason}**\nYou can appeal the ban here: https://msft.chat/member/#ban-appeal-process"); } else { await targetMember.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} You have been permanently banned from **{guild.Name}**!\nReason: **{reason}**"); } } else { await targetMember.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} You have been banned from **{guild.Name}** for {Warnings.TimeToPrettyFormat(banDuration, false)}!\nReason: **{reason}**"); } } catch { // A DM failing to send isn't important. } try { await guild.BanMemberAsync(targetUserId, deleteDays, reason); if (permaBan) { await logChannel.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} <@{targetUserId}> was permanently banned by `{moderator.Username}#{moderator.Discriminator}` (`{moderatorId}`).\nReason: **{reason}**"); } else { await logChannel.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} <@{targetUserId}> was banned for {Warnings.TimeToPrettyFormat(banDuration, false)} by `{moderator.Username}#{moderator.Discriminator}` (`{moderatorId}`).\nReason: **{reason}**"); } } catch { return(false); } return(true); }
public static async Task WarnUserAsync(DiscordUser user, DiscordUser admin, DiscordGuild server, DiscordChannel channel, string reason, bool automsg) { DB.ServerRanks WarnedUserStats = DB.DBLists.ServerRanks.FirstOrDefault(f => server.Id == f.Server_ID && user.Id == f.User_ID); DB.ServerSettings ServerSettings = DB.DBLists.ServerSettings.FirstOrDefault(f => server.Id == f.ID_Server); if (WarnedUserStats == null) { AddUserToServerRanks(user, server); } DiscordMember member = null; try { member = await server.GetMemberAsync(user.Id); } catch (Exception) { await channel.SendMessageAsync($"{user.Username} is no longer in the server."); } string modinfo = ""; StringBuilder SB = new(); decimal uid = user.Id, aid = admin.Id; bool kick = false, ban = false; DiscordEmbedBuilder embed; if (ServerSettings.WKB_Log != 0) { DiscordChannel modlog = server.GetChannel(Convert.ToUInt64(ServerSettings.WKB_Log)); if (WarnedUserStats is null) // creates new entry in DB (Followers set to default value) { DB.ServerRanks newEntry = new() { Server_ID = server.Id, Ban_Count = 0, Kick_Count = 0, Warning_Level = 1, User_ID = user.Id }; DB.DBLists.InsertServerRanks(newEntry); WarnedUserStats = newEntry; } else { WarnedUserStats.Warning_Level++; if (WarnedUserStats.Followers <= 1000 * WarnedUserStats.Warning_Level) { WarnedUserStats.Followers = 0; } else { WarnedUserStats.Followers -= (1000 * WarnedUserStats.Warning_Level); } DB.DBLists.UpdateServerRanks(WarnedUserStats); } DB.Warnings newWarning = new() { Reason = reason, Active = true, Date = DateTime.Now.ToString("yyyy-MM-dd"), Admin_ID = aid, User_ID = uid, Server_ID = server.Id, Type = "warning" }; DB.DBLists.InsertWarnings(newWarning); int warning_count = DB.DBLists.Warnings.Count(w => w.User_ID == user.Id && w.Server_ID == server.Id && w.Type == "warning"); SB.AppendLine($"You have been warned by <@{admin.Id}>.\n**Warning Reason:**\t{reason}\n**Warning Level:** {WarnedUserStats.Warning_Level}\n**Server:** {server.Name}"); embed = new DiscordEmbedBuilder { Color = new DiscordColor(0xf90707), Author = new DiscordEmbedBuilder.EmbedAuthor { IconUrl = user.AvatarUrl, Name = $"{user.Username} ({user.Id})" }, Description = $"**Warned user:**\t{user.Mention}\n**Warning level:**\t {WarnedUserStats.Warning_Level}\t**Warning count:**\t {warning_count}\n**Warned by**\t{admin.Username}\n**Reason:** {reason}" }; if (WarnedUserStats.Warning_Level > 4) { SB.AppendLine($"You have been banned from **{server.Name}** by {admin.Mention} for exceeding the warning level threshold(4)."); ban = true; } else if (WarnedUserStats.Warning_Level > 2 && WarnedUserStats.Warning_Level < 5) { SB.AppendLine($"You have been kicked from **{server.Name}** by {admin.Mention} for exceeding the warning level threshold(2)."); kick = true; } if (automsg) { SB.Append("*This warning is given out by a bot, contact an admin if you think this is a mistake*"); } else { SB.Append($"*(This is an automated message, use the `{Program.CFGJson.CommandPrefix}modmail` feature if you want to report a mistake.)*"); } try { await member.SendMessageAsync(SB.ToString()); } catch { modinfo = $":exclamation:{user.Mention} could not be contacted via DM. Reason not sent"; } if (kick && member != null) { await member.RemoveAsync("Exceeded warning limit!"); } if (ban && user != null) { await server.BanMemberAsync(user.Id, 0, "Exceeded warning limit!"); } await modlog.SendMessageAsync(modinfo, embed : embed); DiscordMessage info = await channel.SendMessageAsync($"{user.Username}, Has been warned!"); await Task.Delay(10000).ContinueWith(t => info.DeleteAsync()); } else { await channel.SendMessageAsync("This server has not set up this feature!"); } }
public async Task CreateInfraction(DiscordGuild guild, DiscordChannel channel, DiscordClient client, DiscordMember moderator, DiscordMember suspect, string reason, InfractionType infractionType) { var suspectLeft = guild.GetMemberAsync(suspect.Id).Result == null; var embed = new Embed(); var owners = client.CurrentApplication.Owners; var verb = infractionType.ToInfractionString().ToLowerInvariant(); var action = infractionType.ToActionString().ToLowerInvariant(); var isSuspectAdministrator = false; var isModerator = await redis.IsModerator(guild.Id, moderator); var isAdministrator = moderator.Roles.Any(role => role.Permissions.HasPermission(Permissions.Administrator)); if (!isModerator && isAdministrator) { isModerator = true; } if (isModerator) { if (!suspectLeft) { if (suspect.Roles.Any(role => role.Permissions.HasPermission(Permissions.Administrator))) { isSuspectAdministrator = true; } if (moderator == suspect) { await channel.SendMessageAsync($"You can not {verb} yourself!"); } else if (owners.Any(x => x.Id == suspect.Id)) { await channel.SendMessageAsync($"You can not {verb} {suspect.Username}!"); } else if (suspect.IsOwner) { await channel.SendMessageAsync($"You can not {verb} the owner!"); } else if (isSuspectAdministrator) { await channel.SendMessageAsync($"You can not {verb} a administrator!"); } else if (await redis.IsModerator(guild.Id, suspect)) { var guildData = await redis.GetAsync <Guild>(RedisKeyNaming.Guild(guild.Id)); switch (infractionType) { case InfractionType.Ban: case InfractionType.Kick: await channel.SendMessageAsync($"You can not {verb} a moderator!"); break; case InfractionType.Warning: { if (!guildData.AllowWarnModerators) { await channel.SendMessageAsync($"You can not {verb} a moderator! [Disabled]"); } break; } case InfractionType.Mute: { if (!guildData.AllowMuteModerators) { await channel.SendMessageAsync($"You can not {verb} a moderator! [Disabled]"); } break; } } } else { var userData = await redis.InitUser(suspect.Id); userData.Infractions.Add(new Infraction() { Id = ++userData.InfractionId, ModeratorId = moderator.Id, ModeratorUsername = moderator.GetUsertag(), GuildId = guild.Id, InfractionType = infractionType, Reason = reason, Date = DateTimeOffset.UtcNow }); await redis.ReplaceAsync <User>(RedisKeyNaming.User(suspect.Id), userData); var description = new StringBuilder().AppendLine($"Moderator: {moderator.GetUsertag()} {Formatter.InlineCode($"{moderator.Id}")}") .AppendLine($"Reason: {reason}"); description.AppendLine("User left the server already!"); embed = new Embed() { Title = $"{suspect.Username} has been {action}!", Description = description.ToString(), Footer = new EmbedFooter() { Text = $"Infractions: {userData.Infractions.Count}" } }; await channel.SendEmbedMessageAsync(embed); embed.Title = $"You have been {action} on {guild.Name}"; await suspect.SendEmbedMessageAsync(embed); switch (infractionType) { case InfractionType.Kick: await suspect.RemoveAsync(reason); break; case InfractionType.Ban: await guild.BanMemberAsync(suspect.Id, 7, reason); break; } } } else { var suspectedUser = await client.GetUserAsync(suspect.Id); var userData = await redis.InitUser(suspectedUser.Id); userData.Infractions.Add(new Infraction() { Id = ++userData.InfractionId, ModeratorId = moderator.Id, ModeratorUsername = moderator.GetUsertag(), GuildId = guild.Id, InfractionType = infractionType, Reason = reason, Date = DateTimeOffset.UtcNow }); await redis.ReplaceAsync <User>(RedisKeyNaming.User(suspectedUser.Id), userData); var description = new StringBuilder().AppendLine($"Moderator: {moderator.GetUsertag()} {Formatter.InlineCode($"{moderator.Id}")}") .AppendLine($"Reason: {reason}") .AppendLine("User left the server already!"); embed = new Embed() { Title = $"{suspect.Username} has been {action}!", Description = description.ToString(), Footer = new EmbedFooter() { Text = $"Infractions: {userData.Infractions.Count}" } }; await channel.SendEmbedMessageAsync(embed); switch (infractionType) { case InfractionType.Kick: await channel.SendMessageAsync("Suspect already left"); break; case InfractionType.Ban: await guild.BanMemberAsync(suspectedUser.Id); break; } } } else { await channel.SendMessageAsync("You are not a moderator of this server."); } }