Example #1
0
        protected async Task PreProcessMessage(BotMessageData messageData, Settings settings)
        {
            this.messageCount++;

            // Update the seen data
            this.UpdateSeen(messageData.Channel + messageData.UserName, new SeenUserData
            {
                Name    = messageData.UserId ?? messageData.UserName,
                Channel = messageData.Channel,
                Server  = messageData.Server,
                //Text = messageData.Content, removed due to discord tos
            });

            var httpMatch = Consts.HttpRegex.Match(messageData.Content);

            if (httpMatch.Success)
            {
                this.urls[messageData.Channel] = httpMatch.Value;
            }

            if (settings.FunResponsesEnabled && !string.IsNullOrEmpty(messageData.Content))
            {
                var repeat = repeatData.GetOrAdd(messageData.Channel + messageData.Server, new RepeatData());
                if (string.Equals(repeat.Text, messageData.Content, StringComparison.OrdinalIgnoreCase))
                {
                    if (!repeat.Nicks.Contains(messageData.UserId ?? messageData.UserName))
                    {
                        repeat.Nicks.Add(messageData.UserId ?? messageData.UserName);
                    }

                    if (repeat.Nicks.Count == 3)
                    {
                        await this.RespondAsync(messageData, messageData.Content);

                        repeat.Reset(string.Empty, string.Empty);
                    }
                }
                else
                {
                    repeat.Reset(messageData.UserId ?? messageData.UserName, messageData.Content);
                }
            }

            string command = messageData.Command;

            if (!CommandsConfig.Instance.Commands.ContainsKey(command))
            {
                command = string.Empty;
            }

            if (string.IsNullOrEmpty(command))
            {
                // match fun
                bool mentionsBot = messageData.MentionsBot(this.Config.Name, Convert.ToUInt64(this.UserId));
                if (CommandsConfig.Instance.TryParseForCommand(messageData.Content, mentionsBot, out string parsedCommand, out string query))
                {
                    messageData.Query = query;
                }
            }
        }
Example #2
0
        protected async Task <BotResponseData> ProcessMessageAsync(BotMessageData messageData, Settings settings)
        {
            var responses    = new List <string>();
            var responseData = new BotResponseData {
                Responses = responses
            };

            if (this.BotApi != null)
            {
                // if an explicit command is being used, it wins out over any implicitly parsed command
                string query   = messageData.Query;
                string command = messageData.Command;

                string[] contentParts = messageData.Content.Split(new[] { ' ' });

                if (string.IsNullOrEmpty(command))
                {
                    if (messageData.Content.IContains("remind "))
                    {
                        // check for reminders
                        Match timerAtMatch  = Consts.TimerOnRegex.Match(messageData.Content);
                        Match timerAt2Match = Consts.TimerOn2Regex.Match(messageData.Content);
                        if (timerAtMatch.Success && Utilities.TryParseAbsoluteReminder(timerAtMatch, messageData, out query) ||
                            timerAt2Match.Success && Utilities.TryParseAbsoluteReminder(timerAt2Match, messageData, out query))
                        {
                            command = "timer";
                        }
                        else // try relative timers if absolute had no match
                        {
                            Match timerMatch  = Consts.TimerRegex.Match(messageData.Content);
                            Match timer2Match = Consts.Timer2Regex.Match(messageData.Content);

                            if (timerMatch.Success || timer2Match.Success)
                            {
                                Match matchToUse = timerMatch.Success && !timerMatch.Groups["prep"].Value.All(char.IsDigit) ? timerMatch : timer2Match;
                                if (Utilities.TryParseReminder(matchToUse, messageData, out query))
                                {
                                    command = "timer";
                                }
                            }
                        }
                    }

                    if (string.IsNullOrEmpty(command))
                    {
                        if (settings.AutoTitlesEnabled && (CommandsConfig.Instance.AutoTitleMatches.Any(t => messageData.Content.Contains(t)) || Consts.RedditRegex.IsMatch(messageData.Content)))
                        {
                            Match  match      = Consts.HttpRegex.Match(messageData.Content);
                            string matchValue = !string.IsNullOrEmpty(match.Value) ? match.Value : Consts.RedditRegex.Match(messageData.Content).Value;
                            if (!string.IsNullOrEmpty(matchValue))
                            {
                                command = "title";
                                query   = $"{command} {matchValue}";
                            }
                        }
                        else if ((settings.FunResponsesEnabled || IsAuthorOwner(messageData)) && contentParts.Length > 1 && contentParts[1] == "face")
                        {
                            command = "face";
                            query   = $"{command} {contentParts[0]}";
                        }
                    }
                }

                // Ignore if the command is disabled on this server
                if (settings.IsCommandDisabled(CommandsConfig.Instance, command) && !IsAuthorOwner(messageData))
                {
                    return(responseData);
                }

                if (CommandsConfig.Instance.Commands.ContainsKey(command))
                {
                    if (!messageData.RateLimitChecked)
                    {
                        // make sure we're not rate limited
                        var commandKey = command + messageData.Server;

                        if (this.Throttler.IsThrottled(commandKey, ThrottleType.Command))
                        {
                            return(responseData);
                        }

                        this.Throttler.Increment(commandKey, ThrottleType.Command);

                        // if we're now throttled after this increment, return a "rate limited" message
                        if (this.Throttler.IsThrottled(commandKey, ThrottleType.Command))
                        {
                            responses.Add("rate limited try later");
                            return(responseData);
                        }

                        // increment the user/guild throttlers as well
                        this.Throttler.Increment(messageData.UserId, ThrottleType.User);
                        this.Throttler.Increment(messageData.Server, ThrottleType.Guild);

                        messageData.RateLimitChecked = true;
                    }

                    var props = new Dictionary <string, string> {
                        { "command", command.ToLowerInvariant() },
                        { "server", messageData.Server },
                        { "channel", messageData.Channel }
                    };
                    this.TrackEvent("commandProcessed", props);

                    // extra processing on ".title" command
                    if ((command == "title" || command == "t") && messageData.Content.EndsWith(command) && urls.ContainsKey(messageData.Channel))
                    {
                        query += $" {this.urls[messageData.Channel]}";
                    }

                    using (DogStatsd.StartTimer("commandDuration", tags: new[] { $"shard:{this.Shard}", $"command:{command.ToLowerInvariant()}", $"{this.BotType}" }))
                    {
                        messageData.Content = $"{settings.Prefix}{query}";
                        responseData        = await this.BotApi.IssueRequestAsync(messageData);
                    }
                }
            }

            if (responseData.Responses.Count == 0 && responseData.Embed == null)
            {
                string response = null;
                if (messageData.MentionsBot(this.Config.Name, Convert.ToUInt64(this.UserId)))
                {
                    var responseValue = PhrasesConfig.Instance.PartialMentionPhrases.FirstOrDefault(kvp => messageData.Content.IContains(kvp.Key)).Value;
                    if (!string.IsNullOrEmpty(responseValue))
                    {
                        response = PhrasesConfig.Instance.Responses[responseValue].Random();
                    }
                }

                if (response == null && PhrasesConfig.Instance.ExactPhrases.ContainsKey(messageData.Content) && (settings.FunResponsesEnabled && new Random().Next(1, 100) <= settings.FunResponseChance || IsAuthorOwner(messageData)))
                {
                    response = PhrasesConfig.Instance.Responses[PhrasesConfig.Instance.ExactPhrases[messageData.Content]].Random();
                }

                if (response == null)
                {
                    response = settings.CustomCommands.FirstOrDefault(c => c.IsExactMatch && c.Command == messageData.Content || !c.IsExactMatch && messageData.Content.IContains(c.Command))?.Response;
                }

                if (response != null)
                {
                    response = response.Replace("%from%", messageData.UserName);
                    string[] resps = response.Split(new char[] { '|' });
                    responseData.Responses.AddRange(resps);
                }
            }

            return(responseData);
        }
