private async Task Find(IMessageChannel channel, CommandArguments commandArgs) { string response = "meep"; bool found = false; int count = 0; guid lastMessageId = 0; while (true) { IEnumerable <IMessage> batch = await channel.GetMessagesAsync(lastMessageId + 1, Direction.After, 100, CacheMode.AllowDownload).FlattenAsync(); if (batch == null || !batch.Any()) { break; } lastMessageId = batch.Last().Id; count++; if (batch.FirstOrDefault(m => m?.Content != null && guid.TryParse(this.UserIdRegex.Match(m.Content).Value, out guid id) && guid.TryParse(commandArgs.TrimmedMessage, out guid argId) && id == argId) is IUserMessage message) { found = true; response = $"Found message `{message.Id}` at position `{count}`\n{message.Content}"; break; } } if (!found) { response = $"Not found after {count} messages."; } await commandArgs.SendReplySafe(response); }
private async Task CloseThread(CommandArguments commandArgs, bool notify = true) { Match match = this.IdRegex.Match(commandArgs.Channel.Topic); if (!match.Success || !guid.TryParse(match.Value, out guid userId)) { await commandArgs.SendReplySafe("This does not seem to be a modmail thread. This command can only be used in a modmail thread channel."); return; } await commandArgs.Channel.ModifyAsync(c => c.CategoryId = this.Client.Config.ModmailArchiveCategoryId); SocketCategoryChannel category = commandArgs.Channel.Guild.GetCategoryChannel(this.Client.Config.ModmailArchiveCategoryId); while ((category?.Channels.Count ?? 0) > this.Client.Config.ModmailArchiveLimit) { SocketGuildChannel oldChannel = category.Channels.OrderBy(c => c.Id).FirstOrDefault(); if (oldChannel == null) { break; } await oldChannel.DeleteAsync(); } if (notify) { await SendModmailPm(commandArgs, userId, "Thread closed. You're welcome to send another message, should you wish to contact the moderators again."); } }
public async Task Bump(CommandArguments commandArgs) { string response = "Unknown error."; foreach (guid channelId in this.CommandChannelPairs.Values) { SocketTextChannel channel = commandArgs.Server.Guild.GetTextChannel(channelId); if (channel == null) { continue; } response = await Bump(channel, commandArgs.Message.Author.Id); } await commandArgs.SendReplySafe(response); }
private async Task SendModmailPm(CommandArguments commandArgs, guid userId, string message, Embed embed = null) { IGuildUser user = null; foreach (Server server in this.Client.Servers.Values) { user = server.Guild.Users.FirstOrDefault(u => u.Id == userId); if (user == null) { user = await this.Client.DiscordClient.Rest.GetGuildUserAsync(server.Id, userId); } if (user != null) { break; } } if (user == null) { await commandArgs.SendReplySafe($"User <@{userId}> not found."); return; } try { await user.SendMessageSafe(message, embed); if (embed != null) { await commandArgs.SendReplySafe("Message sent:", embed); } else { await commandArgs.SendReplySafe("Thread closed."); } } catch (HttpException e) when((int)e.HttpCode == 403 || (e.DiscordCode.HasValue && e.DiscordCode == 50007) || e.Message.Contains("50007")) { await commandArgs.SendReplySafe("I was unable to send the PM - they have disabled PMs from server members!"); } catch (HttpException e) when((int)e.HttpCode >= 500) { await commandArgs.SendReplySafe("I was unable to send the PM - received Discord Server Error 500 - please try again."); } catch (Exception e) { await this.HandleException(e, "SendModmailPm", user.Guild.Id); await commandArgs.SendReplySafe("Unknown error."); } }
private async Task <RoleConfig> CreateTempRole(CommandArguments e, ServerContext dbContext) { if (!e.Server.Guild.CurrentUser.GuildPermissions.ManageRoles) { await e.Message.Channel.SendMessageSafe(ErrorPermissionsString); return(null); } if (string.IsNullOrEmpty(e.TrimmedMessage)) { await e.SendReplySafe("What role? Name? Do you want me to come up with something silly or what? And when do you want to nuke it?"); return(null); } if (e.MessageArgs.Length != 2) { await e.SendReplySafe(e.Command.Description); return(null); } int durationHours = 0; try { Match dayMatch = Regex.Match(e.MessageArgs[1], "\\d+d", RegexOptions.IgnoreCase); Match hourMatch = Regex.Match(e.MessageArgs[1], "\\d+h", RegexOptions.IgnoreCase); if (!hourMatch.Success && !dayMatch.Success) { await e.SendReplySafe(e.Command.Description); dbContext.Dispose(); return(null); } if (hourMatch.Success) { durationHours = int.Parse(hourMatch.Value.Trim('h').Trim('H')); } if (dayMatch.Success) { durationHours += 24 * int.Parse(dayMatch.Value.Trim('d').Trim('D')); } } catch (Exception) { await e.SendReplySafe(e.Command.Description); dbContext.Dispose(); return(null); } RoleConfig roleConfig = null; string response = Localisation.SystemStrings.DiscordShitEmoji; try { RestRole role = await e.Server.Guild.CreateRoleAsync(e.MessageArgs[0], GuildPermissions.None); roleConfig = dbContext.GetOrAddRole(e.Server.Id, role.Id); roleConfig.DeleteAtTime = DateTime.UtcNow + TimeSpan.FromHours(durationHours); response = $"Role created: `{role.Name}`\n Id: `{role.Id}`\n Delete at `{Utils.GetTimestamp(roleConfig.DeleteAtTime)}`"; } catch (Exception exception) { await this.HandleException(exception, "CreateTempRole failed.", e.Server.Id); } await e.SendReplySafe(response); return(roleConfig); }
public async Task SendOrReplaceEmbed(CommandArguments commandArgs) { if (!this.CommandChannelPairs.ContainsKey(commandArgs.CommandId.ToLower())) { return; } if (string.IsNullOrEmpty(commandArgs.TrimmedMessage) || commandArgs.TrimmedMessage == "--help") { await commandArgs.SendReplySafe(this.HelpString); return; } IMessageChannel channel = commandArgs.Server.Guild.GetTextChannel(this.CommandChannelPairs[commandArgs.CommandId.ToLower()]); object returnValue = GetRecruitmentEmbed(commandArgs.TrimmedMessage); if (returnValue != null) { string response = "Unknown error."; if (returnValue is Embed embed) { bool replaced = false; response = "All done!"; guid lastMessageId = 0; while (true) { IEnumerable <IMessage> batch = await channel.GetMessagesAsync(lastMessageId + 1, Direction.After, 100, CacheMode.AllowDownload).FlattenAsync(); if (batch == null || !batch.Any()) { break; } lastMessageId = batch.Last().Id; IMessage message = batch.FirstOrDefault(m => m?.Content != null && guid.TryParse(this.UserIdRegex.Match(m.Content).Value, out guid id) && id == commandArgs.Message.Author.Id); if (message != null) { replaced = true; response = "I've modified your previous post."; switch (message) { case SocketUserMessage msg: await msg.ModifyAsync(m => m.Embed = embed); break; case RestUserMessage msg: await msg.ModifyAsync(m => m.Embed = embed); break; default: response = "I wasn't able to modify the old post."; break; } break; } } if (!replaced) { await channel.SendMessageAsync($"<@{commandArgs.Message.Author.Id}>'s post:", embed : embed); } } else if (returnValue is string errorText) { response = $"{errorText}\n_(Use `{commandArgs.Server.Config.CommandPrefix}{commandArgs.CommandId}` without arguments for help.)_"; } await commandArgs.SendReplySafe(response); } }
public async Task SendEmbedFromCli(CommandArguments cmdArgs, IUser pmInstead = null) { if (string.IsNullOrEmpty(cmdArgs.TrimmedMessage) || cmdArgs.TrimmedMessage == "-h" || cmdArgs.TrimmedMessage == "--help") { await cmdArgs.SendReplySafe("```md\nCreate an embed using the following parameters:\n" + "[ --channel ] Channel where to send the embed.\n" + "[ --edit <msgId>] Replace a MessageId with a new embed (use after --channel)\n" + "[ --text ] Regular content text\n" + "[ --title ] Title\n" + "[ --description ] Description\n" + "[ --footer ] Footer\n" + "[ --color ] #rrggbb hex color used for the embed stripe.\n" + "[ --image ] URL of a Hjuge image in the bottom.\n" + "[ --thumbnail ] URL of a smol image on the side.\n" + "[ --fieldName ] Create a new field with specified name.\n" + "[ --fieldValue ] Text value of a field - has to follow a name.\n" + "[ --fieldInline ] Use to set the field as inline.\n" + "Where you can repeat the field* options multiple times.\n```" ); return; } SocketTextChannel channel = null; bool debug = false; string text = null; IMessage msg = null; EmbedFieldBuilder currentField = null; EmbedBuilder embedBuilder = new EmbedBuilder(); foreach (Match match in this.RegexCliParam.Matches(cmdArgs.TrimmedMessage)) { string optionString = this.RegexCliOption.Match(match.Value).Value; if (optionString == "--debug") { if (IsGlobalAdmin(cmdArgs.Message.Author.Id) || IsSupportTeam(cmdArgs.Message.Author.Id)) { debug = true; } continue; } if (optionString == "--fieldInline") { if (currentField == null) { await cmdArgs.SendReplySafe($"`fieldInline` can not precede `fieldName`."); return; } currentField.WithIsInline(true); if (debug) { await cmdArgs.Channel.SendMessageSafe($"Setting inline for field `{currentField.Name}`"); } continue; } string value; if (match.Value.Length <= optionString.Length || string.IsNullOrWhiteSpace(value = match.Value.Substring(optionString.Length + 1).Trim())) { await cmdArgs.SendReplySafe($"Invalid value for `{optionString}`"); return; } if (value.Length >= UserProfileOption.ValueCharacterLimit) { await cmdArgs.SendReplySafe($"`{optionString}` is too long! (It's {value.Length} characters while the limit is {UserProfileOption.ValueCharacterLimit})"); return; } switch (optionString) { case "--channel": if (!guid.TryParse(value.Trim('<', '>', '#'), out guid id) || (channel = cmdArgs.Server.Guild.GetTextChannel(id)) == null) { await cmdArgs.SendReplySafe($"Channel {value} not found."); return; } if (debug) { await cmdArgs.Channel.SendMessageSafe($"Channel set: `{channel.Name}`"); } break; case "--text": if (value.Length > GlobalConfig.MessageCharacterLimit) { await cmdArgs.SendReplySafe($"`--text` is too long (`{value.Length} > {GlobalConfig.MessageCharacterLimit}`)"); return; } text = value; if (debug) { await cmdArgs.Channel.SendMessageSafe($"Text set: `{value}`"); } break; case "--title": if (value.Length > 256) { await cmdArgs.SendReplySafe($"`--title` is too long (`{value.Length} > 256`)"); return; } embedBuilder.WithTitle(value); if (debug) { await cmdArgs.Channel.SendMessageSafe($"Title set: `{value}`"); } break; case "--description": if (value.Length > 2048) { await cmdArgs.SendReplySafe($"`--description` is too long (`{value.Length} > 2048`)"); return; } embedBuilder.WithDescription(value); if (debug) { await cmdArgs.Channel.SendMessageSafe($"Description set: `{value}`"); } break; case "--footer": if (value.Length > 2048) { await cmdArgs.SendReplySafe($"`--footer` is too long (`{value.Length} > 2048`)"); return; } embedBuilder.WithFooter(value); if (debug) { await cmdArgs.Channel.SendMessageSafe($"Description set: `{value}`"); } break; case "--image": try { embedBuilder.WithImageUrl(value.Trim('<', '>')); } catch (Exception) { await cmdArgs.SendReplySafe($"`--image` is invalid url"); return; } if (debug) { await cmdArgs.Channel.SendMessageSafe($"Image URL set: `{value}`"); } break; case "--thumbnail": try { embedBuilder.WithThumbnailUrl(value.Trim('<', '>')); } catch (Exception) { await cmdArgs.SendReplySafe($"`--thumbnail` is invalid url"); return; } if (debug) { await cmdArgs.Channel.SendMessageSafe($"Thumbnail URL set: `{value}`"); } break; case "--color": try { uint color = uint.Parse(value.TrimStart('#'), System.Globalization.NumberStyles.AllowHexSpecifier); if (color > uint.Parse("FFFFFF", System.Globalization.NumberStyles.AllowHexSpecifier)) { await cmdArgs.SendReplySafe("Color out of range."); return; } embedBuilder.WithColor(color); if (debug) { await cmdArgs.Channel.SendMessageSafe($"Color `{value}` set."); } } catch (Exception) { await cmdArgs.SendReplySafe("Invalid color format."); return; } break; case "--fieldName": if (value.Length > 256) { await cmdArgs.SendReplySafe($"`--fieldName` is too long (`{value.Length} > 256`)\n```\n{value}\n```"); return; } if (currentField != null && currentField.Value == null) { await cmdArgs.SendReplySafe($"Field `{currentField.Name}` is missing a value!"); return; } if (embedBuilder.Fields.Count >= 25) { await cmdArgs.SendReplySafe("Too many fields! (Limit is 25)"); return; } embedBuilder.AddField(currentField = new EmbedFieldBuilder().WithName(value)); if (debug) { await cmdArgs.Channel.SendMessageSafe($"Creating new field `{currentField.Name}`"); } break; case "--fieldValue": if (value.Length > 1024) { await cmdArgs.SendReplySafe($"`--fieldValue` is too long (`{value.Length} > 1024`)\n```\n{value}\n```"); return; } if (currentField == null) { await cmdArgs.SendReplySafe($"`fieldValue` can not precede `fieldName`."); return; } currentField.WithValue(value); if (debug) { await cmdArgs.Channel.SendMessageSafe($"Setting value:\n```\n{value}\n```\n...for field:`{currentField.Name}`"); } break; case "--edit": if (!guid.TryParse(value, out guid msgId) || (msg = await channel?.GetMessageAsync(msgId)) == null) { await cmdArgs.SendReplySafe($"`--edit` did not find a message with ID `{value}` in the <#{(channel?.Id ?? 0)}> channel."); return; } break; default: await cmdArgs.SendReplySafe($"Unknown option: `{optionString}`"); return; } } if (currentField != null && currentField.Value == null) { await cmdArgs.SendReplySafe($"Field `{currentField.Name}` is missing a value!"); return; } switch (msg) { case null: if (pmInstead != null) { await pmInstead.SendMessageAsync(text : text, embed : embedBuilder.Build()); } else if (channel == null) { await cmdArgs.SendReplySafe(text : text, embed : embedBuilder.Build()); } else { await channel.SendMessageAsync(text : text, embed : embedBuilder.Build()); } break; case RestUserMessage message: await message?.ModifyAsync(m => { m.Content = text; m.Embed = embedBuilder.Build(); }); break; case SocketUserMessage message: await message?.ModifyAsync(m => { m.Content = text; m.Embed = embedBuilder.Build(); }); break; default: await cmdArgs.SendReplySafe("GetMessage went bork."); break; } }