Example #1
0
        /// <summary>
        /// Handles simple Http-apis for "reaction" commands
        ///
        /// The incoming argument 0 from context is a collection of IMember, but for later purposes
        /// that type is not required, as we simply use IUser's Mention property, as such converting
        /// down to the lower interface acceptable to allow for implicit targetting
        /// </summary>
        /// <param name="context"></param>
        public static async Task DoReaction(DiscordCommandContext context)
        {
            var          client = context.Services.GetRequiredService <HttpClient>();
            List <IUser> users  = ((IUser?[])context.Arguments[0]).Where(x => x != null).ToList() !;

            var embed = (new LocalEmbed())
                        .WithColor(Program.Color);
            var builder    = new LocalMessage();
            var apiCommand = Program.ApiCommands[context.Command.Name];

            // if no members are specified allow for implicit targeting via the reply system
            if (users.Count == 0 &&
                context.Message.ReferencedMessage.HasValue &&
                context.Message.ReferencedMessage.Value != null &&
                context.Message.ReferencedMessage.Value.Author != null)
            {
                users.Add(context.Message.ReferencedMessage.Value.Author);
            }

            // prepare reaction text if needed
            string?text = null;

            if (apiCommand.Actions.Ranges.Count > 0)
            {
                text = apiCommand.Actions.GetValue(users.Count)?.Random();
            }

            // insert the author as the first "mention"
            users = users.Prepend(context.Author).ToList();

            // insert mentions
            if (text != null)
            {
                // ReSharper disable once CoVariantArrayConversion
                text = string.Format(text, users.Select(x => x.Mention).ToArray());
                embed.WithDescription(text);
            }

            var response = await client.GetAsync(apiCommand.Url);

            if (response.StatusCode != HttpStatusCode.OK)
            {
                await new DiscordResponseCommandResult(context, builder.WithEmbed(embed.WithDescription("An error occurred while fetching reaction!")));
                return;
            }

            // decode the json response, nothing else is supported for the time being
            // we also only care for one level of the response as of now.
            var decoded = JsonConvert.DeserializeObject <Dictionary <string, string> >(await response.Content.ReadAsStringAsync());

            embed.WithImageUrl(apiCommand.GetFixedImageUrl(decoded[apiCommand.Path]));
            await new DiscordResponseCommandResult(context, (new LocalMessage()).WithEmbed(embed));
        }
Example #2
0
        public async Task Help()
        {
            var embeds = new List <LocalEmbed>();

            // normal proper commands
            var commands = new Dictionary <string, List <Tuple <Command, Dictionary <Type, Attribute> > > >();
            // section splits
            var sections = new Dictionary <string, SectionAttribute>();
            // extremely simple commands which will not display a description
            // and share a single row for display
            var simpleCommands = new Dictionary <SectionAttribute, List <Command> >();

            // what we'll be collecting from commands
            var searchAttributes = new List <Type>()
            {
                typeof(SectionAttribute),
                typeof(SimpleCommandAttribute)
            };

            // categorize commands by section first
            foreach (var command in _commands.GetAllCommands())
            {
                var attrs = new Dictionary <Type, Attribute>();
                var copy  = new List <Type>(searchAttributes);

                var attrLists = new List <List <Attribute> >()
                {
                    command.Attributes.ToList(),
                    command.Module.Attributes.ToList()
                };

                var hideCommand = false;
                foreach (var list in attrLists)
                {
                    foreach (var attr in list)
                    {
                        if (attr.GetType() == typeof(HiddenCommandAttribute))
                        {
                            hideCommand = true;
                            break;
                        }

                        for (int i = copy.Count - 1; i > -1; i--)
                        {
                            var item = copy[i];
                            if (attr.GetType() == item)
                            {
                                attrs.Add(item, attr);
                                copy.RemoveAt(i);
                            }
                        }
                    }

                    if (hideCommand)
                    {
                        break;
                    }
                }

                if (hideCommand || !attrs.TryGetValue(typeof(SectionAttribute), out var temp))
                {
                    continue; // invalid or hidden command?
                }

                // re-cast
                SectionAttribute section = (SectionAttribute)temp;
                if (!commands.ContainsKey(section.Name))
                {
                    commands.Add(section.Name, new List <Tuple <Command, Dictionary <Type, Attribute> > >());
                    sections.Add(section.Name, section);
                }

                if (!attrs.ContainsKey(typeof(SimpleCommandAttribute)))
                {
                    commands[section.Name].Add(new Tuple <Command, Dictionary <Type, Attribute> >(command, attrs));
                }
                else
                {
                    if (!simpleCommands.ContainsKey(section))
                    {
                        simpleCommands.Add(section, new List <Command>());
                    }

                    simpleCommands[section].Add(command);
                }
            }

            var last = sections.Last();

            foreach (var attributePair in sections)
            {
                var embed = GetEmbed()
                            .WithTitle(attributePair.Value.Name);

                var description = "\n";
                if (attributePair.Value.Description != null)
                {
                    description = attributePair.Value.Description + "\n\n=======================\n\n";
                }

                // normal commands
                if (commands[attributePair.Value.Name].Count > 0)
                {
                    foreach (var tuple in commands[attributePair.Value.Name])
                    {
                        var name = "**" + tuple.Item1.FullAliases[0] + "**";

                        description += name + " " + string.Join(' ',
                                                                tuple.Item1.Parameters.Select <Parameter, string>(FormatParameter)
                                                                ) + "\n" + (string.IsNullOrEmpty(tuple.Item1.Description) ? "" : "> " + tuple.Item1.Description + "\n\n");
                    }
                }

                // simple commands
                if (simpleCommands.TryGetValue(attributePair.Value, out var simpleList))
                {
                    // show 7 commands in each line
                    foreach (var batch in simpleList.Batch(7))
                    {
                        description += "> " + string.Join(" ", batch.Select(x => x.FullAliases[0])) + "\n\n";
                    }
                }

                if (attributePair.Equals(last))
                {
                    embed.WithFooter("Made by Ly#3449, original concept by zappin#1312, version " + Program.Version);
                }
                else
                {
                    // remove last newlines
                    description = description.Substring(0, description.Length - 1);
                }

                embeds.Add(embed.WithDescription(description));
            }

            var builder       = new LocalMessage();
            var lastEmbed     = embeds.Last();
            var addedReaction = false;

            foreach (var embed in embeds)
            {
                try
                {
                    await Context.Author.SendMessageAsync(builder.WithEmbed(embed));

                    if (!embed.Equals(lastEmbed))
                    {
                        await Task.Delay(500);
                    }

                    if (!addedReaction)
                    {
                        await Context.Message.AddReactionAsync(new LocalEmoji("✅"));
                    }
                }
                catch (Exception) // in case someone has blocked dms
                {
                    await EmbedReply("You seem to have dms disabled or other error occurred!");

                    return;
                }
            }