private void Client_OnInlineQuery(object sender, InlineQueryEventArgs e)
        {
            if (e.Query.Query.StartsWith(IqPrefix))
            {
                _log.Info($"Inline query from {e.Query.From.DisplayName()} ({e.Query.From.ID}) for query {e.Query.Query}");

                e.Query.Query = e.Query.Query.TrimEnd('@');
                string raidID         = e.Query.Query.Substring(IqPrefix.Length);
                var    raidCollection = DB.GetCollection <RaidParticipation>();
                var    raid           = raidCollection.Find(x => x.PublicID == raidID).FirstOrDefault();

                List <InlineQueryResultArticle> results = new List <InlineQueryResultArticle>();

                if (null != raid)
                {
                    string text   = CreateRaidText(raid);
                    var    markup = CreateMarkupFor(raid);
                    results.Add(new InlineQueryResultArticle
                    {
                        id                    = raid.PublicID,
                        title                 = $"{raid.Raid.Raid} {TimeService.AsShortTime(raid.Raid.RaidUnlockTime)}-{TimeService.AsShortTime(raid.Raid.RaidEndTime)}",
                        description           = _HTML_(I18N.GetString("{0} raid at {1} {2}", raid.Raid.Raid, raid.Raid.Gym, raid.Raid.Address)),
                        input_message_content = new InputMessageContent
                        {
                            message_text             = text,
                            parse_mode               = "HTML",
                            disable_web_page_preview = true,
                        },
                        reply_markup = markup,
                    });
                }

                Client.AnswerInlineQuery(e.Query.ID, results);
            }
        }
        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);
            }
        }
        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 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})";
        }
        private void Client_OnQueryCallback(object sender, QueryCallbackEventArgs e)
        {
            string command = e.CallbackQuery.Data.Split(':').FirstOrDefault();

            string[] args = e.CallbackQuery.Data.Split(':').Skip(1).ToArray();
            switch (command)
            {
            case QrArrived:     // :raid
                _log.Trace($"{e.CallbackQuery.From.DisplayName()} has arrived for raid {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Excellent! You arrived.")));
                UpdateUserRaidJoinOrUpdateAttendance(e.CallbackQuery.From, args[0]);
                UpdateUserRaidArrived(e.CallbackQuery.From, args[0]);
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;

            case QrDecline:     // :raid
                _log.Trace($"{e.CallbackQuery.From.DisplayName()} has declined for raid {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("That's too bad 😞")));
                UpdateUserRaidNegative(e.CallbackQuery.From, args[0]);
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;

            case QrJoin:
                this.HandleJoin(args, e);

                break;

            case QrPublish:     // :raid
                _log.Info($"{e.CallbackQuery.From.DisplayName()} published raid {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Publishing the raid.")));
                PublishRaid(e.CallbackQuery.From, args[0]);
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;

            case QrRefresh:     // :raid
                _log.Trace($"{e.CallbackQuery.From.DisplayName()} refreshed {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Refreshing...")));
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;

            case QrSetTime:     // :raid:ticks
                UpdateUserRaidJoinOrUpdateAttendance(e.CallbackQuery.From, args[0]);
                if (long.TryParse(args[1], out long ticks))
                {
                    var utcWhen = new DateTime(ticks, DateTimeKind.Utc);
                    _log.Trace($"{e.CallbackQuery.From.DisplayName()} updated their time for raid {args[0]} to {TimeService.AsShortTime(utcWhen)}");
                    Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("You will be there at {0}.", TimeService.AsShortTime(utcWhen))));
                    UpdateUserRaidTime(e.CallbackQuery.From, args[0], utcWhen);
                }
                else
                {
                    Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Error updating time.")));
                }
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;

            case QrEdit:     // :{raid}
                _log.Info($"{e.CallbackQuery.From.DisplayName()} wants to edit raid {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Go to our private chat to edit the raid.")));
                RaidEditor.EditRaid(e.CallbackQuery.From, args[0]);
                break;

            case QrDone:     // :raid
                _log.Trace($"{e.CallbackQuery.From.DisplayName()} has done raid {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Registered. Thanks.")));
                UpdateUserRaidDone(e.CallbackQuery.From, args[0]);
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;

            case QrMaybe:     // :raid
                _log.Trace($"{e.CallbackQuery.From.DisplayName()} has answered 'maybe' for {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Registered. Thanks.")));
                UpdateUserRaidMaybe(e.CallbackQuery.From, args[0]);
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;
            }
        }
