private async Task HandleErrorAsync(LogMessage logMessage)
        {
            var commandException = logMessage.Exception as CommandException;

            if (commandException == null)
            {
                return;
            }
            await HandleErrorAsync(ExecuteResult.FromError(commandException),
                                   (SocketCommandContext)commandException.Context, commandException);
        }
Beispiel #2
0
        public virtual async Task <IResult> MessageReceived(CommandContext context)
        {
            var message = context.Message;

            int cmdPos = 0;

            if (!(message.HasCharPrefix('!', ref cmdPos) || message.HasMentionPrefix(Client.CurrentUser, ref cmdPos)))
            {
                return(ExecuteResult.FromError(CommandError.UnknownCommand, ""));
            }

            return(await Commands.ExecuteAsync(context, cmdPos, Services));
        }
        /// <summary>
        /// Execute the function based on the interaction data we get.
        /// </summary>
        /// <param name="data">Interaction data from interaction</param>
        /// <param name="interaction">SocketInteraction</param>
        public async Task <IResult> ExecuteAsync(IReadOnlyCollection <SocketInteractionDataOption> data, SocketInteraction interaction)
        {
            // Array of arguments to be passed to the Delegate
            var args = new object[Parameters.Count];

            try
            {
                // For each parameter to try find its coresponding DataOption based on the name.
                // !!! names from `data` will always be lowercase regardless if we defined the command with any
                // number of upercase letters !!!
                for (var i = 0; i < Parameters.Count; i++)
                {
                    var parameter = Parameters[i];

                    if (TryGetInteractionDataOption(data, parameter.Name, out var dataOption))
                    {
                        args[i] = parameter.Parse(dataOption);
                    }
                }
            }
            catch (Exception e)
            {
                return(ExecuteResult.FromError(e));
            }

            var instance = ReflectionUtils.CreateObject <ISlashCommandModule>(Module.ModuleType, Module.Service, Module.ServiceProvider);

            instance.SetContext(interaction);

            var delegateMethod = SlashCommandServiceHelper.CreateDelegate(MethodInfo, instance);

            var callback = new Func <object[], Task <IResult> >(async callbackArgs =>
            {
                // Try-catch it and see what we get - error or success
                try
                {
                    await Task.Run(() => { delegateMethod.DynamicInvoke(callbackArgs); }).ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    return(ExecuteResult.FromError(e));
                }

                return(ExecuteResult.FromSuccess());
            });

            return(await callback.Invoke(args).ConfigureAwait(false));
        }
Beispiel #4
0
        public async Task HandleMessagesAsync(SocketMessage msg)
        {
            if (msg is SocketUserMessage message)
            {
                var _      = 0;
                var prefix = (message.Channel is ITextChannel) ? Configuration.Guilds.GetGuild(
                    (message.Channel as ITextChannel).GuildId).Prefix : Prefix;

                if (message.HasPrefix(prefix, Socket.CurrentUser, ref _))
                {
                    return;
                }

                var context = new CWBContext(this, message);
                foreach (var type in IListeners)
                {
                    var listener = DependencyInjection.CreateInjected <IListener>(type, Services, context);
                    if (listener.GetRunMode() == RunMode.Async)
                    {
                        await Task.Run(async() =>
                        {
                            try
                            {
                                await listener.ExecuteAsync();
                            }
                            catch (Exception e)
                            {
                                await HandleCommandError(ExecuteResult.FromError(e));
                            }
                        });
                    }
                    else
                    {
                        try
                        {
                            await listener.ExecuteAsync();
                        }
                        catch (Exception e)
                        {
                            await HandleCommandError(ExecuteResult.FromError(e));
                        }
                    }
                }
            }
        }
