Ejemplo n.º 1
0
        public static string GetInvasionIcon(this PokestopData pokestop, WhConfig whConfig, string style)
        {
            var iconStyleUrl = whConfig.IconStyles[style];
            var url          = iconStyleUrl.EndsWith('/') ? iconStyleUrl + "grunt/" : $"{iconStyleUrl}/grunt";

            return($"{url}/{Convert.ToInt32(pokestop.GruntType)}.png");
        }
Ejemplo n.º 2
0
        public static string GetLureIcon(this PokestopData pokestop, WhConfig whConfig, string style)
        {
            var iconStyleUrl = whConfig.IconStyles[style];
            var url          = iconStyleUrl.EndsWith('/') ? iconStyleUrl + "rewards" : $"{iconStyleUrl}/rewards";

            return($"{url}/reward_{Convert.ToInt32(pokestop.LureType)}_1.png");
        }
Ejemplo n.º 3
0
 public ScannedPokestop(PokestopData pokestop)
 {
     Latitude           = pokestop.Latitude;
     Longitude          = pokestop.Longitude;
     LureType           = pokestop.LureType;
     LureExpireTime     = pokestop.LureExpireTime;
     GruntType          = pokestop.GruntType;
     InvasionExpireTime = pokestop.InvasionExpireTime;
 }
Ejemplo n.º 4
0
        private void ProcessPokestop(PokestopData pokestop)
        {
            //Skip if EnablePokestops is disabled in the config.
            if (!_alarms.EnablePokestops)
            {
                return;
            }

            //Skip if Pokestop filter is not defined.
            if (pokestop == null)
            {
                return;
            }

            //Skip if alarms list is null or empty.
            if (_alarms.Alarms?.Count == 0)
            {
                return;
            }

            for (var i = 0; i < _alarms.Alarms.Count; i++)
            {
                var alarm = _alarms.Alarms[i];
                if (alarm.Filters.Pokestops == null)
                {
                    continue;
                }

                if (!alarm.Filters.Pokestops.Enabled)
                {
                    _logger.Info($"[{alarm.Name}] Skipping pokestop PokestopId={pokestop.PokestopId}, Name={pokestop.Name}: pokestop filter not enabled.");
                    continue;
                }

                if (!alarm.Filters.Pokestops.Lured && pokestop.HasLure)
                {
                    //_logger.Info($"[{alarm.Name}] Skipping pokestop PokestopId={pokestop.PokestopId}, Name={pokestop.Name}: lure filter not enabled.");
                    continue;
                }

                if (!alarm.Filters.Pokestops.Invasions && pokestop.HasInvasion)
                {
                    //_logger.Info($"[{alarm.Name}] Skipping pokestop PokestopId={pokestop.PokestopId}, Name={pokestop.Name}: invasion filter not enabled.");
                    continue;
                }

                var geofence = InGeofence(alarm.Geofences, new Location(pokestop.Latitude, pokestop.Longitude));
                if (geofence == null)
                {
                    //_logger.Info($"[{alarm.Name}] Skipping pokestop PokestopId={pokestop.PokestopId}, Name={pokestop.Name} because not in geofence.");
                    continue;
                }

                OnPokestopAlarmTriggered(pokestop, alarm);
            }
        }
Ejemplo n.º 5
0
        private void OnInvasionSubscriptionTriggered(object sender, PokestopData e)
        {
            if (_subProcessor == null)
            {
                return;
            }

            if (!ThreadPool.QueueUserWorkItem(async x => await _subProcessor.ProcessInvasionSubscription(e)))
            {
                // Failed to queue thread
                _logger.Error($"Failed to queue thread to process invasion subscription");
            }
        }
Ejemplo n.º 6
0
        private void OnInvasionSubscriptionTriggered(object sender, PokestopData e)
        {
            if (!_whConfig.Discord.EnableSubscriptions)
            {
                return;
            }

            if (_subProcessor == null)
            {
                return;
            }

            new System.Threading.Thread(async() => await _subProcessor.ProcessInvasionSubscription(e))
            {
                IsBackground = true
            }.Start();
        }