예제 #6
0
        private void Client_OnQueryCallback(object sender, QueryCallbackEventArgs e)
        {
            string command = e.CallbackQuery.Data.Split(':').FirstOrDefault();

            string[] args = e.CallbackQuery.Data.Split(':').Skip(1).ToArray();
            switch (command)
            {
            case QrArrived:     // :raid
                _log.Trace($"{e.CallbackQuery.From.DisplayName()} has arrived for raid {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Excellent! You arrived.")));
                UpdateUserRaidJoinOrUpdateAttendance(e.CallbackQuery.From, args[0]);
                UpdateUserRaidArrived(e.CallbackQuery.From, args[0]);
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;

            case QrDecline:     // :raid
                _log.Trace($"{e.CallbackQuery.From.DisplayName()} has declined for raid {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("That's too bad 😞")));
                UpdateUserRaidNegative(e.CallbackQuery.From, args[0]);
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;

            case QrJoin:     // :raid:extra:team
                _log.Trace($"{e.CallbackQuery.From.DisplayName()} will join raid {args[0]} [{e.CallbackQuery.Data}]");
                if (args.Length >= 3 && int.TryParse(args[2], out int teamID) && teamID >= (int)Team.Unknown && teamID <= (int)Team.Instinct)
                {
                    _log.Trace($"{e.CallbackQuery.From.DisplayName()} joined team {((Team)teamID).AsReadableString()}");
                    Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Joined for team {0}", _HTML_(((Team)teamID).AsReadableString()))));
                    UpdateUserSettingsForTeam(e.CallbackQuery.From, (Team)teamID);
                }
                else
                {
                    Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("You're on the list now.")));
                }
                // Because we updated the user settings first, the user will automatically be added or moved to the
                // correct team by the join function.
                UpdateUserRaidJoinOrUpdateAttendance(e.CallbackQuery.From, args[0]);
                if (args.Length >= 2 && int.TryParse(args[1], out int extra) && extra >= 0)
                {
                    UpdateUserRaidExtra(e.CallbackQuery.From, args[0], extra);
                }
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;

            case QrPublish:     // :raid
                _log.Info($"{e.CallbackQuery.From.DisplayName()} published raid {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Publishing the raid.")));
                PublishRaid(e.CallbackQuery.From, args[0]);
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;

            case QrRefresh:     // :raid
                _log.Trace($"{e.CallbackQuery.From.DisplayName()} refreshed {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Refreshing...")));
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;

            case QrSetTime:     // :raid:ticks
                UpdateUserRaidJoinOrUpdateAttendance(e.CallbackQuery.From, args[0]);
                if (long.TryParse(args[1], out long ticks))
                {
                    var utcWhen = new DateTime(ticks);
                    _log.Trace($"{e.CallbackQuery.From.DisplayName()} updated their time for raid {args[0]} to {TimeService.AsShortTime(utcWhen)}");
                    Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("You will be there at {0}.", TimeService.AsShortTime(utcWhen))));
                    UpdateUserRaidTime(e.CallbackQuery.From, args[0], utcWhen);
                }
                else
                {
                    Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Error updating time.")));
                }
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;

            case QrEdit:     // :{raid}
                _log.Info($"{e.CallbackQuery.From.DisplayName()} wants to edit raid {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Go to our private chat to edit the raid.")));
                RaidEditor.EditRaid(e.CallbackQuery.From, args[0]);
                break;

            case QrDone:     // :raid
                _log.Trace($"{e.CallbackQuery.From.DisplayName()} has done raid {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Registered. Thanks.")));
                UpdateUserRaidDone(e.CallbackQuery.From, args[0]);
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;

            case QrMaybe:     // :raid
                _log.Trace($"{e.CallbackQuery.From.DisplayName()} has answered 'maybe' for {args[0]}");
                Client.AnswerCallbackQuery(e.CallbackQuery.ID, _HTML_(I18N.GetString("Registered. Thanks.")));
                UpdateUserRaidMaybe(e.CallbackQuery.From, args[0]);
                RequestUpdateRaidMessage(e.CallbackQuery.Message?.Chat?.ID, e.CallbackQuery.Message?.MessageID, e.CallbackQuery.InlineMessageId, args[0], e.CallbackQuery.Message?.Chat?.Type);
                break;
            }
        }
        private void ShowMenu(User user)
        {
            GetOrCreateRaidDescriptionForUser(user, out DbSet <RaidDescription> collection, out RaidDescription record);

            StringBuilder text = new StringBuilder();

            text.AppendLine($"<b>" + _HTML_(I18N.GetString("Raid")) + $"</b>: {record.Raid}");
            text.AppendLine($"<b>" + _HTML_(I18N.GetString("Gym")) + $"</b>: {record.Gym}");
            text.AppendLine($"<b>" + _HTML_(I18N.GetString("Alignment")) + $"</b>: {record.Alignment.AsReadableString()}");
            text.AppendLine($"<b>" + _HTML_(I18N.GetString("Address")) + $"</b>: {record.Address}");
            text.AppendLine($"<b>" + _HTML_(I18N.GetString("GPS Location")) + $"</b>: lat={record.Location?.Latitude} lon={record.Location?.Longitude}");
            if (record.RaidUnlockTime != default(DateTime))
            {
                text.AppendLine($"<b>" + _HTML_(I18N.GetString("Available from")) + $"</b>: {TimeService.AsShortTime(record.RaidUnlockTime)}");
            }
            if (record.RaidEndTime != default(DateTime))
            {
                text.AppendLine($"<b>" + _HTML_(I18N.GetString("Available until")) + $"</b>: {TimeService.AsShortTime(record.RaidEndTime)}");
            }

            if (null == record.Location)
            {
                text.AppendLine($"\n");
                text.AppendLine(_HTML_(I18N.GetString("Please specify the gym's location. You can send a location from the telegram mobile client by pressing the paperclip button and selecting Location. Then drag the map so the position marker is at the location of the gym. The address information will automatically be added by the bot.")));
            }

            Client.SendMessageToChat(user.ID, text.ToString(), "HTML", true, true, null, CreateWizardMarkup(user, record));
        }
