Ejemplo n.º 1
0
        private void UpdateRaid(RaidTarget target, DbSet <RaidParticipation> coll, RaidParticipation raid)
        {
            _log.Info($"Updating raid {raid.PublicID} / {raid.Raid.Raid} / {raid.Raid.Gym} in channel {target.Description}");

            lock (SharedUpdateLock)
            {
                raid = coll.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                var pe = raid.Raid.Publications.Where(x => x.ChannelID == target.ChannelID).FirstOrDefault();
                if (null == pe)
                {
                    return;
                }
                raid.Raid.Publications.RemoveAll(x => x != pe && x.ChannelID == pe.ChannelID);
                if (pe.TelegramMessageID != -1)
                {
                    pe.LastModificationTimeUTC = DateTime.UtcNow;
                    coll.Update(raid);
                }
                else
                {
                    return;
                }
            }

            string url         = $"{SettingsManager.BotAddress}raids/{raid.PublicID}?r={rnd.Next()}";
            string messageText = $"[{TimeService.AsShortTime(raid.Raid.RaidUnlockTime)}-{TimeService.AsShortTime(raid.Raid.RaidEndTime)}] {MessageUtils.HtmlEscape(raid.Raid.Raid)} @ {MessageUtils.HtmlEscape(raid.Raid.Gym)} ({raid.NumberOfParticipants()})\n<a href=\"{url}\">Klik hier om in te schrijven.</a>";

            lock (SharedUpdateLock)
            {
                raid = coll.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                var pe = raid.Raid.Publications.Where(x => x.ChannelID == target.ChannelID).FirstOrDefault();
                if (null == pe)
                {
                    return;
                }
                // We use -1 as a constant to indicate the message was not sent yet, or was delayed.
                if (pe.TelegramMessageID != -1)
                {
                    try
                    {
                        Client.EditMessageText($"{pe.ChannelID}", pe.TelegramMessageID, null, messageText, "HTML", true, null, "channel");
                    }
                    catch (Exception ex)
                    {
                        _log.Error(ex, "Failed to post new raid message.");

                        raid = coll.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                        pe   = raid.Raid.Publications.Where(x => x.ChannelID == target.ChannelID).FirstOrDefault();
                        if (null == pe)
                        {
                            return;
                        }
                        raid.Raid.Publications.RemoveAll(x => x != pe && x.ChannelID == pe.ChannelID);

                        pe.LastModificationTimeUTC = raid.LastModificationTime - TimeSpan.FromMilliseconds(1);
                        coll.Update(raid);
                    }
                }
            }
        }
        private void UpdateRaid(RaidTarget target, DbSet <RaidParticipation> coll, RaidParticipation raid)
        {
            _log.Info($"Updating raid {raid.PublicID} / {raid.Raid.Raid} / {raid.Raid.Gym} in channel {target.Description}");

            lock (UpdatePublishedRaidsInChannels.SharedUpdateLock)
            {
                raid = coll.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                if (raid.Raid.TelegramMessageID != null && raid.Raid.TelegramMessageID != 0 && raid.Raid.TelegramMessageID != -1)
                {
                    raid.LastRefresh = DateTime.UtcNow;
                    coll.Update(raid);
                }
                else
                {
                    return;
                }
            }

            try
            {
                RaidEventHandler.UpdateRaidMessage(target.ChannelID, raid.Raid.TelegramMessageID, null, raid.PublicID, "channel");
            }
            catch (Exception ex)
            {
                _log.Error(ex, "Failed to update raid message, marking as modified.");
                lock (UpdatePublishedRaidsInChannels.SharedUpdateLock)
                {
                    // error publishing, assume it wasn't updated and try again
                    raid = coll.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                    raid.LastModificationTime = DateTime.UtcNow;
                    coll.Update(raid);
                }
            }
        }
Ejemplo n.º 3
0
        internal void CreateAndSharePrivately(User from, RaidDescription record)
        {
            var raid = new RaidParticipation {
                Raid = record
            };
            var collection = DB.GetCollection <RaidParticipation>();

            collection.Insert(raid);
            ShareRaidToChat(raid, from.ID);
        }
Ejemplo n.º 4
0
        internal Message ShareRaidToChat(RaidParticipation raid, long chatID)
        {
            string text = CreateRaidText(raid);
            InlineKeyboardMarkup markup = CreateMarkupFor(raid);
            var message = Client.SendMessageToChat(chatID, text, "HTML", true, true, null, markup);

            // Requires the summary to be re-posted
            SummarizeActiveRaids.NewRaidPosted = true;

            return(message);
        }
Ejemplo n.º 5
0
 private static void RemoveAnyAndAllCurrentParticipations(RaidParticipation raid, Botje.Messaging.Models.User user)
 {
     foreach (Team t in Enum.GetValues(typeof(Team)).OfType <Team>())
     {
         if (raid.Participants.ContainsKey(t) && null != raid.Participants[t])
         {
             raid.Participants[t].RemoveAll(x => x.User?.ID == user.ID);
         }
     }
     raid.Rejected.RemoveAll(x => x.ID == user.ID);
     raid.Done.RemoveAll(x => x.ID == user.ID);
     raid.Maybe.RemoveAll(x => x.ID == user.ID);
 }
