private Task PrintGameAsync(LocalizationService lcs, DiscordMessage msg, Participant?toMove = null)
        {
            var sb = new StringBuilder();

            sb.AppendLine(Formatter.Bold($"{lcs.GetString(this.Channel.GuildId, "str-house")}: {this.HandValue(this.hand)}"));
            if (this.hand.Any())
            {
                sb.AppendJoin(" | ", this.hand).AppendLine();
            }
            else
            {
                sb.AppendLine(Emojis.Question).AppendLine();
            }

            foreach (Participant participant in this.participants)
            {
                sb.Append(participant.User.Mention).Append(": ");
                sb.AppendLine(Formatter.Bold(this.HandValue(participant.Hand).ToString()));
                sb.AppendJoin(" | ", participant.Hand);
                sb.AppendLine().AppendLine();
            }

            var emb = new LocalizedEmbedBuilder(lcs, this.Channel.GuildId);

            emb.WithLocalizedTitle("fmt-casino-blackjack", Emojis.Cards.Suits[0], Emojis.Cards.Suits[0]);
            emb.WithColor(DiscordColor.DarkGreen);
            emb.WithDescription(sb);

            if (!this.gameOver)
            {
                emb.AddLocalizedTitleField("str-casino-blackjack-hit", toMove?.User.Mention ?? lcs.GetString(this.Channel.GuildId, "str-house"));
            }

            return(msg.ModifyAsync(embed: emb.Build()));
        }