Ejemplo n.º 7
0
        private void ParsePokestop(dynamic message)
        {
            try
            {
                PokestopData pokestop = JsonConvert.DeserializeObject <PokestopData>(Convert.ToString(message));
                if (pokestop == null)
                {
                    _logger.Error($"Failed to parse pokestop webhook object: {message}");
                    return;
                }

                pokestop.SetTimes();

                if (_checkForDuplicates)
                {
                    lock (_processedPokestops)
                    {
                        if (_processedPokestops.ContainsKey(pokestop.PokestopId))
                        {
                            var processedLureAlready     = _processedPokestops[pokestop.PokestopId].LureType == pokestop.LureType && _processedPokestops[pokestop.PokestopId].LureExpireTime == pokestop.LureExpireTime;
                            var processedInvasionAlready = _processedPokestops[pokestop.PokestopId].GruntType == pokestop.GruntType && _processedPokestops[pokestop.PokestopId].InvasionExpireTime == pokestop.InvasionExpireTime;
                            if (processedLureAlready || processedInvasionAlready)
                            {
                                //_logger.Debug($"PROCESSED LURE OR INVASION ALREADY: Id: {pokestop.PokestopId} Name: {pokestop.Name} Lure: {pokestop.LureType} Expires: {pokestop.LureExpireTime} Grunt: {pokestop.GruntType} Expires: {pokestop.InvasionExpireTime}");
                                // Processed pokestop lure or invasion already
                                return;
                            }

                            _processedPokestops[pokestop.PokestopId] = new ScannedPokestop(pokestop);
                        }
                        else
                        {
                            _processedPokestops.Add(pokestop.PokestopId, new ScannedPokestop(pokestop));
                        }
                    }
                }

                OnPokestopReceived(pokestop);
            }
            catch (Exception ex)
            {
                _logger.Error(ex);
                _logger.Debug(Convert.ToString(message));
            }
        }
Ejemplo n.º 8
0
        private void ParsePokestop(dynamic message)
        {
            try
            {
                PokestopData pokestop = JsonConvert.DeserializeObject <PokestopData>(Convert.ToString(message));
                if (pokestop == null)
                {
                    _logger.Error($"Failed to parse pokestop webhook object: {message}");
                    return;
                }

                pokestop.SetTimes();

                OnPokestopReceived(pokestop);
            }
            catch (Exception ex)
            {
                _logger.Error(ex);
                _logger.Debug(Convert.ToString(message));
            }
        }
Ejemplo n.º 9
0
 private void OnPokestopAlarmTriggered(PokestopData pokestop, AlarmObject alarm, ulong guildId)
 {
     PokestopAlarmTriggered?.Invoke(this, new AlarmEventTriggeredEventArgs <PokestopData>(pokestop, alarm, guildId));
 }
Ejemplo n.º 10
0
 private void OnPokestopReceived(PokestopData pokestop) => PokestopReceived?.Invoke(this, new DataReceivedEventArgs <PokestopData>(pokestop));
