Example #1
0
 GroupCommandsIncludeGroupCommand
 (
     GroupCommands groupCommands,
     GroupCommands groupCommand
 )
 {
     return((groupCommands & groupCommand) != 0);
 }
        //*************************************************************************
        //  Constructor: RunGroupCommandEventArgs()
        //
        /// <summary>
        /// Initializes a new instance of the <see
        /// cref="RunGroupCommandEventArgs" /> class.
        /// </summary>
        ///
        /// <param name="groupCommand">
        /// The single group command that needs to be run.
        /// </param>
        ///
        /// <remarks>
        /// Note that although <see cref="GroupCommands" /> flags can be ORed
        /// together, the <paramref name="groupCommand" /> argument should include
        /// only one of these flags.
        /// </remarks>
        //*************************************************************************

        public RunGroupCommandEventArgs
        (
            GroupCommands groupCommand
        )
        {
            m_eGroupCommand = groupCommand;

            AssertValid();
        }
    //*************************************************************************
    //  Constructor: RunGroupCommandEventArgs()
    //
    /// <summary>
    /// Initializes a new instance of the <see
    /// cref="RunGroupCommandEventArgs" /> class.
    /// </summary>
    ///
    /// <param name="groupCommand">
    /// The single group command that needs to be run.
    /// </param>
    ///
    /// <remarks>
    /// Note that although <see cref="GroupCommands" /> flags can be ORed
    /// together, the <paramref name="groupCommand" /> argument should include
    /// only one of these flags.
    /// </remarks>
    //*************************************************************************

    public RunGroupCommandEventArgs
    (
        GroupCommands groupCommand
    )
    {
        m_eGroupCommand = groupCommand;

        AssertValid();
    }
Example #4
0
        protected override void ApplicationStartup(ILifetimeScope container, IPipelines pipelines)
        {
            ClashCaller.Init();
            Bots.Init();
            GroupCommands.Init();
            Mods.Init();
            try
            {
                //The bot can live if the members consistency isn't verified.
                Members.UpdateMembersByGroup(ConfigurationManager.AppSettings["GROUPME_TOKEN"], ConfigurationManager.AppSettings["GENERALCHAT_ID"]);
                Members.UpdateMembersByGroup(ConfigurationManager.AppSettings["GROUPME_TOKEN"], ConfigurationManager.AppSettings["WARCHAT_ID"]);
            }
            catch (Exception ex)
            {
                Bots.TestChatBot.SendMessage("Error while saving members into the database");
                Bots.TestChatBot.SendMessage(ex.ToString());
            }

            base.ApplicationStartup(container, pipelines);
        }
Example #5
0
        GetGroupCommandsToEnableInternal
        (
            Microsoft.Office.Interop.Excel.Workbook oWorkbook
        )
        {
            Debug.Assert(oWorkbook != null);

            GroupCommands eGroupCommandsToEnable = GroupCommands.None;

            ListObject oGroupTable;
            Range      oSelectedTableRange;

            // Are any groups selected in the group table?

            if (ExcelTableUtil.TryGetSelectedTableRange(oWorkbook,
                                                        WorksheetNames.Groups, TableNames.Groups, out oGroupTable,
                                                        out oSelectedTableRange))
            {
                // Yes.

                eGroupCommandsToEnable |= (
                    GroupCommands.CollapseSelectedGroups |
                    GroupCommands.ExpandSelectedGroups |
                    GroupCommands.RemoveSelectedGroups
                    );
            }

            // Are any vertices selected in the vertex table?

            ListObject oVertexTable;

            Boolean bVerticesSelected = ExcelTableUtil.TryGetSelectedTableRange(
                oWorkbook, WorksheetNames.Vertices, TableNames.Vertices,
                out oVertexTable, out oSelectedTableRange);

            if (bVerticesSelected)
            {
                eGroupCommandsToEnable |=
                    GroupCommands.AddSelectedVerticesToGroup;
            }

            // Are there any groups?

            if (!ExcelTableUtil.VisibleTableRangeIsEmpty(oGroupTable))
            {
                // Yes.

                eGroupCommandsToEnable |= (
                    GroupCommands.CollapseAllGroups |
                    GroupCommands.ExpandAllGroups |
                    GroupCommands.SelectAllGroups |
                    GroupCommands.RemoveAllGroups
                    );

                if (bVerticesSelected)
                {
                    eGroupCommandsToEnable |= (
                        GroupCommands.SelectGroupsWithSelectedVertices |
                        GroupCommands.RemoveSelectedVerticesFromGroups
                        );
                }
            }

            return(eGroupCommandsToEnable);
        }
