@@ -628,32 +628,49 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    switch (logChannelType)
 | 
			
		||||
                    {
 | 
			
		||||
                        case LogType.Other:
 | 
			
		||||
                            newLogSetting.LogOtherId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.MessageUpdated:
 | 
			
		||||
                            newLogSetting.MessageUpdatedId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.MessageDeleted:
 | 
			
		||||
                            newLogSetting.MessageDeletedId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.UserJoined:
 | 
			
		||||
                            newLogSetting.UserJoinedId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.UserLeft:
 | 
			
		||||
                            newLogSetting.UserLeftId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.UserBanned:
 | 
			
		||||
                            newLogSetting.UserBannedId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.UserUnbanned:
 | 
			
		||||
                            newLogSetting.UserUnbannedId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.UserUpdated:
 | 
			
		||||
                            newLogSetting.UserUpdatedId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.UserMuted:
 | 
			
		||||
                            newLogSetting.UserMutedId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.ChannelCreated:
 | 
			
		||||
                            newLogSetting.ChannelCreatedId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.ChannelDestroyed:
 | 
			
		||||
                            newLogSetting.ChannelDestroyedId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.ChannelUpdated:
 | 
			
		||||
                            newLogSetting.ChannelUpdatedId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.UserPresence:
 | 
			
		||||
                            newLogSetting.LogUserPresenceId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.VoicePresence:
 | 
			
		||||
                            newLogSetting.LogVoicePresenceId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case LogType.VoicePresenceTTS:
 | 
			
		||||
                            newLogSetting.LogVoicePresenceTTSId = null;
 | 
			
		||||
                            break;
 | 
			
		||||
                        default:
 | 
			
		||||
                            break;
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                var ar = new AnimalRace(channel.Guild.Id, channel);
 | 
			
		||||
 | 
			
		||||
                if (ar.Fail)
 | 
			
		||||
                    await channel.SendErrorAsync("🏁 `Failed starting a race. Another race is probably running.`");
 | 
			
		||||
                    await channel.SendErrorAsync("Animal Race", "Failed starting. Another race is probably running.").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
@@ -45,7 +45,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                AnimalRace ar;
 | 
			
		||||
                if (!AnimalRaces.TryGetValue(channel.Guild.Id, out ar))
 | 
			
		||||
                {
 | 
			
		||||
                    await channel.SendErrorAsync("No race exists on this server");
 | 
			
		||||
                    await channel.SendErrorAsync("No race exists on this server").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                await ar.JoinRace(umsg.Author as IGuildUser, amount);
 | 
			
		||||
@@ -90,21 +90,29 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            try { await raceChannel.SendConfirmAsync($"🏁`Race is starting in 20 seconds or when the room is full. Type {NadekoBot.ModulePrefixes[typeof(Gambling).Name]}jr to join the race.`"); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                await raceChannel.SendConfirmAsync("Animal Race", $"Starting in 20 seconds or when the room is full.",
 | 
			
		||||
                                    footer: $"Type {NadekoBot.ModulePrefixes[typeof(Gambling).Name]}jr to join the race.");
 | 
			
		||||
                            }
 | 
			
		||||
                            catch (Exception ex)
 | 
			
		||||
                            {
 | 
			
		||||
                                _log.Warn(ex);
 | 
			
		||||
                            }
 | 
			
		||||
                            var t = await Task.WhenAny(Task.Delay(20000, token), fullgame);
 | 
			
		||||
                            Started = true;
 | 
			
		||||
                            cancelSource.Cancel();
 | 
			
		||||
                            if (t == fullgame)
 | 
			
		||||
                            {
 | 
			
		||||
                                try { await raceChannel.SendConfirmAsync("🏁`Race full, starting right now!`"); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                                try { await raceChannel.SendConfirmAsync("Animal Race", "Full! Starting immediately."); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                            }
 | 
			
		||||
                            else if (participants.Count > 1)
 | 
			
		||||
                            {
 | 
			
		||||
                                try { await raceChannel.SendConfirmAsync("🏁`Game starting with " + participants.Count + " participants.`"); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                                try { await raceChannel.SendConfirmAsync("Animal Race", "Starting with " + participants.Count + " participants."); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                try { await raceChannel.SendErrorAsync("🏁`Race failed to start since there was not enough participants.`"); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                                try { await raceChannel.SendErrorAsync("Animal Race", "Failed to start since there was not enough participants."); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                                var p = participants.FirstOrDefault();
 | 
			
		||||
 | 
			
		||||
                                if (p != null && p.AmountBet > 0)
 | 
			
		||||
@@ -141,19 +149,26 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                            participants.ForEach(p =>
 | 
			
		||||
                            {
 | 
			
		||||
                                p.Total += 1 + rng.Next(0, 10);
 | 
			
		||||
                                if (p.Total > 60)
 | 
			
		||||
                                {
 | 
			
		||||
                                    p.Total = 60;
 | 
			
		||||
                                    if (winner == null)
 | 
			
		||||
                                    {
 | 
			
		||||
                                        winner = p;
 | 
			
		||||
                                    }
 | 
			
		||||
                                    if (p.Place == 0)
 | 
			
		||||
                                        p.Place = place++;
 | 
			
		||||
                                }
 | 
			
		||||
                            });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                            participants
 | 
			
		||||
                                .OrderByDescending(p => p.Total)
 | 
			
		||||
                                .ForEach(p =>
 | 
			
		||||
                                {
 | 
			
		||||
                                    if (p.Total > 60)
 | 
			
		||||
                                    {
 | 
			
		||||
                                        if (winner == null)
 | 
			
		||||
                                        {
 | 
			
		||||
                                            winner = p;
 | 
			
		||||
                                        }
 | 
			
		||||
                                        p.Total = 60;
 | 
			
		||||
                                        if (p.Place == 0)
 | 
			
		||||
                                            p.Place = place++;
 | 
			
		||||
                                    }
 | 
			
		||||
                                });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                            //draw the state
 | 
			
		||||
 | 
			
		||||
                            var text = $@"|🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|
 | 
			
		||||
@@ -183,13 +198,13 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                    if (winner.AmountBet > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        var wonAmount = winner.AmountBet * (participants.Count - 1);
 | 
			
		||||
                        
 | 
			
		||||
 | 
			
		||||
                        await CurrencyHandler.AddCurrencyAsync(winner.User, "Won a Race", wonAmount, false).ConfigureAwait(false);
 | 
			
		||||
                        await raceChannel.SendConfirmAsync($"🏁 {winner.User.Mention} as {winner.Animal} **Won the race and {wonAmount}{CurrencySign}!**").ConfigureAwait(false);
 | 
			
		||||
                        await raceChannel.SendConfirmAsync("Animal Race", $"{winner.User.Mention} as {winner.Animal} **Won the race and {wonAmount}{CurrencySign}!**").ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        await raceChannel.SendConfirmAsync($"🏁 {winner.User.Mention} as {winner.Animal} **Won the race!**");
 | 
			
		||||
                        await raceChannel.SendConfirmAsync("Animal Race", $"{winner.User.Mention} as {winner.Animal} **Won the race!**").ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
@@ -218,18 +233,18 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                    var animal = "";
 | 
			
		||||
                    if (!animals.TryDequeue(out animal))
 | 
			
		||||
                    {
 | 
			
		||||
                        await raceChannel.SendErrorAsync($"{u.Mention} `There is no running race on this server.`");
 | 
			
		||||
                        await raceChannel.SendErrorAsync($"{u.Mention} `There is no running race on this server.`").ConfigureAwait(false);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    var p = new Participant(u, animal, amount);
 | 
			
		||||
                    if (participants.Contains(p))
 | 
			
		||||
                    {
 | 
			
		||||
                        await raceChannel.SendErrorAsync($"{u.Mention} `You already joined this race.`");
 | 
			
		||||
                        await raceChannel.SendErrorAsync($"{u.Mention} `You already joined this race.`").ConfigureAwait(false);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (Started)
 | 
			
		||||
                    {
 | 
			
		||||
                        await raceChannel.SendErrorAsync($"{u.Mention} `Race is already started`");
 | 
			
		||||
                        await raceChannel.SendErrorAsync($"{u.Mention} `Race is already started`").ConfigureAwait(false);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (amount > 0)
 | 
			
		||||
@@ -239,7 +254,8 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                    participants.Add(p);
 | 
			
		||||
                    await raceChannel.SendConfirmAsync($"{u.Mention} **joined the race as a {p.Animal}" + (amount > 0 ? $" and bet {amount} {CurrencySign}!**" : "**"));
 | 
			
		||||
                    await raceChannel.SendConfirmAsync("Animal Race", $"{u.Mention} **joined as a {p.Animal}" + (amount > 0 ? $" and bet {amount} {CurrencySign}!**" : "**"))
 | 
			
		||||
                        .ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
 | 
			
		||||
        private int QuestionDurationMiliseconds { get; } = 30000;
 | 
			
		||||
        private int HintTimeoutMiliseconds { get; } = 6000;
 | 
			
		||||
        public bool ShowHints { get; set; } = true;
 | 
			
		||||
        public bool ShowHints { get; } = true;
 | 
			
		||||
        private CancellationTokenSource triviaCancelSource { get; set; }
 | 
			
		||||
 | 
			
		||||
        public TriviaQuestion CurrentQuestion { get; private set; }
 | 
			
		||||
@@ -35,95 +35,111 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
 | 
			
		||||
        public int WinRequirement { get; } = 10;
 | 
			
		||||
 | 
			
		||||
        public TriviaGame(IGuild guild, ITextChannel channel, bool showHints, int winReq = 10)
 | 
			
		||||
        public TriviaGame(IGuild guild, ITextChannel channel, bool showHints, int winReq)
 | 
			
		||||
        {
 | 
			
		||||
            _log = LogManager.GetCurrentClassLogger();
 | 
			
		||||
            ShowHints = showHints;
 | 
			
		||||
            this._log = LogManager.GetCurrentClassLogger();
 | 
			
		||||
 | 
			
		||||
            this.ShowHints = showHints;
 | 
			
		||||
            this.guild = guild;
 | 
			
		||||
            this.channel = channel;
 | 
			
		||||
            WinRequirement = winReq;
 | 
			
		||||
            Task.Run(async () => { try { await StartGame().ConfigureAwait(false); } catch { } });
 | 
			
		||||
            this.WinRequirement = winReq;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task StartGame()
 | 
			
		||||
        public async Task StartGame()
 | 
			
		||||
        {
 | 
			
		||||
            while (!ShouldStopGame)
 | 
			
		||||
            {
 | 
			
		||||
                // reset the cancellation source
 | 
			
		||||
                triviaCancelSource = new CancellationTokenSource();
 | 
			
		||||
                var token = triviaCancelSource.Token;
 | 
			
		||||
 | 
			
		||||
                // load question
 | 
			
		||||
                CurrentQuestion = TriviaQuestionPool.Instance.GetRandomQuestion(oldQuestions);
 | 
			
		||||
                if (CurrentQuestion == null)
 | 
			
		||||
                {
 | 
			
		||||
                    try { await channel.SendErrorAsync($":exclamation: Failed loading a trivia question.").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                    await End().ConfigureAwait(false);
 | 
			
		||||
                    await channel.SendErrorAsync("Trivia Game", "Failed loading a question.").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                oldQuestions.Add(CurrentQuestion); //add it to exclusion list so it doesn't show up again
 | 
			
		||||
                                                   //sendquestion
 | 
			
		||||
                try { await channel.SendConfirmAsync($":question: Question",$"**{CurrentQuestion.Question}**").ConfigureAwait(false); }
 | 
			
		||||
                catch (HttpException ex) when (ex.StatusCode  == System.Net.HttpStatusCode.NotFound || ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
 | 
			
		||||
                {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
 | 
			
		||||
                //receive messages
 | 
			
		||||
                NadekoBot.Client.MessageReceived += PotentialGuess;
 | 
			
		||||
 | 
			
		||||
                //allow people to guess
 | 
			
		||||
                GameActive = true;
 | 
			
		||||
 | 
			
		||||
                EmbedBuilder questionEmbed;
 | 
			
		||||
                IUserMessage questionMessage;
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    //hint
 | 
			
		||||
                    await Task.Delay(HintTimeoutMiliseconds, token).ConfigureAwait(false);
 | 
			
		||||
                    if (ShowHints)
 | 
			
		||||
                        try { await channel.SendConfirmAsync($":exclamation: Hint", CurrentQuestion.GetHint()).ConfigureAwait(false); }
 | 
			
		||||
                        catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound || ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
 | 
			
		||||
                        {
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
 | 
			
		||||
                    //timeout
 | 
			
		||||
                    await Task.Delay(QuestionDurationMiliseconds - HintTimeoutMiliseconds, token).ConfigureAwait(false);
 | 
			
		||||
                    questionEmbed = new EmbedBuilder().WithOkColor()
 | 
			
		||||
                        .WithTitle("Trivia Game")
 | 
			
		||||
                        .AddField(eab => eab.WithName("Category").WithValue(CurrentQuestion.Category))
 | 
			
		||||
                        .AddField(eab => eab.WithName("Question").WithValue(CurrentQuestion.Question));
 | 
			
		||||
 | 
			
		||||
                    questionMessage = await channel.EmbedAsync(questionEmbed.Build()).ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
                catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound || ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
 | 
			
		||||
                {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
                {
 | 
			
		||||
                    _log.Warn(ex);
 | 
			
		||||
                    await Task.Delay(2000).ConfigureAwait(false);
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                //receive messages
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    NadekoBot.Client.MessageReceived += PotentialGuess;
 | 
			
		||||
 | 
			
		||||
                    //allow people to guess
 | 
			
		||||
                    GameActive = true;
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        //hint
 | 
			
		||||
                        await Task.Delay(HintTimeoutMiliseconds, triviaCancelSource.Token).ConfigureAwait(false);
 | 
			
		||||
                        if (ShowHints)
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                await questionMessage.ModifyAsync(m => m.Embed = questionEmbed.WithFooter(efb => efb.WithText(CurrentQuestion.GetHint())).Build())
 | 
			
		||||
                                    .ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound || ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
 | 
			
		||||
                            {
 | 
			
		||||
                                break;
 | 
			
		||||
                            }
 | 
			
		||||
                            catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
 | 
			
		||||
                        //timeout
 | 
			
		||||
                        await Task.Delay(QuestionDurationMiliseconds - HintTimeoutMiliseconds, triviaCancelSource.Token).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (TaskCanceledException) { } //means someone guessed the answer
 | 
			
		||||
                }
 | 
			
		||||
                finally
 | 
			
		||||
                {
 | 
			
		||||
                    GameActive = false;
 | 
			
		||||
                    NadekoBot.Client.MessageReceived -= PotentialGuess;
 | 
			
		||||
                }
 | 
			
		||||
                catch (TaskCanceledException) { } //means someone guessed the answer
 | 
			
		||||
                GameActive = false;
 | 
			
		||||
                if (!triviaCancelSource.IsCancellationRequested)
 | 
			
		||||
                    try { await channel.SendConfirmAsync($":clock2: :question: **Time's up!** The correct answer was **{CurrentQuestion.Answer}**").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                NadekoBot.Client.MessageReceived -= PotentialGuess;
 | 
			
		||||
                // load next question if game is still running
 | 
			
		||||
                    try { await channel.SendErrorAsync("Trivia Game", $"**Time's up!** The correct answer was **{CurrentQuestion.Answer}**").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                await Task.Delay(2000).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            try { NadekoBot.Client.MessageReceived -= PotentialGuess; } catch { }
 | 
			
		||||
            GameActive = false;
 | 
			
		||||
            await End().ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task End()
 | 
			
		||||
        public async Task EnsureStopped()
 | 
			
		||||
        {
 | 
			
		||||
            ShouldStopGame = true;
 | 
			
		||||
            TriviaGame throwaway;
 | 
			
		||||
            Games.TriviaCommands.RunningTrivias.TryRemove(channel.Guild.Id, out throwaway);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
 | 
			
		||||
                      .WithTitle("Leaderboard")
 | 
			
		||||
                      .WithDescription(GetLeaderboard())
 | 
			
		||||
                      .Build(), "Trivia game ended.").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            catch { }
 | 
			
		||||
 | 
			
		||||
            await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
 | 
			
		||||
                    .WithAuthor(eab => eab.WithName("Trivia Game Ended"))
 | 
			
		||||
                    .WithTitle("Final Results")
 | 
			
		||||
                    .WithDescription(GetLeaderboard())
 | 
			
		||||
                    .Build()).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task StopGame()
 | 
			
		||||
        {
 | 
			
		||||
            if (!ShouldStopGame)
 | 
			
		||||
                try { await channel.SendConfirmAsync(":exclamation: Trivia will stop after this question.").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
            var old = ShouldStopGame;
 | 
			
		||||
            ShouldStopGame = true;
 | 
			
		||||
            if (!old)
 | 
			
		||||
                try { await channel.SendConfirmAsync("Trivia Game", "Stopping after this question.").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task PotentialGuess(IMessage imsg)
 | 
			
		||||
@@ -137,11 +153,11 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    if (!(umsg.Channel is IGuildChannel && umsg.Channel is ITextChannel)) return;
 | 
			
		||||
                    if ((umsg.Channel as ITextChannel).Guild != guild) return;
 | 
			
		||||
                    if (umsg.Author.Id == NadekoBot.Client.GetCurrentUser().Id) return;
 | 
			
		||||
                    var textChannel = umsg.Channel as ITextChannel;
 | 
			
		||||
                    if (textChannel == null || textChannel.Guild != guild)
 | 
			
		||||
                        return;
 | 
			
		||||
 | 
			
		||||
                    var guildUser = umsg.Author as IGuildUser;
 | 
			
		||||
                    var guildUser = (IGuildUser)umsg.Author;
 | 
			
		||||
 | 
			
		||||
                    var guess = false;
 | 
			
		||||
                    await _guessLock.WaitAsync().ConfigureAwait(false);
 | 
			
		||||
@@ -156,10 +172,15 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
                    finally { _guessLock.Release(); }
 | 
			
		||||
                    if (!guess) return;
 | 
			
		||||
                    triviaCancelSource.Cancel();
 | 
			
		||||
                    try { await channel.SendConfirmAsync($"☑️ {guildUser.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                    if (Users[guildUser] != WinRequirement) return;
 | 
			
		||||
                    ShouldStopGame = true;
 | 
			
		||||
                    await channel.SendConfirmAsync($":exclamation: We have a winner! It's {guildUser.Mention}.").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                    
 | 
			
		||||
                    if (Users[guildUser] == WinRequirement) {
 | 
			
		||||
                        ShouldStopGame = true;
 | 
			
		||||
                        await channel.SendConfirmAsync("Trivia Game", $"{guildUser.Mention} guessed it and WON the game! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    await channel.SendConfirmAsync("Trivia Game", $"{guildUser.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
            });
 | 
			
		||||
@@ -169,7 +190,7 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
        public string GetLeaderboard()
 | 
			
		||||
        {
 | 
			
		||||
            if (Users.Count == 0)
 | 
			
		||||
                return "";
 | 
			
		||||
                return "No results.";
 | 
			
		||||
 | 
			
		||||
            var sb = new StringBuilder();
 | 
			
		||||
 | 
			
		||||
@@ -181,4 +202,4 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
            return sb.ToString();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -18,9 +18,9 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
        };
 | 
			
		||||
        public static int maxStringLength = 22;
 | 
			
		||||
 | 
			
		||||
        public string Category;
 | 
			
		||||
        public string Question;
 | 
			
		||||
        public string Answer;
 | 
			
		||||
        public string Category { get; set; }
 | 
			
		||||
        public string Question { get; set; }
 | 
			
		||||
        public string Answer { get; set; }
 | 
			
		||||
 | 
			
		||||
        public TriviaQuestion(string q, string a, string c)
 | 
			
		||||
        {
 | 
			
		||||
@@ -79,9 +79,6 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
            return str;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override string ToString() =>
 | 
			
		||||
            "Question: **" + this.Question + "?**";
 | 
			
		||||
 | 
			
		||||
        private static string Scramble(string word)
 | 
			
		||||
        {
 | 
			
		||||
            var letters = word.ToArray();
 | 
			
		||||
@@ -101,7 +98,7 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
                if (letters[i] != ' ')
 | 
			
		||||
                    letters[i] = '_';
 | 
			
		||||
            }
 | 
			
		||||
            return "`" + string.Join(" ", letters) + "`";
 | 
			
		||||
            return string.Join(" ", letters);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using NadekoBot.Services;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using Newtonsoft.Json.Linq;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
@@ -11,36 +12,31 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
{
 | 
			
		||||
    public class TriviaQuestionPool
 | 
			
		||||
    {
 | 
			
		||||
        public static TriviaQuestionPool Instance { get; } = new TriviaQuestionPool();
 | 
			
		||||
        public ConcurrentHashSet<TriviaQuestion> pool = new ConcurrentHashSet<TriviaQuestion>();
 | 
			
		||||
        private static TriviaQuestionPool _instance;
 | 
			
		||||
        public static TriviaQuestionPool Instance { get; } = _instance ?? (_instance = new TriviaQuestionPool());
 | 
			
		||||
 | 
			
		||||
        private const string questionsFile = "data/trivia_questions.json";
 | 
			
		||||
 | 
			
		||||
        private Random rng { get; } = new NadekoRandom();
 | 
			
		||||
        
 | 
			
		||||
        private TriviaQuestion[] pool { get; }
 | 
			
		||||
 | 
			
		||||
        static TriviaQuestionPool() { }
 | 
			
		||||
 | 
			
		||||
        private TriviaQuestionPool()
 | 
			
		||||
        {
 | 
			
		||||
            Reload();
 | 
			
		||||
            pool = JsonConvert.DeserializeObject<TriviaQuestion[]>(File.ReadAllText(questionsFile));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public TriviaQuestion GetRandomQuestion(IEnumerable<TriviaQuestion> exclude)
 | 
			
		||||
        public TriviaQuestion GetRandomQuestion(HashSet<TriviaQuestion> exclude)
 | 
			
		||||
        {
 | 
			
		||||
            var list = pool.Except(exclude).ToList();
 | 
			
		||||
            var rand = rng.Next(0, list.Count);
 | 
			
		||||
            return list[rand];
 | 
			
		||||
        }
 | 
			
		||||
            if (pool.Length == 0)
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
        public void Reload()
 | 
			
		||||
        {
 | 
			
		||||
            var arr = JArray.Parse(File.ReadAllText("data/questions.json"));
 | 
			
		||||
            TriviaQuestion randomQuestion;
 | 
			
		||||
            while (exclude.Contains(randomQuestion = pool[rng.Next(0, pool.Length)])) ;
 | 
			
		||||
 | 
			
		||||
            foreach (var item in arr)
 | 
			
		||||
            {
 | 
			
		||||
                var tq = new TriviaQuestion(item["Question"].ToString().SanitizeMentions(), item["Answer"].ToString().SanitizeMentions(), item["Category"]?.ToString());
 | 
			
		||||
                pool.Add(tq);
 | 
			
		||||
            }
 | 
			
		||||
            var r = new NadekoRandom();
 | 
			
		||||
            pool = new ConcurrentHashSet<TriviaQuestion>(pool.OrderBy(x => r.Next()));
 | 
			
		||||
            return randomQuestion;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,29 +20,33 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Trivia(IUserMessage umsg, params string[] args)
 | 
			
		||||
            public Task Trivia(IUserMessage umsg, [Remainder] string additionalArgs = "")
 | 
			
		||||
                => Trivia(umsg, 10, additionalArgs);
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Trivia(IUserMessage umsg, int winReq = 10, [Remainder] string additionalArgs = "")
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
 | 
			
		||||
                TriviaGame trivia;
 | 
			
		||||
                if (!RunningTrivias.TryGetValue(channel.Guild.Id, out trivia))
 | 
			
		||||
                var showHints = !additionalArgs.Contains("nohint");
 | 
			
		||||
 | 
			
		||||
                TriviaGame trivia = new TriviaGame(channel.Guild, channel, showHints, winReq);
 | 
			
		||||
                if (RunningTrivias.TryAdd(channel.Guild.Id, trivia))
 | 
			
		||||
                {
 | 
			
		||||
                    var showHints = !args.Contains("nohint");
 | 
			
		||||
                    var number = args.Select(s =>
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        int num;
 | 
			
		||||
                        return new Tuple<bool, int>(int.TryParse(s, out num), num);
 | 
			
		||||
                    }).Where(t => t.Item1).Select(t => t.Item2).FirstOrDefault();
 | 
			
		||||
                    if (number < 0)
 | 
			
		||||
                        return;
 | 
			
		||||
                    var triviaGame = new TriviaGame(channel.Guild, (ITextChannel)umsg.Channel, showHints, number == 0 ? 10 : number);
 | 
			
		||||
                    if (RunningTrivias.TryAdd(channel.Guild.Id, triviaGame))
 | 
			
		||||
                        await channel.SendConfirmAsync($"**Trivia game started! {triviaGame.WinRequirement} points needed to win.**").ConfigureAwait(false);
 | 
			
		||||
                    else
 | 
			
		||||
                        await triviaGame.StopGame().ConfigureAwait(false);
 | 
			
		||||
                        await trivia.StartGame().ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                    finally
 | 
			
		||||
                    {
 | 
			
		||||
                        RunningTrivias.TryRemove(channel.Guild.Id, out trivia);
 | 
			
		||||
                        await trivia.EnsureStopped().ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                    return;                    
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                    await channel.SendErrorAsync("Trivia game is already running on this server.\n" + trivia.CurrentQuestion).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                await channel.SendErrorAsync("Trivia game is already running on this server.\n" + trivia.CurrentQuestion).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
@@ -53,9 +57,12 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
 | 
			
		||||
                TriviaGame trivia;
 | 
			
		||||
                if (RunningTrivias.TryGetValue(channel.Guild.Id, out trivia))
 | 
			
		||||
                {
 | 
			
		||||
                    await channel.SendConfirmAsync("Leaderboard", trivia.GetLeaderboard()).ConfigureAwait(false);
 | 
			
		||||
                else
 | 
			
		||||
                    await channel.SendErrorAsync("No trivia is running on this server.").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                await channel.SendErrorAsync("No trivia is running on this server.").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
@@ -68,9 +75,10 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
                if (RunningTrivias.TryGetValue(channel.Guild.Id, out trivia))
 | 
			
		||||
                {
 | 
			
		||||
                    await trivia.StopGame().ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                    await channel.SendErrorAsync("No trivia is running on this server.").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                await channel.SendErrorAsync("No trivia is running on this server.").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,17 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
    {
 | 
			
		||||
        private IAudioClient audioClient { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Player will prioritize different queuer name
 | 
			
		||||
        /// over the song position in the playlist
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool FairPlay { get; set; } = true;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Users who recently got their music wish
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private ConcurrentHashSet<string> recentlyPlayedUsers { get; } = new ConcurrentHashSet<string>();
 | 
			
		||||
 | 
			
		||||
        private readonly List<Song> playlist = new List<Song>();
 | 
			
		||||
        public IReadOnlyCollection<Song> Playlist => playlist;
 | 
			
		||||
 | 
			
		||||
@@ -107,11 +118,13 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        CurrentSong = GetNextSong();
 | 
			
		||||
                        RemoveSongAt(0);
 | 
			
		||||
 | 
			
		||||
                        if (CurrentSong == null)
 | 
			
		||||
                            continue;
 | 
			
		||||
 | 
			
		||||
                        var index = playlist.IndexOf(CurrentSong);
 | 
			
		||||
                        if (index != -1)
 | 
			
		||||
                            RemoveSongAt(index);
 | 
			
		||||
 | 
			
		||||
                        OnStarted(this, CurrentSong);
 | 
			
		||||
                        await CurrentSong.Play(audioClient, cancelToken);
 | 
			
		||||
@@ -183,8 +196,26 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
            return volume;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Song GetNextSong() =>
 | 
			
		||||
            playlist.FirstOrDefault();
 | 
			
		||||
        private Song GetNextSong()
 | 
			
		||||
        {
 | 
			
		||||
            if (!FairPlay)
 | 
			
		||||
            {
 | 
			
		||||
                return playlist.FirstOrDefault();
 | 
			
		||||
            }
 | 
			
		||||
            var song = playlist.FirstOrDefault(c => !recentlyPlayedUsers.Contains(c.QueuerName))
 | 
			
		||||
                ?? playlist.FirstOrDefault();
 | 
			
		||||
 | 
			
		||||
            if (song == null)
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            if (recentlyPlayedUsers.Contains(song.QueuerName))
 | 
			
		||||
            {
 | 
			
		||||
                recentlyPlayedUsers.Clear();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            recentlyPlayedUsers.Add(song.QueuerName);
 | 
			
		||||
            return song;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Shuffle()
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -126,6 +126,20 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Fairplay(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return;
 | 
			
		||||
            if (((IGuildUser)umsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
 | 
			
		||||
                return;
 | 
			
		||||
            var val = musicPlayer.FairPlay = !musicPlayer.FairPlay;
 | 
			
		||||
 | 
			
		||||
            await channel.SendConfirmAsync("Fair play " + (val ? "enabled" : "disabled") + ".").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Queue(IUserMessage umsg, [Remainder] string query)
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,22 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Searches.Commands.Models
 | 
			
		||||
{
 | 
			
		||||
    public struct GoogleSearchResult
 | 
			
		||||
    {
 | 
			
		||||
        public string Title { get; }
 | 
			
		||||
        public string Link { get; }
 | 
			
		||||
        public string Text { get; }
 | 
			
		||||
 | 
			
		||||
        public GoogleSearchResult(string title, string link, string text)
 | 
			
		||||
        {
 | 
			
		||||
            this.Title = title;
 | 
			
		||||
            this.Link = link;
 | 
			
		||||
            this.Text = text;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -18,6 +18,10 @@ using NadekoBot.Extensions;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using NadekoBot.Modules.Searches.Commands.OMDB;
 | 
			
		||||
using NadekoBot.Modules.Searches.Commands.Models;
 | 
			
		||||
using AngleSharp.Parser.Html;
 | 
			
		||||
using AngleSharp;
 | 
			
		||||
using AngleSharp.Dom.Html;
 | 
			
		||||
using AngleSharp.Dom;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Searches
 | 
			
		||||
{
 | 
			
		||||
@@ -41,7 +45,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
            var embed = new EmbedBuilder()
 | 
			
		||||
                .AddField(fb => fb.WithName("🌍 **Location**").WithValue(data.name + ", " + data.sys.country).WithIsInline(true))
 | 
			
		||||
                .AddField(fb => fb.WithName("📏 **Lat,Long**").WithValue($"{data.coord.lat}, {data.coord.lon}").WithIsInline(true))
 | 
			
		||||
                .AddField(fb => fb.WithName("☁ **Condition**").WithValue(String.Join(", ", data.weather.Select(w=>w.main))).WithIsInline(true))
 | 
			
		||||
                .AddField(fb => fb.WithName("☁ **Condition**").WithValue(String.Join(", ", data.weather.Select(w => w.main))).WithIsInline(true))
 | 
			
		||||
                .AddField(fb => fb.WithName("😓 **Humidity**").WithValue($"{data.main.humidity}%").WithIsInline(true))
 | 
			
		||||
                .AddField(fb => fb.WithName("💨 **Wind Speed**").WithValue(data.wind.speed + " km/h").WithIsInline(true))
 | 
			
		||||
                .AddField(fb => fb.WithName("🌡 **Temperature**").WithValue(data.main.temp + "°C").WithIsInline(true))
 | 
			
		||||
@@ -214,18 +218,63 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                                                            .ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //private readonly Regex googleSearchRegex = new Regex(@"<h3 class=""r""><a href=""(?:\/url?q=)?(?<link>.*?)"".*?>(?<title>.*?)<\/a>.*?class=""st"">(?<text>.*?)<\/span>", RegexOptions.Compiled);
 | 
			
		||||
        //private readonly Regex htmlReplace = new Regex(@"(?:<b>(.*?)<\/b>|<em>(.*?)<\/em>)", RegexOptions.Compiled);
 | 
			
		||||
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Google(IUserMessage umsg, [Remainder] string terms = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            terms = terms?.Trim();
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(terms))
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            await channel.SendMessageAsync($"https://google.com/search?q={ WebUtility.UrlEncode(terms).Replace(' ', '+') }")
 | 
			
		||||
                           .ConfigureAwait(false);
 | 
			
		||||
            terms = WebUtility.UrlEncode(terms).Replace(' ', '+');
 | 
			
		||||
 | 
			
		||||
            var fullQueryLink = $"https://www.google.com/search?q={ terms }&gws_rd=cr,ssl";
 | 
			
		||||
            var config = Configuration.Default.WithDefaultLoader();
 | 
			
		||||
            var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink);
 | 
			
		||||
 | 
			
		||||
            var elems = document.QuerySelectorAll("div.g");
 | 
			
		||||
 | 
			
		||||
            var resultsElem = document.QuerySelectorAll("#resultStats").FirstOrDefault();
 | 
			
		||||
            var totalResults = resultsElem?.TextContent;
 | 
			
		||||
            //var time = resultsElem.Children.FirstOrDefault()?.TextContent
 | 
			
		||||
            //^ this doesn't work for some reason, <nobr> is completely missing in parsed collection
 | 
			
		||||
            if (!elems.Any())
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            var results = elems.Select<IElement, GoogleSearchResult?>(elem =>
 | 
			
		||||
            {
 | 
			
		||||
                var aTag = (elem.Children.FirstOrDefault().Children.FirstOrDefault() as IHtmlAnchorElement); // <h3> -> <a>
 | 
			
		||||
                var href = aTag?.Href;
 | 
			
		||||
                var name = aTag?.TextContent;
 | 
			
		||||
                if (href == null || name == null)
 | 
			
		||||
                    return null;
 | 
			
		||||
 | 
			
		||||
                var txt = elem.QuerySelectorAll(".st").FirstOrDefault()?.TextContent;
 | 
			
		||||
 | 
			
		||||
                if (txt == null)
 | 
			
		||||
                    return null;
 | 
			
		||||
 | 
			
		||||
                return new GoogleSearchResult(name, href, txt);
 | 
			
		||||
            }).Where(x => x != null).Take(5);
 | 
			
		||||
 | 
			
		||||
            var embed = new EmbedBuilder()
 | 
			
		||||
                .WithOkColor()
 | 
			
		||||
                .WithAuthor(eab => eab.WithName("Search For: " + terms)
 | 
			
		||||
                    .WithUrl(fullQueryLink)
 | 
			
		||||
                    .WithIconUrl("http://i.imgur.com/G46fm8J.png"))
 | 
			
		||||
                .WithTitle(umsg.Author.Mention)
 | 
			
		||||
                .WithFooter(efb => efb.WithText(totalResults));
 | 
			
		||||
            string desc = "";
 | 
			
		||||
            foreach (GoogleSearchResult res in results)
 | 
			
		||||
            {
 | 
			
		||||
                desc += $"[{Format.Bold(res.Title)}]({res.Link})\n{res.Text}\n\n";
 | 
			
		||||
            }
 | 
			
		||||
            await channel.EmbedAsync(embed.WithDescription(desc).Build()).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
@@ -265,7 +314,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                                    .AddField(efb => efb.WithName("Store Url").WithValue(storeUrl).WithIsInline(true))
 | 
			
		||||
                                    .AddField(efb => efb.WithName("Cost").WithValue(cost).WithIsInline(true))
 | 
			
		||||
                                    .AddField(efb => efb.WithName("Types").WithValue(types).WithIsInline(true));
 | 
			
		||||
                                    //.AddField(efb => efb.WithName("Store Url").WithValue(await NadekoBot.Google.ShortenUrl(items[0]["store_url"].ToString())).WithIsInline(true));
 | 
			
		||||
                    //.AddField(efb => efb.WithName("Store Url").WithValue(await NadekoBot.Google.ShortenUrl(items[0]["store_url"].ToString())).WithIsInline(true));
 | 
			
		||||
 | 
			
		||||
                    await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
@@ -614,7 +663,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                return "http:" + matches[rng.Next(0, matches.Count)].Groups["url"].Value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Wikia(IUserMessage umsg, string target, [Remainder] string query = null)
 | 
			
		||||
@@ -730,4 +779,4 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <DnxInvisibleContent Include="data\questions.json" />
 | 
			
		||||
    <DnxInvisibleContent Include="data\questions2.json" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
 | 
			
		||||
</Project>
 | 
			
		||||
							
								
								
									
										39
									
								
								src/NadekoBot/Resources/CommandStrings.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										39
									
								
								src/NadekoBot/Resources/CommandStrings.Designer.cs
									
									
									
										generated
									
									
									
								
							@@ -1374,7 +1374,7 @@ namespace NadekoBot.Resources {
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        ///    Looks up a localized string similar to `{0}cm "module name" enable SomeChannel`.
 | 
			
		||||
        ///    Looks up a localized string similar to `{0}cm ModuleName enable SomeChannel`.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string chnlmdl_usage {
 | 
			
		||||
            get {
 | 
			
		||||
@@ -2435,6 +2435,33 @@ namespace NadekoBot.Resources {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        ///    Looks up a localized string similar to fairplay fp.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string fairplay_cmd {
 | 
			
		||||
            get {
 | 
			
		||||
                return ResourceManager.GetString("fairplay_cmd", resourceCulture);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        ///    Looks up a localized string similar to Toggles fairplay. While enabled, music player will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue..
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string fairplay_desc {
 | 
			
		||||
            get {
 | 
			
		||||
                return ResourceManager.GetString("fairplay_desc", resourceCulture);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        ///    Looks up a localized string similar to `{0}fp`.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string fairplay_usage {
 | 
			
		||||
            get {
 | 
			
		||||
                return ResourceManager.GetString("fairplay_usage", resourceCulture);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        ///    Looks up a localized string similar to fw.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -5856,7 +5883,7 @@ namespace NadekoBot.Resources {
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        ///    Looks up a localized string similar to `{0}rm "module name" enable MyRole`.
 | 
			
		||||
        ///    Looks up a localized string similar to `{0}rm ModuleName enable MyRole`.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string rolemdl_usage {
 | 
			
		||||
            get {
 | 
			
		||||
@@ -5901,7 +5928,7 @@ namespace NadekoBot.Resources {
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        ///    Looks up a localized string similar to Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y..
 | 
			
		||||
        ///    Looks up a localized string similar to Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. Y can be a letter 'F' if you want to roll fate dice instead of dnd..
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string roll_desc {
 | 
			
		||||
            get {
 | 
			
		||||
@@ -5910,7 +5937,7 @@ namespace NadekoBot.Resources {
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        ///    Looks up a localized string similar to `{0}roll` or `{0}roll 7` or `{0}roll 3d5`.
 | 
			
		||||
        ///    Looks up a localized string similar to `{0}roll` or `{0}roll 7` or `{0}roll 3d5` or `{0}roll 5dF`.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string roll_usage {
 | 
			
		||||
            get {
 | 
			
		||||
@@ -6909,7 +6936,7 @@ namespace NadekoBot.Resources {
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        ///    Looks up a localized string similar to `{0}sm "module name" enable`.
 | 
			
		||||
        ///    Looks up a localized string similar to `{0}sm ModuleName enable`.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string srvrmdl_usage {
 | 
			
		||||
            get {
 | 
			
		||||
@@ -7692,7 +7719,7 @@ namespace NadekoBot.Resources {
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        ///    Looks up a localized string similar to `{0}um "module name" enable SomeUsername`.
 | 
			
		||||
        ///    Looks up a localized string similar to `{0}um ModuleName enable SomeUsername`.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string usrmdl_usage {
 | 
			
		||||
            get {
 | 
			
		||||
 
 | 
			
		||||
@@ -2817,4 +2817,13 @@
 | 
			
		||||
  <data name="log_usage" xml:space="preserve">
 | 
			
		||||
    <value>`{0}log userpresence` or `{0}log userbanned`</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="fairplay_cmd" xml:space="preserve">
 | 
			
		||||
    <value>fairplay fp</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="fairplay_desc" xml:space="preserve">
 | 
			
		||||
    <value>Toggles fairplay. While enabled, music player will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue.</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="fairplay_usage" xml:space="preserve">
 | 
			
		||||
    <value>`{0}fp`</value>
 | 
			
		||||
  </data>
 | 
			
		||||
</root>
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1
									
								
								src/NadekoBot/data/trivia_questions.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/NadekoBot/data/trivia_questions.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -25,8 +25,10 @@
 | 
			
		||||
    "Discord.Net": {
 | 
			
		||||
      "target": "project"
 | 
			
		||||
    },
 | 
			
		||||
    "AngleSharp": "0.9.9",
 | 
			
		||||
    "Google.Apis.Urlshortener.v1": "1.19.0.138",
 | 
			
		||||
    "Google.Apis.YouTube.v3": "1.20.0.701",
 | 
			
		||||
    "Google.Apis.Customsearch.v1": "1.20.0.466",
 | 
			
		||||
    "ImageSharp": "1.0.0-alpha-000079",
 | 
			
		||||
    "Microsoft.EntityFrameworkCore": "1.1.0",
 | 
			
		||||
    "Microsoft.EntityFrameworkCore.Design": "1.1.0",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user