Ejemplo n.º 11
0
        private void ProcessPokestop(PokestopData pokestop)
        {
            //Skip if Pokestop filter is not defined.
            if (pokestop == null)
            {
                return;
            }

            Statistics.Instance.TotalReceivedPokestops++;

            var keys = _alarms.Keys.ToList();

            for (var i = 0; i < keys.Count; i++)
            {
                var guildId = keys[i];
                var alarms  = _alarms[guildId];

                //Skip if EnablePokestops is disabled in the config.
                if (!alarms.EnablePokestops)
                {
                    continue;
                }

                //Skip if alarms list is null or empty.
                if (alarms.Alarms?.Count == 0)
                {
                    continue;
                }

                var pokestopAlarms = alarms.Alarms.FindAll(x => x.Filters?.Pokestops != null);
                for (var j = 0; j < pokestopAlarms.Count; j++)
                {
                    var alarm = pokestopAlarms[j];
                    if (alarm.Filters.Pokestops == null)
                    {
                        continue;
                    }

                    if (!alarm.Filters.Pokestops.Enabled)
                    {
                        //_logger.Info($"[{alarm.Name}] Skipping pokestop PokestopId={pokestop.PokestopId}, Name={pokestop.Name}: pokestop filter not enabled.");
                        continue;
                    }

                    if (!alarm.Filters.Pokestops.Lured && pokestop.HasLure)
                    {
                        //_logger.Info($"[{alarm.Name}] Skipping pokestop PokestopId={pokestop.PokestopId}, Name={pokestop.Name}: lure filter not enabled.");
                        continue;
                    }

                    if (!alarm.Filters.Pokestops.Invasions && pokestop.HasInvasion)
                    {
                        //_logger.Info($"[{alarm.Name}] Skipping pokestop PokestopId={pokestop.PokestopId}, Name={pokestop.Name}: invasion filter not enabled.");
                        continue;
                    }

                    var geofence = GeofenceService.InGeofence(alarm.Geofences, new Location(pokestop.Latitude, pokestop.Longitude));
                    if (geofence == null)
                    {
                        //_logger.Info($"[{alarm.Name}] Skipping pokestop PokestopId={pokestop.PokestopId}, Name={pokestop.Name} because not in geofence.");
                        continue;
                    }

                    OnPokestopAlarmTriggered(pokestop, alarm, guildId);
                }
            }
        }
Ejemplo n.º 12
0
        public async Task ProcessLureSubscription(PokestopData pokestop)
        {
            // Cache the result per-guild so that geospatial stuff isn't queried for every single subscription below
            Dictionary <ulong, GeofenceItem> locationCache = new Dictionary <ulong, GeofenceItem>();

            GeofenceItem GetGeofence(ulong guildId)
            {
                if (!locationCache.TryGetValue(guildId, out var geofence))
                {
                    geofence = _whm.GetGeofence(guildId, pokestop.Latitude, pokestop.Longitude);
                    locationCache.Add(guildId, geofence);
                }

                return(geofence);
            }

            var subscriptions = Manager.GetUserSubscriptionsByLureType(pokestop.LureType);

            if (subscriptions == null)
            {
                _logger.Warn($"Failed to get subscriptions from database table.");
                return;
            }

            SubscriptionObject user;

            for (int i = 0; i < subscriptions.Count; i++)
            {
                //var start = DateTime.Now;
                try
                {
                    user = subscriptions[i];
                    if (user == null)
                    {
                        continue;
                    }

                    if (!user.Enabled)
                    {
                        continue;
                    }

                    if (!_whConfig.Instance.Servers.ContainsKey(user.GuildId))
                    {
                        continue;
                    }

                    if (!_whConfig.Instance.Servers[user.GuildId].Subscriptions.Enabled)
                    {
                        continue;
                    }

                    if (!_servers.ContainsKey(user.GuildId))
                    {
                        continue;
                    }

                    var client = _servers[user.GuildId];

                    var member = await client.GetMemberById(user.GuildId, user.UserId);

                    if (member == null)
                    {
                        _logger.Warn($"Failed to find member with id {user.UserId}.");
                        continue;
                    }

                    if (!member.HasSupporterRole(_whConfig.Instance.Servers[user.GuildId].DonorRoleIds))
                    {
                        _logger.Info($"User {user.UserId} is not a supporter, skipping Pokestop lure {pokestop.Name}...");
                        // Automatically disable users subscriptions if not supporter to prevent issues
                        //user.Enabled = false;
                        //user.Save(false);
                        continue;
                    }

                    var subLure = user.Lures.FirstOrDefault(x => x.LureType == pokestop.LureType);
                    // Not subscribed to lure
                    if (subLure == null)
                    {
                        //_logger.Debug($"Skipping notification for user {member.DisplayName} ({member.Id}) for Pokestop lure {pokemon.Name}, lure is in city '{loc.Name}'.");
                        continue;
                    }

                    var geofence = GetGeofence(user.GuildId);
                    if (geofence == null)
                    {
                        //_logger.Warn($"Failed to lookup city from coordinates {pokestop.Latitude},{pokestop.Longitude} {pokestop.PokestopId} {pokestop.Name}, skipping...");
                        continue;
                    }

                    var distanceMatches = user.DistanceM > 0 && user.DistanceM > new Coordinates(user.Latitude, user.Longitude).DistanceTo(new Coordinates(pokestop.Latitude, pokestop.Longitude));
                    var geofenceMatches = subLure.Areas.Select(x => x.ToLower()).Contains(geofence.Name.ToLower());

                    // If set distance does not match and no geofences match, then skip lure...
                    if (!distanceMatches && !geofenceMatches)
                    {
                        continue;
                    }

                    var embed = pokestop.GeneratePokestopMessage(user.GuildId, client, _whConfig.Instance, null, geofence.Name, true, false);
                    //var end = DateTime.Now.Subtract(start);
                    //_logger.Debug($"Took {end} to process lure subscription for user {user.UserId}");
                    embed.Embeds.ForEach(x => _queue.Enqueue(new NotificationItem(user, member, x, pokestop.Name, geofence.Name)));

                    Statistics.Instance.SubscriptionLuresSent++;
                    Thread.Sleep(5);
                }
                catch (Exception ex)
                {
                    _logger.Error(ex);
                }
            }

            subscriptions.Clear();
            subscriptions = null;
            user          = null;

            await Task.CompletedTask;
        }
