Ejemplo n.º 1
0
        public async Task Handle(MessageCreateEventArgs evt)
        {
            if (evt.Message.MessageType != MessageType.Default)
            {
                return;
            }
            if (IsDuplicateMessage(evt.Message))
            {
                return;
            }

            // Log metrics and message info
            _metrics.Measure.Meter.Mark(BotMetrics.MessagesReceived);
            _lastMessageCache.AddMessage(evt.Channel.Id, evt.Message.Id);

            // Get message context from DB (tracking w/ metrics)
            MessageContext ctx;

            await using (var conn = await _db.Obtain())
                using (_metrics.Measure.Timer.Time(BotMetrics.MessageContextQueryTime))
                    ctx = await conn.QueryMessageContext(evt.Author.Id, evt.Channel.GuildId, evt.Channel.Id);

            // Try each handler until we find one that succeeds
            var _ = await TryHandleLogClean(evt, ctx) ||
                    await TryHandleCommand(evt, ctx) ||
                    await TryHandleProxy(evt, ctx);
        }
Ejemplo n.º 2
0
        public async Task Handle(Shard shard, MessageCreateEvent evt)
        {
            if (evt.Author.Id == shard.User?.Id)
            {
                return;
            }
            if (evt.Type != Message.MessageType.Default && evt.Type != Message.MessageType.Reply)
            {
                return;
            }
            if (IsDuplicateMessage(evt))
            {
                return;
            }

            var guild = evt.GuildId != null?_cache.GetGuild(evt.GuildId.Value) : null;

            var channel     = _cache.GetChannel(evt.ChannelId);
            var rootChannel = _cache.GetRootChannel(evt.ChannelId);

            // Log metrics and message info
            _metrics.Measure.Meter.Mark(BotMetrics.MessagesReceived);
            _lastMessageCache.AddMessage(evt);

            // Get message context from DB (tracking w/ metrics)
            MessageContext ctx;

            await using (var conn = await _db.Obtain())
                using (_metrics.Measure.Timer.Time(BotMetrics.MessageContextQueryTime))
                    ctx = await _repo.GetMessageContext(conn, evt.Author.Id, evt.GuildId ?? default, rootChannel.Id);

            // Try each handler until we find one that succeeds
            if (await TryHandleLogClean(evt, ctx))
            {
                return;
            }

            // Only do command/proxy handling if it's a user account
            if (evt.Author.Bot || evt.WebhookId != null || evt.Author.System == true)
            {
                return;
            }

            if (await TryHandleCommand(shard, evt, guild, channel, ctx))
            {
                return;
            }
            await TryHandleProxy(shard, evt, guild, channel, ctx);
        }
Ejemplo n.º 3
0
        public async Task Handle(MessageCreateEventArgs evt)
        {
            if (evt.Author?.Id == _client.CurrentUser?.Id)
            {
                return;
            }
            if (evt.Message.MessageType != MessageType.Default)
            {
                return;
            }
            if (IsDuplicateMessage(evt.Message))
            {
                return;
            }

            // Log metrics and message info
            _metrics.Measure.Meter.Mark(BotMetrics.MessagesReceived);
            _lastMessageCache.AddMessage(evt.Channel.Id, evt.Message.Id);

            // Get message context from DB (tracking w/ metrics)
            MessageContext ctx;

            await using (var conn = await _db.Obtain())
                using (_metrics.Measure.Timer.Time(BotMetrics.MessageContextQueryTime))
                    ctx = await _repo.GetMessageContext(conn, evt.Author.Id, evt.Channel.GuildId, evt.Channel.Id);

            // Try each handler until we find one that succeeds
            if (await TryHandleLogClean(evt, ctx))
            {
                return;
            }

            // Only do command/proxy handling if it's a user account
            if (evt.Message.Author.IsBot || evt.Message.WebhookMessage || evt.Message.Author.IsSystem == true)
            {
                return;
            }
            if (await TryHandleCommand(evt, ctx))
            {
                return;
            }
            await TryHandleProxy(evt, ctx);
        }
Ejemplo n.º 4
0
        public async Task HandleMessage(SocketMessage arg)
        {
            var shard = _client.GetShardFor((arg.Channel as IGuildChannel)?.Guild);
            if (shard.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;
            
            // Fetch information about the guild early, as we need it for the logger cleanup
            GuildConfig cachedGuild = default; // todo: is this default correct?
            if (msg.Channel is ITextChannel textChannel) cachedGuild = await _cache.GetGuildDataCached(textChannel.GuildId);
            
            // Pass guild bot/WH messages onto the logger cleanup service, but otherwise ignore
            if ((msg.Author.IsBot || msg.Author.IsWebhook) && msg.Channel is ITextChannel)
            {
                await _loggerClean.HandleLoggerBotCleanup(arg, cachedGuild);
                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()},
            });
            _sentryScope.SetTag("shard", shard.ShardId.ToString());
            
            // Add to last message cache
            _lastMessageCache.AddMessage(arg.Channel.Id, arg.Id);
            
            // We fetch information about the sending account from the cache
            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 && StringUtils.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, doAutoProxy: true);
                }
                catch (PKError e)
                {
                    await arg.Channel.SendMessageAsync($"{Emojis.Error} {e.Message}");
                }
            }
        }