Example #6
0
        TryRunGroupCommand
        (
            GroupCommands groupCommand,
            Microsoft.Office.Interop.Excel.Workbook workbook,
            Sheet2 vertexWorksheet,
            Sheet5 groupWorksheet
        )
        {
            Debug.Assert(workbook != null);
            Debug.Assert(vertexWorksheet != null);
            Debug.Assert(groupWorksheet != null);

            switch (groupCommand)
            {
            case GroupCommands.None:

                return(true);

            case GroupCommands.CollapseSelectedGroups:

                return(TryCollapseOrExpandSelectedGroups(workbook, true));

            case GroupCommands.ExpandSelectedGroups:

                return(TryCollapseOrExpandSelectedGroups(workbook, false));

            case GroupCommands.CollapseAllGroups:

                return(TryCollapseOrExpandAllGroups(workbook, true));

            case GroupCommands.ExpandAllGroups:

                return(TryCollapseOrExpandAllGroups(workbook, false));

            case GroupCommands.SelectGroupsWithSelectedVertices:

                return(TrySelectGroupsWithSelectedVertices(workbook,
                                                           vertexWorksheet, groupWorksheet));

            case GroupCommands.SelectAllGroups:

                return(TrySelectAllGroups(workbook));

            case GroupCommands.AddSelectedVerticesToGroup:

                return(TryAddSelectedVerticesToGroup(workbook,
                                                     vertexWorksheet));

            case GroupCommands.RemoveSelectedVerticesFromGroups:

                ICollection <String> oSelectedVertexNames;

                return(TryRemoveSelectedVerticesFromGroups(workbook,
                                                           vertexWorksheet, out oSelectedVertexNames));

            case GroupCommands.RemoveSelectedGroups:

                return(TryRemoveSelectedGroups(workbook, groupWorksheet));

            case GroupCommands.RemoveAllGroups:

                return(TryRemoveAllGroups(workbook));

            default:

                Debug.Assert(false);
                return(false);
            }
        }
        private void RegisterCommands(Type t, ulong?guildid)
        {
            CommandMethod[]   InternalCommandMethods   = Array.Empty <CommandMethod>();
            GroupCommand[]    InternalGroupCommands    = Array.Empty <GroupCommand>();
            SubGroupCommand[] InternalSubGroupCommands = Array.Empty <SubGroupCommand>();

            Client.Ready += (s, e) =>
            {
                _ = Task.Run(async() =>
                {
                    try
                    {
                        List <CommandCreatePayload> ToUpdate = new List <CommandCreatePayload>();

                        var ti = t.GetTypeInfo();

                        var classes = ti.DeclaredNestedTypes;
                        foreach (var tti in classes.Where(x => x.GetCustomAttribute <SlashCommandGroupAttribute>() != null))
                        {
                            var groupatt   = tti.GetCustomAttribute <SlashCommandGroupAttribute>();
                            var submethods = tti.DeclaredMethods;
                            var subclasses = tti.DeclaredNestedTypes;
                            if (subclasses.Any(x => x.GetCustomAttribute <SlashCommandGroupAttribute>() != null) && submethods.Any(x => x.GetCustomAttribute <SlashCommandAttribute>() != null))
                            {
                                throw new ArgumentException("Slash command groups cannot have both subcommands and subgroups!");
                            }
                            var payload = new CommandCreatePayload
                            {
                                Name        = groupatt.Name,
                                Description = groupatt.Description
                            };
                            var commandmethods = new Dictionary <string, MethodInfo>();
                            foreach (var submethod in submethods.Where(x => x.GetCustomAttribute <SlashCommandAttribute>() != null))
                            {
                                var commandattribute = submethod.GetCustomAttribute <SlashCommandAttribute>();
                                var subpayload       = new DiscordApplicationCommandOption(commandattribute.Name, commandattribute.Description);

                                var parameters = submethod.GetParameters();
                                if (!ReferenceEquals(parameters.First().ParameterType, typeof(InteractionContext)))
                                {
                                    throw new ArgumentException($"The first argument must be an InteractionContext!");
                                }
                                parameters = parameters.Skip(1).ToArray();
                                foreach (var parameter in parameters)
                                {
                                    var optionattribute = parameter.GetCustomAttribute <OptionAttribute>();
                                    if (optionattribute == null)
                                    {
                                        throw new ArgumentException("Arguments must have the Option attribute!");
                                    }

                                    var type = parameter.ParameterType;
                                    ApplicationCommandOptionType parametertype;
                                    if (ReferenceEquals(type, typeof(string)))
                                    {
                                        parametertype = ApplicationCommandOptionType.String;
                                    }
                                    else if (ReferenceEquals(type, typeof(long)))
                                    {
                                        parametertype = ApplicationCommandOptionType.Integer;
                                    }
                                    else if (ReferenceEquals(type, typeof(bool)))
                                    {
                                        parametertype = ApplicationCommandOptionType.Boolean;
                                    }
                                    else if (ReferenceEquals(type, typeof(DiscordChannel)))
                                    {
                                        parametertype = ApplicationCommandOptionType.Channel;
                                    }
                                    else if (ReferenceEquals(type, typeof(DiscordUser)))
                                    {
                                        parametertype = ApplicationCommandOptionType.User;
                                    }
                                    else if (ReferenceEquals(type, typeof(DiscordRole)))
                                    {
                                        parametertype = ApplicationCommandOptionType.Role;
                                    }
                                    else
                                    {
                                        throw new ArgumentException("Cannot convert type! Argument types must be string, long, bool, DiscordChannel, DiscordUser or DiscordRole.");
                                    }

                                    DiscordApplicationCommandOptionChoice[] choices = null;
                                    var choiceattributes = parameter.GetCustomAttributes <ChoiceAttribute>();
                                    if (choiceattributes.Any())
                                    {
                                        choices = Array.Empty <DiscordApplicationCommandOptionChoice>();
                                        foreach (var att in choiceattributes)
                                        {
                                            choices = choices.Append(new DiscordApplicationCommandOptionChoice(att.Name, att.Value)).ToArray();
                                        }
                                    }

                                    var list = subpayload.Options?.ToList() ?? new List <DiscordApplicationCommandOption>();

                                    list.Add(new DiscordApplicationCommandOption(optionattribute.Name, optionattribute.Description)
                                    {
                                        Required = !parameter.IsOptional,
                                        Type     = parametertype,
                                        Choices  = choices
                                    });

                                    subpayload.Options = list;
                                }

                                commandmethods.Add(commandattribute.Name, submethod);

                                payload.Options.Add(new DiscordApplicationCommandOption(commandattribute.Name, commandattribute.Description)
                                {
                                    Required = null,
                                    Options  = subpayload.Options,
                                    Type     = ApplicationCommandOptionType.SubCommand
                                });

                                InternalGroupCommands = InternalGroupCommands.Append(new GroupCommand {
                                    Name = groupatt.Name, ParentClass = tti, Methods = commandmethods
                                }).ToArray();
                            }
                            foreach (var subclass in subclasses.Where(x => x.GetCustomAttribute <SlashCommandGroupAttribute>() != null))
                            {
                                var subgroupatt   = subclass.GetCustomAttribute <SlashCommandGroupAttribute>();
                                var subsubmethods = subclass.DeclaredMethods.Where(x => x.GetCustomAttribute <SlashCommandAttribute>() != null);

                                var command = new SubGroupCommand {
                                    Name = groupatt.Name
                                };

                                var subpayload = new DiscordApplicationCommandOption(subgroupatt.Name, subgroupatt.Description)
                                {
                                    Required = null,
                                    Type     = ApplicationCommandOptionType.SubCommandGroup,
                                    Options  = new List <DiscordApplicationCommandOption>()
                                };

                                foreach (var subsubmethod in subsubmethods)
                                {
                                    var commatt       = subsubmethod.GetCustomAttribute <SlashCommandAttribute>();
                                    var subsubpayload = new DiscordApplicationCommandOption(commatt.Name, commatt.Description)
                                    {
                                        Type = ApplicationCommandOptionType.SubCommand,
                                    };
                                    var parameters = subsubmethod.GetParameters();
                                    if (!ReferenceEquals(parameters.First().ParameterType, typeof(InteractionContext)))
                                    {
                                        throw new ArgumentException($"The first argument must be an InteractionContext!");
                                    }
                                    parameters = parameters.Skip(1).ToArray();
                                    foreach (var parameter in parameters)
                                    {
                                        var optionattribute = parameter.GetCustomAttribute <OptionAttribute>();
                                        if (optionattribute == null)
                                        {
                                            throw new ArgumentException("Arguments must have the Option attribute!");
                                        }

                                        var type = parameter.ParameterType;
                                        ApplicationCommandOptionType parametertype;
                                        if (ReferenceEquals(type, typeof(string)))
                                        {
                                            parametertype = ApplicationCommandOptionType.String;
                                        }
                                        else if (ReferenceEquals(type, typeof(long)))
                                        {
                                            parametertype = ApplicationCommandOptionType.Integer;
                                        }
                                        else if (ReferenceEquals(type, typeof(bool)))
                                        {
                                            parametertype = ApplicationCommandOptionType.Boolean;
                                        }
                                        else if (ReferenceEquals(type, typeof(DiscordChannel)))
                                        {
                                            parametertype = ApplicationCommandOptionType.Channel;
                                        }
                                        else if (ReferenceEquals(type, typeof(DiscordUser)))
                                        {
                                            parametertype = ApplicationCommandOptionType.User;
                                        }
                                        else if (ReferenceEquals(type, typeof(DiscordRole)))
                                        {
                                            parametertype = ApplicationCommandOptionType.Role;
                                        }
                                        else
                                        {
                                            throw new ArgumentException("Cannot convert type! Argument types must be string, long, bool, DiscordChannel, DiscordUser or DiscordRole.");
                                        }

                                        DiscordApplicationCommandOptionChoice[] choices = null;
                                        var choiceattributes = parameter.GetCustomAttributes <ChoiceAttribute>();
                                        if (choiceattributes.Any())
                                        {
                                            choices = Array.Empty <DiscordApplicationCommandOptionChoice>();
                                            foreach (var att in choiceattributes)
                                            {
                                                choices = choices.Append(new DiscordApplicationCommandOptionChoice(att.Name, att.Value)).ToArray();
                                            }
                                        }

                                        var list = subsubpayload.Options?.ToList() ?? new List <DiscordApplicationCommandOption>();

                                        list.Add(new DiscordApplicationCommandOption(optionattribute.Name, optionattribute.Description)
                                        {
                                            Required = !parameter.IsOptional,
                                            Type     = parametertype,
                                            Choices  = choices
                                        });

                                        subsubpayload.Options = list;
                                    }
                                    subpayload.Options = subpayload.Options.ToArray().Append(subsubpayload).ToList();
                                    commandmethods.Add(commatt.Name, subsubmethod);
                                }
                                command.SubCommands.Add(new GroupCommand {
                                    Name = subgroupatt.Name, ParentClass = subclass, Methods = commandmethods
                                });
                                InternalSubGroupCommands = InternalSubGroupCommands.Append(command).ToArray();
                                payload.Options.Add(subpayload);
                            }
                            ToUpdate.Add(payload);
                        }

                        var methods = ti.DeclaredMethods;
                        foreach (var method in methods.Where(x => x.GetCustomAttribute <SlashCommandAttribute>() != null))
                        {
                            var commandattribute = method.GetCustomAttribute <SlashCommandAttribute>();
                            var payload          = new CommandCreatePayload
                            {
                                Name        = commandattribute.Name,
                                Description = commandattribute.Description
                            };

                            var parameters = method.GetParameters();
                            if (!ReferenceEquals(parameters.First().ParameterType, typeof(InteractionContext)))
                            {
                                throw new ArgumentException($"The first argument must be an InteractionContext!");
                            }
                            parameters = parameters.Skip(1).ToArray();
                            foreach (var parameter in parameters)
                            {
                                var optionattribute = parameter.GetCustomAttribute <OptionAttribute>();
                                if (optionattribute == null)
                                {
                                    throw new ArgumentException("Arguments must have the SlashOption attribute!");
                                }

                                var type = parameter.ParameterType;
                                ApplicationCommandOptionType parametertype;
                                if (ReferenceEquals(type, typeof(string)))
                                {
                                    parametertype = ApplicationCommandOptionType.String;
                                }
                                else if (ReferenceEquals(type, typeof(long)))
                                {
                                    parametertype = ApplicationCommandOptionType.Integer;
                                }
                                else if (ReferenceEquals(type, typeof(bool)))
                                {
                                    parametertype = ApplicationCommandOptionType.Boolean;
                                }
                                else if (ReferenceEquals(type, typeof(DiscordChannel)))
                                {
                                    parametertype = ApplicationCommandOptionType.Channel;
                                }
                                else if (ReferenceEquals(type, typeof(DiscordUser)))
                                {
                                    parametertype = ApplicationCommandOptionType.User;
                                }
                                else if (ReferenceEquals(type, typeof(DiscordRole)))
                                {
                                    parametertype = ApplicationCommandOptionType.Role;
                                }
                                else
                                {
                                    throw new ArgumentException($"Cannot convert type! Argument types must be string, long, bool, DiscordChannel, DiscordUser or DiscordRole.");
                                }

                                DiscordApplicationCommandOptionChoice[] choices = null;
                                var choiceattributes = parameter.GetCustomAttributes <ChoiceAttribute>();
                                if (choiceattributes.Any())
                                {
                                    choices = Array.Empty <DiscordApplicationCommandOptionChoice>();
                                    foreach (var att in choiceattributes)
                                    {
                                        choices = choices.Append(new DiscordApplicationCommandOptionChoice(att.Name, att.Value)).ToArray();
                                    }
                                }

                                payload.Options.Add(new DiscordApplicationCommandOption(optionattribute.Name, optionattribute.Description)
                                {
                                    Required = !parameter.IsOptional,
                                    Type     = parametertype,
                                    Choices  = choices
                                });
                            }
                            InternalCommandMethods = InternalCommandMethods.Append(new CommandMethod {
                                Method = method, Name = commandattribute.Name, ParentClass = t
                            }).ToArray();
                            ToUpdate.Add(payload);
                        }

                        var commands = await BulkCreateCommandsAsync(ToUpdate, guildid);
                        foreach (var command in commands)
                        {
                            if (InternalCommandMethods.Any(x => x.Name == command.Name))
                            {
                                InternalCommandMethods.First(x => x.Name == command.Name).Id = command.Id;
                            }

                            else if (InternalGroupCommands.Any(x => x.Name == command.Name))
                            {
                                InternalGroupCommands.First(x => x.Name == command.Name).Id = command.Id;
                            }

                            else if (InternalSubGroupCommands.Any(x => x.Name == command.Name))
                            {
                                InternalSubGroupCommands.First(x => x.Name == command.Name).Id = command.Id;
                            }
                        }
                        CommandMethods.AddRange(InternalCommandMethods);
                        GroupCommands.AddRange(InternalGroupCommands);
                        SubGroupCommands.AddRange(InternalSubGroupCommands);
                    }
                    catch (Exception ex)
                    {
                        Client.Logger.LogError(ex, $"There was an error registering slash commands");
                        Environment.Exit(-1);
                    }
                });

                return(Task.CompletedTask);
            };
        }
        //Handler
        internal Task InteractionHandler(DiscordClient client, InteractionCreateEventArgs e)
        {
            _ = Task.Run(async() =>
            {
                InteractionContext context = new InteractionContext
                {
                    Interaction            = e.Interaction,
                    Channel                = e.Interaction.Channel,
                    Guild                  = e.Interaction.Guild,
                    User                   = e.Interaction.User,
                    Client                 = client,
                    SlashCommandsExtension = this,
                    CommandName            = e.Interaction.Data.Name,
                    InteractionId          = e.Interaction.Id,
                    Token                  = e.Interaction.Token
                };

                try
                {
                    var methods   = CommandMethods.Where(x => x.Id == e.Interaction.Data.Id);
                    var groups    = GroupCommands.Where(x => x.Id == e.Interaction.Data.Id);
                    var subgroups = SubGroupCommands.Where(x => x.Id == e.Interaction.Data.Id);
                    if (!methods.Any() && !groups.Any() && !subgroups.Any())
                    {
                        throw new SlashCommandNotFoundException("An interaction was created, but no command was registered for it");
                    }
                    if (methods.Any())
                    {
                        var method = methods.First();

                        List <object> args = new List <object> {
                            context
                        };
                        var parameters = method.Method.GetParameters().Skip(1);

                        for (int i = 0; i < parameters.Count(); i++)
                        {
                            var parameter = parameters.ElementAt(i);
                            if (parameter.IsOptional && (e.Interaction.Data.Options == null || e.Interaction.Data.Options?.ElementAtOrDefault(i) == default))
                            {
                                args.Add(parameter.DefaultValue);
                            }
                            else
                            {
                                var option = e.Interaction.Data.Options.ElementAt(i);

                                if (ReferenceEquals(parameter.ParameterType, typeof(string)))
                                {
                                    args.Add(option.Value.ToString());
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(long)))
                                {
                                    args.Add((long)option.Value);
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(bool)))
                                {
                                    args.Add((bool)option.Value);
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(DiscordUser)))
                                {
                                    if (e.Interaction.Data.Resolved.Members.TryGetValue((ulong)option.Value, out var member))
                                    {
                                        args.Add(member);
                                    }
                                    else if (e.Interaction.Data.Resolved.Users.TryGetValue((ulong)option.Value, out var user))
                                    {
                                        args.Add(user);
                                    }
                                    else
                                    {
                                        args.Add(await Client.GetUserAsync((ulong)option.Value));
                                    }
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(DiscordChannel)))
                                {
                                    if (e.Interaction.Data.Resolved.Channels.TryGetValue((ulong)option.Value, out var channel))
                                    {
                                        args.Add(channel);
                                    }
                                    else
                                    {
                                        args.Add(e.Interaction.Guild.GetChannel((ulong)option.Value));
                                    }
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(DiscordRole)))
                                {
                                    if (e.Interaction.Data.Resolved.Roles.TryGetValue((ulong)option.Value, out var role))
                                    {
                                        args.Add(role);
                                    }
                                    else
                                    {
                                        args.Add(e.Interaction.Guild.GetRole((ulong)option.Value));
                                    }
                                }
                                else
                                {
                                    throw new ArgumentException($"How on earth did that happen");
                                }
                            }
                        }
                        var classinstance = Activator.CreateInstance(method.ParentClass);
                        var task          = (Task)method.Method.Invoke(classinstance, args.ToArray());
                        await task;
                    }
                    else if (groups.Any())
                    {
                        var command = e.Interaction.Data.Options.First();
                        var method  = groups.First().Methods.First(x => x.Key == command.Name).Value;

                        List <object> args = new List <object> {
                            context
                        };
                        var parameters = method.GetParameters().Skip(1);

                        for (int i = 0; i < parameters.Count(); i++)
                        {
                            var parameter = parameters.ElementAt(i);
                            if (parameter.IsOptional && (command.Options == null || command.Options?.ElementAtOrDefault(i) == default))
                            {
                                args.Add(parameter.DefaultValue);
                            }
                            else
                            {
                                var option = command.Options.ElementAt(i);

                                if (ReferenceEquals(parameter.ParameterType, typeof(string)))
                                {
                                    args.Add(option.Value.ToString());
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(long)))
                                {
                                    args.Add((long)option.Value);
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(bool)))
                                {
                                    args.Add((bool)option.Value);
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(DiscordUser)))
                                {
                                    if (e.Interaction.Data.Resolved.Members.TryGetValue((ulong)option.Value, out var member))
                                    {
                                        args.Add(member);
                                    }
                                    else if (e.Interaction.Data.Resolved.Users.TryGetValue((ulong)option.Value, out var user))
                                    {
                                        args.Add(user);
                                    }
                                    else
                                    {
                                        args.Add(await Client.GetUserAsync((ulong)option.Value));
                                    }
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(DiscordChannel)))
                                {
                                    if (e.Interaction.Data.Resolved.Channels.TryGetValue((ulong)option.Value, out var channel))
                                    {
                                        args.Add(channel);
                                    }
                                    else
                                    {
                                        args.Add(e.Interaction.Guild.GetChannel((ulong)option.Value));
                                    }
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(DiscordRole)))
                                {
                                    if (e.Interaction.Data.Resolved.Roles.TryGetValue((ulong)option.Value, out var role))
                                    {
                                        args.Add(role);
                                    }
                                    else
                                    {
                                        args.Add(e.Interaction.Guild.GetRole((ulong)option.Value));
                                    }
                                }
                                else
                                {
                                    throw new ArgumentException($"How on earth did that happen");
                                }
                            }
                        }
                        var classinstance = Activator.CreateInstance(groups.First().ParentClass);
                        var task          = (Task)method.Invoke(classinstance, args.ToArray());
                        await task;
                    }
                    else if (subgroups.Any())
                    {
                        var command = e.Interaction.Data.Options.First();
                        var group   = subgroups.First(x => x.SubCommands.Any(y => y.Name == command.Name)).SubCommands.First(x => x.Name == command.Name);

                        var method = group.Methods.First(x => x.Key == command.Options.First().Name).Value;

                        List <object> args = new List <object> {
                            context
                        };
                        var parameters = method.GetParameters().Skip(1);

                        for (int i = 0; i < parameters.Count(); i++)
                        {
                            var parameter = parameters.ElementAt(i);
                            if (parameter.IsOptional && (command.Options == null || command.Options?.ElementAtOrDefault(i) == default))
                            {
                                args.Add(parameter.DefaultValue);
                            }
                            else
                            {
                                var option = command.Options.ElementAt(i);

                                if (ReferenceEquals(parameter.ParameterType, typeof(string)))
                                {
                                    args.Add(option.Value.ToString());
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(long)))
                                {
                                    args.Add((long)option.Value);
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(bool)))
                                {
                                    args.Add((bool)option.Value);
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(DiscordUser)))
                                {
                                    if (e.Interaction.Data.Resolved.Members.TryGetValue((ulong)option.Value, out var member))
                                    {
                                        args.Add(member);
                                    }
                                    else if (e.Interaction.Data.Resolved.Users.TryGetValue((ulong)option.Value, out var user))
                                    {
                                        args.Add(user);
                                    }
                                    else
                                    {
                                        args.Add(await Client.GetUserAsync((ulong)option.Value));
                                    }
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(DiscordChannel)))
                                {
                                    if (e.Interaction.Data.Resolved.Channels.TryGetValue((ulong)option.Value, out var channel))
                                    {
                                        args.Add(channel);
                                    }
                                    else
                                    {
                                        args.Add(e.Interaction.Guild.GetChannel((ulong)option.Value));
                                    }
                                }
                                else if (ReferenceEquals(parameter.ParameterType, typeof(DiscordRole)))
                                {
                                    if (e.Interaction.Data.Resolved.Roles.TryGetValue((ulong)option.Value, out var role))
                                    {
                                        args.Add(role);
                                    }
                                    else
                                    {
                                        args.Add(e.Interaction.Guild.GetRole((ulong)option.Value));
                                    }
                                }
                                else
                                {
                                    throw new ArgumentException($"How on earth did that happen");
                                }
                            }
                        }
                        var classinstance = Activator.CreateInstance(group.ParentClass);
                        var task          = (Task)method.Invoke(classinstance, args.ToArray());
                        await task;
                    }

                    await _executed.InvokeAsync(this, new SlashCommandExecutedEventArgs {
                        Context = context
                    });
                }
                catch (Exception ex)
                {
                    await _error.InvokeAsync(this, new SlashCommandErrorEventArgs {
                        Context = context, Exception = ex
                    });
                }
            });
            return(Task.CompletedTask);
        }