Ejemplo n.º 13
0
        public async Task ProcessInvasionSubscription(PokestopData pokestop)
        {
            var loc = _whm.GetGeofence(pokestop.Latitude, pokestop.Longitude);

            if (loc == null)
            {
                //_logger.Warn($"Failed to lookup city for coordinates {pokestop.Latitude},{pokestop.Longitude}, skipping...");
                return;
            }

            var invasion   = MasterFile.Instance.GruntTypes.ContainsKey(pokestop.GruntType) ? MasterFile.Instance.GruntTypes[pokestop.GruntType] : null;
            var encounters = invasion?.GetEncounterRewards();

            if (encounters == null)
            {
                return;
            }

            var subscriptions = Manager.GetUserSubscriptionsByEncounterReward(encounters);

            if (subscriptions == null)
            {
                _logger.Warn($"Failed to get subscriptions from database table.");
                return;
            }

            if (!MasterFile.Instance.GruntTypes.ContainsKey(pokestop.GruntType))
            {
                //_logger.Error($"Failed to parse grunt type {pokestop.GruntType}, not in `grunttype.json` list.");
                return;
            }

            SubscriptionObject user;

            for (int i = 0; i < subscriptions.Count; i++)
            {
                try
                {
                    user = subscriptions[i];
                    if (user == null)
                    {
                        continue;
                    }

                    if (!user.Enabled)
                    {
                        continue;
                    }

                    if (!_whConfig.Servers.ContainsKey(user.GuildId))
                    {
                        continue;
                    }

                    if (!_whConfig.Servers[user.GuildId].Subscriptions.Enabled)
                    {
                        continue;
                    }

                    if (!_servers.ContainsKey(user.GuildId))
                    {
                        continue;
                    }

                    var client = _servers[user.GuildId];

                    var member = await client.GetMemberById(user.GuildId, user.UserId);

                    if (member == null)
                    {
                        _logger.Warn($"Failed to find member with id {user.UserId}.");
                        continue;
                    }

                    if (!member.HasSupporterRole(_whConfig.Servers[user.GuildId].DonorRoleIds))
                    {
                        _logger.Info($"User {user.UserId} is not a supporter, skipping Team Rocket invasion {pokestop.Name}...");
                        // Automatically disable users subscriptions if not supporter to prevent issues
                        user.Enabled = false;
                        user.Save(false);
                        continue;
                    }

                    var subInvasion = user.Invasions.FirstOrDefault(x => encounters.Contains(x.RewardPokemonId));
                    // Not subscribed to invasion
                    if (subInvasion == null)
                    {
                        //_logger.Debug($"Skipping notification for user {member.DisplayName} ({member.Id}) for raid boss {pokemon.Name}, raid is in city '{loc.Name}'.");
                        continue;
                    }

                    var distanceMatches = user.DistanceM > 0 && user.DistanceM > new Coordinates(user.Latitude, user.Longitude).DistanceTo(new Coordinates(pokestop.Latitude, pokestop.Longitude));
                    var geofenceMatches = subInvasion.Areas.Select(x => x.ToLower()).Contains(loc.Name.ToLower());

                    // If set distance does not match and no geofences match, then skip Pokemon...
                    if (!distanceMatches && !geofenceMatches)
                    {
                        continue;
                    }

                    var embed = pokestop.GeneratePokestopMessage(user.GuildId, client, _whConfig, null, loc?.Name);
                    foreach (var emb in embed.Embeds)
                    {
                        _queue.Enqueue(new NotificationItem(user, member, emb, pokestop.Name, loc.Name));
                    }

                    Statistics.Instance.SubscriptionInvasionsSent++;
                    Thread.Sleep(5);
                }
                catch (Exception ex)
                {
                    _logger.Error(ex);
                }
            }

            subscriptions.Clear();
            subscriptions = null;
            user          = null;
            loc           = null;

            await Task.CompletedTask;
        }