Ejemplo n.º 6
0
        private void UpdateAddress(DbSet <RaidParticipation> raidCollection, RaidParticipation raid, Location location)
        {
            bool wasInTime = AddressServicie.GetAddress(location.Latitude, location.Longitude).ContinueWith((t) =>
            {
                raid.Raid.Address         = t.Result;
                raid.LastModificationTime = DateTime.UtcNow;
                raidCollection.Update(raid);
            }).Wait(TimeSpan.FromSeconds(5));

            if (wasInTime)
            {
                _log.Trace("Got address in time...");
            }
            else
            {
                _log.Warn("Address arrived too late from Google, not waiting. We'll update when we get it.");
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Takes care that the user's participation type gets updated for the given raid.
        /// </summary>
        /// <param name="user"></param>
        /// <param name="raidID"></param>
        /// <param name="userParticipationType"></param>
        private void UpdateUserRaidParticipationType(User user, string raidID, UserParticipationType userParticipationType)
        {
            DbSet <RaidParticipation> raidParticipationCollection = this.DB.GetCollection <RaidParticipation>();

            lock (RaidParticipation.Lock)
            {
                RaidParticipation raidParticipation = raidParticipationCollection.Find(rp => rp.PublicID == raidID).First();
                UserSettings      userSettings      = UserSettings.GetOrCreateUserSettings(user, DB.GetCollection <UserSettings>());

                UserParticipation userParticipation = raidParticipation.Participants[userSettings.Team].FirstOrDefault(rp => rp.User.ID == user.ID);

                if (userParticipation != null)
                {
                    userParticipation.Type = userParticipationType;
                    raidParticipationCollection.Update(raidParticipation);
                }
            }
        }
Ejemplo n.º 8
0
        internal Message ShareRaidToChat(RaidParticipation raid, long chatID)
        {
            string text = CreateRaidText(raid);
            InlineKeyboardMarkup markup = CreateMarkupFor(raid);

            _log.Info($"Publishing raid for {raid.Raid.Raid} at {raid.Raid.Gym} to {chatID}");
            try
            {
                var message = Client.SendMessageToChat(chatID, text, "HTML", true, true, null, markup);

                // Requires the summary to be re-posted
                SummarizeActiveRaids.NewRaidPosted = true;
                return(message);
            }
            catch (Exception ex)
            {
                _log.Error(ex, $"Error publishing raid for {raid.Raid.Raid} at {raid.Raid.Gym} to {chatID}");
                throw;
            }
        }
        private void DeleteRaid(RaidTarget target, DbSet <RaidParticipation> coll, RaidParticipation raid)
        {
            _log.Info($"Deleting raid {raid.PublicID} / {raid.Raid.Raid} / {raid.Raid.Gym} from channel {target.Description}");

            if (raid.Raid.TelegramMessageID != null && raid.Raid.TelegramMessageID != 0 && raid.Raid.TelegramMessageID != -1)
            {
                Client.DeleteMessage(target.ChannelID, raid.Raid.TelegramMessageID ?? 0);
            }
            else
            {
                return; // nothing happened.
            }

            // Only update the database when DELETE succeeded
            lock (UpdatePublishedRaidsInChannels.SharedUpdateLock)
            {
                raid = coll.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                raid.Raid.TelegramMessageID = 0;
                coll.Update(raid);
            }
        }
        private void UpdateAddress(DbSet <RaidParticipation> raidCollection, RaidParticipation raid, Location location)
        {
            raid.Raid.Address = $"{location.Latitude} {location.Longitude}";
            bool wasInTime = AddressServicie.GetAddress(location.Latitude, location.Longitude).ContinueWith((t) =>
            {
                if (raid.Raid.Address != t.Result && !string.IsNullOrWhiteSpace(t.Result))
                {
                    var nwRaid                  = raidCollection.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                    nwRaid.Raid.Address         = t.Result;
                    nwRaid.LastModificationTime = DateTime.UtcNow;
                    raidCollection.Update(nwRaid);
                }
            }).Wait(TimeSpan.FromSeconds(5));

            if (wasInTime)
            {
                _log.Trace("Got address in time...");
            }
            else
            {
                _log.Warn("Address arrived too late from Google, not waiting. We'll update when we get it.");
            }
        }
Ejemplo n.º 11
0
        private void DeleteRaid(RaidTarget target, DbSet <RaidParticipation> coll, RaidParticipation raid)
        {
            _log.Info($"Deleting raid {raid.PublicID} / {raid.Raid.Raid} / {raid.Raid.Gym} from channel {target.Description}");

            var pe = raid.Raid.Publications.Where(x => x.ChannelID == target.ChannelID).FirstOrDefault();

            if (null != pe && pe.TelegramMessageID != -1)
            {
                Client.DeleteMessage(target.ChannelID, pe.TelegramMessageID);
            }
            else
            {
                return; // nothing happened.
            }

            // Only update the database when DELETE succeeded
            lock (SharedUpdateLock)
            {
                raid = coll.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                raid.Raid.Publications.RemoveAll(x => x.ChannelID == pe.ChannelID);
                coll.Update(raid);
            }
        }
        private void PostRaid(RaidTarget target, DbSet <RaidParticipation> coll, RaidParticipation raid)
        {
            _log.Info($"Posting raid {raid.PublicID} / {raid.Raid.Raid} / {raid.Raid.Gym} in channel {target.Description}");

            lock (UpdatePublishedRaidsInChannels.SharedUpdateLock)
            {
                // Mark the raid as updated with posting in progress, by setting the telegram message ID to -1
                raid = coll.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                raid.Raid.TelegramMessageID = -1; // hardcoded to indicate the message was not sent
                coll.Update(raid);
            }

            try
            {
                var  message   = RaidEventHandler.ShareRaidToChat(raid, target.ChannelID);
                long messageID = message?.MessageID ?? default(long);

                lock (UpdatePublishedRaidsInChannels.SharedUpdateLock)
                {
                    // The record may have changed by now, so load it again, then update tge nessage ID
                    raid = coll.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                    raid.Raid.TelegramMessageID = messageID;
                    coll.Update(raid);
                }
            }
            catch (Exception ex)
            {
                _log.Error(ex, "Failed to post new raid message, marking as 'new'.");
                lock (UpdatePublishedRaidsInChannels.SharedUpdateLock)
                {
                    // error publishing, assume it wasn't published and try again
                    raid = coll.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                    raid.Raid.TelegramMessageID = 0;
                    coll.Update(raid);
                }
            }
        }
Ejemplo n.º 13
0
        private string CreateRaidText(RaidParticipation raid)
        {
            StringBuilder participationSB = new StringBuilder();

            CalculateParticipationBlock(raid, participationSB, out string tps);

            StringBuilder sb = new StringBuilder();

            // sb.AppendLine($"<b>" + _HTML_(I18N.GetString("Subscribed")) + $":</b> {tps}");
            if (!string.IsNullOrWhiteSpace(raid.Raid.Gym))
            {
                string timestr = String.Empty;

                if (raid.Raid.RaidUnlockTime != default && raid.Raid.RaidUnlockTime >= DateTime.UtcNow)
                {
                    timestr += TimeService.AsShortTime(raid.Raid.RaidUnlockTime);
                }
                else if (raid.Raid.RaidUnlockTime != default && raid.Raid.RaidUnlockTime < DateTime.UtcNow)
                {
                    timestr += I18N.GetString("now");
                }
                if (raid.Raid.RaidEndTime != default && raid.Raid.RaidEndTime >= DateTime.UtcNow)
                {
                    timestr += (timestr.Length > 0 ? "-" : String.Empty) + TimeService.AsShortTime(raid.Raid.RaidEndTime);
                }

                string url = $"{Settings.BotAddress}raids/{raid.PublicID}";

                sb.AppendLine($"<b>{MessageUtils.HtmlEscape(raid.Raid.Gym)} ({raid.NumberOfParticipants()} - {timestr})</b>");
                sb.AppendLine($"<a href=\"{url}\">Online inschrijven (nieuw)</a>");
            }
            if (!string.IsNullOrWhiteSpace(raid.Raid.Remarks))
            {
                sb.AppendLine($"{MessageUtils.HtmlEscape(raid.Raid.Remarks)}");
            }
            if (!string.IsNullOrWhiteSpace(raid.Raid.Raid))
            {
                sb.AppendLine($"<b>" + _HTML_(I18N.GetString("Raid")) + $":</b> {MessageUtils.HtmlEscape(raid.Raid.Raid)}");
            }
            if (raid.Raid.Alignment != Team.Unknown)
            {
                sb.AppendLine($"<b>" + _HTML_(I18N.GetString("Alignment")) + $":</b> {MessageUtils.HtmlEscape(raid.Raid.Alignment.AsReadableString())}");
            }
            if (!string.IsNullOrWhiteSpace(raid.Raid.Address))
            {
                sb.AppendLine($"<b>" + _HTML_(I18N.GetString("Address")) + $":</b> {MessageUtils.HtmlEscape(raid.Raid.Address)}");
            }

            if (null != raid.Raid.Location)
            {
                string lat          = raid.Raid.Location.Latitude.ToString(CultureInfo.InvariantCulture);
                string lon          = raid.Raid.Location.Longitude.ToString(CultureInfo.InvariantCulture);
                string externalurls = String.Empty;
                if (raid.Raid.Sources != null)
                {
                    foreach (var source in raid.Raid.Sources.Where(x => !string.IsNullOrEmpty(x.URL)).ToArray())
                    {
                        externalurls += $"<a href=\"{source.URL}\">" + _HTML_(source.SourceID) + $"</a>, ";
                    }
                }
                sb.AppendLine($"<b>" + _HTML_(I18N.GetString("Links")) + $":</b> ({externalurls}<a href=\"https://www.google.com/maps/?daddr={lat},{lon}\">" + _HTML_(I18N.GetString("route")) + $"</a>, <a href=\"https://ingress.com/intel?ll={lat},{lon}&z=17\">" + _HTML_(I18N.GetString("portal map")) + $"</a>)");
            }

            sb.Append(participationSB);

            var naySayers = raid.Rejected.Select(x => x).OrderBy(x => x.ShortName());

            if (naySayers.Any())
            {
                sb.AppendLine(String.Empty);
                var str = string.Join(", ", naySayers.Select(x => $"{x.ShortName()}"));
                sb.AppendLine($"<b>" + _HTML_(I18N.GetString("Declined")) + $":</b> {str}");
            }

            var userSettingsCollection = DB.GetCollection <UserSettings>();
            var undecided = raid.Maybe.Select(x => x).OrderBy(x => x.ShortName());

            if (undecided.Any())
            {
                sb.AppendLine(String.Empty);
                var str = string.Join(", ", undecided.Select(x =>
                {
                    string name    = x.ShortName().TrimStart('@');
                    var userRecord = userSettingsCollection.Find(y => y.User.ID == x.ID).FirstOrDefault();
                    if (!string.IsNullOrWhiteSpace(userRecord?.Alias))
                    {
                        name = userRecord.Alias;
                    }
                    if (userRecord?.Level > 0)
                    {
                        name += $" (" + _HTML_(I18N.GetString("level")) + $" {userRecord?.Level})";
                    }
                    return(name);
                }));
                sb.AppendLine($"<b>" + _HTML_(I18N.GetString("Maybe")) + $":</b> {str}");
            }

            var alreadyDone = raid.Done.Select(x => x).OrderBy(x => x.ShortName());

            if (alreadyDone.Any())
            {
                sb.AppendLine(String.Empty);
                var str = string.Join(", ", alreadyDone.Select(x => $"{x.ShortName()}"));
                sb.AppendLine($"<b>" + _HTML_(I18N.GetString("Done")) + $":</b> {str}");
            }

            sb.AppendLine($"\n#raid updated: <i>{TimeService.AsFullTime(DateTime.UtcNow)}</i>");
            return(sb.ToString());
        }
        private void CreateRaidsFromScanResult(PogoAfoMapping map, PogoAfoResult pogoAfoResult, long channel)
        {
            var raidParticipationCollection = DB.GetCollection <RaidParticipation>();
            var raidsList = raidParticipationCollection.Find(x => x.Raid.RaidEndTime >= DateTime.UtcNow).ToArray();

            foreach (var entry in pogoAfoResult.raids ?? new Dictionary <string, PogoAfoRaidInfo>())
            {
                _log.Trace($"{SourceID} - Incoming raid {entry.Key} @{entry.Value.raid_battle} / pokémon: {entry.Value.raid_pokemon_id} / gym: {entry.Value.name} / url: {entry.Value.url}");

                DateTimeOffset raidStartTime = entry.Value.raid_battle.HasValue ? DateTimeOffset.FromUnixTimeSeconds(entry.Value.raid_battle ?? 0) : DateTimeOffset.MinValue;
                DateTimeOffset raidEndTime   = entry.Value.raid_end.HasValue ? DateTimeOffset.FromUnixTimeSeconds(entry.Value.raid_end ?? 0) : DateTimeOffset.MinValue;

                // Look for this exact raid
                var raidStruct = raidsList.Where(x => (x.Raid.Sources != null) && (x.Raid.Sources.Where(s => s.SourceID == SourceID && s.ExternalID == entry.Key).Any())).FirstOrDefault();
                if (null != raidStruct)
                {
                    _log.Trace($"Found existing raid with same external ID: pokémon: {entry.Value.raid_pokemon_id} / gym: {entry.Value.name} / url: {entry.Value.url} === id: {raidStruct.PublicID} / {raidStruct.Raid.Raid} / {raidStruct.Raid.Gym}");
                }

                // search for a PUBLISHED raid that's similar in location and time
                if (null == raidStruct)
                {
                    raidStruct = raidsList.Where(rp =>
                    {
                        if (rp.Raid != null && rp.Raid.Location != null && raidEndTime != null && rp.Raid.RaidEndTime != null)
                        {
                            var loc1     = new GeoCoordinate(rp.Raid.Location.Latitude, rp.Raid.Location.Longitude);
                            var loc2     = new GeoCoordinate(entry.Value.latitude ?? 0, entry.Value.longitude ?? 0);
                            var distance = loc1.GetDistanceTo(loc2);
                            return((distance <= 50) && (Math.Abs((raidEndTime.UtcDateTime - rp.Raid.RaidEndTime).TotalSeconds) <= 300) && rp.IsPublished);
                        }
                        else
                        {
                            return(false);
                        }
                    }).FirstOrDefault();

                    if (null != raidStruct)
                    {
                        _log.Trace($"Merging raid pokémon: {entry.Value.raid_pokemon_id} / gym: {entry.Value.name} / url: {entry.Value.url} with existing raid id: {raidStruct.PublicID} / {raidStruct.Raid.Raid} / {raidStruct.Raid.Gym}");
                    }
                }

                string currentValues;
                // Create a new raid
                if (null == raidStruct)
                {
                    _log.Trace($"{SourceID} - Adding new raid {entry.Key} @{entry.Value.raid_battle} / pokémon: {entry.Value.raid_pokemon_id} / gym: {entry.Value.name} / url: {entry.Value.url}");
                    raidStruct = new RaidParticipation
                    {
                        Raid = new RaidDescription
                        {
                            Alignment = Team.Unknown,
                            Sources   = new List <ExternalSource>()
                            {
                                new ExternalSource
                                {
                                    ExternalID = entry.Key,
                                    SourceID   = SourceID,
                                    URL        = entry.Value.url
                                }
                            },
                            User = new Botje.Messaging.Models.User {
                                IsBot = true, ID = -1, FirstName = SourceID, LastName = SourceID, Username = SourceID
                            },
                            UpdateCount = 1,
                        }
                    };
                    raidParticipationCollection.Insert(raidStruct);
                    currentValues = "";
                }
                else
                {
                    currentValues = raidStruct.AllValuesAsString();
                }

                // update raidStruct
                if (entry.Value.raid_pokemon_id != null)
                {
                    var pokedexEntry = Pokedex.All.Where(x => x.id == entry.Value.raid_pokemon_id).FirstOrDefault();
                    if (null == pokedexEntry)
                    {
                        raidStruct.Raid.Raid = $"Pokémon {entry.Value.raid_pokemon_id} (level {entry.Value.raid_level})";
                    }
                    else
                    {
                        raidStruct.Raid.Raid = $"{pokedexEntry.name} (level {entry.Value.raid_level})";
                    }
                }
                else
                {
                    raidStruct.Raid.Raid = $"Level {entry.Value.raid_level} raid";
                }

                if (raidStruct.Raid.RaidUnlockTime != raidStartTime.UtcDateTime)
                {
                    raidStruct.Raid.RaidUnlockTime = raidStartTime.UtcDateTime;
                }
                if (raidStruct.Raid.RaidEndTime != raidEndTime.UtcDateTime)
                {
                    raidStruct.Raid.RaidEndTime = raidEndTime.UtcDateTime;
                }
                if (raidStruct.Raid.Gym != entry.Value.name)
                {
                    raidStruct.Raid.Gym = entry.Value.name;
                }
                if (entry.Value.ex_trigger && string.IsNullOrEmpty(raidStruct.Raid.Remarks))
                {
                    raidStruct.Raid.Remarks = $"EX Raid Trigger";
                }

                if (entry.Value.longitude.HasValue && entry.Value.latitude.HasValue && (null == raidStruct.Raid.Location || raidStruct.Raid.Location.Latitude != entry.Value.latitude.Value || raidStruct.Raid.Location.Longitude != entry.Value.longitude.Value))
                {
                    raidStruct.Raid.Location = new Location
                    {
                        Latitude  = entry.Value.latitude.Value,
                        Longitude = entry.Value.longitude.Value
                    };
                }

                var newValues = raidStruct.AllValuesAsString();
                if (newValues != currentValues)
                {
                    // TODO: REWRITE THIS TO MARK THE MESSAGE FOR PUBLICATION AND THE PUBLISH IT IN A SEPARATE LOOP
                    PublishRaidToPrimaryChannelIfNeeded(channel, entry, raidStruct);

                    if (null == raidStruct.Raid.Publications)
                    {
                        raidStruct.Raid.Publications = new List <PublicationEntry>();
                    }
                    if (null != map.Targets && map.Targets.Count > 0)
                    {
                        CreatePublicationEntriesForAlternativeTargets(map.Targets, entry, raidStruct);
                    }

                    raidStruct.LastModificationTime = DateTime.UtcNow;
                    raidParticipationCollection.Update(raidStruct);
                }
                else
                {
                    _log.Trace($"Nothing changed for raid {raidStruct.PublicID}, not updating anything.");
                }

                if (string.IsNullOrEmpty(raidStruct.Raid.Address))
                {
                    UpdateAddress(raidParticipationCollection, raidStruct, raidStruct.Raid.Location);
                }
            }
        }
        private void CreatePublicationEntriesForAlternativeTargets(List <RaidTarget> targets, KeyValuePair <string, PogoAfoRaidInfo> entry, RaidParticipation raidStruct)
        {
            // Just create a publication entry for these alternative targets. A separate process will take care of the actual
            // publication for those.
            foreach (var target in targets)
            {
                // It either is in the list of levels (always if not defined) OR it's an ex trigger gym and it's in the list of ex levels
                bool addToThisChannel = (target.Levels == null || target.Levels.Any(x => x == entry.Value.raid_level)) ||
                                        (target.ExRaidLevels != null && entry.Value.ex_trigger && target.ExRaidLevels.Any(x => x == entry.Value.raid_level));

                // If it's outside the specified rectangle on the map, it's going to be ignored
                if (target.NorthEastCorner != null && target.SouthWestCorner != null && entry.Value.latitude.HasValue && entry.Value.longitude.HasValue)
                {
                    if (!(Between(entry.Value.latitude.Value, target.NorthEastCorner.Latitude, target.SouthWestCorner.Latitude) && Between(entry.Value.longitude.Value, target.NorthEastCorner.Longitude, target.SouthWestCorner.Longitude)))
                    {
                        addToThisChannel = false;
                    }
                }

                if (addToThisChannel)
                {
                    _log.Trace($"{SourceID} - For target {target.Description}: adding publication for {entry.Key} @{entry.Value.raid_battle} (level {entry.Value.raid_level}).");

                    var existingEntry = raidStruct.Raid.Publications.Where(x => x.ChannelID == target.ChannelID).FirstOrDefault();
                    if (null == existingEntry)
                    {
                        var publicationEntry = new PublicationEntry
                        {
                            ChannelID = target.ChannelID,
                            LastModificationTimeUTC = DateTime.MinValue,
                            TelegramMessageID       = 0
                        };
                        raidStruct.Raid.Publications.Add(publicationEntry);
                    }
                    else
                    {
                        // request update
                        existingEntry.LastModificationTimeUTC = DateTime.MinValue;
                    }
                }
            }
        }
Ejemplo n.º 16
0
        private void CalculateParticipationBlock(RaidParticipation raid, StringBuilder sb, out string tps)
        {
            var           userSettingsCollection = DB.GetCollection <UserSettings>();
            List <string> tpsElements            = new List <string>();

            tps = String.Empty;
            int counter = 0;

            foreach (Team team in raid.Participants.Keys.OrderBy(x => x))
            {
                var participants = raid.Participants[team];
                if (participants.Count > 0)
                {
                    sb.AppendLine();
                    sb.AppendLine($"<b>{team.AsReadableString()} ({participants.Select(x => 1 + x.Extra).Sum()}):</b>");

                    foreach (UserParticipation userParticipation in participants.OrderBy(p => p.User.ShortName()))
                    {
                        string       name       = userParticipation.User.ShortName().TrimStart('@');
                        UserSettings userRecord = userSettingsCollection.Find(x => x.User.ID == userParticipation.User.ID).FirstOrDefault();

                        if (!String.IsNullOrWhiteSpace(userRecord?.Alias))
                        {
                            name = userRecord.Alias;
                        }

                        if (userRecord?.Level > 0)
                        {
                            name += $" (" + this._HTML_(I18N.GetString("level")) + $" {userRecord?.Level})";
                        }

                        sb.Append($" - {MessageUtils.HtmlEscape(name)}");

                        if (userParticipation.Extra > 0)
                        {
                            counter += userParticipation.Extra;
                            sb.Append($" +{userParticipation.Extra}");
                        }

                        if (userParticipation.UtcArrived != default)
                        {
                            // Text and plural text are the same in this case.
                            string arrivedAtString = this._HTML_(I18N.GetPluralString("there for {0}", "there for {0}", userParticipation.Extra + 1,
                                                                                      TimeService.AsReadableTimespan(DateTime.UtcNow - userParticipation.UtcArrived)));

                            sb.Append($" [{arrivedAtString}]");
                        }
                        else if (userParticipation.UtcWhen != default)
                        {
                            sb.Append($" [{TimeService.AsShortTime(userParticipation.UtcWhen)}]");
                        }

                        if (userParticipation.Type != default)
                        {
                            sb.Append($" {this.GetParticipationTypeTitle(userParticipation.Type)}");
                        }

                        sb.AppendLine();
                    }
                }
                tpsElements.Add($"{participants.Sum(x => 1 + x.Extra)}{team.AsIcon()}");
                counter += participants.Count;
            }

            var tpsSub = string.Join(" ", tpsElements);

            tps = $"{counter} ({tpsSub})";
        }
Ejemplo n.º 17
0
        private void CreateRaidsFromScanResult(PogoAfoMapping map, PogoAfoResult pogoAfoResult, long channel)
        {
            var raidParticipationCollection = DB.GetCollection <RaidParticipation>();
            var raidsList = raidParticipationCollection.FindAll().ToArray();

            foreach (var entry in pogoAfoResult.raids ?? new Dictionary <string, PogoAfoRaidInfo>())
            {
                // TODO: Should be part of the query already, why ask for items then discard them?
                if (entry.Value.raid_level < 4 && !entry.Value.ex_trigger)
                {
                    _log.Trace($"{SourceID} - Ignoring raid {entry.Key} @{entry.Value.raid_battle} level: {entry.Value.raid_level} / trigger: {entry.Value.ex_trigger} / pokémon: {entry.Value.raid_pokemon_id} / gym: {entry.Value.name} / url: {entry.Value.url}");
                    continue;
                }

                if (map.NorthEastCorner != null && map.SouthWestCorner != null && entry.Value.latitude.HasValue && entry.Value.longitude.HasValue)
                {
                    if (!(Between(entry.Value.latitude.Value, map.NorthEastCorner.Latitude, map.SouthWestCorner.Latitude) && Between(entry.Value.longitude.Value, map.NorthEastCorner.Longitude, map.SouthWestCorner.Longitude)))
                    {
                        _log.Trace($"{SourceID} - Ignoring raid {entry.Key} @{entry.Value.raid_battle} based on location, it's outside my area of interest.");
                        continue;
                    }
                }

                _log.Trace($"{SourceID} - Incoming raid {entry.Key} @{entry.Value.raid_battle} / pokémon: {entry.Value.raid_pokemon_id} / gym: {entry.Value.name} / url: {entry.Value.url}");

                DateTimeOffset raidStartTime = entry.Value.raid_battle.HasValue ? DateTimeOffset.FromUnixTimeSeconds(entry.Value.raid_battle ?? 0) : DateTimeOffset.MinValue;
                DateTimeOffset raidEndTime   = entry.Value.raid_end.HasValue ? DateTimeOffset.FromUnixTimeSeconds(entry.Value.raid_end ?? 0) : DateTimeOffset.MinValue;

                // Look for this exact raid
                var raidStruct = raidsList.Where(x => (x.Raid.Sources != null) && (x.Raid.Sources.Where(s => s.SourceID == SourceID && s.ExternalID == entry.Key).Any())).FirstOrDefault();
                if (null != raidStruct)
                {
                    _log.Trace($"Found existing raid with same external ID: pokémon: {entry.Value.raid_pokemon_id} / gym: {entry.Value.name} / url: {entry.Value.url} === id: {raidStruct.PublicID} / {raidStruct.Raid.Raid} / {raidStruct.Raid.Gym}");
                }

                // search for a PUBLISHED raid that's similar in location and time
                if (null == raidStruct)
                {
                    raidStruct = raidsList.Where(rp =>
                    {
                        if (rp.Raid != null && rp.Raid.Location != null && raidEndTime != null && rp.Raid.RaidEndTime != null)
                        {
                            var loc1     = new GeoCoordinate(rp.Raid.Location.Latitude, rp.Raid.Location.Longitude);
                            var loc2     = new GeoCoordinate(entry.Value.latitude ?? 0, entry.Value.longitude ?? 0);
                            var distance = loc1.GetDistanceTo(loc2);
                            return((distance <= 50) && (Math.Abs((raidEndTime.UtcDateTime - rp.Raid.RaidEndTime).TotalSeconds) <= 300) && rp.IsPublished);
                        }
                        else
                        {
                            return(false);
                        }
                    }).FirstOrDefault();

                    if (null != raidStruct)
                    {
                        _log.Trace($"Merging raid pokémon: {entry.Value.raid_pokemon_id} / gym: {entry.Value.name} / url: {entry.Value.url} with existing raid id: {raidStruct.PublicID} / {raidStruct.Raid.Raid} / {raidStruct.Raid.Gym}");
                    }
                }

                string currentValues;
                // Create a new raid
                if (null == raidStruct)
                {
                    _log.Trace($"{SourceID} - Adding new raid {entry.Key} @{entry.Value.raid_battle} / pokémon: {entry.Value.raid_pokemon_id} / gym: {entry.Value.name} / url: {entry.Value.url}");
                    raidStruct = new RaidParticipation
                    {
                        Raid = new RaidDescription
                        {
                            Alignment = Team.Unknown,
                            Sources   = new List <ExternalSource>()
                            {
                                new ExternalSource
                                {
                                    ExternalID = entry.Key,
                                    SourceID   = SourceID,
                                    URL        = entry.Value.url
                                }
                            },
                            User = new Botje.Messaging.Models.User {
                                IsBot = true, ID = -1, FirstName = SourceID, LastName = SourceID, Username = SourceID
                            },
                            UpdateCount = 1,
                        }
                    };
                    raidParticipationCollection.Insert(raidStruct);
                    currentValues = "";
                }
                else
                {
                    currentValues = raidStruct.AllValuesAsString();
                }

                // update raidStruct
                if (entry.Value.raid_pokemon_id != null)
                {
                    var pokedexEntry = Pokedex.All.Where(x => x.id == entry.Value.raid_pokemon_id).FirstOrDefault();
                    if (null == pokedexEntry)
                    {
                        raidStruct.Raid.Raid = $"Pokémon {entry.Value.raid_pokemon_id} (level {entry.Value.raid_level})";
                    }
                    else
                    {
                        raidStruct.Raid.Raid = $"{pokedexEntry.name} (level {entry.Value.raid_level})";
                    }
                }
                else
                {
                    raidStruct.Raid.Raid = $"Level {entry.Value.raid_level} raid";
                }

                if (raidStruct.Raid.RaidUnlockTime != raidStartTime.UtcDateTime)
                {
                    raidStruct.Raid.RaidUnlockTime = raidStartTime.UtcDateTime;
                }
                if (raidStruct.Raid.RaidEndTime != raidEndTime.UtcDateTime)
                {
                    raidStruct.Raid.RaidEndTime = raidEndTime.UtcDateTime;
                }
                if (raidStruct.Raid.Gym != entry.Value.name)
                {
                    raidStruct.Raid.Gym = entry.Value.name;
                }
                if (entry.Value.ex_trigger && string.IsNullOrEmpty(raidStruct.Raid.Remarks))
                {
                    raidStruct.Raid.Remarks = $"EX Raid Trigger";
                }

                if (raidStruct.Raid.Publications == null)
                {
                    raidStruct.Raid.Publications = new List <PublicationEntry>();
                }


                if (entry.Value.longitude.HasValue && entry.Value.latitude.HasValue && (null == raidStruct.Raid.Location || raidStruct.Raid.Location.Latitude != entry.Value.latitude.Value || raidStruct.Raid.Location.Longitude != entry.Value.longitude.Value))
                {
                    raidStruct.Raid.Location = new Location
                    {
                        Latitude  = entry.Value.latitude.Value,
                        Longitude = entry.Value.longitude.Value
                    };
                }

                if (string.IsNullOrEmpty(raidStruct.Raid.Address))
                {
                    UpdateAddress(raidParticipationCollection, raidStruct, raidStruct.Raid.Location);
                }

                var newValues = raidStruct.AllValuesAsString();
                if (newValues != currentValues)
                {
                    if (!raidStruct.Raid.Publications.Where(x => x.ChannelID == channel).Any())
                    {
                        _log.Trace($"{SourceID} - Publishing {entry.Key} @{entry.Value.raid_battle} / pokémon: {entry.Value.raid_pokemon_id} / gym: {entry.Value.name} / url: {entry.Value.url}");
                        var message = RaidEventHandler.ShareRaidToChat(raidStruct, channel);
                        if (channel == Settings.PublicationChannel)
                        {
                            raidStruct.Raid.TelegramMessageID = message?.MessageID;
                            raidStruct.IsPublished            = true;
                        }
                        raidStruct.Raid.Publications.Add(new PublicationEntry
                        {
                            ChannelID         = channel,
                            TelegramMessageID = message?.MessageID ?? long.MaxValue
                        });
                    }

                    raidStruct.LastModificationTime = DateTime.UtcNow;
                    raidParticipationCollection.Update(raidStruct);
                }
                else
                {
                    _log.Trace($"Nothing changed for raid {raidStruct.PublicID}, not updating anything.");
                }
            }
        }
        private void PublishRaidToPrimaryChannelIfNeeded(long channel, KeyValuePair <string, PogoAfoRaidInfo> entry, RaidParticipation raidStruct)
        {
            if (!raidStruct.IsPublished && entry.Value.raid_level >= 5)
            {
                _log.Trace($"{SourceID} - Marking for publication: {entry.Key} @{entry.Value.raid_battle} / pokémon: {entry.Value.raid_pokemon_id} / gym: {entry.Value.name} / url: {entry.Value.url}");

                raidStruct.IsPublished = true;
            }
        }
Ejemplo n.º 19
0
        private InlineKeyboardMarkup CreateMarkupFor(RaidParticipation raid)
        {
            if (raid.Raid.RaidEndTime <= DateTime.UtcNow)
            {
                return(null); // no buttons
            }
            else
            {
                InlineKeyboardMarkup result = new InlineKeyboardMarkup {
                    inline_keyboard = new List <List <InlineKeyboardButton> >()
                };
                string shareString = $"{IqPrefix}{raid.PublicID}";

                List <InlineKeyboardButton> row;

                row = new List <InlineKeyboardButton>
                {
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("Yes")), callback_data = $"{QrJoin}:{raid.PublicID}:0::0"
                    },
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("❤️")), callback_data = $"{QrJoin}:{raid.PublicID}::{(int)Team.Valor}"
                    },
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("💙")), callback_data = $"{QrJoin}:{raid.PublicID}::{(int)Team.Mystic}"
                    },
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("💛")), callback_data = $"{QrJoin}:{raid.PublicID}::{(int)Team.Instinct}"
                    },
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("👻")), callback_data = $"{QrJoin}:{raid.PublicID}:0::{(int)UserParticipationType.Remote}"
                    }
                };

                result.inline_keyboard.Add(row);

                row = new List <InlineKeyboardButton>
                {
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("I +1")), callback_data = $"{QrJoin}:{raid.PublicID}:1"
                    },
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("I +2")), callback_data = $"{QrJoin}:{raid.PublicID}:2"
                    },
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("I +3")), callback_data = $"{QrJoin}:{raid.PublicID}:3"
                    },
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("I +4")), callback_data = $"{QrJoin}:{raid.PublicID}:4"
                    },
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("I +5")), callback_data = $"{QrJoin}:{raid.PublicID}:5"
                    }
                };

                result.inline_keyboard.Add(row);

                row = new List <InlineKeyboardButton>
                {
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("🔄")), callback_data = $"{QrRefresh}:{raid.PublicID}"
                    },
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("✏️")), callback_data = $"{QrEdit}:{raid.PublicID}"
                    },
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("🤷🏼")), callback_data = $"{QrMaybe}:{raid.PublicID}"
                    },
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("Done")), callback_data = $"{QrDone}:{raid.PublicID}"
                    },
                    new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("Cancel")), callback_data = $"{QrDecline}:{raid.PublicID}"
                    }
                };
                // row.Add(new InlineKeyboardButton { text = _HTML_(I18N.GetString("Share")), switch_inline_query = $"{shareString}" });

                result.inline_keyboard.Add(row);

                if (!raid.IsPublished)
                {
                    row = new List <InlineKeyboardButton>
                    {
                        new InlineKeyboardButton {
                            text = _HTML_(I18N.GetString("📣 Publish")), callback_data = $"{QrPublish}:{raid.PublicID}"
                        }
                    };
                    result.inline_keyboard.Add(row);
                }

                row = new List <InlineKeyboardButton>();
                var dtStart = DateTime.UtcNow;
                if (raid.Raid.RaidUnlockTime > dtStart)
                {
                    dtStart = raid.Raid.RaidUnlockTime;
                }
                if (dtStart.Minute % 5 != 0)
                {
                    dtStart += TimeSpan.FromMinutes(5 - (dtStart.Minute % 5));
                }

                while (dtStart <= raid.Raid.RaidEndTime)
                {
                    row.Add(new InlineKeyboardButton {
                        text = $"{TimeService.AsShortTime(dtStart)}", callback_data = $"{QrSetTime}:{raid.PublicID}:{dtStart.Ticks}"
                    });;
                    dtStart += TimeSpan.FromMinutes(5);
                }
                row.Add(new InlineKeyboardButton {
                    text = _HTML_(I18N.GetString("Arrived")), callback_data = $"{QrArrived}:{raid.PublicID}"
                });;
                var addnRows = SplitButtonsIntoLines(row, maxElementsPerLine: 5, maxCharactersPerLine: 30);

                result.inline_keyboard.AddRange(addnRows);
                return(result);
            }
        }