Example #3
0
        protected async Task <BotResponseData> ProcessMessageAsync(BotMessageData messageData, Settings settings)
        {
            var responses    = new List <string>();
            var responseData = new BotResponseData {
                Responses = responses
            };

            if (this.BotApi != null)
            {
                // if an explicit command is being used, it wins out over any implicitly parsed command
                string query   = messageData.Query;
                string command = messageData.Command;

                string[] contentParts = messageData.Content.Split(new[] { ' ' });

                if (string.IsNullOrEmpty(command))
                {
                    if (messageData.Content.ToLowerInvariant().Contains("remind "))
                    {
                        // check for reminders
                        Match timerAtMatch  = Consts.TimerOnRegex.Match(messageData.Content);
                        Match timerAt2Match = Consts.TimerOn2Regex.Match(messageData.Content);
                        if (timerAtMatch.Success && Utilities.TryParseAbsoluteReminder(timerAtMatch, messageData, out query) ||
                            timerAt2Match.Success && Utilities.TryParseAbsoluteReminder(timerAt2Match, messageData, out query))
                        {
                            command = "timer";
                        }
                        else // try relative timers if absolute had no match
                        {
                            Match timerMatch  = Consts.TimerRegex.Match(messageData.Content);
                            Match timer2Match = Consts.Timer2Regex.Match(messageData.Content);

                            if (timerMatch.Success || timer2Match.Success)
                            {
                                Match matchToUse = timerMatch.Success && !timerMatch.Groups["prep"].Value.All(char.IsDigit) ? timerMatch : timer2Match;
                                if (Utilities.TryParseReminder(matchToUse, messageData, out query))
                                {
                                    command = "timer";
                                }
                            }
                        }
                    }

                    if (string.IsNullOrEmpty(command))
                    {
                        if (settings.AutoTitlesEnabled && CommandsConfig.Instance.AutoTitleMatches.Any(t => messageData.Content.Contains(t)))
                        {
                            Match  match      = Consts.HttpRegex.Match(messageData.Content);
                            string matchValue = !string.IsNullOrEmpty(match.Value) ? match.Value : Consts.RedditRegex.Match(messageData.Content).Value;
                            if (!string.IsNullOrEmpty(matchValue))
                            {
                                command = "title";
                                query   = $"{command} {matchValue}";
                            }
                        }
                        else if ((settings.FunResponsesEnabled || IsAuthorOwner(messageData)) && contentParts.Length > 1 && contentParts[1] == "face")
                        {
                            command = "face";
                            query   = $"{command} {contentParts[0]}";
                        }
                    }
                }

                // Ignore if the command is disabled on this server
                if (settings.IsCommandDisabled(CommandsConfig.Instance, command) && !IsAuthorOwner(messageData))
                {
                    return(responseData);
                }

                if (CommandsConfig.Instance.Commands.ContainsKey(command))
                {
                    if (!messageData.RateLimitChecked)
                    {
                        // make sure we're not rate limited
                        var commandKey   = command + messageData.Server;
                        var commandCount = this.commandsIssued.AddOrUpdate(commandKey, 1, (key, val) =>
                        {
                            return(val + 1);
                        });

                        if (commandCount > 12)
                        {
                            return(responseData);
                        }
                        else if (commandCount > 10)
                        {
                            responses.Add("rate limited try later");
                            return(responseData);
                        }
                    }

                    var props = new Dictionary <string, string> {
                        { "serverId", messageData.Server },
                    };
                    this.AppInsights?.TrackEvent(command.ToLowerInvariant(), props);

                    // extra processing on ".title" command
                    if ((command == "title" || command == "t") && messageData.Content.EndsWith(command) && urls.ContainsKey(messageData.Channel))
                    {
                        query += $" {this.urls[messageData.Channel]}";
                    }

                    responseData = await this.BotApi.IssueRequestAsync(messageData, query);
                }
            }

            if (responseData.Responses.Count == 0 && responseData.Embed == null)
            {
                string response = null;
                if (messageData.MentionsBot(this.Config.Name, Convert.ToUInt64(this.UserId)))
                {
                    var responseValue = PhrasesConfig.Instance.PartialMentionPhrases.Where(kvp => messageData.Content.ToLowerInvariant().Contains(kvp.Key.ToLowerInvariant())).FirstOrDefault().Value;
                    if (!string.IsNullOrEmpty(responseValue))
                    {
                        response = PhrasesConfig.Instance.Responses[responseValue].Random();
                    }
                }

                if (response == null && (settings.FunResponsesEnabled || IsAuthorOwner(messageData)) && PhrasesConfig.Instance.ExactPhrases.ContainsKey(messageData.Content) && new Random().Next(1, 100) <= settings.FunResponseChance)
                {
                    response = PhrasesConfig.Instance.Responses[PhrasesConfig.Instance.ExactPhrases[messageData.Content]].Random();
                }

                if (response != null)
                {
                    response = response.Replace("%from%", messageData.UserName);
                    string[] resps = response.Split(new char[] { '|' });
                    responseData.Responses.AddRange(resps);
                }
            }

            return(responseData);
        }
