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; } } }
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); }
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); }
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}"; } } }