public async Task WarnUserAsync( [Summary("The user to warn.")] SocketGuildUser user, [Summary("The reason to warn the user."), Remainder] string reason) { UserData data = Data.UserData.GetUser(user.Id); EmbedBuilder builder = new EmbedBuilder() .WithColor(Color.Orange); bool printInfractions = data != null && data.Infractions?.Count > 0; string previousInfractions = null; // Collect the previous infractions before applying new ones, otherwise we will also collect this // new infraction when printing them if (printInfractions) { previousInfractions = string.Join('\n', data.Infractions.OrderByDescending(i => i.Time).Select(i => i.ToString())); } Moderation.AddInfraction(user, Infraction.Create(Moderation.RequestInfractionID()) .WithType(InfractionType.Warning) .WithModerator(Context.User) .WithDescription(reason)); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.Warn) .WithReason(reason) .WithTarget(user) .WithAdditionalInfo(previousInfractions), Context.Channel); }
public override void InitiateClient(DiscordClient _client) { _client.GetService <CommandService>().CreateCommand("purge") .Alias("delet") .Alias("delete") .Alias("settler-colonize") .Description("Clears messages from a channel.") .Parameter("number", type: ParameterType.Required) .Parameter("user", ParameterType.Optional) .Do(async e => { if (Config.INSTANCE.GetPermissionLevel(e.User, e.Server) > 1) { var purgemessages = await e.Channel.DownloadMessages(Int32.Parse(e.Args[0]) + 1); if (e.GetArg("user") == "") { // Delete any messages await e.Channel.DeleteMessages(purgemessages); } else { // Delete messages from specified user foreach (Message msg in purgemessages) { if (msg.User == e.Message.MentionedUsers.First()) { await msg.Delete(); } } } } await e.Message.Delete(); ModerationLog.LogToPublic($"User {e.User.Name} purged {e.GetArg("number")} messages in #{e.Channel.Name}", e.Server); } ); }
public async Task BanAsync( [Summary("The user to ban.")] GuildUserProxy user, [Summary("The reason why to ban the user."), Remainder] string reason = DefaultReason) { if (user.HasValue) { await user.GuildUser.TrySendMessageAsync($"You were banned from **{Context.Guild.Name}** because of {reason}."); } await Context.Guild.AddBanAsync(user.ID, _pruneDays, reason); Infraction infraction = Infraction.Create(Moderation.RequestInfractionID()) .WithType(InfractionType.Ban) .WithModerator(Context.User) .WithDescription(reason); // Normally it would be preferred to use the AddInfraction(IUser, Infraction) method but that one implicitly // sends a DM to the target which will not be in the server anymore at this point AND this method already // attempts to send a DM to the target. Moderation.AddInfraction(user.ID, infraction); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithInfractionId(infraction.ID) .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.Ban) .WithTarget(user.ID) .WithReason(reason), Context.Channel); }
public async Task ClearInfractionsAsync( [Summary("The user to clear the infractions from.")] GuildUserProxy user) { ulong userId = user.HasValue ? user.GuildUser.Id : user.ID; int clearedInfractions = Moderation.ClearInfractions(userId); EmbedBuilder builder = GetDefaultBuilder() .WithColor(Color.Green); if (user.HasValue) { builder.WithDescription($"**{clearedInfractions}** infraction(s) were cleared from {user.GuildUser}."); } else { builder.WithDescription($"**{clearedInfractions}** infraction(s) were cleared from {userId}."); } await builder.Build() .SendToChannel(Context.Channel); if (clearedInfractions > 0) { await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.ClearInfractions) .WithTarget(userId)); } }
public async Task KickUser( [Summary("The user to kick.")] GuildUserProxy user, [Summary("The reason to kick the user for."), Remainder] string reason = DefaultReason) { if (!user.HasValue) { throw new ArgumentException($"User with ID {user.ID} is not in the server!"); } await user.GuildUser.KickAsync(reason); Infraction infraction = Infraction.Create(Moderation.RequestInfractionID()) .WithType(InfractionType.Kick) .WithModerator(Context.User) .WithDescription(reason); if (user.HasValue) { Moderation.AddInfraction(user.GuildUser, infraction); } else { Moderation.AddInfraction(user.ID, infraction); } await ModerationLog.CreateEntry(ModerationLogEntry.New .WithInfractionId(infraction.ID) .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.Kick) .WithReason(reason) .WithTarget(user), Context.Channel); }
public async Task ClearMessagesAsync( [Summary("The user to clear messages of")] SocketGuildUser user, [Summary("The amount of messages to clear")] int count, [Summary("The history length to delete from")] int history = 100) { int maxHistory = Context.Configuration.ClearMessageMaxHistory; if (history > maxHistory) { history = maxHistory; } var aMessages = await Context.Channel.GetMessagesAsync(history).FlattenAsync(); var fMessages = aMessages.Where(m => m.Author.Id == user.Id) .Where(m => (DateTimeOffset.Now - m.CreatedAt).Days < 14); if (fMessages.Count() > 0) { var messages = fMessages.Take(count); await(Context.Channel as ITextChannel).DeleteMessagesAsync(messages); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithReason($"Deleted {messages.Count()} message(s) of {user.Mention}") .WithActionType(ModerationActionType.ClearMessages) .WithChannel(Context.Channel as ITextChannel)); } }
public async Task TempmuteAsync( [Summary("The user to mute.")] GuildUserProxy user, [Summary("The duration for the mute."), OverrideTypeReader(typeof(AbbreviatedTimeSpanTypeReader))] TimeSpan duration, [Summary("The reason why to mute the user."), Remainder] string reason = DefaultReason) { if (!user.HasValue) { throw new ArgumentException($"User with ID {user.ID} is not in the server!"); } bool unlimitedTime = (Context.User as IGuildUser).GetPermissionLevel(Data.Configuration) >= PermissionLevel.Moderator; double givenDuration = duration.TotalMilliseconds; int maxHelperMuteDuration = Data.Configuration.HelperMuteMaxDuration; if (!unlimitedTime && givenDuration > maxHelperMuteDuration) { duration = TimeSpan.FromMilliseconds(maxHelperMuteDuration); } await user.GuildUser.MuteAsync(Context); SetUserMuted(user.ID, true); Infraction infraction = Moderation.AddTemporaryInfraction(TemporaryInfractionType.TempMute, user.GuildUser, Context.User, duration, reason); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithInfractionId(infraction.ID) .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.TempMute) .WithTarget(user) .WithDuration(duration) .WithReason(reason), Context.Channel); }
public async Task MuteAsync( [Summary("The user to mute.")] GuildUserProxy user, [Summary("The reason why to mute the user."), Remainder] string reason = DefaultReason) { if (!user.HasValue) { throw new ArgumentException($"User with ID {user.ID} is not in the server!"); } await user.GuildUser.MuteAsync(Context); SetUserMuted(user.ID, true); Infraction infraction = Infraction.Create(Moderation.RequestInfractionID()) .WithType(InfractionType.Mute) .WithModerator(Context.User) .WithDescription(reason); Moderation.AddInfraction(user.GuildUser, infraction); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithInfractionId(infraction.ID) .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.Mute) .WithTarget(user) .WithReason(reason), Context.Channel); }
public override void InitiateClient(DiscordClient _client) { _client.GetService <CommandService>().CreateCommand("kick") .Description("Kicks a user.") .Parameter("user") .Do(async e => { if (Config.INSTANCE.GetPermissionLevel(e.User, e.Server) > 1) { String usersKicked = ""; foreach (User user in e.Message.MentionedUsers) { if (!user.IsBot) { usersKicked += (user.Name + " "); await user.Kick(); } } ModerationLog.LogToPublic($"User {e.User.Name} kicked user(s) {usersKicked}", e.Server); } } ); _client.GetService <CommandService>().CreateCommand("ban") .Description("Bans a user.") .Parameter("user") .Do(async e => { if (Config.INSTANCE.GetPermissionLevel(e.User, e.Server) > 1) { String usersBanned = ""; foreach (User user in e.Message.MentionedUsers) { if (!user.IsBot) { usersBanned += (user.Name + " "); await e.Server.Ban(user, 3); } } ModerationLog.LogToPublic($"User {e.User.Name} banned user(s) {usersBanned}", e.Server); } } ); _client.GetService <CommandService>().CreateCommand("forcenick") .Alias("fn") .Description("Forces a user's nickname to be changed.") .Parameter("user") .Parameter("nick") .Do(async e => { if (Config.INSTANCE.GetPermissionLevel(e.User, e.Server) > 1) { User user = e.Server.FindUsers(e.GetArg("user")).First(); await user.Edit(nickname: e.GetArg("nick")); } } ); }
private static void LogTransfer(IChatbotContext context, string moderatorUsername, string oldUsername, string newUsername) { var logRecord = new ModerationLog { Username = moderatorUsername, Action = ModerationAction.UsernameTransfer, ActionTakenTime = DateTime.UtcNow, ExtraInformation = $"{moderatorUsername} has transferred {oldUsername}'s account to {newUsername}" }; context.ModerationLogs.Add(logRecord); }
public async Task UnbanAsync( [Summary("The user ID to unban.")] GuildUserProxy user) { await Context.Guild.RemoveBanAsync(user.ID); Moderation.ClearTemporaryInfraction(TemporaryInfractionType.TempBan, user.ID); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.Unban) .WithTarget(user.ID), Context.Channel); }
public async Task UnmuteAsync( [Summary("The user to unmute.")] SocketGuildUser user) { await user.UnmuteAsync(Context); SetUserMuted(user.Id, false); Moderation.ClearTemporaryInfraction(TemporaryInfractionType.TempMute, user); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.Unmute) .WithTarget(user), Context.Channel); }
public async Task <ModerationLog> RecordModerationAsync(string action, DiscordGuild guild, DiscordUser subject, DiscordUser moderator = null, string reason = null) { if (string.IsNullOrWhiteSpace(action)) { throw new ArgumentNullException("action"); } ModerationLog log = new ModerationLog(action, guild, subject, moderator, reason); await log.SaveAsync(DbContext); await ReportModerationLogAsync(log, guild, subject : subject, moderator : moderator); return(log); }
private async Task ReportModerationLogAsync(ModerationLog log, DiscordGuild guild = null, DiscordUser subject = null, DiscordUser moderator = null) { if (guild == null) { guild = await Bot.Discord.GetGuildAsync(log.GuildId); } if (moderator == null && log.ModeratorId > 0) { moderator = await Bot.Discord.GetUserAsync(log.ModeratorId); } if (subject == null && log.SubjectId > 0) { subject = await Bot.Discord.GetUserAsync(log.SubjectId); } //Figure out what hte guild modlog folder is var gs = await GuildSettings.GetGuildSettingsAsync(guild); if (gs.ModLogId > 0) { StringBuilder content = new StringBuilder(); content.AppendFormat($"**{log.Action}** | {log.Id}\n"); if (subject != null) { content.AppendLine($"**User** : {subject.Mention} ( {subject.Id} )"); } if (moderator != null) { content.AppendLine($"**Moderator** : {moderator.Mention} ( {moderator.Id} )"); } if (!string.IsNullOrWhiteSpace(log.Reason)) { content.AppendLine($"**Reason**: ```{log.Reason}```"); } //Send the message and update our log var msg = await gs.GetModLogChannel().SendMessageAsync(content.ToString()); log.Message = msg.Id; //Save the log await log.SaveAsync(DbContext); } }
public override async void ParseMessageAsync(Channel channel, Message message) { foreach (string word in Config.INSTANCE.Blacklist) { if (message.Text.ToLower().Contains(word) && !message.User.IsBot && Config.INSTANCE.GetPermissionLevel(message.User, message.Server) < 2) { ModerationLog.LogToPublic($"User {message.User} used blacklisted word {word} in channel #{channel.Name}. Message was as follows: \n {message}", message.Server); await channel.DeleteMessages(new Message[] { message }); await channel.SendMessage("``` Message redacted for the sake of the Motherland. ```"); break; } } }
public async Task BanAsync( [Summary("The user to ban.")] GuildUserProxy user, [Summary("The reason why to ban the user."), Remainder] string reason = DefaultReason) { if (user.HasValue) { await user.GuildUser.TrySendMessageAsync($"You were banned from **{Context.Guild.Name}** because of {reason}."); } await Context.Guild.AddBanAsync(user.ID, _pruneDays, reason); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.Ban) .WithTarget(user.ID) .WithReason(reason), Context.Channel); }
public async Task KickUser( [Summary("The user to kick.")] SocketGuildUser user, [Summary("The reason to kick the user for."), Remainder] string reason = DefaultReason) { await user.KickAsync(reason); Moderation.AddInfraction(user, Infraction.Create(Moderation.RequestInfractionID()) .WithType(InfractionType.Kick) .WithModerator(Context.User) .WithDescription(reason)); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.Kick) .WithReason(reason) .WithTarget(user), Context.Channel); }
public async Task BanAsync( [Summary("The user to ban")] GuildUserProxy user, [Summary("The duration for the ban."), OverrideTypeReader(typeof(AbbreviatedTimeSpanTypeReader))] TimeSpan duration, [Summary("The reason why to ban the user."), Remainder] string reason = DefaultReason) { // Since the user cannot be found (we are using the GuildUserProxy) we don't need to attempt to message him await Context.Guild.AddBanAsync(user.ID, _pruneDays, reason); Moderation.AddTemporaryInfraction(TemporaryInfractionType.TempBan, user.ID, Context.User, duration, reason); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.TempBan) .WithTarget(user.ID) .WithDuration(duration) .WithReason(reason), Context.Channel); }
public async Task ClearMessagesAsync( [Summary("The amount of messages to clear")] int count) { int maxHistory = Context.Configuration.ClearMessageMaxHistory; count = count + 1 > maxHistory ? maxHistory : count + 1; var messages = await Context.Channel.GetMessagesAsync(count).FlattenAsync(); var validMessages = messages.Where(m => (DateTimeOffset.Now - m.CreatedAt).Days < 14); await(Context.Channel as ITextChannel).DeleteMessagesAsync(validMessages); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.ClearMessages) .WithChannel(Context.Channel as ITextChannel)); }
private async Task AddModerationLog(ModerationLog.ModAction action, IGuildUser user, string reason) { using (NekoDbContext dbContext = new NekoDbContext()) { ModerationLog newModerationLog = new ModerationLog { ExecutingUserId = context.User.Id, ExecutingUsername = context.User.Username, TargetedUserId = user.Id, TargetUsername = user.Username, Reason = reason, Timestamp = DateTime.UtcNow }; dbContext.ModerationLogs.Add(newModerationLog); await dbContext.SaveChangesAsync(); } }
public async Task TempmuteAsync( [Summary("The user to mute.")] SocketGuildUser user, [Summary("The duration for the mute."), OverrideTypeReader(typeof(AbbreviatedTimeSpanTypeReader))] TimeSpan duration, [Summary("The reason why to mute the user."), Remainder] string reason = DefaultReason) { await user.MuteAsync(Context); SetUserMuted(user.Id, true); Moderation.AddTemporaryInfraction(TemporaryInfractionType.TempMute, user, Context.User, duration, reason); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.TempMute) .WithTarget(user) .WithDuration(duration) .WithReason(reason), Context.Channel); }
public async Task ClearInfractionsAsync( [Summary("The user to clear the infractions from.")] SocketGuildUser user) { int clearedInfractions = Moderation.ClearInfractions(user); await GetDefaultBuilder() .WithDescription($"{clearedInfractions} infraction(s) were cleared from {user.Mention}.") .Build() .SendToChannel(Context.Channel); if (clearedInfractions > 0) { await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.ClearInfractions) .WithTarget(user)); } }
public async Task TempbanAsync( [Summary("The user to temporarily ban.")] SocketGuildUser user, [Summary("The duration for the ban."), OverrideTypeReader(typeof(AbbreviatedTimeSpanTypeReader))] TimeSpan duration, [Summary("The reason why to ban the user."), Remainder] string reason = DefaultReason) { await user.TrySendMessageAsync($"You were banned from **{Context.Guild.Name}** for {duration.Humanize(7)} because of **{reason}**."); await user.BanAsync(_pruneDays, reason); Moderation.AddTemporaryInfraction(TemporaryInfractionType.TempBan, user, Context.User, duration, reason); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.TempBan) .WithTarget(user) .WithDuration(duration) .WithReason(reason), Context.Channel); }
public async Task MuteAsync( [Summary("The user to mute.")] SocketGuildUser user, [Summary("The reason why to mute the user."), Remainder] string reason = DefaultReason) { await user.MuteAsync(Context); SetUserMuted(user.Id, true); Moderation.AddInfraction(user, Infraction.Create(Moderation.RequestInfractionID()) .WithType(InfractionType.Mute) .WithModerator(Context.User) .WithDescription(reason)); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.Mute) .WithTarget(user) .WithReason(reason), Context.Channel); }
public async Task UnmuteAsync( [Summary("The user to unmute.")] GuildUserProxy user) { if (!user.HasValue) { throw new ArgumentException($"User with ID {user.ID} is not in the server!"); } await user.GuildUser.UnmuteAsync(Context); SetUserMuted(user.ID, false); Moderation.ClearTemporaryInfraction(TemporaryInfractionType.TempMute, user.GuildUser); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.Unmute) .WithTarget(user), Context.Channel); }
private async Task SetLockdown(bool lockdown = false) { IRole everyone = Context.Guild.EveryoneRole; GuildPermissions newPermissions = everyone.Permissions.Modify(sendMessages: !lockdown); await everyone.ModifyAsync(x => x.Permissions = newPermissions); string message = $"Lockdown {(lockdown ? "enabled" : "disabled")}!"; await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithReason(message) .WithActionType(ModerationActionType.Lockdown)); await new EmbedBuilder() .WithColor(Color.DarkGreen) .WithDescription(message) .Build() .SendToChannel(Context.Channel); }
/// <summary> /// Records a moderative action /// </summary> /// <param name="action"></param> /// <param name="moderator"></param> /// <param name="subject"></param> /// <param name="reason"></param> /// <returns></returns> public async Task <ModerationLog> RecordModerationAsync(string action, DiscordMember moderator, DiscordUser subject, string reason) { if (string.IsNullOrWhiteSpace(action)) { throw new ArgumentNullException("action"); } if (moderator == null) { throw new ArgumentNullException("moderator"); } //Get the moderation log and save it ModerationLog log = new ModerationLog(action, moderator, subject, reason); await log.SaveAsync(DbContext); //Report the log await ReportModerationLogAsync(log, moderator.Guild, subject : subject, moderator : moderator); return(log); }
public async Task SlowModeAsync( [Summary("The duration of slowmode"), OverrideTypeReader(typeof(AbbreviatedTimeSpanTypeReader))] TimeSpan duration) { EmbedBuilder builder = new EmbedBuilder(); int slowmodeDuration = (int)duration.TotalSeconds; if (slowmodeDuration > _maxSlowMode || slowmodeDuration < 0) { builder.WithColor(Color.Red) .WithDescription($"Duration ({duration.Humanize(3)}) out of bounds (0 - {_maxSlowMode / 3600} hours)!"); } else { builder.WithColor(Color.Green); if (slowmodeDuration == 0) { builder.WithDescription($"Slowmode is turned off!"); } else { builder.WithDescription($"Slowmode is set to {duration.Humanize(3)}!"); } ITextChannel channel = await Context.Guild.GetTextChannelAsync(Context.Channel.Id); await channel.ModifyAsync(x => x.SlowModeInterval = slowmodeDuration); await ModerationLog.CreateEntry(ModerationLogEntry.New .WithDefaultsFromContext(Context) .WithActionType(ModerationActionType.SlowMode) .WithDuration(duration)); } await builder.Build().SendToChannel(Context.Channel); }
public override void InitiateClient(DiscordClient _client) { _client.GetService <CommandService>().CreateGroup("blacklist", bgp => { bgp.CreateCommand("print") .Do(async e => { await e.Channel.SendIsTyping(); String line = ""; line += "================== CURRENT BLACKLIST ================\n"; line += $" Blacklist contains {Config.INSTANCE.Blacklist.Count} words\n"; line += "==================================================\n"; foreach (String word in Config.INSTANCE.Blacklist) { if (line.Length + word.Length + 1 <= MESSAGE_MAX_LENGTH) { line += word + '\n'; } else { await e.Channel.SendMessage(line); line = word + '\n'; } } if (line.Length > 0) { await e.Channel.SendMessage(line); } await e.Channel.SendMessage("================== BLACKLIST ENDS ==================="); }); bgp.CreateCommand("add") .Parameter("word") .Do(e => { if (Config.INSTANCE.GetPermissionLevel(e.User, e.Server) > 1) { //String word = e.GetArg("word"); //bool is_pattern = word.StartsWith("/") && word.EndsWith("/"); if (Config.INSTANCE.Blacklist.Contains(e.GetArg("word"))) { e.Channel.SendMessage($"Word \"{e.Args[0]}\" already in blacklist."); return; } Config.INSTANCE.Blacklist.Add(e.GetArg("word")); ModerationLog.LogToPublic($"User {e.User} added the word {e.Args[0]} to the blacklist.", e.Server); e.Channel.SendMessage($"Added \"{e.Args[0]}\" to the blacklist."); Config.INSTANCE.Commit(); } }); bgp.CreateCommand("remove") .Parameter("word") .Do(e => { if (Config.INSTANCE.GetPermissionLevel(e.User, e.Server) > 1) { if (!Config.INSTANCE.Blacklist.Contains(e.GetArg("word"))) { e.Channel.SendMessage($"Word \"{e.Args[0]}\" not in blacklist."); return; } Config.INSTANCE.Blacklist.Remove(e.Args[0]); ModerationLog.LogToPublic($"User {e.User} removed the word {e.Args[0]} from the blacklist.", e.Server); e.Channel.SendMessage($"Removed \"{e.Args[0]}\" from the blacklist."); Config.INSTANCE.Commit(); } }); }); }
public override void InitiateClient(DiscordClient _client) { // set up message checking timer removeMessagesTimer.Interval = 15000; // 15 seconds removeMessagesTimer.Elapsed += (sender, e) => MessageChecker(sender, e, _client); removeMessagesTimer.AutoReset = true; removeMessagesTimer.Start(); // check any outdated self-assignable roles without "group" properties int rolesFound = 0; foreach (SelfAssignRole r in Config.INSTANCE.selfAssignRoles) { if (String.IsNullOrEmpty(r.group)) { r.group = ""; rolesFound++; } } if (rolesFound > 0) { Config.INSTANCE.Commit(); } // set up commands _client.GetService <CommandService>().CreateCommand("roles") .Description("Prints out all server roles.") .Do(e => { // check permissions if (Config.INSTANCE.GetPermissionLevel(e.User, e.Server) < 2) { e.Channel.SendMessage("Sorry, you don't have permission to do that."); return; } // print all server roles String roleString = "```"; for (int i = 0; i < e.Server.RoleCount; i++) { Role role = e.Server.Roles.ElementAt(i); roleString += $"{role.Name}" + (i == e.Server.RoleCount - 1 ? "" : ", "); } roleString += "```"; e.Channel.SendMessage($"Server roles ({e.Server.RoleCount}/{MAX_ROLES}):\n{roleString}"); }); _client.GetService <CommandService>().CreateCommand("iam") .Alias("giverole") .Alias("setrole") .Description("Gives the user a self-assignable role.") .Parameter("role", ParameterType.Multiple) .Do(e => { String roleName = String.Join(" ", e.Args); Role role = e.Server.FindRoles(roleName, true).FirstOrDefault(); ModerationLog.LogToPublic($"User {e.User.Name} attempted to give themselves role {roleName} in #{e.Channel.Name}", e.Server); // check if role exists if (role == null) { GiveFeedback(e, $"Role `{roleName}` does not exist."); return; } // check if role is self-assignable if (!RoleIsAssignable(role)) { GiveFeedback(e, $"Role `{roleName}` is not self-assignable."); return; } // assign role if (e.User.HasRole(role)) { GiveFeedback(e, "You already have this role."); } else { e.User.AddRoles(role); GiveFeedback(e, $"Assigned role `{roleName}`."); } }); _client.GetService <CommandService>().CreateCommand("iamn") .Alias("iamnot") .Alias("removerole") .Description("Removes a self-assignable role from the user.") .Parameter("role", ParameterType.Multiple) .Do(e => { String roleName = String.Join(" ", e.Args); Role role = e.Server.FindRoles(roleName, true).FirstOrDefault(); // check if role exists if (role == null) { GiveFeedback(e, $"Role `{roleName}` does not exist."); return; } // check if role is self-assignable if (!RoleIsAssignable(role)) { GiveFeedback(e, $"Role `{roleName}` is not self-assignable."); return; } // unassign role if (!e.User.HasRole(role)) { GiveFeedback(e, "You do not have this role to remove."); } else { e.User.RemoveRoles(role); GiveFeedback(e, $"Unassigned role `{roleName}`."); ModerationLog.LogToPublic($"User {e.User.Name} removed their role {roleName} in #{e.Channel.Name}", e.Server); } }); _client.GetService <CommandService>().CreateGroup("aroles", egp => { egp.CreateCommand("add") .Description("Makes a role self-assignable, optionally adding it to a group.") .Parameter("role") .Parameter("group", ParameterType.Optional) .Do(e => { // check permissions if (Config.INSTANCE.GetPermissionLevel(e.User, e.Server) < 2) { e.Channel.SendMessage("Sorry, you don't have permission to do that."); return; } String roleName = e.GetArg("role"); String groupName = e.GetArg("group").ToLower(); Role role = e.Server.FindRoles(roleName, true).FirstOrDefault(); // check if role exists if (role == null) { e.Channel.SendMessage($"Role `{roleName}` does not exist."); return; } // check if role is already self-assignable if (RoleIsAssignable(role)) { e.Channel.SendMessage($"Role `{roleName}` is already self-assignable."); return; } // set role as self-assignable SelfAssignRole newRole = new SelfAssignRole { server_id = role.Server.Id, role_id = role.Id, group = groupName }; String groupText = String.IsNullOrEmpty(groupName) ? "." : $" (added to group \"{groupName}\")"; Config.INSTANCE.selfAssignRoles.Add(newRole); e.Channel.SendMessage($"Role `{roleName}` is now self-assignable{groupText}"); ModerationLog.LogToPublic($"User {e.User.Name} made role {roleName} self-assignable", e.Server); Config.INSTANCE.Commit(); }); egp.CreateCommand("remove") .Description("Removes a role from being self-assignable.") .Parameter("role", ParameterType.Multiple) .Do(e => { // check permissions if (Config.INSTANCE.GetPermissionLevel(e.User, e.Server) < 2) { e.Channel.SendMessage("Sorry, you don't have permission to do that."); return; } String roleName = String.Join(" ", e.Args); Role role = e.Server.FindRoles(roleName, true).FirstOrDefault(); // check if role exists if (role == null) { e.Channel.SendMessage($"Role `{roleName}` does not exist."); return; } // check if role is self-assignable if (!RoleIsAssignable(role)) { e.Channel.SendMessage($"Role `{roleName}` is not self-assignable."); return; } // remove role from being self-assignable foreach (SelfAssignRole r in Config.INSTANCE.selfAssignRoles) { if (r.server_id == e.Server.Id && r.role_id == role.Id) { Config.INSTANCE.selfAssignRoles.Remove(r); e.Channel.SendMessage($"Role `{roleName}` is no longer self-assignable."); ModerationLog.LogToPublic($"User {e.User.Name} removed role {roleName} from being self-assignable", e.Server); Config.INSTANCE.Commit(); break; } } }); egp.CreateCommand("print") .Description("Prints all self-assignable roles.") .Parameter("group", ParameterType.Optional) .Do(e => { // print all self-assignable roles String roleString = ""; int saRoleCount = 0; SortedDictionary <String, List <Role> > groups = new SortedDictionary <String, List <Role> >(); String groupFilter = e.GetArg("group"); // compile all self-assignable roles by group foreach (SelfAssignRole r in Config.INSTANCE.selfAssignRoles) { // only roles on this server if (r.server_id == e.Server.Id) { // get valid role Role role = e.Server.GetRole(r.role_id); if (role == null) { continue; } // if group filter specified, exclude all roles not belonging to that group if (!String.IsNullOrEmpty(groupFilter) && r.group != groupFilter) { continue; } // create group list if it doesn't exist if (!groups.ContainsKey(r.group)) { groups.Add(r.group, new List <Role>()); } // add role to group list groups[r.group].Add(role); } } // print roles foreach (KeyValuePair <String, List <Role> > group in groups) { String groupName = group.Key == "" ? "Ungrouped" : group.Key; roleString += $"```{groupName} ({group.Value.Count}):\n"; for (int i = 0; i < group.Value.Count; i++) { saRoleCount++; Role role = group.Value.ElementAt(i); roleString += $"{role.Name}" + (i == group.Value.Count - 1 ? "" : ", "); } roleString += "```"; } // print message if (saRoleCount > 0) { roleString = "Self-assignable roles" + (String.IsNullOrEmpty(groupFilter) ? ":\n" : $" in group `{groupFilter}`:\n") + roleString; roleString += "\nThe above roles are self-assignable using the commands:\n"; roleString += "`!iam [role]` -- assigns a role\n"; roleString += "`!iamn [role]` -- removes a role"; if (Config.INSTANCE.GetPermissionLevel(e.User, e.Server) < 2) { // feedback messages to non-mods are temporary GiveFeedback(e, roleString); } else { // feedback messages to mods are regular messages e.Channel.SendMessage(roleString); } } else if (!String.IsNullOrEmpty(groupFilter)) { GiveFeedback(e, $"There are no self-assignable roles in group `{groupFilter}`."); } else { GiveFeedback(e, "There are no self-assignable roles on this server."); } }); egp.CreateCommand("setgroup") .Description("Add a self-assignable role to a group for organization.") .Parameter("role") .Parameter("group") .Do(e => { // check permissions if (Config.INSTANCE.GetPermissionLevel(e.User, e.Server) < 2) { e.Channel.SendMessage("Sorry, you don't have permission to do that."); return; } String roleName = e.GetArg("role"); String groupName = e.GetArg("group").ToLower(); Role role = e.Server.FindRoles(roleName, true).FirstOrDefault(); // check if role exists if (role == null) { e.Channel.SendMessage($"Role `{roleName}` does not exist."); return; } // check if role is self-assignable if (!RoleIsAssignable(role)) { e.Channel.SendMessage($"Role `{roleName}` is not self-assignable."); return; } // set role group foreach (SelfAssignRole r in Config.INSTANCE.selfAssignRoles) { if (r.server_id == e.Server.Id && r.role_id == role.Id) { if (String.IsNullOrEmpty(r.group)) { // add new group to role e.Channel.SendMessage($"Role `{roleName}` added to group `{groupName}`."); ModerationLog.LogToPublic($"User {e.User.Name} added role {roleName} to group {groupName}", e.Server); } else { // move role to other group e.Channel.SendMessage($"Role `{roleName}` moved from group `{r.group}` to `{groupName}`."); ModerationLog.LogToPublic($"User {e.User.Name} moved role {roleName} from group {r.group} to {groupName}", e.Server); } r.group = groupName; Config.INSTANCE.Commit(); break; } } }); egp.CreateCommand("removegroup") .Alias("unsetgroup") .Description("Remove a self-assignable role from a group.") .Parameter("role", ParameterType.Multiple) .Do(e => { // check permissions if (Config.INSTANCE.GetPermissionLevel(e.User, e.Server) < 2) { e.Channel.SendMessage("Sorry, you don't have permission to do that."); return; } String roleName = e.GetArg("role"); Role role = e.Server.FindRoles(roleName, true).FirstOrDefault(); // check if role exists if (role == null) { e.Channel.SendMessage($"Role `{roleName}` does not exist."); return; } // check if role is self-assignable if (!RoleIsAssignable(role)) { e.Channel.SendMessage($"Role `{roleName}` is not self-assignable."); return; } // remove role group foreach (SelfAssignRole r in Config.INSTANCE.selfAssignRoles) { if (r.server_id == e.Server.Id && r.role_id == role.Id) { if (String.IsNullOrEmpty(r.group)) { e.Channel.SendMessage($"Role `{roleName}` already not in any group."); } else { e.Channel.SendMessage($"Role `{roleName}` removed from group `{r.group}`."); ModerationLog.LogToPublic($"User {e.User.Name} removed role {roleName} to group {r.group}", e.Server); r.group = ""; Config.INSTANCE.Commit(); } break; } } }); egp.CreateCommand("renamegroup") .Description("Rename a group containing self-assignable roles.") .Parameter("current") .Parameter("new") .Do(e => { // check permissions if (Config.INSTANCE.GetPermissionLevel(e.User, e.Server) < 2) { e.Channel.SendMessage("Sorry, you don't have permission to do that."); return; } String currName = e.GetArg("current").ToLower(); String newName = e.GetArg("new").ToLower(); // change group property on matching roles int foundRoles = 0; foreach (SelfAssignRole r in Config.INSTANCE.selfAssignRoles) { if (r.group == currName) { r.group = newName; foundRoles++; } } // save changes if (foundRoles > 0) { e.Channel.SendMessage($"Group `{currName}` renamed to `{newName}`."); ModerationLog.LogToPublic($"User {e.User.Name} renamed role group {currName} to {newName}", e.Server); Config.INSTANCE.Commit(); } else { e.Channel.SendMessage($"Group `{currName}` does not exist."); } }); }); }