Example #9
0
        private void RegisterCommands(Type[] types, ulong?guildid)
        {
            CommandMethod[]   InternalCommandMethods   = Array.Empty <CommandMethod>();
            GroupCommand[]    InternalGroupCommands    = Array.Empty <GroupCommand>();
            SubGroupCommand[] InternalSubGroupCommands = Array.Empty <SubGroupCommand>();
            List <DiscordApplicationCommand> ToUpdate  = new List <DiscordApplicationCommand>();

            _ = Task.Run(async() =>
            {
                foreach (var t in types)
                {
                    try
                    {
                        var ti = t.GetTypeInfo();

                        var classes = ti.DeclaredNestedTypes;
                        foreach (var tti in classes.Where(x => x.GetCustomAttribute <SlashCommandGroupAttribute>() != null))
                        {
                            var groupatt   = tti.GetCustomAttribute <SlashCommandGroupAttribute>();
                            var submethods = tti.DeclaredMethods;
                            var subclasses = tti.DeclaredNestedTypes;
                            if (subclasses.Any(x => x.GetCustomAttribute <SlashCommandGroupAttribute>() != null) && submethods.Any(x => x.GetCustomAttribute <SlashCommandAttribute>() != null))
                            {
                                throw new ArgumentException("Slash command groups cannot have both subcommands and subgroups!");
                            }
                            var payload = new DiscordApplicationCommand(groupatt.Name, groupatt.Description);


                            var commandmethods = new Dictionary <string, MethodInfo>();
                            foreach (var submethod in submethods.Where(x => x.GetCustomAttribute <SlashCommandAttribute>() != null))
                            {
                                var commandattribute = submethod.GetCustomAttribute <SlashCommandAttribute>();


                                var parameters = submethod.GetParameters();
                                if (!ReferenceEquals(parameters.First().ParameterType, typeof(InteractionContext)))
                                {
                                    throw new ArgumentException($"The first argument must be an InteractionContext!");
                                }
                                parameters = parameters.Skip(1).ToArray();

                                var options = ParseParameters(parameters);

                                var subpayload = new DiscordApplicationCommandOption(commandattribute.Name, commandattribute.Description, ApplicationCommandOptionType.SubCommand, null, null, options);

                                commandmethods.Add(commandattribute.Name, submethod);

                                payload = new DiscordApplicationCommand(payload.Name, payload.Description, payload.Options != null ? payload.Options.ToArray().Append(subpayload) : new DiscordApplicationCommandOption[] { subpayload });

                                InternalGroupCommands = InternalGroupCommands.Append(new GroupCommand {
                                    Name = groupatt.Name, ParentClass = tti, Methods = commandmethods
                                }).ToArray();
                            }
                            foreach (var subclass in subclasses.Where(x => x.GetCustomAttribute <SlashCommandGroupAttribute>() != null))
                            {
                                var subgroupatt   = subclass.GetCustomAttribute <SlashCommandGroupAttribute>();
                                var subsubmethods = subclass.DeclaredMethods.Where(x => x.GetCustomAttribute <SlashCommandAttribute>() != null);

                                var command = new SubGroupCommand {
                                    Name = groupatt.Name
                                };

                                var options = new List <DiscordApplicationCommandOption>();

                                foreach (var subsubmethod in subsubmethods)
                                {
                                    var suboptions = new List <DiscordApplicationCommandOption>();
                                    var commatt    = subsubmethod.GetCustomAttribute <SlashCommandAttribute>();
                                    var parameters = subsubmethod.GetParameters();
                                    if (!ReferenceEquals(parameters.First().ParameterType, typeof(InteractionContext)))
                                    {
                                        throw new ArgumentException($"The first argument must be an InteractionContext!");
                                    }
                                    parameters = parameters.Skip(1).ToArray();
                                    options    = options.Concat(ParseParameters(parameters)).ToList();

                                    var subsubpayload = new DiscordApplicationCommandOption(commatt.Name, commatt.Description, ApplicationCommandOptionType.SubCommand, null, null, suboptions);
                                    options.Add(subsubpayload);
                                    commandmethods.Add(commatt.Name, subsubmethod);
                                }

                                var subpayload = new DiscordApplicationCommandOption(subgroupatt.Name, subgroupatt.Description, ApplicationCommandOptionType.SubCommandGroup, null, null, options);
                                command.SubCommands.Add(new GroupCommand {
                                    Name = subgroupatt.Name, ParentClass = subclass, Methods = commandmethods
                                });
                                InternalSubGroupCommands = InternalSubGroupCommands.Append(command).ToArray();
                                payload = new DiscordApplicationCommand(payload.Name, payload.Description, payload.Options != null ? payload.Options.ToArray().Append(subpayload) : new DiscordApplicationCommandOption[] { subpayload });
                            }
                            ToUpdate.Add(payload);
                        }

                        var methods = ti.DeclaredMethods;
                        foreach (var method in methods.Where(x => x.GetCustomAttribute <SlashCommandAttribute>() != null))
                        {
                            var commandattribute = method.GetCustomAttribute <SlashCommandAttribute>();

                            var options = new List <DiscordApplicationCommandOption>();

                            var parameters = method.GetParameters();
                            if (parameters.Length == 0 || parameters == null || !ReferenceEquals(parameters.FirstOrDefault()?.ParameterType, typeof(InteractionContext)))
                            {
                                throw new ArgumentException($"The first argument must be an InteractionContext!");
                            }
                            parameters = parameters.Skip(1).ToArray();
                            foreach (var parameter in parameters)
                            {
                                var optionattribute = parameter.GetCustomAttribute <OptionAttribute>();
                                if (optionattribute == null)
                                {
                                    throw new ArgumentException("Arguments must have the SlashOption attribute!");
                                }

                                var type = parameter.ParameterType;
                                ApplicationCommandOptionType parametertype = GetParameterType(type);

                                DiscordApplicationCommandOptionChoice[] choices = GetChoiceAttributesFromParameter(parameter.GetCustomAttributes <ChoiceAttribute>());

                                options.Add(new DiscordApplicationCommandOption(optionattribute.Name, optionattribute.Description, parametertype, !parameter.IsOptional, choices));
                            }
                            InternalCommandMethods = InternalCommandMethods.Append(new CommandMethod {
                                Method = method, Name = commandattribute.Name, ParentClass = t
                            }).ToArray();

                            var payload = new DiscordApplicationCommand(commandattribute.Name, commandattribute.Description, options);
                            ToUpdate.Add(payload);
                        }
                    }
                    catch (Exception ex)
                    {
                        Client.Logger.LogError(ex, $"There was an error registering slash commands");
                        Environment.Exit(-1);
                    }
                }
                try
                {
                    IEnumerable <DiscordApplicationCommand> commands;
                    if (guildid == null)
                    {
                        commands = await Client.BulkOverwriteGlobalApplicationCommandsAsync(ToUpdate);
                    }
                    else
                    {
                        commands = await Client.BulkOverwriteGuildApplicationCommandsAsync(guildid.Value, ToUpdate);
                    }
                    foreach (var command in commands)
                    {
                        if (InternalCommandMethods.Any(x => x.Name == command.Name))
                        {
                            InternalCommandMethods.First(x => x.Name == command.Name).Id = command.Id;
                        }

                        else if (InternalGroupCommands.Any(x => x.Name == command.Name))
                        {
                            InternalGroupCommands.First(x => x.Name == command.Name).Id = command.Id;
                        }

                        else if (InternalSubGroupCommands.Any(x => x.Name == command.Name))
                        {
                            InternalSubGroupCommands.First(x => x.Name == command.Name).Id = command.Id;
                        }
                    }
                    CommandMethods.AddRange(InternalCommandMethods);
                    GroupCommands.AddRange(InternalGroupCommands);
                    SubGroupCommands.AddRange(InternalSubGroupCommands);
                }
                catch (Exception ex)
                {
                    Client.Logger.LogError(ex, $"There was an error registering slash commands");
                    Environment.Exit(-1);
                }
            });
        }