Ejemplo n.º 14
0
 public PokestopDataEventArgs(PokestopData pokestop)
 {
     Pokestop = pokestop;
 }
Ejemplo n.º 15
0
 private void OnInvasionSubscriptionTriggered(PokestopData pokestop)
 {
     InvasionSubscriptionTriggered?.Invoke(this, pokestop);
 }
Ejemplo n.º 16
0
        public async Task ProcessInvasionSubscription(PokestopData pokestop)
        {
            var loc = _whm.GetGeofence(pokestop.Latitude, pokestop.Longitude);

            if (loc == null)
            {
                //_logger.Warn($"Failed to lookup city for coordinates {pokestop.Latitude},{pokestop.Longitude}, skipping...");
                return;
            }

            var invasion   = MasterFile.Instance.GruntTypes.ContainsKey(pokestop.GruntType) ? MasterFile.Instance.GruntTypes[pokestop.GruntType] : null;
            var encounters = invasion?.GetEncounterRewards();

            if (encounters == null)
            {
                return;
            }

            var subscriptions = Manager.GetUserSubscriptionsByEncounterReward(encounters);

            if (subscriptions == null)
            {
                _logger.Warn($"Failed to get subscriptions from database table.");
                return;
            }

            if (!MasterFile.Instance.GruntTypes.ContainsKey(pokestop.GruntType))
            {
                //_logger.Error($"Failed to parse grunt type {pokestop.GruntType}, not in `grunttype.json` list.");
                return;
            }

            SubscriptionObject user;

            for (int i = 0; i < subscriptions.Count; i++)
            {
                try
                {
                    user = subscriptions[i];
                    if (user == null)
                    {
                        continue;
                    }

                    if (!user.Enabled)
                    {
                        continue;
                    }

                    if (!_whConfig.Servers.ContainsKey(user.GuildId))
                    {
                        continue;
                    }

                    if (!_whConfig.Servers[user.GuildId].EnableSubscriptions)
                    {
                        continue;
                    }

                    if (!_servers.ContainsKey(user.GuildId))
                    {
                        continue;
                    }

                    var client = _servers[user.GuildId];

                    var member = await client.GetMemberById(user.GuildId, user.UserId);

                    if (member == null)
                    {
                        _logger.Warn($"Failed to find member with id {user.UserId}.");
                        continue;
                    }

                    if (!member.HasSupporterRole(_whConfig.Servers[user.GuildId].DonorRoleIds))
                    {
                        _logger.Info($"User {user.UserId} is not a supporter, skipping Team Rocket invasion {pokestop.Name}...");
                        continue;
                    }

                    var exists = user.Invasions.FirstOrDefault(x =>
                                                               encounters.Contains(x.RewardPokemonId) &&
                                                               (string.IsNullOrEmpty(x.City) || (!string.IsNullOrEmpty(x.City) && string.Compare(loc.Name, x.City, true) == 0))
                                                               ) != null;
                    if (!exists)
                    {
                        //_logger.Debug($"Skipping notification for user {member.DisplayName} ({member.Id}) for raid boss {pokemon.Name}, raid is in city '{loc.Name}'.");
                        continue;
                    }

                    // Only check distance if user has it set
                    if (user.DistanceM > 0)
                    {
                        var distance = new Coordinates(user.Latitude, user.Longitude).DistanceTo(new Coordinates(pokestop.Latitude, pokestop.Longitude));
                        if (user.DistanceM < distance)
                        {
                            //Skip if distance is set and is not met.
                            _logger.Debug($"Skipping notification for user {member.DisplayName} ({member.Id}) for TR Invasion {pokestop.Name}, TR Invasion is farther than set distance of '{user.DistanceM} meters.");
                            continue;
                        }
                    }

                    var embed = pokestop.GeneratePokestopMessage(user.GuildId, client, _whConfig, null, loc?.Name);
                    foreach (var emb in embed.Embeds)
                    {
                        _queue.Enqueue(new NotificationItem(user, member, emb, pokestop.Name, loc.Name));
                    }

                    Statistics.Instance.SubscriptionInvasionsSent++;
                    Thread.Sleep(5);
                }
                catch (Exception ex)
                {
                    _logger.Error(ex);
                }
            }

            subscriptions.Clear();
            subscriptions = null;
            user          = null;
            loc           = null;

            await Task.CompletedTask;
        }