Beispiel #5
0
        protected virtual ExecuteResult OnExecute(IExecuteContext executionContext, TraceInfo traceInfo)
        {
            _ = executionContext ?? throw new ArgumentNullException(nameof(executionContext));
            _ = traceInfo ?? throw new ArgumentNullException(nameof(traceInfo));
            IActionContext actionContext = null;

            try
            {
                //1 resolve action name
                var actionName = this.OnResolveActionName(executionContext.ActionFullName);
                traceInfo.ActionName = actionName;
                //2 get runtime info
                var runtimeInfo = this.OnGetActionRuntime(actionName);
                traceInfo.ActionRuntime = runtimeInfo;
                //3 prepare package
                this.OnPrepareAction(actionName, runtimeInfo);
                //4 get meta info
                var metaInfo = this.OnGetActionMeta(actionName);
                traceInfo.ActionMeta = metaInfo;
                //5 resolve action factory
                var actionFactory = this.OnResolveActionFactory(metaInfo);
                //6 create action context
                actionContext = this.OnCreateActionContext(executionContext, actionName, runtimeInfo, metaInfo);

                //7 check premission
                this.OnCheckPremission(actionContext);
                //8 valid inputs
                this.OnValidInputs(actionContext);
                //9 create action instance
                var actionInstance = this.OnCreateActionInstance(actionFactory, actionContext);
                //10 run action
                var result = OnRunAction(actionInstance, executionContext, actionContext);
                //11 valid output
                this.OnValidOutput(actionContext, result);
                return(ExecuteResult.FromResult(result, actionContext.Logger.ToString()));
            }
            catch (Exception ex)
            {
                return(ExecuteResult.FromError(ex, actionContext?.Logger?.ToString()));
            }
        }
Beispiel #6
0
        /// <summary>
        /// Sends a consent request to the given DM channel.
        /// </summary>
        /// <param name="channel">The channel.</param>
        /// <param name="content">The content service.</param>
        /// <param name="feedback">The feedback service.</param>
        /// <returns>An execution result.</returns>
        public async Task <ExecuteResult> RequestConsentAsync
        (
            [NotNull] IDMChannel channel,
            [NotNull] ContentService content,
            [NotNull] UserFeedbackService feedback
        )
        {
            try
            {
                var consentBuilder = feedback.CreateEmbedBase(Color.Orange);
                consentBuilder.WithDescription
                (
                    "Hello there! This appears to be the first time you're using the bot (or you've not granted your " +
                    "consent for it to store potentially sensitive or identifiable data about you).\n" +
                    "\n" +
                    "In order to use Amby and her commands, you need to give her your consent to store various data " +
                    "about you. We need this consent in order to be compliant with data regulations in the European " +
                    "Union (and it'd be rude not to ask!).\n" +
                    "\n" +
                    "In short, if you use the bot, we're going to be storing " +
                    "stuff like your Discord ID, some messages, server IDs, etc. You can - and should! - read the " +
                    "full privacy policy before you agree to anything. It's not very long (3 pages) and shouldn't take " +
                    "more than five minutes to read through.\n" +
                    "\n" +
                    "Once you've read it, you can grant consent by running the `!privacy grant-consent` command over DM. If you " +
                    "don't want to consent to anything, just don't use the bot :smiley:"
                );

                await channel.SendMessageAsync(string.Empty, embed : consentBuilder.Build());

                await SendPrivacyPolicyAsync(channel, content, feedback);
            }
            catch (HttpException hex) when(hex.HttpCode == HttpStatusCode.Forbidden)
            {
                return(ExecuteResult.FromError(CommandError.Exception, "Could not send the privacy message over DM."));
            }

            return(ExecuteResult.FromSuccess());
        }
Beispiel #7
0
        // Commands
        public static ExecuteResult AddRoleToAutoAssign(SocketCommandContext context, ulong roleID)
        {
            SQLiteConnection _connect = new SQLiteConnection(Constants.ConnectionString);

            try
            {
                SQLiteCommand command = new SQLiteCommand {
                    Connection = _connect
                };
            }
            catch (Exception ex)
            {
                LoggingService.LogAsync(LogSeverity.Error, _className, ex.Message);
                _result = ExecuteResult.FromError(CommandError.Unsuccessful, ex.Message);
            }
            finally
            {
                _connect.Close();
            }

            return(_result);
        }
Beispiel #8
0
        public async Task <IResult> ExecuteAsync(string commandString, IEnumerable <object> argList, IEnumerable <object> paramList, IServiceProvider services)
        {
            services = services ?? EmptyServiceProvider.Instance;

            try
            {
                object[] args = GenerateArgs(argList, paramList);

                for (int position = 0; position < Parameters.Count; position++)
                {
                    var    parameter = Parameters[position];
                    object argument  = args[position];
                    var    result    = await parameter.CheckPreconditionsAsync(commandString, argument, services).ConfigureAwait(false);

                    if (!result.IsSuccess)
                    {
                        return(ExecuteResult.FromError(result));
                    }
                }

                switch (RunMode)
                {
                case RunMode.Sync:     //Always sync
                    return(await ExecuteInternalAsync(commandString, args, services).ConfigureAwait(false));

                case RunMode.Async:     //Always async
                    var t2 = Task.Run(async() =>
                    {
                        await ExecuteInternalAsync(commandString, args, services).ConfigureAwait(false);
                    });
                    break;
                }
                return(ExecuteResult.FromSuccess());
            }
            catch (Exception ex)
            {
                return(ExecuteResult.FromError(ex));
            }
        }
