Example #1
0
        private async ValueTask <bool> TryHandleCommand(MessageCreateEventArgs evt, MessageContext ctx)
        {
            var content = evt.Message.Content;

            if (content == null)
            {
                return(false);
            }

            // Check for command prefix
            if (!HasCommandPrefix(content, out var cmdStart))
            {
                return(false);
            }

            // Trim leading whitespace from command without actually modifying the string
            // This just moves the argPos pointer by however much whitespace is at the start of the post-argPos string
            var trimStartLengthDiff = content.Substring(cmdStart).Length - content.Substring(cmdStart).TrimStart().Length;

            cmdStart += trimStartLengthDiff;

            try
            {
                var system = ctx.SystemId != null ? await _db.Execute(c => c.QuerySystem(ctx.SystemId.Value)) : null;

                await _tree.ExecuteCommand(new Context(_services, evt.Client, evt.Message, cmdStart, system, ctx));
            }
            catch (PKError)
            {
                // Only permission errors will ever bubble this far and be caught here instead of Context.Execute
                // so we just catch and ignore these. TODO: this may need to change.
            }

            return(true);
        }
        private async ValueTask <bool> TryHandleCommand(MessageCreateEventArgs evt, MessageContext ctx)
        {
            var content = evt.Message.Content;

            if (content == null)
            {
                return(false);
            }

            var argPos = -1;

            // Check if message starts with the command prefix
            if (content.StartsWith("pk;", StringComparison.InvariantCultureIgnoreCase))
            {
                argPos = 3;
            }
            else if (content.StartsWith("pk!", StringComparison.InvariantCultureIgnoreCase))
            {
                argPos = 3;
            }
            else if (StringUtils.HasMentionPrefix(content, ref argPos, out var id)) // Set argPos to the proper value
            {
                if (id != _client.CurrentUser.Id)                                   // But undo it if it's someone else's ping
                {
                    argPos = -1;
                }
            }

            // If we didn't find a prefix, give up handling commands
            if (argPos == -1)
            {
                return(false);
            }

            // Trim leading whitespace from command without actually modifying the wring
            // This just moves the argPos pointer by however much whitespace is at the start of the post-argPos string
            var trimStartLengthDiff = content.Substring(argPos).Length - content.Substring(argPos).TrimStart().Length;

            argPos += trimStartLengthDiff;

            try
            {
                var system = ctx?.SystemId != null ? await _db.Execute(c => c.QuerySystem(ctx.SystemId.Value)) : null;

                await _tree.ExecuteCommand(new Context(_services, evt.Client, evt.Message, argPos, system, ctx));
            }
            catch (PKError)
            {
                // Only permission errors will ever bubble this far and be caught here instead of Context.Execute
                // so we just catch and ignore these. TODO: this may need to change.
            }

            return(true);
        }