Example #10
0
        //Handler
        private Task InteractionHandler(DiscordClient client, InteractionCreateEventArgs e)
        {
            _ = Task.Run(async() =>
            {
                InteractionContext context = new InteractionContext
                {
                    Interaction            = e.Interaction,
                    Channel                = e.Interaction.Channel,
                    Guild                  = e.Interaction.Guild,
                    User                   = e.Interaction.User,
                    Client                 = client,
                    SlashCommandsExtension = this,
                    CommandName            = e.Interaction.Data.Name,
                    InteractionId          = e.Interaction.Id,
                    Token                  = e.Interaction.Token,
                    Services               = _configuration?.Services
                };

                try
                {
                    var methods   = CommandMethods.Where(x => x.Id == e.Interaction.Data.Id);
                    var groups    = GroupCommands.Where(x => x.Id == e.Interaction.Data.Id);
                    var subgroups = SubGroupCommands.Where(x => x.Id == e.Interaction.Data.Id);
                    if (!methods.Any() && !groups.Any() && !subgroups.Any())
                    {
                        throw new Exception("An interaction was created, but no command was registered for it");
                    }
                    if (methods.Any())
                    {
                        var method = methods.First();

                        var args          = await ResloveInteractionCommandParameters(e, context, method.Method);
                        var classinstance = ActivatorUtilities.CreateInstance(_configuration?.Services, method.ParentClass);
                        var task          = (Task)method.Method.Invoke(classinstance, args.ToArray());
                        await task;
                    }
                    else if (groups.Any())
                    {
                        var command = e.Interaction.Data.Options.First();
                        var method  = groups.First().Methods.First(x => x.Key == command.Name).Value;

                        var args          = await ResloveInteractionCommandParameters(e, context, method);
                        var classinstance = ActivatorUtilities.CreateInstance(_configuration?.Services, groups.First().ParentClass);
                        var task          = (Task)method.Invoke(classinstance, args.ToArray());
                        await task;
                    }
                    else if (subgroups.Any())
                    {
                        var command = e.Interaction.Data.Options.First();
                        var group   = subgroups.First(x => x.SubCommands.Any(y => y.Name == command.Name)).SubCommands.First(x => x.Name == command.Name);

                        var method = group.Methods.First(x => x.Key == command.Options.First().Name).Value;

                        var args          = await ResloveInteractionCommandParameters(e, context, method);
                        var classinstance = ActivatorUtilities.CreateInstance(_configuration?.Services, group.ParentClass);
                        var task          = (Task)method.Invoke(classinstance, args.ToArray());
                        await task;
                    }

                    await _executed.InvokeAsync(this, new SlashCommandExecutedEventArgs {
                        Context = context
                    });
                }
                catch (Exception ex)
                {
                    await _error.InvokeAsync(this, new SlashCommandErrorEventArgs {
                        Context = context, Exception = ex
                    });
                }
            });
            return(Task.CompletedTask);
        }