Beispiel #9
0
        public static ExecuteResult ChangeModuleStatus(string moduleName, string guildID, bool moduleStatus)
        {
            SQLiteConnection _connect = new SQLiteConnection(Constants.ConnectionString);

            try
            {
                SQLiteCommand command = new SQLiteCommand {
                    Connection = _connect
                };

                if (CheckModuleStatus(moduleName, guildID) == false)
                {
                    command.CommandText = $"UPDATE Guilds SET [{moduleName}] = '1' WHERE [GuildID] = '{guildID}'";
                    _result             = ExecuteResult.FromSuccess();
                }
                else if (CheckModuleStatus(moduleName, guildID) == true)
                {
                    command.CommandText = $"UPDATE Guilds SET [{moduleName}] = '0' WHERE [GuildID] = {guildID}";
                    _result             = ExecuteResult.FromSuccess();
                }

                _connect.Open();
                command.ExecuteNonQuery();

                LoggingService.LogAsync(LogSeverity.Info, _className, $"{moduleName} has been changed for {guildID}.");
            }
            catch (Exception ex)
            {
                LoggingService.LogAsync(LogSeverity.Error, _className, ex.Message);
                _result = ExecuteResult.FromError(CommandError.Unsuccessful, ex.Message);
            }
            finally
            {
                _connect.Close();
            }

            return(_result);
        }
Beispiel #10
0
        public static ExecuteResult CheckGuild(string guildID, string guildName)
        {
            SQLiteConnection _connect = new SQLiteConnection(Constants.ConnectionString);

            try
            {
                SQLiteCommand command = new SQLiteCommand {
                    Connection = _connect
                };

                command.CommandText = $"SELECT COUNT(*) FROM Guilds WHERE (GuildID = '{guildID}')";

                _connect.Open();

                if (Convert.ToInt32(command.ExecuteScalar()) == 0)
                {
                    AddGuild(guildID, guildName);
                    _result = ExecuteResult.FromSuccess();
                }
                else
                {
                    LoggingService.LogAsync(LogSeverity.Info, _className, $"Guild {guildName} already exists in database.");
                    _result = ExecuteResult.FromError(CommandError.Unsuccessful, $"Guild {guildName} already exists in database.");
                }
            }
            catch (Exception ex)
            {
                LoggingService.LogAsync(LogSeverity.Error, _className, ex.Message);
                _result = ExecuteResult.FromError(CommandError.Exception, ex.Message);
            }
            finally
            {
                _connect.Close();
            }

            return(_result);
        }
Beispiel #11
0
        /// <summary>
        /// Invites the user to the given roleplay.
        /// </summary>
        /// <param name="db">The database where the roleplays are stored.</param>
        /// <param name="roleplay">The roleplay to invite the user to.</param>
        /// <param name="invitedUser">The user to invite.</param>
        /// <returns>An execution result which may or may not have succeeded.</returns>
        public async Task <ExecuteResult> InviteUserAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] Roleplay roleplay,
            [NotNull] IUser invitedUser
        )
        {
            if (roleplay.IsPublic)
            {
                return(ExecuteResult.FromError(CommandError.UnmetPrecondition, "The roleplay is not set to private."));
            }

            if (roleplay.InvitedUsers.Any(p => p.User.DiscordID == (long)invitedUser.Id))
            {
                return(ExecuteResult.FromError(CommandError.Unsuccessful, "The user has already been invited to that roleplay."));
            }

            // Remove the invited user from the kick list, if they're on it
            var participantEntry = roleplay.ParticipatingUsers.FirstOrDefault(p => p.User.DiscordID == (long)invitedUser.Id);

            if (participantEntry is null)
            {
                var user = await db.GetOrRegisterUserAsync(invitedUser);

                participantEntry = new RoleplayParticipant(roleplay, user, ParticipantStatus.Invited);
                roleplay.ParticipatingUsers.Add(participantEntry);
            }
            else
            {
                participantEntry.Status = ParticipantStatus.Invited;
            }

            await db.SaveChangesAsync();

            return(ExecuteResult.FromSuccess());
        }