Example #3
0
        public async Task HandleMessage(SocketMessage arg)
        {
            if (_client.GetShardFor((arg.Channel as IGuildChannel)?.Guild).ConnectionState != ConnectionState.Connected)
            {
                return; // Discard messages while the bot "catches up" to avoid unnecessary CPU pressure causing timeouts
            }
            RegisterMessageMetrics(arg);

            // Ignore system messages (member joined, message pinned, etc)
            var msg = arg as SocketUserMessage;

            if (msg == null)
            {
                return;
            }

            // Ignore bot messages
            if (msg.Author.IsBot || msg.Author.IsWebhook)
            {
                return;
            }

            // Add message info as Sentry breadcrumb
            _msg = msg;
            _sentryScope.AddBreadcrumb(msg.Content, "event.message", data: new Dictionary <string, string>
            {
                { "user", msg.Author.Id.ToString() },
                { "channel", msg.Channel.Id.ToString() },
                { "guild", ((msg.Channel as IGuildChannel)?.GuildId ?? 0).ToString() },
                { "message", msg.Id.ToString() },
            });

            // We fetch information about the sending account *and* guild from the cache
            GuildConfig cachedGuild = default; // todo: is this default correct?

            if (msg.Channel is ITextChannel textChannel)
            {
                cachedGuild = await _cache.GetGuildDataCached(textChannel.GuildId);
            }
            var cachedAccount = await _cache.GetAccountDataCached(msg.Author.Id);

            // this ^ may be null, do remember that down the line

            int argPos = -1;

            // Check if message starts with the command prefix
            if (msg.Content.StartsWith("pk;", StringComparison.InvariantCultureIgnoreCase))
            {
                argPos = 3;
            }
            else if (msg.Content.StartsWith("pk!", StringComparison.InvariantCultureIgnoreCase))
            {
                argPos = 3;
            }
            else if (msg.Content != null && Utils.HasMentionPrefix(msg.Content, ref argPos, out var id)) // Set argPos to the proper value
            {
                if (id != _client.CurrentUser.Id)                                                        // But undo it if it's someone else's ping
                {
                    argPos = -1;
                }
            }

            // If it does, try executing a command
            if (argPos > -1)
            {
                _logger.Verbose("Parsing command {Command} from message {Channel}-{Message}", msg.Content, msg.Channel.Id, msg.Id);

                // Essentially move the argPos pointer by however much whitespace is at the start of the post-argPos string
                var trimStartLengthDiff = msg.Content.Substring(argPos).Length -
                                          msg.Content.Substring(argPos).TrimStart().Length;
                argPos += trimStartLengthDiff;

                await _tree.ExecuteCommand(new Context(_services, msg, argPos, cachedAccount?.System));
            }
            else if (cachedAccount != null)
            {
                // If not, try proxying anyway
                // but only if the account data we got before is present
                // no data = no account = no system = no proxy!
                try
                {
                    await _proxy.HandleMessageAsync(cachedGuild, cachedAccount, msg);
                }
                catch (PKError e)
                {
                    await arg.Channel.SendMessageAsync($"{Emojis.Error} {e.Message}");
                }
            }
        }
Example #4
0
        public async Task HandleMessage(SocketMessage arg)
        {
            if (_client.GetShardFor((arg.Channel as IGuildChannel)?.Guild).ConnectionState != ConnectionState.Connected)
            {
                return; // Discard messages while the bot "catches up" to avoid unnecessary CPU pressure causing timeouts
            }
            RegisterMessageMetrics(arg);

            // Ignore system messages (member joined, message pinned, etc)
            var msg = arg as SocketUserMessage;

            if (msg == null)
            {
                return;
            }

            // Ignore bot messages
            if (msg.Author.IsBot || msg.Author.IsWebhook)
            {
                return;
            }

            int argPos = -1;

            // Check if message starts with the command prefix
            if (msg.Content.StartsWith("pk;", StringComparison.InvariantCultureIgnoreCase))
            {
                argPos = 3;
            }
            else if (msg.Content.StartsWith("pk!", StringComparison.InvariantCultureIgnoreCase))
            {
                argPos = 3;
            }
            else if (Utils.HasMentionPrefix(msg.Content, ref argPos, out var id)) // Set argPos to the proper value
            {
                if (id != _client.CurrentUser.Id)                                 // But undo it if it's someone else's ping
                {
                    argPos = -1;
                }
            }

            // If it does, try executing a command
            if (argPos > -1)
            {
                _logger.Verbose("Parsing command {Command} from message {Channel}-{Message}", msg.Content, msg.Channel.Id, msg.Id);

                // Essentially move the argPos pointer by however much whitespace is at the start of the post-argPos string
                var trimStartLengthDiff = msg.Content.Substring(argPos).Length -
                                          msg.Content.Substring(argPos).TrimStart().Length;
                argPos += trimStartLengthDiff;

                // If it does, fetch the sender's system (because most commands need that) into the context,
                // and start command execution
                // Note system may be null if user has no system, hence `OrDefault`
                PKSystem system;
                using (var conn = await _connectionFactory.Obtain())
                    system = await conn.QueryFirstOrDefaultAsync <PKSystem>(
                        "select systems.* from systems, accounts where accounts.uid = @Id and systems.id = accounts.system",
                        new { Id = msg.Author.Id });

                try
                {
                    await _tree.ExecuteCommand(new Context(_services, msg, argPos, system));
                }
                catch (Exception e)
                {
                    await HandleCommandError(msg, e);

                    // HandleCommandError only *reports* the error, we gotta pass it through to the parent
                    // error handler by rethrowing:
                    throw;
                }
            }
            else
            {
                // If not, try proxying anyway
                try
                {
                    await _proxy.HandleMessageAsync(msg);
                }
                catch (PKError e)
                {
                    await arg.Channel.SendMessageAsync($"{Emojis.Error} {e.Message}");
                }
            }
        }