Ejemplo n.º 17
0
        private void ProcessPokestop(PokestopData pokestop)
        {
            //Skip if Pokestop filter is not defined.
            if (pokestop == null)
            {
                return;
            }

            Statistics.Instance.TotalReceivedPokestops++;

            foreach (var(guildId, alarms) in _alarms)
            {
                //Skip if EnablePokestops is disabled in the config.
                if (!alarms.EnablePokestops)
                {
                    continue;
                }

                //Skip if alarms list is null or empty.
                if (alarms.Alarms?.Count == 0)
                {
                    continue;
                }

                var pokestopAlarms = alarms.Alarms.FindAll(x => x.Filters?.Pokestops != null);
                for (var j = 0; j < pokestopAlarms.Count; j++)
                {
                    var alarm = pokestopAlarms[j];
                    if (alarm.Filters.Pokestops == null)
                    {
                        continue;
                    }

                    if (!alarm.Filters.Pokestops.Enabled)
                    {
                        //_logger.Info($"[{alarm.Name}] Skipping pokestop PokestopId={pokestop.PokestopId}, Name={pokestop.Name}: pokestop filter not enabled.");
                        continue;
                    }

                    if (!alarm.Filters.Pokestops.Lured && pokestop.HasLure)
                    {
                        //_logger.Info($"[{alarm.Name}] Skipping pokestop PokestopId={pokestop.PokestopId}, Name={pokestop.Name}: lure filter not enabled.");
                        continue;
                    }

                    if (!alarm.Filters.Pokestops.LureTypes.Select(x => x.ToLower()).Contains(pokestop.LureType.ToString().ToLower()) && alarm.Filters.Pokestops?.LureTypes?.Count > 0)
                    {
                        //_logger.Info($"[{alarm.Name}] Skipping pokestop PokestopId={pokestop.PokestopId}, Name={pokestop.Name}, LureType={pokestop.LureType}: lure type not included.");
                        continue;
                    }

                    if (!alarm.Filters.Pokestops.Invasions && pokestop.HasInvasion)
                    {
                        //_logger.Info($"[{alarm.Name}] Skipping pokestop PokestopId={pokestop.PokestopId}, Name={pokestop.Name}: invasion filter not enabled.");
                        continue;
                    }

                    var geofence = GeofenceService.GetGeofence(alarm.GeofenceItems, new Location(pokestop.Latitude, pokestop.Longitude));
                    if (geofence == null)
                    {
                        //_logger.Info($"[{alarm.Name}] Skipping pokestop PokestopId={pokestop.PokestopId}, Name={pokestop.Name} because not in geofence.");
                        continue;
                    }

                    OnPokestopAlarmTriggered(pokestop, alarm, guildId);
                }
            }
        }