Beispiel #12
0
        /// <summary>
        /// Removes the given user from the given roleplay.
        /// </summary>
        /// <param name="db">The database where the roleplays are stored.</param>
        /// <param name="context">The context of the user.</param>
        /// <param name="roleplay">The roleplay to remove the user from.</param>
        /// <param name="removedUser">The user to remove from the roleplay.</param>
        /// <returns>An execution result which may or may not have succeeded.</returns>
        public async Task <ExecuteResult> RemoveUserFromRoleplayAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] SocketCommandContext context,
            [NotNull] Roleplay roleplay,
            [NotNull] IUser removedUser
        )
        {
            var isCurrentUser = context.Message.Author.Id == removedUser.Id;

            if (!roleplay.HasJoined(removedUser))
            {
                var errorMessage = isCurrentUser
                                        ? "You're not in that roleplay."
                                        : "No matching user found in the roleplay.";

                return(ExecuteResult.FromError(CommandError.Unsuccessful, errorMessage));
            }

            if (roleplay.IsOwner(removedUser))
            {
                var errorMessage = isCurrentUser
                                        ? "You can't leave a roleplay you own."
                                        : "The owner of a roleplay can't be removed from it.";

                return(ExecuteResult.FromError(CommandError.Unsuccessful, errorMessage));
            }

            var participantEntry = roleplay.JoinedUsers.First(p => p.User.DiscordID == (long)removedUser.Id);

            participantEntry.Status = ParticipantStatus.None;

            await db.SaveChangesAsync();

            return(ExecuteResult.FromSuccess());
        }
        private async Task <ExecuteResult> HelpOverallAsync(ICommandContext context, object[] parameters, IServiceProvider services, CommandInfo invokedHelpCmd)
        {
            const int pageSize = 4;

            // param logic is enforced by the command service
            int pageNumber = (int)parameters[0];

            CommandInfo[] cmds = await _commands.Commands.ToAsyncEnumerable()
                                 .WhereAsync(async cmd =>
            {
                ModuleInfo rootModule = cmd.Module;
                while (rootModule?.Parent != null)
                {
                    rootModule = rootModule.Parent;
                }

                if (rootModule.Name == "help" && cmd.Aliases.SingleIfOne() != "help")
                {
                    return(false);
                }

                bool preconditionSuccess = false;
                try
                {
                    preconditionSuccess = (await cmd.CheckPreconditionsAsync(context, services)).IsSuccess;
                }
                catch { }

                // all commands OK, except: generated help commands and commands where preconditions are not met
                // only the overall help command should be displayed in help
                return(preconditionSuccess);
            }).OrderBy(cmd => cmd.Aliases[0]).ToArray().ConfigureAwait(false);

            int pageCount = Utilities.CeilingDivision(cmds.Length, pageSize);

            if (pageNumber < 1 || pageNumber > pageCount)
            {
                return(ExecuteResult.FromError(CommandError.Unsuccessful, "The given page number is invalid (too high or too low)."));
            }

            EmbedBuilder builder = new EmbedBuilder()
            {
                Title       = "Help",
                Description = "Commands applicable in the current context (e.g. DM, guild channel) with your permission level.",
                Color       = Color.DarkBlue
            };

            Models.Guild guildPrefs;
            if (context.Guild != null && (guildPrefs = await _database.FindOneAsync <Models.Guild>(g => g.Id == context.Guild.Id)) != null && guildPrefs.Prefix != null)
            {
                builder.Description += "\n\nThis guild's prefix is: `" + guildPrefs.Prefix + "`";
            }

            foreach (var cmd in cmds.Skip((pageNumber - 1) * pageSize).Take(pageSize))
            {
                BuildHelpAsField(builder, cmd);
            }

            builder.WithFooter(footer => footer.WithText($"Page {pageNumber} of {pageCount}"));

            await context.Channel.SendMessageAsync(string.Empty, embed : builder.Build()).ConfigureAwait(false);

            return(ExecuteResult.FromSuccess());
        }