Example #1
0
            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.");
            }
        }
Example #3
0
            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.");
            }
        }
Example #5
0
        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);
        }
Example #6
0
            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;
            }
        }