Example #11
0
        //*************************************************************************
        //  Method: TryRunGroupCommand()
        //
        /// <summary>
        /// Attempts to run a group command.
        /// </summary>
        ///
        /// <param name="groupCommand">
        /// One of the flags in the <see cref="GroupCommands" /> enumeration.
        /// </param>
        ///
        /// <param name="workbook">
        /// NodeXL workbook.
        /// </param>
        ///
        /// <param name="vertexWorksheet">
        /// The vertex worksheet in the NodeXL workbook.
        /// </param>
        ///
        /// <param name="groupWorksheet">
        /// The group worksheet in the NodeXL workbook.
        /// </param>
        ///
        /// <returns>
        /// true if successful.
        /// </returns>
        ///
        /// <remarks>
        /// This method may modify the contents of the workbook.  It does not
        /// interact with the TaskPane, which contains the graph created from the
        /// workbook.  It is the responsibility of the caller to communicate
        /// group changes to the TaskPane when necessary.
        ///
        /// <para>
        /// This method activates various worksheets to read their selection and
        /// write their contents.  It is the responsibility of the caller to save
        /// the active worksheet state before calling this method and restore it
        /// afterward.
        /// </para>
        ///
        /// </remarks>
        //*************************************************************************
        public static Boolean TryRunGroupCommand(
            GroupCommands groupCommand,
            Microsoft.Office.Interop.Excel.Workbook workbook,
            Sheet2 vertexWorksheet,
            Sheet5 groupWorksheet
            )
        {
            Debug.Assert(workbook != null);
            Debug.Assert(vertexWorksheet != null);
            Debug.Assert(groupWorksheet != null);

            switch (groupCommand)
            {
            case GroupCommands.None:

                return (true);

            case GroupCommands.CollapseSelectedGroups:

                return ( TryCollapseOrExpandSelectedGroups(workbook, true) );

            case GroupCommands.ExpandSelectedGroups:

                return ( TryCollapseOrExpandSelectedGroups(workbook, false) );

            case GroupCommands.CollapseAllGroups:

                return ( TryCollapseOrExpandAllGroups(workbook, true) );

            case GroupCommands.ExpandAllGroups:

                return ( TryCollapseOrExpandAllGroups(workbook, false) );

            case GroupCommands.SelectGroupsWithSelectedVertices:

                return ( TrySelectGroupsWithSelectedVertices(workbook,
                    vertexWorksheet, groupWorksheet) );

            case GroupCommands.SelectAllGroups:

                return ( TrySelectAllGroups(workbook) );

            case GroupCommands.AddSelectedVerticesToGroup:

                return ( TryAddSelectedVerticesToGroup(workbook,
                    vertexWorksheet) );

            case GroupCommands.RemoveSelectedVerticesFromGroups:

                ICollection<String> oSelectedVertexNames;

                return ( TryRemoveSelectedVerticesFromGroups(workbook,
                    vertexWorksheet, out oSelectedVertexNames) );

            case GroupCommands.RemoveSelectedGroups:

                return ( TryRemoveSelectedGroups(workbook, groupWorksheet) );

            case GroupCommands.RemoveAllGroups:

                return ( TryRemoveAllGroups(workbook) );

            default:

                Debug.Assert(false);
                return (false);
            }
        }
 GroupCommandsIncludeGroupCommand
 (
     GroupCommands groupCommands,
     GroupCommands groupCommand
 )
 {
     return ( (groupCommands & groupCommand) != 0 );
 }
