private void ProcessQueue() { _logger.Trace($"SubscriptionProcessor::ProcessQueue"); new Thread(async() => { while (true) { if (_queue.Count == 0) { Thread.Sleep(50); continue; } if (_queue.Count > Strings.MaxQueueCountWarning) { _logger.Warn($"Subscription queue is {_queue.Count:N0} items long."); } var item = _queue.Dequeue(); if (item == null || item?.Subscription == null || item?.Member == null || item?.Embed == null) { continue; } // Check if user is receiving messages too fast. if (item.Subscription.Limiter.IsLimited()) { _logger.Warn($"{item.Member.Username} notifications rate limited, waiting {(60 - item.Subscription.Limiter.TimeLeft.TotalSeconds)} seconds...", item.Subscription.Limiter.TimeLeft.TotalSeconds.ToString("N0")); // Send ratelimited notification to user if not already sent to adjust subscription settings to more reasonable settings. if (!item.Subscription.RateLimitNotificationSent) { var guildName = _servers.ContainsKey(item.Subscription.GuildId) ? _servers[item.Subscription.GuildId].Guilds[item.Subscription.GuildId]?.Name : Strings.Creator; var guildIconUrl = _servers.ContainsKey(item.Subscription.GuildId) ? _servers[item.Subscription.GuildId].Guilds[item.Subscription.GuildId]?.IconUrl : string.Empty; var rateLimitMessage = $"Your notification subscriptions have exceeded the {NotificationLimiter.MaxNotificationsPerMinute:N0}) per minute and you are now being rate limited." + $"Please adjust your subscriptions to receive a maximum of {NotificationLimiter.MaxNotificationsPerMinute:N0} notifications within a 60 second time span."; var eb = new DiscordEmbedBuilder { Title = "Rate Limited", Description = rateLimitMessage, Color = DiscordColor.Red, Footer = new DiscordEmbedBuilder.EmbedFooter { Text = $"{guildName} | {DateTime.Now}", IconUrl = guildIconUrl } }; if (!_servers.ContainsKey(item.Subscription.GuildId)) { continue; } await _servers[item.Subscription.GuildId].SendDirectMessage(item.Member, string.Empty, eb.Build()); item.Subscription.RateLimitNotificationSent = true; } continue; } // Ratelimit is up, allow for ratelimiting again item.Subscription.RateLimitNotificationSent = false; if (!_servers.ContainsKey(item.Subscription.GuildId)) { _logger.Error($"User subscription for guild that's not configured. UserId={item.Subscription.UserId} GuildId={item.Subscription.GuildId}"); continue; } // Send text message notification to user if a phone number is set if (!string.IsNullOrEmpty(item.Subscription.PhoneNumber)) { // Check if user is in the allowed text message list or server owner if (_whConfig.Twilio.UserIds.Contains(item.Member.Id) || _whConfig.Servers[item.Subscription.GuildId].OwnerId == item.Member.Id) { // Send text message (max 160 characters) if (item.Pokemon != null && IsUltraRare(_whConfig.Twilio, item.Pokemon)) { var result = Utils.SendSmsMessage(StripEmbed(item), _whConfig.Twilio, item.Subscription.PhoneNumber); if (!result) { _logger.Error($"Failed to send text message to phone number '{item.Subscription.PhoneNumber}' for user {item.Subscription.UserId}"); } } } } // Send direct message notification to user var client = _servers[item.Subscription.GuildId]; await client.SendDirectMessage(item.Member, item.Embed); _logger.Info($"[WEBHOOK] Notified user {item.Member.Username} of {item.Description}."); Thread.Sleep(10); } }) { IsBackground = true }.Start(); }
private void ProcessQueue() { _logger.Trace($"SubscriptionProcessor::ProcessQueue"); #pragma warning disable RECS0165 // Asynchronous methods should return a Task instead of void new Thread(async() => #pragma warning restore RECS0165 // Asynchronous methods should return a Task instead of void { while (true) { if (_queue.Count == 0) { Thread.Sleep(50); continue; } if (_queue.Count > MaxQueueCountWarning) { _logger.Warn($"Subscription queue is {_queue.Count.ToString("N0")} items long."); } var item = _queue.Dequeue(); if (item == null || item?.Item1 == null || item?.Item3 == null) { continue; } var member = item.Item1; var user = Manager.Subscriptions.FirstOrDefault(x => x.UserId == item.Item1.Id); if (user == null) { continue; } if (user.Limiter.IsLimited()) { _logger.Warn($"{member.Username} notifications rate limited, waiting {(60 - user.Limiter.TimeLeft.TotalSeconds)} seconds...", user.Limiter.TimeLeft.TotalSeconds.ToString("N0")); if (!user.RateLimitNotificationSent) { var rateLimitMessage = $"Your Pokemon notifications have exceeded {NotificationLimiter.MaxNotificationsPerMinute} per minute and you are now being rate limited. Please adjust your subscriptions to receive a maximum of {NotificationLimiter.MaxNotificationsPerMinute} notifications within a 60 second time span."; var eb = new DiscordEmbedBuilder { Title = "Rate Limited", Description = rateLimitMessage, Color = DiscordColor.Red, Footer = new DiscordEmbedBuilder.EmbedFooter { Text = $"{(_client.Guilds.ContainsKey(_whConfig.Discord.GuildId) ? _client.Guilds[_whConfig.Discord.GuildId]?.Name : Strings.Creator)} | {DateTime.Now}", IconUrl = _client.Guilds.ContainsKey(_whConfig.Discord.GuildId) ? _client.Guilds[_whConfig.Discord.GuildId]?.IconUrl : string.Empty } }; await _client.SendDirectMessage(member, string.Empty, eb.Build()); user.RateLimitNotificationSent = true; } continue; } user.RateLimitNotificationSent = false; await _client.SendDirectMessage(item.Item1, item.Item3); _logger.Info($"[WEBHOOK] Notified user {item.Item1.Username} of {item.Item2}."); Thread.Sleep(10); } }) { IsBackground = true }.Start(); }