예제 #8
0
        private void Run()
        {
            var channelID = Settings.PublicationChannel.Value;

            _log.Info($"Starting worker thread for {nameof(SummarizeActiveRaids)}");
            while (!_cts.IsCancellationRequested)
            {
                _log.Info("Run");
                try
                {
                    if (DateTime.UtcNow.Hour >= 21 || DateTime.UtcNow.Hour < 4)
                    {
                        _log.Trace($"Skipping summary update cycle because the server rests.");
                        continue;
                    }

                    var publishedRaids = DB.GetCollection <RaidParticipation>().Find(x => x.Raid != null && x.Raid.RaidEndTime >= DateTime.UtcNow && x.Raid.RaidUnlockTime <= (DateTime.UtcNow + TimeSpan.FromHours(1)) && x.IsPublished).ToArray();

                    List <long> channels = new List <long> {
                        Settings.PublicationChannel ?? 0
                    };
                    // (only main channel) channels.AddRange(publishedRaids.SelectMany(r => r.Raid?.Publications?.Select(x => x.ChannelID) ?? new long[] { }));

                    // Restricted to only the main channel. All other channels are managed separately by different code.
                    foreach (var channel in channels.Distinct().ToArray())
                    {
                        StringBuilder message         = new StringBuilder();
                        var           raidsForChannel = publishedRaids.Where(x => (channel == Settings.PublicationChannel) && x.IsPublished).ToArray();
                        foreach (var raid in raidsForChannel.OrderBy(x => x.Raid.RaidEndTime))
                        {
                            string url = $"{Settings.BotAddress}raids/{raid.PublicID}";

                            message.AppendLine($"{TimeService.AsShortTime(raid.Raid.RaidUnlockTime)}: {_HTML_(raid.Raid.Raid)} @ {_HTML_(raid.Raid.Gym)} ({raid.NumberOfParticipants()})\r\n<a href=\"{url}\">Online inschrijven (nieuw)</a>");
                        }

                        var updateRecord = DB.GetCollection <ChannelUpdateMessage>().Find(x => x.ChannelID == channel).FirstOrDefault();
                        if (null == updateRecord)
                        {
                            updateRecord = new ChannelUpdateMessage
                            {
                                ChannelID = channel,
                                MessageID = long.MaxValue,
                                Hash      = string.Empty
                            };
                            DB.GetCollection <ChannelUpdateMessage>().Insert(updateRecord);
                        }

                        var hash = HashUtils.CalculateSHA1Hash(message.ToString());
                        if (!string.Equals(hash, updateRecord.Hash) /*|| (DateTime.UtcNow - updateRecord.LastModificationDate > TimeSpan.FromSeconds(60))*/)
                        {
                            if (NewRaidPosted || updateRecord.MessageID == long.MaxValue)
                            {
                                NewRaidPosted = false;

                                // A new message was posted or the summary was never posted yet, delete the current message and posty a new summary
                                if (updateRecord.MessageID != long.MaxValue)
                                {
                                    try
                                    {
                                        Client.DeleteMessage(channel, updateRecord.MessageID);
                                        updateRecord.MessageID = long.MaxValue;
                                        updateRecord.Hash      = hash;
                                    }
                                    catch (Exception ex)
                                    {
                                        _log.Warn(ex, $"Could not delete summary-message {updateRecord.MessageID} from channel {channel}");
                                    }
                                }

                                try
                                {
                                    var postedMessage = Client.SendMessageToChat(channel, message.ToString(), "HTML", true, true, null, null);
                                    if (null != postedMessage)
                                    {
                                        updateRecord.MessageID = postedMessage.MessageID;
                                    }
                                    else
                                    {
                                        _log.Warn($"Could not post summary-message to channel {channel} - null reply");
                                    }
                                }
                                catch (Exception ex)
                                {
                                    _log.Warn(ex, $"Could not post summary-message to channel {channel}");
                                }
                            }
                            else if (updateRecord.MessageID != long.MaxValue)
                            {
                                // There is no new raid posted, so update the current one
                                Client.EditMessageText($"{channel}", updateRecord.MessageID, null, message.ToString(), "HTML", true, null, "channel");
                                updateRecord.Hash = hash;
                            }
                        }

                        updateRecord.LastModificationDate = DateTime.UtcNow;
                        DB.GetCollection <ChannelUpdateMessage>().Update(updateRecord);
                    }
                }
                catch (ThreadAbortException)
                {
                    _log.Info($"Abort requested for thread.");
                    break;
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Error in SummarizeActiveRaids thread. Ignoring.");
                }
                finally
                {
                    Thread.Sleep(Interval);
                }
            }
            _log.Info($"Stopped worker thread for {nameof(SummarizeActiveRaids)}");
        }