Example #13
0
        //*************************************************************************
        //  Method: RunGroupCommand()
        //
        /// <summary>
        /// Runs a group command.
        /// </summary>
        ///
        /// <param name="groupCommand">
        /// One of the flags in the <see cref="GroupCommands" /> enumeration.
        /// </param>
        //*************************************************************************
        public void RunGroupCommand(
            GroupCommands groupCommand
            )
        {
            AssertValid();

            if ( !this.ExcelApplicationIsReady(true) )
            {
            return;
            }

            // Various worksheets must be activated for reading and writing.  Save
            // the active worksheet state.

            ExcelActiveWorksheetRestorer oExcelActiveWorksheetRestorer =
            new ExcelActiveWorksheetRestorer(this.InnerObject);

            ExcelActiveWorksheetState oExcelActiveWorksheetState =
            oExcelActiveWorksheetRestorer.GetActiveWorksheetState();

            try
            {
            if ( !GroupManager.TryRunGroupCommand(groupCommand,
                this.InnerObject, Globals.Sheet2, Globals.Sheet5) )
            {
                return;
            }

            switch (groupCommand)
            {
                case GroupCommands.CollapseSelectedGroups:
                case GroupCommands.ExpandSelectedGroups:

                    // Let the TaskPane know about the collapsed or expanded
                    // groups.

                    FireCollapseOrExpandGroups(
                        groupCommand == GroupCommands.CollapseSelectedGroups,
                        Globals.Sheet5.GetSelectedGroupNames() );

                    break;

                case GroupCommands.CollapseAllGroups:
                case GroupCommands.ExpandAllGroups:

                    ICollection<String> oUniqueGroupNames;

                    if ( ExcelUtil.TryGetUniqueTableColumnStringValues(
                            this.InnerObject, WorksheetNames.Groups,
                            TableNames.Groups, GroupTableColumnNames.Name,
                            out oUniqueGroupNames) )
                    {
                        FireCollapseOrExpandGroups(
                            groupCommand == GroupCommands.CollapseAllGroups,
                            oUniqueGroupNames);
                    }

                    break;

                default:

                    break;
            }
            }
            catch (Exception oException)
            {
            ErrorUtil.OnException(oException);
            }
            finally
            {
            oExcelActiveWorksheetRestorer.Restore(oExcelActiveWorksheetState);
            }
        }