Example #4
0
        protected async Task PreProcessMessage(BotMessageData messageData, Settings settings)
        {
            this.messageCount++;

            if (settings.SeenEnabled)
            {
                var userKey = messageData.UserId ?? messageData.UserName;
                this.UpdateSeen(messageData.Server + userKey, new SeenUserData
                {
                    Name    = userKey,
                    Channel = messageData.Channel,
                    Server  = messageData.Server,
                });
            }

            var httpMatch = Consts.UrlRegex.Match(messageData.Content);

            if (httpMatch.Success)
            {
                this.urls[messageData.Channel] = httpMatch.Value;
            }

            if (settings.FunResponsesEnabled && !string.IsNullOrEmpty(messageData.Content))
            {
                var repeat = repeatData.GetOrAdd(messageData.Channel + messageData.Server, new RepeatData());
                if (string.Equals(repeat.Text, messageData.Content, StringComparison.OrdinalIgnoreCase))
                {
                    if (!repeat.Nicks.Contains(messageData.UserId ?? messageData.UserName))
                    {
                        repeat.Nicks.Add(messageData.UserId ?? messageData.UserName);
                    }

                    if (repeat.Nicks.Count == 3)
                    {
                        var commandKey = $"{messageData.Channel}_{messageData.Server}";
                        this.Throttler.Increment(commandKey, ThrottleType.Repeat);

                        if (!this.Throttler.IsThrottled(commandKey, ThrottleType.Repeat))
                        {
                            await this.RespondAsync(messageData, messageData.Content);
                        }
                        else
                        {
                            Log.Debug("repeat throttled");
                        }

                        repeat.Reset(string.Empty, string.Empty);
                    }
                }
                else
                {
                    repeat.Reset(messageData.UserId ?? messageData.UserName, messageData.Content);
                }
            }

            string command = messageData.Command;

            if (!CommandsConfig.Instance.Commands.ContainsKey(command))
            {
                command = string.Empty;
            }

            if (string.IsNullOrEmpty(command))
            {
                // match fun
                bool mentionsBot = messageData.MentionsBot(this.Config.Name, Convert.ToUInt64(this.UserId));
                if (CommandsConfig.Instance.TryParseForCommand(messageData.Content, mentionsBot, out _, out string query))
                {
                    messageData.Content = $"{settings.Prefix}{query}";
                }
            }
        }