Exemple #2
0
        public static async Task HandleAdded(LineNews lineNews)
        {
            // Localize the embed title
            Dictionary <Language, string> localizedTitles = Localizer.LocalizeToAllLanguagesWithFormat("line_news.title", Nintendo.SmashUltimate.Bcat.Container.LanguageOrder, lineNews.Id);

            // Localize the embed description
            // Dictionary<Language, string> localizedDescriptions = Localizer.LocalizeToAllLanguages("line_news.more_info", $"https://smash.oatmealdome.me/line_news/{lineNews.Id}/{pair.Key.GetCode()}/");

            // Create localized Embeds
            LocalizedEmbedBuilder localizedEmbedBuilder = new LocalizedEmbedBuilder(Nintendo.SmashUltimate.Bcat.Container.LanguageOrder)
                                                          .WithTitle(localizedTitles)
                                                          //.WithDescription(localizedDescriptions)
                                                          .AddField("line_news.start_time", Localizer.LocalizeDateTimeToAllLanguages(lineNews.StartDateTime))
                                                          .AddField("line_news.end_time", Localizer.LocalizeDateTimeToAllLanguages(lineNews.EndDateTime));

            // Add every OneLine
            foreach (OneLine oneLine in lineNews.OneLines)
            {
                localizedEmbedBuilder.AddField(Localizer.LocalizeToAllLanguagesWithFormat("line_news.line_title", oneLine.Id), oneLine.Text);
            }

            // Create localized Embeds
            Dictionary <Language, Embed> localizedEmbeds = localizedEmbedBuilder.Build();

            // Send the notifications
            await DiscordBot.SendNotificationAsync("**[Line News]**", localizedEmbeds);
        }
        private async Task CreateWebhookAsync(CommandContext ctx, DiscordChannel channel, string name, Uri?avatarUrl, string?reason)
        {
            // TODO what about other channel types? news, store etc?
            if (channel?.Type != ChannelType.Text)
            {
                throw new InvalidCommandUsageException(ctx, "cmd-err-chn-type-text");
            }

            if (string.IsNullOrWhiteSpace(name) || name.Length > DiscordLimits.NameLimit)
            {
                throw new CommandFailedException(ctx, "cmd-err-name", DiscordLimits.NameLimit);
            }

            DiscordWebhook wh;

            if (avatarUrl is null)
            {
                wh = await channel.CreateWebhookAsync(name, reason : ctx.BuildInvocationDetailsString(reason));
            }
            else
            {
                (_, HttpContentHeaders headers) = await HttpService.HeadAsync(avatarUrl);

                if (!headers.ContentTypeHeaderIsImage() || headers.ContentLength.GetValueOrDefault() > 8 * 1024 * 1024)
                {
                    throw new CommandFailedException(ctx, "err-url-image-8mb");
                }
                try {
                    using MemoryStream ms = await HttpService.GetMemoryStreamAsync(avatarUrl);

                    wh = await channel.CreateWebhookAsync(name, ms, reason : ctx.BuildInvocationDetailsString(reason));
                } catch (WebException e) {
                    throw new CommandFailedException(ctx, "err-url-image-fail", e);
                }
            }

            if (await ctx.WaitForBoolReplyAsync("q-send-token"))
            {
                try {
                    DiscordDmChannel?dm = await ctx.Client.CreateDmChannelAsync(ctx.User.Id);

                    if (dm is { })
                    {
                        var emb = new LocalizedEmbedBuilder(this.Localization, ctx.Guild.Id);
                        emb.WithLocalizedTitle("fmt-wh-add", Formatter.Bold(Formatter.Strip(wh.Name)), channel.Mention);
                        emb.WithDescription($"||{wh.BuildUrlString()}||");
                        emb.WithColor(this.ModuleColor);
                        emb.WithThumbnail(wh.AvatarUrl);
                        emb.AddLocalizedTitleField("str-id", wh.Id, inline: true);
                        emb.AddLocalizedTitleField("str-name", wh.Name, inline: true);
                        emb.AddLocalizedTitleField("str-token", $"||{wh.Token}||");
                        await dm.SendMessageAsync(embed : emb.Build());
                    }
                    else
                    {
                        await ctx.FailAsync("err-dm-fail");
                    }
                } catch {
Exemple #4
0
        public static Task <DiscordMessage> RespondWithLocalizedEmbedAsync(this CommandContext ctx, Action <LocalizedEmbedBuilder> action,
                                                                           DiscordChannel?channel = null)
        {
            channel ??= ctx.Channel;
            LocalizationService lcs = ctx.Services.GetRequiredService <LocalizationService>();
            var emb = new LocalizedEmbedBuilder(lcs, ctx.Guild?.Id);

            action(emb);
            return(channel.SendMessageAsync(embed: emb.Build()));
        }
Exemple #5
0
        private async Task AdvanceAsync(LocalizationService lcs)
        {
            this.DealDamage();
            await this.WaitForPotionUseAsync();

            this.UpdateHpBars();

            string header = $"{this.player1.Mention} {this.hp1str} {Emojis.DuelSwords} {this.hp2str} {this.player2.Mention}";
            var    emb    = new LocalizedEmbedBuilder(lcs, this.Channel.GuildId);

            emb.WithDescription($"{header}\n\n{this.eb}");
            emb.WithColor(DiscordColor.Teal);

            this.msgHandle = await this.msgHandle.ModifyOrResendAsync(this.Channel, emb.Build());
        }
Exemple #6
0
        public DiscordEmbed EmbedResults(LocalizationService lcs, IEnumerable <KeyValuePair <DiscordUser, int> > results)
        {
            var sb = new StringBuilder();

            foreach ((DiscordUser user, int result) in results)
            {
                sb.AppendLine(lcs.GetString(this.Channel.GuildId, "fmt-game-tr-errors", user.Mention, result));
            }

            var emb = new LocalizedEmbedBuilder(lcs, this.Channel.GuildId);

            emb.WithLocalizedTitle("fmt-game-tr-res");
            emb.WithDescription(sb);
            emb.WithColor(DiscordColor.Teal);
            return(emb.Build());
        }
        private Task PrintGameAsync(LocalizationService lcs, DiscordMessage msg, IEnumerable <int> numbers, int step)
        {
            var sb = new StringBuilder();

            sb.Append(Formatter.Bold(lcs.GetString(this.Channel.GuildId, "str-casino-lottery-drawn"))).Append(' ');
            sb.AppendLine(Formatter.Bold(numbers.Take(step).JoinWith(" "))).AppendLine();

            foreach (Participant participant in this.participants)
            {
                sb.Append(participant.User.Mention).Append(" | ");
                sb.AppendLine(Formatter.Bold(participant.Numbers.JoinWith(" ")));
                sb.AppendLine();
            }

            var emb = new LocalizedEmbedBuilder(lcs, this.Channel.GuildId);

            emb.WithLocalizedTitle("fmt-casino-lottery", Emojis.MoneyBag, Emojis.MoneyBag);
            emb.WithColor(DiscordColor.DarkGreen);
            emb.WithDescription(sb);

            return(msg.ModifyAsync(embed: emb.Build()));
        }
Exemple #8
0
        public async Task AnnounceAsync(CommandContext ctx,
                                        [RemainingText, Description("desc-announcement")] string message)
        {
            if (!await ctx.WaitForBoolReplyAsync("q-announcement", args: Formatter.Strip(message)))
            {
                return;
            }

            var emb = new LocalizedEmbedBuilder(this.Localization, ctx.Guild?.Id);

            emb.WithLocalizedTitle("str-announcement");
            emb.WithDescription(message);
            emb.WithColor(DiscordColor.Red);

            var eb = new StringBuilder();
            IEnumerable <(int, IEnumerable <DiscordGuild>)> shardGuilds = TheGodfather.Bot !.Client.ShardClients
                                                                          .Select(kvp => (kvp.Key, kvp.Value.Guilds.Values));

            foreach ((int shardId, IEnumerable <DiscordGuild> guilds) in shardGuilds)
            {
                foreach (DiscordGuild guild in guilds)
                {
                    try {
                        await guild.GetDefaultChannel().SendMessageAsync(embed: emb.Build());
                    } catch {
                        eb.AppendLine(this.Localization.GetString(ctx.Guild?.Id, "cmd-err-announce", shardId, guild.Name, guild.Id));
                    }
                }
            }

            if (eb.Length > 0)
            {
                await ctx.ImpInfoAsync(this.ModuleColor, "fmt-err", eb.ToString());
            }
            else
            {
                await ctx.InfoAsync(this.ModuleColor);
            }
        }
Exemple #9
0
        public async Task InfoAsync(CommandContext ctx,
                                    [Description("desc-emoji-info")] DiscordEmoji emoji)
        {
            try {
                DiscordGuildEmoji gemoji = await ctx.Guild.GetEmojiAsync(emoji.Id);

                var emb = new LocalizedEmbedBuilder(this.Localization, ctx.Guild.Id);
                emb.WithColor(this.ModuleColor);
                emb.WithLocalizedTitle("str-emoji-details");
                emb.WithDescription($"{gemoji.GetDiscordName()} ({gemoji.Id})");
                emb.WithThumbnail(gemoji.Url);

                emb.AddLocalizedTitleField("str-created-by", gemoji.User?.ToDiscriminatorString(), inline: true);
                emb.AddLocalizedTitleField("str-animated", gemoji.IsAnimated, inline: true);
                emb.AddLocalizedTitleField("str-managed", gemoji.IsManaged, inline: true);
                emb.AddLocalizedTitleField("str-url", gemoji.Url);
                emb.AddLocalizedTimestampField("str-created-at", gemoji.CreationTimestamp);

                await ctx.RespondAsync(embed : emb.Build());
            } catch (NotFoundException) {
                throw new CommandFailedException(ctx, "cmd-err-emoji-404");
            }
        }
        public override async Task RunAsync(LocalizationService lcs)
        {
            this.Started = true;

            var rng = new SecureRandom();

            for (int round = 1; round <= 5 && this.ParticipantCount > 1; round++)
            {
                DiscordMessage msg = await this.Channel.LocalizedEmbedAsync(lcs, Emojis.Gun, DiscordColor.DarkRed, "fmt-game-rr-starting", round);

                await Task.Delay(TimeSpan.FromSeconds(5));

                var eb = new StringBuilder();
                foreach (DiscordUser participant in this.participants)
                {
                    if (rng.NextBool(round))
                    {
                        eb.AppendLine($"{participant.Mention} {Emojis.Dead} {Emojis.Blast} {Emojis.Gun}");
                        this.participants.TryRemove(participant);
                    }
                    else
                    {
                        eb.AppendLine($"{participant.Mention} {Emojis.Relieved} {Emojis.Gun}");
                    }

                    var emb = new LocalizedEmbedBuilder(lcs, this.Channel.GuildId);
                    emb.WithLocalizedTitle("fmt-game-rr-round", round);
                    emb.WithDescription(eb.ToString());
                    emb.WithColor(DiscordColor.DarkRed);
                    msg = await msg.ModifyOrResendAsync(this.Channel, emb.Build());

                    await Task.Delay(TimeSpan.FromSeconds(2));
                }
            }

            this.Survivors = this.participants.ToList().AsReadOnly();
        }
Exemple #11
0
        public override async Task RunAsync(LocalizationService lcs)
        {
            if (_countries is null)
            {
                throw new InvalidOperationException("The quiz flag paths have not been loaded.");
            }

            var questions = new Queue <string>(_countries.Keys.Shuffle().Take(this.NumberOfQuestions));

            int timeouts = 0;

            for (int i = 0; i < this.NumberOfQuestions; i++)
            {
                string question = questions.Dequeue();

                var emb = new LocalizedEmbedBuilder(lcs, this.Channel.GuildId);
                emb.WithLocalizedDescription("fmt-game-quiz-q", i + 1);
                await this.Channel.SendFileAsync("flag.png", new FileStream(question, FileMode.Open), embed : emb.Build());

                bool timeout     = true;
                var  failed      = new ConcurrentHashSet <ulong>();
                var  answerRegex = new Regex($@"\b{_countries[question]}\b", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
                InteractivityResult <DiscordMessage> res = await this.Interactivity.WaitForMessageAsync(
                    xm => {
                    if (xm.ChannelId != this.Channel.Id || xm.Author.IsBot || failed.Contains(xm.Author.Id))
                    {
                        return(false);
                    }
                    timeout = false;
                    if (answerRegex.IsMatch(xm.Content))
                    {
                        return(true);
                    }
                    else
                    {
                        failed.Add(xm.Author.Id);
                    }
                    return(false);
                },
                    TimeSpan.FromSeconds(10)
                    );

                if (res.TimedOut)
                {
                    if (!failed.Any())
                    {
                        timeouts = timeout ? timeouts + 1 : 0;
                        if (timeouts == 3)
                        {
                            this.IsTimeoutReached = true;
                            return;
                        }
                    }
                    else
                    {
                        timeouts = 0;
                    }
                    await this.Channel.LocalizedEmbedAsync(lcs, Emojis.AlarmClock, DiscordColor.Teal, "fmt-game-quiz-timeout", _countries[question]);
                }
                else
                {
                    await this.Channel.LocalizedEmbedAsync(lcs, Emojis.CheckMarkSuccess, DiscordColor.Teal, "fmt-game-quiz-correct", res.Result.Author.Mention);

                    this.results.AddOrUpdate(res.Result.Author, u => 1, (u, v) => v + 1);
                }

                await Task.Delay(TimeSpan.FromSeconds(2));
            }
        }
Exemple #12
0
        public static DiscordEmbed ToDiscordEmbed(this GuildConfig gcfg, DiscordGuild guild, LocalizationService lcs, bool update = false)
        {
            var emb = new LocalizedEmbedBuilder(lcs, guild.Id);

            emb.WithLocalizedTitle(DiscordEventType.GuildUpdated, update ? "evt-cfg-update" : "str-guild-cfg");
            emb.WithThumbnail(guild.IconUrl);

            emb.AddLocalizedTitleField("str-prefix", gcfg.Prefix ?? lcs.GetString(guild.Id, "str-default"), inline: true);
            emb.AddLocalizedTitleField("str-silent", gcfg.ReactionResponse, inline: true);
            emb.AddLocalizedTitleField("str-cmd-suggestions", gcfg.SuggestionsEnabled, inline: true);

            if (gcfg.LoggingEnabled)
            {
                DiscordChannel?logchn = guild.GetChannel(gcfg.LogChannelId);
                if (logchn is null)
                {
                    emb.AddLocalizedField("str-logging", "err-log-404", inline: true);
                }
                else
                {
                    emb.AddLocalizedField("str-logging", "fmt-logs", inline: true, contentArgs: new[] { logchn.Mention });
                }
            }
            else
            {
                emb.AddLocalizedField("str-logging", "str-off", inline: true);
            }

            emb.AddLocalizedField("str-backup", gcfg.BackupEnabled ? "str-enabled" : "str-disabled", inline: true);

            if (gcfg.WelcomeChannelId != default)
            {
                DiscordChannel?wchn = guild.GetChannel(gcfg.WelcomeChannelId);
                if (wchn is null)
                {
                    emb.AddLocalizedField("str-memupd-w", "err-memupd-w-404", inline: true);
                }
                else
                {
                    emb.AddLocalizedField("str-memupd-w", "fmt-memupd", inline: true, contentArgs: new[] {
                        wchn.Mention,
                        Formatter.Strip(gcfg.WelcomeMessage ?? lcs.GetString(guild.Id, "str-default"))
                    });
                }
            }
            else
            {
                emb.AddLocalizedField("str-memupd-w", "str-off", inline: true);
            }

            if (gcfg.LeaveChannelId != default)
            {
                DiscordChannel?lchn = guild.GetChannel(gcfg.LeaveChannelId);
                if (lchn is null)
                {
                    emb.AddLocalizedField("str-memupd-l", "err-memupd-l-404", inline: true);
                }
                else
                {
                    emb.AddLocalizedField("str-memupd-l", "fmt-memupd", inline: true, contentArgs: new[] {
                        lchn.Mention,
                        Formatter.Strip(gcfg.LeaveMessage ?? lcs.GetString(guild.Id, "str-default"))
                    });
                }
            }
            else
            {
                emb.AddLocalizedField("str-memupd-l", "str-off", inline: true);
            }

            emb.AddLocalizedTitleField("str-ratelimit", gcfg.RatelimitSettings.ToEmbedFieldString(guild.Id, lcs), inline: true);
            emb.AddLocalizedTitleField("str-antispam", gcfg.AntispamSettings.ToEmbedFieldString(guild.Id, lcs), inline: true);
            emb.AddLocalizedTitleField("str-antiflood", gcfg.AntifloodSettings.ToEmbedFieldString(guild.Id, lcs), inline: true);
            emb.AddLocalizedTitleField("str-instantleave", gcfg.AntiInstantLeaveSettings.ToEmbedFieldString(guild.Id, lcs), inline: true);

            if (gcfg.MuteRoleId != default)
            {
                DiscordRole?muteRole = guild.GetRole(gcfg.MuteRoleId);
                if (muteRole is null)
                {
                    emb.AddLocalizedField("str-muterole", "err-muterole-404", inline: true);
                }
                else
                {
                    emb.AddLocalizedTitleField("str-muterole", muteRole.Name, inline: true);
                }
            }
            else
            {
                emb.AddLocalizedField("str-muterole", "str-none", inline: true);
            }

            emb.AddLocalizedTitleField("str-lf", gcfg.LinkfilterSettings.ToEmbedFieldString(guild.Id, lcs), inline: true);

            return(emb.Build());
        }
Exemple #13
0
        public static async Task HandleFestival(RomType romType, Dictionary <string, byte[]> data, FestivalSetting previousFestival, FestivalSetting newFestival, byte[] rawFile)
        {
            // Don't do anything
            if (previousFestival.FestivalId == newFestival.FestivalId)
            {
                return;
            }

            // Get the Color for the neutral team
            System.Drawing.Color drawingColor = newFestival.Teams[2].GetColor4fAsColor();

            // Localize the times
            Dictionary <Language, string> startTime = Localizer.LocalizeDateTimeToAllLanguages(newFestival.Times.Start);
            Dictionary <Language, string> endTime   = Localizer.LocalizeDateTimeToAllLanguages(newFestival.Times.End);

            // Create the format parameters
            Dictionary <Language, object[]> formatParams = new Dictionary <Language, object[]>();

            foreach (Language language in BlitzUtil.SupportedLanguages)
            {
                formatParams[language] = new object[] { startTime[language], endTime[language] };
            }

            // Format the final string
            Dictionary <Language, string> periodStr = Localizer.LocalizeToAllLanguagesWithFormat("festival.period_format", BlitzUtil.SupportedLanguages, formatParams);

            Dictionary <Language, string> AddMissingLocalizations(Dictionary <Language, string> originalDict)
            {
                // Add any missing strings for team alpha
                Dictionary <Language, string> names = new Dictionary <Language, string>();

                foreach (Language language in BlitzUtil.SupportedLanguages)
                {
                    // Try getting the name from the original dictionary
                    if (originalDict.TryGetValue(language, out string name))
                    {
                        names.Add(language, $"**{name}**");
                    }
                    else
                    {
                        // Use the RomType to get the name
                        switch (romType)
                        {
                        case RomType.NorthAmerica:
                            names.Add(language, $"**{originalDict[Language.EnglishUS]}**");
                            break;

                        case RomType.Europe:
                            names.Add(language, $"**{originalDict[Language.EnglishUK]}**");
                            break;

                        case RomType.Japan:
                            names.Add(language, $"**{originalDict[Language.Japanese]}**");
                            break;

                        default:
                            throw new Exception("Unsupported RomType");
                        }
                    }
                }

                return(names);
            }

            // Add any missing strings for the teams
            Dictionary <Language, string> alphaNames = AddMissingLocalizations(newFestival.Teams[0].Name);
            Dictionary <Language, string> bravoNames = AddMissingLocalizations(newFestival.Teams[1].Name);

            // Localize the RomType
            Dictionary <Language, string> localizedRomType = Localizer.LocalizeToAllLanguages($"romtype.{romType.ToString().ToLower()}");

            // Use the special title if necessary
            Dictionary <Language, string> localizedTitle;

            if (newFestival.SpecialType != null)
            {
                // Localize the special type
                Dictionary <Language, string> localizedSpecialTypes = Localizer.LocalizeToAllLanguages($"festival.special_type.{newFestival.SpecialType.ToLower()}");

                // Create the format parameters
                formatParams = new Dictionary <Language, object[]>();
                foreach (Language language in BlitzUtil.SupportedLanguages)
                {
                    formatParams[language] = new object[] { localizedRomType[language], localizedSpecialTypes[language] };
                }

                // Localize the title
                localizedTitle = Localizer.LocalizeToAllLanguagesWithFormat("festival.title_special", BlitzUtil.SupportedLanguages, formatParams);
            }
            else
            {
                // Create the format parameters
                formatParams = new Dictionary <Language, object[]>();
                foreach (Language language in BlitzUtil.SupportedLanguages)
                {
                    formatParams[language] = new object[] { localizedRomType[language] };
                }

                // Localize the title
                localizedTitle = Localizer.LocalizeToAllLanguagesWithFormat("festival.title", BlitzUtil.SupportedLanguages, formatParams);
            }

            // Start building the embed
            LocalizedEmbedBuilder embedBuilder = new LocalizedEmbedBuilder(BlitzUtil.SupportedLanguages)
                                                 .WithTitle(localizedTitle)
                                                 .AddField("festival.team_alpha", alphaNames, true)
                                                 .AddField("festival.team_bravo", bravoNames, true)
                                                 .AddField("festival.rule", BlitzLocalizer.LocalizeRuleToAllLanguages(newFestival.VersusRule), true)
                                                 .AddField("festival.special_stage", BlitzLocalizer.LocalizeStageToAllLanguages(newFestival.SpecialStage), true)
                                                 .AddField("festival.announcement_time", Localizer.LocalizeDateTimeToAllLanguages(newFestival.Times.Announcement))
                                                 .AddField("festival.period", periodStr)
                                                 .AddField("festival.results_time", Localizer.LocalizeDateTimeToAllLanguages(newFestival.Times.Result))
                                                 .WithImageUrl($"https://cdn.oatmealdome.me/splatoon/festival/{romType.ToString()}/{newFestival.FestivalId}/panel.png")
                                                 .WithColor(new Color(drawingColor.R, drawingColor.G, drawingColor.B));

            // Send the notification
            await DiscordBot.SendNotificationAsync("**[Splatfest]**", embedBuilder.Build());
        }
Exemple #14
0
        public override async Task RunAsync(LocalizationService lcs)
        {
            int timeouts = 0;

            foreach ((QuizQuestion question, int i) in this.questions.Select((q, i) => (q, i)))
            {
                var emb = new LocalizedEmbedBuilder(lcs, this.Channel.GuildId);
                emb.WithLocalizedTitle("fmt-game-quiz-q", i + 1);
                emb.WithDescription(Formatter.Bold(question.Content));
                emb.WithColor(DiscordColor.Teal);
                emb.AddLocalizedTitleField("str-category", question.Category, inline: false);

                var answers = new List <string>(question.IncorrectAnswers)
                {
                    question.CorrectAnswer
                }.Shuffle().ToList();

                foreach ((string answer, int index) in answers.Select((a, i) => (a, i)))
                {
                    emb.AddLocalizedTitleField("fmt-game-quiz-a", answer, inline: true, titleArgs: index + 1);
                }

                var            options = Emojis.Numbers.All.Skip(1).Take(4).ToList();
                DiscordMessage msg     = await this.Channel.SendMessageAsync(embed : emb.Build());

                foreach (DiscordEmoji emoji in options)
                {
                    await msg.CreateReactionAsync(emoji);
                }

                bool timeout = true;
                var  failed  = new ConcurrentHashSet <ulong>();
                InteractivityResult <MessageReactionAddEventArgs> res = await this.Interactivity.WaitForReactionAsync(
                    e => {
                    if (e.User.IsBot || failed.Contains(e.User.Id) || e.Message != msg)
                    {
                        return(false);
                    }
                    int opt = options.IndexOf(e.Emoji);
                    if (opt == -1)
                    {
                        return(false);
                    }
                    if (answers[opt].Equals(question.CorrectAnswer))
                    {
                        return(true);
                    }
                    else
                    {
                        failed.Add(e.User.Id);
                    }
                    return(false);
                },
                    TimeSpan.FromSeconds(10)
                    );

                if (res.TimedOut)
                {
                    if (!failed.Any())
                    {
                        timeouts = timeout ? timeouts + 1 : 0;
                        if (timeouts == 3)
                        {
                            this.IsTimeoutReached = true;
                            return;
                        }
                    }
                    else
                    {
                        timeouts = 0;
                    }
                    await this.Channel.LocalizedEmbedAsync(lcs, Emojis.AlarmClock, DiscordColor.Teal, "fmt-game-quiz-timeout", question.CorrectAnswer);
                }
                else
                {
                    await this.Channel.LocalizedEmbedAsync(lcs, Emojis.CheckMarkSuccess, DiscordColor.Teal, "fmt-game-quiz-correct", res.Result.User.Mention);

                    this.results.AddOrUpdate(res.Result.User, u => 1, (u, v) => v + 1);
                }

                await Task.Delay(TimeSpan.FromSeconds(2));
            }
        }