Ejemplo n.º 20
0
        private void PostRaid(RaidTarget target, DbSet <RaidParticipation> coll, RaidParticipation raid)
        {
            _log.Info($"Posting raid {raid.PublicID} / {raid.Raid.Raid} / {raid.Raid.Gym} in channel {target.Description}");

            lock (SharedUpdateLock)
            {
                // Mark the raid as updated with posting in progress, by setting the telegram message ID to -1
                raid = coll.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                var pe = raid.Raid.Publications.Where(x => x.ChannelID == target.ChannelID).FirstOrDefault();
                if (null == pe)
                {
                    return;
                }
                raid.Raid.Publications.RemoveAll(x => x != pe && x.ChannelID == pe.ChannelID);
                pe.TelegramMessageID       = -1; // hardcoded to indicate the message was not sent
                pe.LastModificationTimeUTC = DateTime.UtcNow;
                coll.Update(raid);
            }

            // Next post the message, this may take some time if we managed to hit the rate limit
            string url         = $"{SettingsManager.BotAddress}raids/{raid.PublicID}?r={rnd.Next()}";
            string messageText = $"[{TimeService.AsShortTime(raid.Raid.RaidUnlockTime)}-{TimeService.AsShortTime(raid.Raid.RaidEndTime)}] {MessageUtils.HtmlEscape(raid.Raid.Raid)} @ {MessageUtils.HtmlEscape(raid.Raid.Gym)} ({raid.NumberOfParticipants()})\n<a href=\"{url}\">Klik hier om in te schrijven.</a>";

            try
            {
                var  message   = Client.SendMessageToChat(target.ChannelID, messageText, "HTML", true, true);
                long messageID = message?.MessageID ?? default(long);

                lock (SharedUpdateLock)
                {
                    // The record may have changed by now, so load it again, then update tge nessage ID
                    raid = coll.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                    var pe = raid.Raid.Publications.Where(x => x.ChannelID == target.ChannelID).FirstOrDefault();
                    if (null == pe)
                    {
                        return;
                    }
                    raid.Raid.Publications.RemoveAll(x => x != pe && x.ChannelID == pe.ChannelID);
                    pe.TelegramMessageID = messageID;
                    coll.Update(raid);
                }
            }
            catch (Exception ex)
            {
                _log.Error(ex, "Failed to post new raid message, marking as 'new'.");
                lock (SharedUpdateLock)
                {
                    // The record may have changed by now, so load it again, then update tge nessage ID
                    raid = coll.Find(x => x.UniqueID == raid.UniqueID).FirstOrDefault();
                    var pe = raid.Raid.Publications.Where(x => x.ChannelID == target.ChannelID).FirstOrDefault();
                    if (null == pe)
                    {
                        return;
                    }
                    raid.Raid.Publications.RemoveAll(x => x != pe && x.ChannelID == pe.ChannelID);
                    pe.TelegramMessageID       = 0;
                    pe.LastModificationTimeUTC = DateTime.MinValue;
                    coll.Update(raid);
                }
            }
        }