Ejemplo n.º 18
0
        public async Task ProcessInvasionSubscription(PokestopData pokestop)
        {
            if (!_whConfig.Discord.EnableSubscriptions)
            {
                return;
            }

            var loc = _whm.GetGeofence(pokestop.Latitude, pokestop.Longitude);

            if (loc == null)
            {
                //_logger.Warn($"Failed to lookup city for coordinates {pokestop.Latitude},{pokestop.Longitude}, skipping...");
                return;
            }

            var subscriptions = Manager.GetUserSubscriptionsByGruntType(pokestop.GruntType);

            if (subscriptions == null)
            {
                _logger.Warn($"Failed to get subscriptions from database table.");
                return;
            }

            SubscriptionObject user;
            //var embed = _embedBuilder.BuildPokestopMessage(pokestop, loc.Name);
            var embed = pokestop.GeneratePokestopMessage(_client, _whConfig, null, loc.Name);

            for (int i = 0; i < subscriptions.Count; i++)
            {
                try
                {
                    user = subscriptions[i];
                    if (user == null)
                    {
                        continue;
                    }

                    if (!user.Enabled)
                    {
                        continue;
                    }

                    var member = await _client.GetMemberById(_whConfig.Discord.GuildId, user.UserId);

                    if (member == null)
                    {
                        _logger.Warn($"Failed to find member with id {user.UserId}.");
                        continue;
                    }

                    if (!member.HasSupporterRole(_whConfig.Discord.DonorRoleIds))
                    {
                        _logger.Info($"User {user.UserId} is not a supporter, skipping Team Rocket invasion {pokestop.Name}...");
                        continue;
                    }

                    var exists = user.Invasions.FirstOrDefault(x =>
                                                               x.GruntType == pokestop.GruntType &&
                                                               (string.IsNullOrEmpty(x.City) || (!string.IsNullOrEmpty(x.City) && string.Compare(loc.Name, x.City, true) == 0))
                                                               ) != null;
                    if (!exists)
                    {
                        //_logger.Debug($"Skipping notification for user {member.DisplayName} ({member.Id}) for raid boss {pokemon.Name}, raid is in city '{loc.Name}'.");
                        continue;
                    }

                    if (user.DistanceM > 0)
                    {
                        var distance = new Coordinates(user.Latitude, user.Longitude).DistanceTo(new Coordinates(pokestop.Latitude, pokestop.Longitude));
                        if (user.DistanceM < distance)
                        {
                            //Skip if distance is set and is not met.
                            _logger.Debug($"Skipping notification for user {member.DisplayName} ({member.Id}) for TR Invasion {pokestop.Name}, TR Invasion is farther than set distance of '{user.DistanceM} meters.");
                            continue;
                        }
                    }

                    //_logger.Debug($"Notifying user {member.Username} that a {raid.PokemonId} raid is available...");

                    _queue.Enqueue(new Tuple <DiscordUser, string, DiscordEmbed>(member, pokestop.Name, embed));

                    //if (!Manager.AddRaidStatistic(member.Id, raid))
                    //{
                    //    _logger.Warn($"Failed to add {pokemon.Name} raid statistic for user {user.Id}.");
                    //}
                    Statistics.Instance.SubscriptionInvasionsSent++;
                    Thread.Sleep(5);
                }
                catch (Exception ex)
                {
                    _logger.Error(ex);
                }
            }

            subscriptions.Clear();
            subscriptions = null;
            embed         = null;
            user          = null;
            loc           = null;

            await Task.CompletedTask;
        }