예제 #9
0
        internal void EditRaid(User user, string raidPublicID)
        {
            ConversationManager.SetState(user, null);

            DoForPublicRaid(raidPublicID, (raidCollection, raid) =>
            {
                var record = raid.Raid;

                StringBuilder text = new StringBuilder();
                text.AppendLine($"<b>" + _HTML_(I18N.GetString("Raid")) + $"</b>: {record.Raid}");
                text.AppendLine($"<b>" + _HTML_(I18N.GetString("Gym")) + $"</b>: {record.Gym}");
                text.AppendLine($"<b>" + _HTML_(I18N.GetString("Alignment")) + $"</b>: {record.Alignment.AsReadableString()}");
                text.AppendLine($"<b>" + _HTML_(I18N.GetString("Address")) + $"</b>: {record.Address}");
                text.AppendLine($"<b>" + _HTML_(I18N.GetString("GPS Location")) + $"</b>: lat={record.Location?.Latitude} lon={record.Location?.Longitude}");
                if (record.RaidUnlockTime != default(DateTime))
                {
                    text.AppendLine($"<b>" + _HTML_(I18N.GetString("Available from")) + $"</b>: {TimeService.AsShortTime(record.RaidUnlockTime)}");
                }
                if (record.RaidEndTime != default(DateTime))
                {
                    text.AppendLine($"<b>" + _HTML_(I18N.GetString("Available until")) + $"</b>: {TimeService.AsShortTime(record.RaidEndTime)}");
                }
                text.AppendLine($"<b>" + _HTML_(I18N.GetString("Remarks")) + $"</b>: {record.Remarks}");

                string shareString = $"{IqPrefix}{raid.PublicID}";

                InlineKeyboardMarkup keyboardMarkup = new InlineKeyboardMarkup();
                keyboardMarkup.inline_keyboard      = new List <List <InlineKeyboardButton> >();

                List <InlineKeyboardButton> row;
                row = new List <InlineKeyboardButton>();
                row.Add(new InlineKeyboardButton {
                    text = I18N.GetString("Gym"), callback_data = $"{QrEditGym}:{raidPublicID}"
                });
                row.Add(new InlineKeyboardButton {
                    text = I18N.GetString("Pokémon"), callback_data = $"{QrEditPokemon}:{raidPublicID}"
                });
                keyboardMarkup.inline_keyboard.Add(row);
                row = new List <InlineKeyboardButton>();
                row.Add(new InlineKeyboardButton {
                    text = I18N.GetString("Alignment"), callback_data = $"{QrEditAlignment}:{raidPublicID}"
                });
                row.Add(new InlineKeyboardButton {
                    text = I18N.GetString("Time"), callback_data = $"{QrEditTime}:{raidPublicID}"
                });
                keyboardMarkup.inline_keyboard.Add(row);
                row = new List <InlineKeyboardButton>();
                row.Add(new InlineKeyboardButton {
                    text = I18N.GetString("Remarks"), callback_data = $"{QrEditRemarks}:{raidPublicID}"
                });
                row.Add(new InlineKeyboardButton {
                    text = I18N.GetString("Location"), callback_data = $"{QrEditLocation}:{raidPublicID}"
                });
                keyboardMarkup.inline_keyboard.Add(row);
                row = new List <InlineKeyboardButton>();
                row.Add(new InlineKeyboardButton {
                    text = _HTML_(I18N.GetString("Share")), switch_inline_query = $"{shareString}"
                });
                keyboardMarkup.inline_keyboard.Add(row);
                row = new List <InlineKeyboardButton>();
                if (raid.IsPublished)
                {
                    row.Add(new InlineKeyboardButton {
                        text = I18N.GetString("Unpublish"), callback_data = $"{QrUnpublish}:{raidPublicID}"
                    });
                    keyboardMarkup.inline_keyboard.Add(row);
                    row = new List <InlineKeyboardButton>();
                }
                else
                {
                    row.Add(new InlineKeyboardButton {
                        text = _HTML_(I18N.GetString("📣 Publish")), callback_data = $"{RaidEventHandler.QrPublish}:{raidPublicID}"
                    });
                    keyboardMarkup.inline_keyboard.Add(row);
                    row = new List <InlineKeyboardButton>();
                }

                row = new List <InlineKeyboardButton>();
                row.Add(new InlineKeyboardButton {
                    text = _HTML_(I18N.GetString("🔄")), callback_data = $"{QrRefresh}:{raid.PublicID}"
                });
                keyboardMarkup.inline_keyboard.Add(row);

                try
                {
                    Client.SendMessageToChat(user.ID, text.ToString(), "HTML", true, true, null, keyboardMarkup);
                }
                catch (Exception ex)
                {
                    _log.Warn($"Could not start edit chat with user {user.ToString()}: {ex.GetType().Name} - {ex.Message}");
                }
            });
        }