From fa29131818fec2b650422ae960b8f75ea8957ad0 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 6 Jun 2017 00:46:58 +0200 Subject: [PATCH] Made events run async where needed, fixed .startevent flowerreaction and running commands in DMs --- src/NadekoBot/Command Errors 2017-06-05.txt | 34 + .../Commands/LocalizationCommands.cs | 2 - .../Modules/Gambling/Commands/AnimalRacing.cs | 2 +- .../Gambling/Commands/CurrencyEvents.cs | 4 +- .../Modules/Games/Commands/Acropobia.cs | 168 +-- .../Games/Commands/Hangman/HangmanGame.cs | 116 +- .../Games/Commands/Models/TypingGame.cs | 58 +- .../Modules/Games/Commands/TicTacToe.cs | 2 +- .../Games/Commands/Trivia/TriviaGame.cs | 102 +- .../Searches/Commands/AnimeSearchCommands.cs | 88 +- src/NadekoBot/NadekoBot.cs | 2 + src/NadekoBot/NadekoBot.csproj | 4 +- .../Administration/AutoAssignRoleService.cs | 25 +- .../Administration/LogCommandService.cs | 1121 +++++++++-------- .../Services/Administration/MuteService.cs | 9 +- src/NadekoBot/Services/CommandHandler.cs | 2 +- src/NadekoBot/Services/Games/GamesService.cs | 70 +- .../Services/Searches/AnimeSearchService.cs | 98 ++ .../Searches}/Models/AnimeResult.cs | 2 +- .../Searches/{ => Models}/MagicItem.cs | 0 .../Searches}/Models/MangaResult.cs | 2 +- .../Searches/{ => Models}/SearchPokemon.cs | 0 .../Searches/{ => Models}/StreamResponses.cs | 0 .../Services/Searches/{ => Models}/WoWJoke.cs | 0 .../Services/Searches/SearchesService.cs | 47 +- .../Services/Utility/UtilityService.cs | 62 +- 26 files changed, 1089 insertions(+), 931 deletions(-) create mode 100644 src/NadekoBot/Command Errors 2017-06-05.txt create mode 100644 src/NadekoBot/Services/Searches/AnimeSearchService.cs rename src/NadekoBot/{Modules/Searches/Commands => Services/Searches}/Models/AnimeResult.cs (93%) rename src/NadekoBot/Services/Searches/{ => Models}/MagicItem.cs (100%) rename src/NadekoBot/{Modules/Searches/Commands => Services/Searches}/Models/MangaResult.cs (92%) rename src/NadekoBot/Services/Searches/{ => Models}/SearchPokemon.cs (100%) rename src/NadekoBot/Services/Searches/{ => Models}/StreamResponses.cs (100%) rename src/NadekoBot/Services/Searches/{ => Models}/WoWJoke.cs (100%) diff --git a/src/NadekoBot/Command Errors 2017-06-05.txt b/src/NadekoBot/Command Errors 2017-06-05.txt new file mode 100644 index 00000000..c1dfe433 --- /dev/null +++ b/src/NadekoBot/Command Errors 2017-06-05.txt @@ -0,0 +1,34 @@ +[16:25-2017-06-05] +System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.Http.WinHttpException: The server name or address could not be resolved + at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) + at System.Net.Http.WinHttpHandler.d__105.MoveNext() + --- End of inner exception stack trace --- + at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) + at System.Net.Http.HttpClient.d__58.MoveNext() +--- End of stack trace from previous location where exception was thrown --- + at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) + at System.Net.Http.HttpClient.d__32`1.MoveNext() +--- End of stack trace from previous location where exception was thrown --- + at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) + at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() + at NadekoBot.Modules.Searches.Searches.JokeCommands.d__3.MoveNext() in C:\Users\Kwoth\Documents\projekti\NadekoBot1.0\src\NadekoBot\Modules\Searches\Commands\JokeCommands.cs:line 40 +--- End of stack trace from previous location where exception was thrown --- + at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) + at Discord.Commands.ModuleClassBuilder.<>c__DisplayClass6_1.<b__1>d.MoveNext() +--- End of stack trace from previous location where exception was thrown --- + at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) + at Discord.Commands.CommandInfo.d__38.MoveNext() +--- End of stack trace from previous location where exception was thrown --- + at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + at Discord.Commands.CommandInfo.d__38.MoveNext() +--- End of stack trace from previous location where exception was thrown --- + at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) + at Discord.Commands.CommandInfo.d__37.MoveNext() +------ diff --git a/src/NadekoBot/Modules/Administration/Commands/LocalizationCommands.cs b/src/NadekoBot/Modules/Administration/Commands/LocalizationCommands.cs index ac0789a0..eef4b14c 100644 --- a/src/NadekoBot/Modules/Administration/Commands/LocalizationCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/LocalizationCommands.cs @@ -16,8 +16,6 @@ namespace NadekoBot.Modules.Administration [Group] public class LocalizationCommands : NadekoSubmodule { - //Română, România - //Bahasa Indonesia, Indonesia private static ImmutableDictionary supportedLocales { get; } = new Dictionary() { {"ar", "العربية" }, diff --git a/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs b/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs index 00cbf7ae..70b0dd14 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs @@ -255,7 +255,7 @@ namespace NadekoBot.Modules.Gambling return Task.CompletedTask; if ((msg.Author.Id == _client.CurrentUser.Id) || !(imsg.Channel is ITextChannel) || imsg.Channel != _raceChannel) return Task.CompletedTask; - _messagesSinceGameStarted++; + Interlocked.Increment(ref _messagesSinceGameStarted); return Task.CompletedTask; } diff --git a/src/NadekoBot/Modules/Gambling/Commands/CurrencyEvents.cs b/src/NadekoBot/Modules/Gambling/Commands/CurrencyEvents.cs index acb1169a..9ae419be 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/CurrencyEvents.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/CurrencyEvents.cs @@ -194,10 +194,10 @@ namespace NadekoBot.Modules.Gambling StartingMessage = umsg; _client.MessageDeleted += MessageDeletedEventHandler; - try { await StartingMessage.AddReactionAsync(Emote.Parse("🌸")).ConfigureAwait(false); } + try { await StartingMessage.AddReactionAsync(new Emoji("🌸")).ConfigureAwait(false); } catch { - try { await StartingMessage.AddReactionAsync(Emote.Parse("🌸")).ConfigureAwait(false); } + try { await StartingMessage.AddReactionAsync(new Emoji("🌸")).ConfigureAwait(false); } catch { try { await StartingMessage.DeleteAsync().ConfigureAwait(false); } diff --git a/src/NadekoBot/Modules/Games/Commands/Acropobia.cs b/src/NadekoBot/Modules/Games/Commands/Acropobia.cs index ef0c08f8..dd1c49b2 100644 --- a/src/NadekoBot/Modules/Games/Commands/Acropobia.cs +++ b/src/NadekoBot/Modules/Games/Commands/Acropobia.cs @@ -186,101 +186,105 @@ $@"-- private async Task PotentialAcro(SocketMessage arg) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - var msg = arg as SocketUserMessage; - if (msg == null || msg.Author.IsBot || msg.Channel.Id != _channel.Id) - return; - - ++_spamCount; - - var guildUser = (IGuildUser)msg.Author; - - var input = msg.Content.ToUpperInvariant().Trim(); - - if (phase == AcroPhase.Submitting) + try { - if (_spamCount > 10) - { - _spamCount = 0; - try { await _channel.EmbedAsync(GetEmbed()).ConfigureAwait(false); } - catch { } - } - var inputWords = input.Split(' '); //get all words - - if (inputWords.Length != _startingLetters.Length) // number of words must be the same as the number of the starting letters + var msg = arg as SocketUserMessage; + if (msg == null || msg.Author.IsBot || msg.Channel.Id != _channel.Id) return; - for (int i = 0; i < _startingLetters.Length; i++) - { - var letter = _startingLetters[i]; + ++_spamCount; - if (!inputWords[i].StartsWith(letter.ToString())) // all first letters must match + var guildUser = (IGuildUser)msg.Author; + + var input = msg.Content.ToUpperInvariant().Trim(); + + if (phase == AcroPhase.Submitting) + { + if (_spamCount > 10) + { + _spamCount = 0; + try { await _channel.EmbedAsync(GetEmbed()).ConfigureAwait(false); } + catch { } + } + var inputWords = input.Split(' '); //get all words + + if (inputWords.Length != _startingLetters.Length) // number of words must be the same as the number of the starting letters return; - } + + for (int i = 0; i < _startingLetters.Length; i++) + { + var letter = _startingLetters[i]; + + if (!inputWords[i].StartsWith(letter.ToString())) // all first letters must match + return; + } - if (!_usersWhoSubmitted.Add(guildUser.Id)) - return; - //try adding it to the list of answers - if (!_submissions.TryAdd(input, guildUser)) - { - _usersWhoSubmitted.TryRemove(guildUser.Id); - return; - } - - // all good. valid input. answer recorded - await _channel.SendConfirmAsync(GetText("acrophobia"), - GetText("acro_submit", guildUser.Mention, - _submissions.Count)); - try - { - await msg.DeleteAsync(); - } - catch - { - await msg.DeleteAsync(); //try twice - } - } - else if (phase == AcroPhase.Voting) - { - if (_spamCount > 10) - { - _spamCount = 0; - try { await _channel.EmbedAsync(GetEmbed()).ConfigureAwait(false); } - catch { } - } - - //if (submissions.TryGetValue(input, out usr) && usr.Id != guildUser.Id) - //{ - // if (!usersWhoVoted.Add(guildUser.Id)) - // return; - // votes.AddOrUpdate(input, 1, (key, old) => ++old); - // await channel.SendConfirmAsync("Acrophobia", $"{guildUser.Mention} cast their vote!").ConfigureAwait(false); - // await msg.DeleteAsync().ConfigureAwait(false); - // return; - //} - - int num; - if (int.TryParse(input, out num) && num > 0 && num <= _submissions.Count) - { - var kvp = _submissions.Skip(num - 1).First(); - var usr = kvp.Value; - //can't vote for yourself, can't vote multiple times - if (usr.Id == guildUser.Id || !_usersWhoVoted.Add(guildUser.Id)) + if (!_usersWhoSubmitted.Add(guildUser.Id)) return; - _votes.AddOrUpdate(kvp.Key, 1, (key, old) => ++old); + //try adding it to the list of answers + if (!_submissions.TryAdd(input, guildUser)) + { + _usersWhoSubmitted.TryRemove(guildUser.Id); + return; + } + + // all good. valid input. answer recorded await _channel.SendConfirmAsync(GetText("acrophobia"), - GetText("acro_vote_cast", Format.Bold(guildUser.ToString()))).ConfigureAwait(false); - await msg.DeleteAsync().ConfigureAwait(false); + GetText("acro_submit", guildUser.Mention, + _submissions.Count)); + try + { + await msg.DeleteAsync(); + } + catch + { + await msg.DeleteAsync(); //try twice + } } + else if (phase == AcroPhase.Voting) + { + if (_spamCount > 10) + { + _spamCount = 0; + try { await _channel.EmbedAsync(GetEmbed()).ConfigureAwait(false); } + catch { } + } + //if (submissions.TryGetValue(input, out usr) && usr.Id != guildUser.Id) + //{ + // if (!usersWhoVoted.Add(guildUser.Id)) + // return; + // votes.AddOrUpdate(input, 1, (key, old) => ++old); + // await channel.SendConfirmAsync("Acrophobia", $"{guildUser.Mention} cast their vote!").ConfigureAwait(false); + // await msg.DeleteAsync().ConfigureAwait(false); + // return; + //} + + int num; + if (int.TryParse(input, out num) && num > 0 && num <= _submissions.Count) + { + var kvp = _submissions.Skip(num - 1).First(); + var usr = kvp.Value; + //can't vote for yourself, can't vote multiple times + if (usr.Id == guildUser.Id || !_usersWhoVoted.Add(guildUser.Id)) + return; + _votes.AddOrUpdate(kvp.Key, 1, (key, old) => ++old); + await _channel.SendConfirmAsync(GetText("acrophobia"), + GetText("acro_vote_cast", Format.Bold(guildUser.ToString()))).ConfigureAwait(false); + await msg.DeleteAsync().ConfigureAwait(false); + } + + } } - } - catch (Exception ex) - { - _log.Warn(ex); - } + catch (Exception ex) + { + _log.Warn(ex); + } + }); } public async Task End() diff --git a/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs b/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs index c59ada3a..4793ea9b 100644 --- a/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs +++ b/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs @@ -119,77 +119,81 @@ namespace NadekoBot.Modules.Games.Hangman private async Task PotentialGuess(SocketMessage msg) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - if (!(msg is SocketUserMessage)) - return; - - if (msg.Channel != GameChannel) - return; // message's channel has to be the same as game's - if (msg.Content.Length == 1) // message must be 1 char long + try { - if (++MessagesSinceLastPost > 10) + if (!(msg is SocketUserMessage)) + return; + + if (msg.Channel != GameChannel) + return; // message's channel has to be the same as game's + if (msg.Content.Length == 1) // message must be 1 char long { - MessagesSinceLastPost = 0; - try + if (++MessagesSinceLastPost > 10) { - await GameChannel.SendConfirmAsync("Hangman Game", - ScrambledWord + "\n" + GetHangman(), - footer: string.Join(" ", Guesses)).ConfigureAwait(false); + MessagesSinceLastPost = 0; + try + { + await GameChannel.SendConfirmAsync("Hangman Game", + ScrambledWord + "\n" + GetHangman(), + footer: string.Join(" ", Guesses)).ConfigureAwait(false); + } + catch { } } - catch { } - } - if (!(char.IsLetter(msg.Content[0]) || char.IsDigit(msg.Content[0])))// and a letter or a digit - return; + if (!(char.IsLetter(msg.Content[0]) || char.IsDigit(msg.Content[0])))// and a letter or a digit + return; - var guess = char.ToUpperInvariant(msg.Content[0]); - if (Guesses.Contains(guess)) - { - MessagesSinceLastPost = 0; - ++Errors; - if (Errors < MaxErrors) - await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author} Letter `{guess}` has already been used.\n" + ScrambledWord + "\n" + GetHangman(), - footer: string.Join(" ", Guesses)).ConfigureAwait(false); - else - await End().ConfigureAwait(false); - return; - } - - Guesses.Add(guess); - - if (Term.Word.ToUpperInvariant().Contains(guess)) - { - if (GuessedAll) + var guess = char.ToUpperInvariant(msg.Content[0]); + if (Guesses.Contains(guess)) { - try { await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author} guessed a letter `{guess}`!").ConfigureAwait(false); } catch { } - - await End().ConfigureAwait(false); + MessagesSinceLastPost = 0; + ++Errors; + if (Errors < MaxErrors) + await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author} Letter `{guess}` has already been used.\n" + ScrambledWord + "\n" + GetHangman(), + footer: string.Join(" ", Guesses)).ConfigureAwait(false); + else + await End().ConfigureAwait(false); return; } - MessagesSinceLastPost = 0; - try + + Guesses.Add(guess); + + if (Term.Word.ToUpperInvariant().Contains(guess)) { - await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author} guessed a letter `{guess}`!\n" + ScrambledWord + "\n" + GetHangman(), - footer: string.Join(" ", Guesses)).ConfigureAwait(false); + if (GuessedAll) + { + try { await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author} guessed a letter `{guess}`!").ConfigureAwait(false); } catch { } + + await End().ConfigureAwait(false); + return; + } + MessagesSinceLastPost = 0; + try + { + await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author} guessed a letter `{guess}`!\n" + ScrambledWord + "\n" + GetHangman(), + footer: string.Join(" ", Guesses)).ConfigureAwait(false); + } + catch { } + } - catch { } - - } - else - { - MessagesSinceLastPost = 0; - ++Errors; - if (Errors < MaxErrors) - await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author} Letter `{guess}` does not exist.\n" + ScrambledWord + "\n" + GetHangman(), - footer: string.Join(" ", Guesses)).ConfigureAwait(false); else - await End().ConfigureAwait(false); - } + { + MessagesSinceLastPost = 0; + ++Errors; + if (Errors < MaxErrors) + await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author} Letter `{guess}` does not exist.\n" + ScrambledWord + "\n" + GetHangman(), + footer: string.Join(" ", Guesses)).ConfigureAwait(false); + else + await End().ConfigureAwait(false); + } + } } - } - catch (Exception ex) { _log.Warn(ex); } + catch (Exception ex) { _log.Warn(ex); } + }); } public string GetHangman() => $@". ┌─────┐ diff --git a/src/NadekoBot/Modules/Games/Commands/Models/TypingGame.cs b/src/NadekoBot/Modules/Games/Commands/Models/TypingGame.cs index 071739a4..eff53fb4 100644 --- a/src/NadekoBot/Modules/Games/Commands/Models/TypingGame.cs +++ b/src/NadekoBot/Modules/Games/Commands/Models/TypingGame.cs @@ -109,38 +109,42 @@ namespace NadekoBot.Modules.Games.Models private async Task AnswerReceived(SocketMessage imsg) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - if (imsg.Author.IsBot) - return; - var msg = imsg as SocketUserMessage; - if (msg == null) - return; - - if (this.Channel == null || this.Channel.Id != msg.Channel.Id) return; - - var guess = msg.Content; - - var distance = CurrentSentence.LevenshteinDistance(guess); - var decision = Judge(distance, guess.Length); - if (decision && !finishedUserIds.Contains(msg.Author.Id)) + try { - var elapsed = sw.Elapsed; - var wpm = CurrentSentence.Length / WORD_VALUE / elapsed.TotalSeconds * 60; - finishedUserIds.Add(msg.Author.Id); - await this.Channel.EmbedAsync(new EmbedBuilder().WithOkColor() - .WithTitle($"{msg.Author} finished the race!") - .AddField(efb => efb.WithName("Place").WithValue($"#{finishedUserIds.Count}").WithIsInline(true)) - .AddField(efb => efb.WithName("WPM").WithValue($"{wpm:F1} *[{elapsed.TotalSeconds:F2}sec]*").WithIsInline(true)) - .AddField(efb => efb.WithName("Errors").WithValue(distance.ToString()).WithIsInline(true))) - .ConfigureAwait(false); - if (finishedUserIds.Count % 4 == 0) + if (imsg.Author.IsBot) + return; + var msg = imsg as SocketUserMessage; + if (msg == null) + return; + + if (this.Channel == null || this.Channel.Id != msg.Channel.Id) return; + + var guess = msg.Content; + + var distance = CurrentSentence.LevenshteinDistance(guess); + var decision = Judge(distance, guess.Length); + if (decision && !finishedUserIds.Contains(msg.Author.Id)) { - await this.Channel.SendConfirmAsync($":exclamation: A lot of people finished, here is the text for those still typing:\n\n**{Format.Sanitize(CurrentSentence.Replace(" ", " \x200B")).SanitizeMentions()}**").ConfigureAwait(false); + var elapsed = sw.Elapsed; + var wpm = CurrentSentence.Length / WORD_VALUE / elapsed.TotalSeconds * 60; + finishedUserIds.Add(msg.Author.Id); + await this.Channel.EmbedAsync(new EmbedBuilder().WithOkColor() + .WithTitle($"{msg.Author} finished the race!") + .AddField(efb => efb.WithName("Place").WithValue($"#{finishedUserIds.Count}").WithIsInline(true)) + .AddField(efb => efb.WithName("WPM").WithValue($"{wpm:F1} *[{elapsed.TotalSeconds:F2}sec]*").WithIsInline(true)) + .AddField(efb => efb.WithName("Errors").WithValue(distance.ToString()).WithIsInline(true))) + .ConfigureAwait(false); + if (finishedUserIds.Count % 4 == 0) + { + await this.Channel.SendConfirmAsync($":exclamation: A lot of people finished, here is the text for those still typing:\n\n**{Format.Sanitize(CurrentSentence.Replace(" ", " \x200B")).SanitizeMentions()}**").ConfigureAwait(false); + } } } - } - catch (Exception ex) { _log.Warn(ex); } + catch (Exception ex) { _log.Warn(ex); } + }); } private bool Judge(int errors, int textLength) => errors <= textLength / 25; diff --git a/src/NadekoBot/Modules/Games/Commands/TicTacToe.cs b/src/NadekoBot/Modules/Games/Commands/TicTacToe.cs index c0e7e8b1..7de40565 100644 --- a/src/NadekoBot/Modules/Games/Commands/TicTacToe.cs +++ b/src/NadekoBot/Modules/Games/Commands/TicTacToe.cs @@ -237,7 +237,7 @@ namespace NadekoBot.Modules.Games return true; } - private Task Client_MessageReceived(Discord.WebSocket.SocketMessage msg) + private Task Client_MessageReceived(SocketMessage msg) { var _ = Task.Run(async () => { diff --git a/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs b/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs index 0521d3cc..8a89dbbf 100644 --- a/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs +++ b/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs @@ -180,64 +180,68 @@ namespace NadekoBot.Modules.Games.Trivia private async Task PotentialGuess(SocketMessage imsg) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - if (imsg.Author.IsBot) - return; - - var umsg = imsg as SocketUserMessage; - - var textChannel = umsg?.Channel as ITextChannel; - if (textChannel == null || textChannel.Guild != Guild) - return; - - var guildUser = (IGuildUser)umsg.Author; - - var guess = false; - await _guessLock.WaitAsync().ConfigureAwait(false); try { - if (GameActive && CurrentQuestion.IsAnswerCorrect(umsg.Content) && !triviaCancelSource.IsCancellationRequested) - { - Users.AddOrUpdate(guildUser, 1, (gu, old) => ++old); - guess = true; - } - } - finally { _guessLock.Release(); } - if (!guess) return; - triviaCancelSource.Cancel(); + if (imsg.Author.IsBot) + return; + var umsg = imsg as SocketUserMessage; - if (Users[guildUser] == WinRequirement) - { - ShouldStopGame = true; + var textChannel = umsg?.Channel as ITextChannel; + if (textChannel == null || textChannel.Guild != Guild) + return; + + var guildUser = (IGuildUser)umsg.Author; + + var guess = false; + await _guessLock.WaitAsync().ConfigureAwait(false); try { - await Channel.EmbedAsync(new EmbedBuilder().WithOkColor() - .WithTitle(GetText("trivia_game")) - .WithDescription(GetText("trivia_win", - guildUser.Mention, - Format.Bold(CurrentQuestion.Answer))) - .WithImageUrl(CurrentQuestion.AnswerImageUrl)) - .ConfigureAwait(false); + if (GameActive && CurrentQuestion.IsAnswerCorrect(umsg.Content) && !triviaCancelSource.IsCancellationRequested) + { + Users.AddOrUpdate(guildUser, 1, (gu, old) => ++old); + guess = true; + } } - catch - { - // ignored - } - var reward = _bc.TriviaCurrencyReward; - if (reward > 0) - await _cs.AddAsync(guildUser, "Won trivia", reward, true).ConfigureAwait(false); - return; - } + finally { _guessLock.Release(); } + if (!guess) return; + triviaCancelSource.Cancel(); - await Channel.EmbedAsync(new EmbedBuilder().WithOkColor() - .WithTitle(GetText("trivia_game")) - .WithDescription(GetText("trivia_guess", guildUser.Mention, Format.Bold(CurrentQuestion.Answer))) - .WithImageUrl(CurrentQuestion.AnswerImageUrl)) - .ConfigureAwait(false); - } - catch (Exception ex) { _log.Warn(ex); } + + if (Users[guildUser] == WinRequirement) + { + ShouldStopGame = true; + try + { + await Channel.EmbedAsync(new EmbedBuilder().WithOkColor() + .WithTitle(GetText("trivia_game")) + .WithDescription(GetText("trivia_win", + guildUser.Mention, + Format.Bold(CurrentQuestion.Answer))) + .WithImageUrl(CurrentQuestion.AnswerImageUrl)) + .ConfigureAwait(false); + } + catch + { + // ignored + } + var reward = _bc.TriviaCurrencyReward; + if (reward > 0) + await _cs.AddAsync(guildUser, "Won trivia", reward, true).ConfigureAwait(false); + return; + } + + await Channel.EmbedAsync(new EmbedBuilder().WithOkColor() + .WithTitle(GetText("trivia_game")) + .WithDescription(GetText("trivia_guess", guildUser.Mention, Format.Bold(CurrentQuestion.Answer))) + .WithImageUrl(CurrentQuestion.AnswerImageUrl)) + .ConfigureAwait(false); + } + catch (Exception ex) { _log.Warn(ex); } + }); } public string GetLeaderboard() diff --git a/src/NadekoBot/Modules/Searches/Commands/AnimeSearchCommands.cs b/src/NadekoBot/Modules/Searches/Commands/AnimeSearchCommands.cs index 8b5c012a..c80bd2c1 100644 --- a/src/NadekoBot/Modules/Searches/Commands/AnimeSearchCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/AnimeSearchCommands.cs @@ -4,13 +4,9 @@ using Discord; using Discord.Commands; using NadekoBot.Attributes; using NadekoBot.Extensions; -using NadekoBot.Modules.Searches.Models; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using NadekoBot.Services.Searches; using System; -using System.Collections.Generic; using System.Linq; -using System.Net.Http; using System.Threading; using System.Threading.Tasks; @@ -21,37 +17,11 @@ namespace NadekoBot.Modules.Searches [Group] public class AnimeSearchCommands : NadekoSubmodule { - private static readonly Timer anilistTokenRefresher; - private static string anilistToken { get; set; } + private readonly AnimeSearchService _service; - static AnimeSearchCommands() + public AnimeSearchCommands(AnimeSearchService service) { - anilistTokenRefresher = new Timer(async (state) => - { - try - { - var headers = new Dictionary - { - {"grant_type", "client_credentials"}, - {"client_id", "kwoth-w0ki9"}, - {"client_secret", "Qd6j4FIAi1ZK6Pc7N7V4Z"}, - }; - - using (var http = new HttpClient()) - { - //http.AddFakeHeaders(); - http.DefaultRequestHeaders.Clear(); - var formContent = new FormUrlEncodedContent(headers); - var response = await http.PostAsync("https://anilist.co/api/auth/access_token", formContent).ConfigureAwait(false); - var stringContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - anilistToken = JObject.Parse(stringContent)["access_token"].ToString(); - } - } - catch - { - // ignored - } - }, null, TimeSpan.FromSeconds(0), TimeSpan.FromMinutes(29)); + _service = service; } [NadekoCommand, Usage, Description, Aliases] @@ -171,7 +141,7 @@ namespace NadekoBot.Modules.Searches if (string.IsNullOrWhiteSpace(query)) return; - var animeData = await GetAnimeData(query).ConfigureAwait(false); + var animeData = await _service.GetAnimeData(query).ConfigureAwait(false); if (animeData == null) { @@ -198,7 +168,7 @@ namespace NadekoBot.Modules.Searches if (string.IsNullOrWhiteSpace(query)) return; - var mangaData = await GetMangaData(query).ConfigureAwait(false); + var mangaData = await _service.GetMangaData(query).ConfigureAwait(false); if (mangaData == null) { @@ -218,52 +188,6 @@ namespace NadekoBot.Modules.Searches await Context.Channel.EmbedAsync(embed).ConfigureAwait(false); } - - private async Task GetAnimeData(string query) - { - if (string.IsNullOrWhiteSpace(query)) - throw new ArgumentNullException(nameof(query)); - try - { - - var link = "http://anilist.co/api/anime/search/" + Uri.EscapeUriString(query); - using (var http = new HttpClient()) - { - var res = await http.GetStringAsync(link + $"?access_token={anilistToken}").ConfigureAwait(false); - var smallObj = JArray.Parse(res)[0]; - var aniData = await http.GetStringAsync("http://anilist.co/api/anime/" + smallObj["id"] + $"?access_token={anilistToken}").ConfigureAwait(false); - - return await Task.Run(() => { try { return JsonConvert.DeserializeObject(aniData); } catch { return null; } }).ConfigureAwait(false); - } - } - catch (Exception ex) - { - _log.Warn(ex, "Failed anime search for {0}", query); - return null; - } - } - - private async Task GetMangaData(string query) - { - if (string.IsNullOrWhiteSpace(query)) - throw new ArgumentNullException(nameof(query)); - try - { - using (var http = new HttpClient()) - { - var res = await http.GetStringAsync("http://anilist.co/api/manga/search/" + Uri.EscapeUriString(query) + $"?access_token={anilistToken}").ConfigureAwait(false); - var smallObj = JArray.Parse(res)[0]; - var aniData = await http.GetStringAsync("http://anilist.co/api/manga/" + smallObj["id"] + $"?access_token={anilistToken}").ConfigureAwait(false); - - return await Task.Run(() => { try { return JsonConvert.DeserializeObject(aniData); } catch { return null; } }).ConfigureAwait(false); - } - } - catch (Exception ex) - { - _log.Warn(ex, "Failed anime search for {0}", query); - return null; - } - } } } } \ No newline at end of file diff --git a/src/NadekoBot/NadekoBot.cs b/src/NadekoBot/NadekoBot.cs index 4c2cd91a..7e300591 100644 --- a/src/NadekoBot/NadekoBot.cs +++ b/src/NadekoBot/NadekoBot.cs @@ -132,6 +132,7 @@ namespace NadekoBot #region Searches var searchesService = new SearchesService(Client, GoogleApi, Db); var streamNotificationService = new StreamNotificationService(Db, Client, Strings); + var animeSearchService = new AnimeSearchService(); #endregion var clashService = new ClashOfClansService(Client, Db, Localization, Strings); @@ -184,6 +185,7 @@ namespace NadekoBot .Add(converterService) .Add(searchesService) .Add(streamNotificationService) + .Add(animeSearchService) .Add(clashService) .Add(musicService) .Add(greetSettingsService) diff --git a/src/NadekoBot/NadekoBot.csproj b/src/NadekoBot/NadekoBot.csproj index f63cf65e..0cc722bc 100644 --- a/src/NadekoBot/NadekoBot.csproj +++ b/src/NadekoBot/NadekoBot.csproj @@ -31,6 +31,9 @@ + + + Always @@ -87,6 +90,5 @@ - diff --git a/src/NadekoBot/Services/Administration/AutoAssignRoleService.cs b/src/NadekoBot/Services/Administration/AutoAssignRoleService.cs index 46d26ddf..14679b6d 100644 --- a/src/NadekoBot/Services/Administration/AutoAssignRoleService.cs +++ b/src/NadekoBot/Services/Administration/AutoAssignRoleService.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace NadekoBot.Services.Administration { @@ -25,21 +26,25 @@ namespace NadekoBot.Services.Administration gcs.Where(x => x.AutoAssignRoleId != 0) .ToDictionary(k => k.GuildId, v => v.AutoAssignRoleId)); - _client.UserJoined += async (user) => + _client.UserJoined += (user) => { - try + var _ = Task.Run(async () => { - AutoAssignedRoles.TryGetValue(user.Guild.Id, out ulong roleId); + try + { + AutoAssignedRoles.TryGetValue(user.Guild.Id, out ulong roleId); - if (roleId == 0) - return; + if (roleId == 0) + return; - var role = user.Guild.Roles.FirstOrDefault(r => r.Id == roleId); + var role = user.Guild.Roles.FirstOrDefault(r => r.Id == roleId); - if (role != null) - await user.AddRoleAsync(role).ConfigureAwait(false); - } - catch (Exception ex) { _log.Warn(ex); } + if (role != null) + await user.AddRoleAsync(role).ConfigureAwait(false); + } + catch (Exception ex) { _log.Warn(ex); } + }); + return Task.CompletedTask; }; } } diff --git a/src/NadekoBot/Services/Administration/LogCommandService.cs b/src/NadekoBot/Services/Administration/LogCommandService.cs index 51fb392d..b14dcee5 100644 --- a/src/NadekoBot/Services/Administration/LogCommandService.cs +++ b/src/NadekoBot/Services/Administration/LogCommandService.cs @@ -31,7 +31,7 @@ namespace NadekoBot.Services.Administration private readonly MuteService _mute; private readonly ProtectionService _prot; - public LogCommandService(DiscordShardedClient client, NadekoStrings strings, + public LogCommandService(DiscordShardedClient client, NadekoStrings strings, IEnumerable gcs, DbService db, MuteService mute, ProtectionService prot) { _client = client; @@ -96,664 +96,731 @@ namespace NadekoBot.Services.Administration private async Task _client_UserUpdated(SocketUser before, SocketUser uAfter) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - var after = uAfter as SocketGuildUser; - - if (after == null) - return; - - var g = after.Guild; - - if (!GuildLogSettings.TryGetValue(g.Id, out LogSetting logSetting) - || (logSetting.UserUpdatedId == null)) - return; - - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(g, logSetting, LogType.UserUpdated)) == null) - return; - - var embed = new EmbedBuilder(); - - - if (before.Username != after.Username) + try { - embed.WithTitle("👥 " + GetText(g, "username_changed")) - .WithDescription($"{before.Username}#{before.Discriminator} | {before.Id}") - .AddField(fb => fb.WithName("Old Name").WithValue($"{before.Username}").WithIsInline(true)) - .AddField(fb => fb.WithName("New Name").WithValue($"{after.Username}").WithIsInline(true)) - .WithFooter(fb => fb.WithText(CurrentTime)) - .WithOkColor(); + var after = uAfter as SocketGuildUser; + + if (after == null) + return; + + var g = after.Guild; + + if (!GuildLogSettings.TryGetValue(g.Id, out LogSetting logSetting) + || (logSetting.UserUpdatedId == null)) + return; + + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(g, logSetting, LogType.UserUpdated)) == null) + return; + + var embed = new EmbedBuilder(); + + + if (before.Username != after.Username) + { + embed.WithTitle("👥 " + GetText(g, "username_changed")) + .WithDescription($"{before.Username}#{before.Discriminator} | {before.Id}") + .AddField(fb => fb.WithName("Old Name").WithValue($"{before.Username}").WithIsInline(true)) + .AddField(fb => fb.WithName("New Name").WithValue($"{after.Username}").WithIsInline(true)) + .WithFooter(fb => fb.WithText(CurrentTime)) + .WithOkColor(); + } + else if (before.AvatarId != after.AvatarId) + { + embed.WithTitle("👥" + GetText(g, "avatar_changed")) + .WithDescription($"{before.Username}#{before.Discriminator} | {before.Id}") + .WithThumbnailUrl(before.GetAvatarUrl()) + .WithImageUrl(after.GetAvatarUrl()) + .WithFooter(fb => fb.WithText(CurrentTime)) + .WithOkColor(); + } + else + { + return; + } + + await logChannel.EmbedAsync(embed).ConfigureAwait(false); + + //var guildsMemberOf = _client.GetGuilds().Where(g => g.Users.Select(u => u.Id).Contains(before.Id)).ToList(); + //foreach (var g in guildsMemberOf) + //{ + // LogSetting logSetting; + // if (!GuildLogSettings.TryGetValue(g.Id, out logSetting) + // || (logSetting.UserUpdatedId == null)) + // return; + + // ITextChannel logChannel; + // if ((logChannel = await TryGetLogChannel(g, logSetting, LogType.UserUpdated)) == null) + // return; + + // try { await logChannel.SendMessageAsync(str).ConfigureAwait(false); } catch { } + //} } - else if (before.AvatarId != after.AvatarId) + catch { - embed.WithTitle("👥" + GetText(g, "avatar_changed")) - .WithDescription($"{before.Username}#{before.Discriminator} | {before.Id}") - .WithThumbnailUrl(before.GetAvatarUrl()) - .WithImageUrl(after.GetAvatarUrl()) - .WithFooter(fb => fb.WithText(CurrentTime)) - .WithOkColor(); + // ignored } - else - { - return; - } - - await logChannel.EmbedAsync(embed).ConfigureAwait(false); - - //var guildsMemberOf = _client.GetGuilds().Where(g => g.Users.Select(u => u.Id).Contains(before.Id)).ToList(); - //foreach (var g in guildsMemberOf) - //{ - // LogSetting logSetting; - // if (!GuildLogSettings.TryGetValue(g.Id, out logSetting) - // || (logSetting.UserUpdatedId == null)) - // return; - - // ITextChannel logChannel; - // if ((logChannel = await TryGetLogChannel(g, logSetting, LogType.UserUpdated)) == null) - // return; - - // try { await logChannel.SendMessageAsync(str).ConfigureAwait(false); } catch { } - //} - } - catch - { - // ignored - } + }); } private async Task _client_UserVoiceStateUpdated_TTS(SocketUser iusr, SocketVoiceState before, SocketVoiceState after) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - var usr = iusr as IGuildUser; - if (usr == null) - return; - - var beforeVch = before.VoiceChannel; - var afterVch = after.VoiceChannel; - - if (beforeVch == afterVch) - return; - - if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out LogSetting logSetting) - || (logSetting.LogVoicePresenceTTSId == null)) - return; - - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresenceTTS)) == null) - return; - - var str = ""; - if (beforeVch?.Guild == afterVch?.Guild) + try { - str = GetText(logChannel.Guild, "moved", usr.Username, beforeVch?.Name, afterVch?.Name); + var usr = iusr as IGuildUser; + if (usr == null) + return; + + var beforeVch = before.VoiceChannel; + var afterVch = after.VoiceChannel; + + if (beforeVch == afterVch) + return; + + if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out LogSetting logSetting) + || (logSetting.LogVoicePresenceTTSId == null)) + return; + + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresenceTTS)) == null) + return; + + var str = ""; + if (beforeVch?.Guild == afterVch?.Guild) + { + str = GetText(logChannel.Guild, "moved", usr.Username, beforeVch?.Name, afterVch?.Name); + } + else if (beforeVch == null) + { + str = GetText(logChannel.Guild, "joined", usr.Username, afterVch.Name); + } + else if (afterVch == null) + { + str = GetText(logChannel.Guild, "left", usr.Username, beforeVch.Name); + } + var toDelete = await logChannel.SendMessageAsync(str, true).ConfigureAwait(false); + toDelete.DeleteAfter(5); } - else if (beforeVch == null) + catch { - str = GetText(logChannel.Guild, "joined", usr.Username, afterVch.Name); + // ignored } - else if (afterVch == null) - { - str = GetText(logChannel.Guild, "left", usr.Username, beforeVch.Name); - } - var toDelete = await logChannel.SendMessageAsync(str, true).ConfigureAwait(false); - toDelete.DeleteAfter(5); - } - catch - { - // ignored - } + }); } private async void MuteCommands_UserMuted(IGuildUser usr, MuteType muteType) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out LogSetting logSetting) - || (logSetting.UserMutedId == null)) - return; - - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null) - return; - var mutes = ""; - var mutedLocalized = GetText(logChannel.Guild, "muted_sn"); - switch (muteType) + try { - case MuteType.Voice: - mutes = "🔇 " + GetText(logChannel.Guild, "xmuted_voice", mutedLocalized); - break; - case MuteType.Chat: - mutes = "🔇 " + GetText(logChannel.Guild, "xmuted_text", mutedLocalized); - break; - case MuteType.All: - mutes = "🔇 " + GetText(logChannel.Guild, "xmuted_text_and_voice", mutedLocalized); - break; + if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out LogSetting logSetting) + || (logSetting.UserMutedId == null)) + return; + + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null) + return; + var mutes = ""; + var mutedLocalized = GetText(logChannel.Guild, "muted_sn"); + switch (muteType) + { + case MuteType.Voice: + mutes = "🔇 " + GetText(logChannel.Guild, "xmuted_voice", mutedLocalized); + break; + case MuteType.Chat: + mutes = "🔇 " + GetText(logChannel.Guild, "xmuted_text", mutedLocalized); + break; + case MuteType.All: + mutes = "🔇 " + GetText(logChannel.Guild, "xmuted_text_and_voice", mutedLocalized); + break; + } + + var embed = new EmbedBuilder().WithAuthor(eab => eab.WithName(mutes)) + .WithTitle($"{usr.Username}#{usr.Discriminator} | {usr.Id}") + .WithFooter(fb => fb.WithText(CurrentTime)) + .WithOkColor(); + + await logChannel.EmbedAsync(embed).ConfigureAwait(false); } - - var embed = new EmbedBuilder().WithAuthor(eab => eab.WithName(mutes)) - .WithTitle($"{usr.Username}#{usr.Discriminator} | {usr.Id}") - .WithFooter(fb => fb.WithText(CurrentTime)) - .WithOkColor(); - - await logChannel.EmbedAsync(embed).ConfigureAwait(false); - } - catch - { - // ignored - } + catch + { + // ignored + } + }); } private async void MuteCommands_UserUnmuted(IGuildUser usr, MuteType muteType) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out LogSetting logSetting) - || (logSetting.UserMutedId == null)) - return; - - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null) - return; - - var mutes = ""; - var unmutedLocalized = GetText(logChannel.Guild, "unmuted_sn"); - switch (muteType) + try { - case MuteType.Voice: - mutes = "🔊 " + GetText(logChannel.Guild, "xmuted_voice", unmutedLocalized); - break; - case MuteType.Chat: - mutes = "🔊 " + GetText(logChannel.Guild, "xmuted_text", unmutedLocalized); - break; - case MuteType.All: - mutes = "🔊 " + GetText(logChannel.Guild, "xmuted_text_and_voice", unmutedLocalized); - break; + if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out LogSetting logSetting) + || (logSetting.UserMutedId == null)) + return; + + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null) + return; + + var mutes = ""; + var unmutedLocalized = GetText(logChannel.Guild, "unmuted_sn"); + switch (muteType) + { + case MuteType.Voice: + mutes = "🔊 " + GetText(logChannel.Guild, "xmuted_voice", unmutedLocalized); + break; + case MuteType.Chat: + mutes = "🔊 " + GetText(logChannel.Guild, "xmuted_text", unmutedLocalized); + break; + case MuteType.All: + mutes = "🔊 " + GetText(logChannel.Guild, "xmuted_text_and_voice", unmutedLocalized); + break; + } + + var embed = new EmbedBuilder().WithAuthor(eab => eab.WithName(mutes)) + .WithTitle($"{usr.Username}#{usr.Discriminator} | {usr.Id}") + .WithFooter(fb => fb.WithText($"{CurrentTime}")) + .WithOkColor(); + + await logChannel.EmbedAsync(embed).ConfigureAwait(false); } - - var embed = new EmbedBuilder().WithAuthor(eab => eab.WithName(mutes)) - .WithTitle($"{usr.Username}#{usr.Discriminator} | {usr.Id}") - .WithFooter(fb => fb.WithText($"{CurrentTime}")) - .WithOkColor(); - - await logChannel.EmbedAsync(embed).ConfigureAwait(false); - } - catch - { - // ignored - } + catch + { + // ignored + } + }); } public async Task TriggeredAntiProtection(PunishmentAction action, ProtectionType protection, params IGuildUser[] users) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - if (users.Length == 0) - return; - - if (!GuildLogSettings.TryGetValue(users.First().Guild.Id, out LogSetting logSetting) - || (logSetting.LogOtherId == null)) - return; - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(users.First().Guild, logSetting, LogType.Other)) == null) - return; - - var punishment = ""; - switch (action) + try { - case PunishmentAction.Mute: - punishment = "🔇 " + GetText(logChannel.Guild, "muted_pl").ToUpperInvariant(); - break; - case PunishmentAction.Kick: - punishment = "👢 " + GetText(logChannel.Guild, "kicked_pl").ToUpperInvariant(); - break; - case PunishmentAction.Softban: - punishment = "☣ " + GetText(logChannel.Guild, "soft_banned_pl").ToUpperInvariant(); - break; - case PunishmentAction.Ban: - punishment = "⛔️ " + GetText(logChannel.Guild, "banned_pl").ToUpperInvariant(); - break; + if (users.Length == 0) + return; + + if (!GuildLogSettings.TryGetValue(users.First().Guild.Id, out LogSetting logSetting) + || (logSetting.LogOtherId == null)) + return; + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(users.First().Guild, logSetting, LogType.Other)) == null) + return; + + var punishment = ""; + switch (action) + { + case PunishmentAction.Mute: + punishment = "🔇 " + GetText(logChannel.Guild, "muted_pl").ToUpperInvariant(); + break; + case PunishmentAction.Kick: + punishment = "👢 " + GetText(logChannel.Guild, "kicked_pl").ToUpperInvariant(); + break; + case PunishmentAction.Softban: + punishment = "☣ " + GetText(logChannel.Guild, "soft_banned_pl").ToUpperInvariant(); + break; + case PunishmentAction.Ban: + punishment = "⛔️ " + GetText(logChannel.Guild, "banned_pl").ToUpperInvariant(); + break; + } + + var embed = new EmbedBuilder().WithAuthor(eab => eab.WithName($"🛡 Anti-{protection}")) + .WithTitle(GetText(logChannel.Guild, "users") + " " + punishment) + .WithDescription(string.Join("\n", users.Select(u => u.ToString()))) + .WithFooter(fb => fb.WithText($"{CurrentTime}")) + .WithOkColor(); + + await logChannel.EmbedAsync(embed).ConfigureAwait(false); } - - var embed = new EmbedBuilder().WithAuthor(eab => eab.WithName($"🛡 Anti-{protection}")) - .WithTitle(GetText(logChannel.Guild, "users") + " " + punishment) - .WithDescription(string.Join("\n", users.Select(u => u.ToString()))) - .WithFooter(fb => fb.WithText($"{CurrentTime}")) - .WithOkColor(); - - await logChannel.EmbedAsync(embed).ConfigureAwait(false); - } - catch - { - // ignored - } + catch + { + // ignored + } + }); } private async Task _client_GuildUserUpdated(SocketGuildUser before, SocketGuildUser after) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - if (!GuildLogSettings.TryGetValue(before.Guild.Id, out LogSetting logSetting) - || (logSetting.UserUpdatedId == null)) - return; - - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(before.Guild, logSetting, LogType.UserUpdated)) == null) - return; - var embed = new EmbedBuilder().WithOkColor().WithFooter(efb => efb.WithText(CurrentTime)) - .WithTitle($"{before.Username}#{before.Discriminator} | {before.Id}"); - if (before.Nickname != after.Nickname) + try { - embed.WithAuthor(eab => eab.WithName("👥 " + GetText(logChannel.Guild, "nick_change"))) + if (!GuildLogSettings.TryGetValue(before.Guild.Id, out LogSetting logSetting) + || (logSetting.UserUpdatedId == null)) + return; - .AddField(efb => efb.WithName(GetText(logChannel.Guild, "old_nick")).WithValue($"{before.Nickname}#{before.Discriminator}")) - .AddField(efb => efb.WithName(GetText(logChannel.Guild, "new_nick")).WithValue($"{after.Nickname}#{after.Discriminator}")); + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(before.Guild, logSetting, LogType.UserUpdated)) == null) + return; + var embed = new EmbedBuilder().WithOkColor().WithFooter(efb => efb.WithText(CurrentTime)) + .WithTitle($"{before.Username}#{before.Discriminator} | {before.Id}"); + if (before.Nickname != after.Nickname) + { + embed.WithAuthor(eab => eab.WithName("👥 " + GetText(logChannel.Guild, "nick_change"))) + + .AddField(efb => efb.WithName(GetText(logChannel.Guild, "old_nick")).WithValue($"{before.Nickname}#{before.Discriminator}")) + .AddField(efb => efb.WithName(GetText(logChannel.Guild, "new_nick")).WithValue($"{after.Nickname}#{after.Discriminator}")); + } + else if (!before.Roles.SequenceEqual(after.Roles)) + { + if (before.Roles.Count < after.Roles.Count) + { + var diffRoles = after.Roles.Where(r => !before.Roles.Contains(r)).Select(r => r.Name); + embed.WithAuthor(eab => eab.WithName("⚔ " + GetText(logChannel.Guild, "user_role_add"))) + .WithDescription(string.Join(", ", diffRoles).SanitizeMentions()); + } + else if (before.Roles.Count > after.Roles.Count) + { + var diffRoles = before.Roles.Where(r => !after.Roles.Contains(r)).Select(r => r.Name); + embed.WithAuthor(eab => eab.WithName("⚔ " + GetText(logChannel.Guild, "user_role_rem"))) + .WithDescription(string.Join(", ", diffRoles).SanitizeMentions()); + } + } + else + return; + await logChannel.EmbedAsync(embed).ConfigureAwait(false); } - else if (!before.Roles.SequenceEqual(after.Roles)) + catch { - if (before.Roles.Count < after.Roles.Count) - { - var diffRoles = after.Roles.Where(r => !before.Roles.Contains(r)).Select(r => r.Name); - embed.WithAuthor(eab => eab.WithName("⚔ " + GetText(logChannel.Guild, "user_role_add"))) - .WithDescription(string.Join(", ", diffRoles).SanitizeMentions()); - } - else if (before.Roles.Count > after.Roles.Count) - { - var diffRoles = before.Roles.Where(r => !after.Roles.Contains(r)).Select(r => r.Name); - embed.WithAuthor(eab => eab.WithName("⚔ " + GetText(logChannel.Guild, "user_role_rem"))) - .WithDescription(string.Join(", ", diffRoles).SanitizeMentions()); - } + // ignored } - else - return; - await logChannel.EmbedAsync(embed).ConfigureAwait(false); - } - catch - { - // ignored - } + }); } private async Task _client_ChannelUpdated(IChannel cbefore, IChannel cafter) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - var before = cbefore as IGuildChannel; - if (before == null) - return; - var after = (IGuildChannel)cafter; - - if (!GuildLogSettings.TryGetValue(before.Guild.Id, out LogSetting logSetting) - || (logSetting.ChannelUpdatedId == null) - || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == after.Id)) - return; - - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(before.Guild, logSetting, LogType.ChannelUpdated)) == null) - return; - - var embed = new EmbedBuilder().WithOkColor().WithFooter(efb => efb.WithText(CurrentTime)); - - var beforeTextChannel = cbefore as ITextChannel; - var afterTextChannel = cafter as ITextChannel; - - if (before.Name != after.Name) + try { - embed.WithTitle("ℹ️ " + GetText(logChannel.Guild, "ch_name_change")) - .WithDescription($"{after} | {after.Id}") - .AddField(efb => efb.WithName(GetText(logChannel.Guild, "ch_old_name")).WithValue(before.Name)); - } - else if (beforeTextChannel?.Topic != afterTextChannel?.Topic) - { - embed.WithTitle("ℹ️ " + GetText(logChannel.Guild, "ch_topic_change")) - .WithDescription($"{after} | {after.Id}") - .AddField(efb => efb.WithName(GetText(logChannel.Guild, "old_topic")).WithValue(beforeTextChannel?.Topic ?? "-")) - .AddField(efb => efb.WithName(GetText(logChannel.Guild, "new_topic")).WithValue(afterTextChannel?.Topic ?? "-")); - } - else - return; + var before = cbefore as IGuildChannel; + if (before == null) + return; + var after = (IGuildChannel)cafter; - await logChannel.EmbedAsync(embed).ConfigureAwait(false); - } - catch - { - // ignored - } + if (!GuildLogSettings.TryGetValue(before.Guild.Id, out LogSetting logSetting) + || (logSetting.ChannelUpdatedId == null) + || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == after.Id)) + return; + + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(before.Guild, logSetting, LogType.ChannelUpdated)) == null) + return; + + var embed = new EmbedBuilder().WithOkColor().WithFooter(efb => efb.WithText(CurrentTime)); + + var beforeTextChannel = cbefore as ITextChannel; + var afterTextChannel = cafter as ITextChannel; + + if (before.Name != after.Name) + { + embed.WithTitle("ℹ️ " + GetText(logChannel.Guild, "ch_name_change")) + .WithDescription($"{after} | {after.Id}") + .AddField(efb => efb.WithName(GetText(logChannel.Guild, "ch_old_name")).WithValue(before.Name)); + } + else if (beforeTextChannel?.Topic != afterTextChannel?.Topic) + { + embed.WithTitle("ℹ️ " + GetText(logChannel.Guild, "ch_topic_change")) + .WithDescription($"{after} | {after.Id}") + .AddField(efb => efb.WithName(GetText(logChannel.Guild, "old_topic")).WithValue(beforeTextChannel?.Topic ?? "-")) + .AddField(efb => efb.WithName(GetText(logChannel.Guild, "new_topic")).WithValue(afterTextChannel?.Topic ?? "-")); + } + else + return; + + await logChannel.EmbedAsync(embed).ConfigureAwait(false); + } + catch + { + // ignored + } + }); } private async Task _client_ChannelDestroyed(IChannel ich) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - var ch = ich as IGuildChannel; - if (ch == null) - return; - - if (!GuildLogSettings.TryGetValue(ch.Guild.Id, out LogSetting logSetting) - || (logSetting.ChannelDestroyedId == null) - || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == ch.Id)) - return; - - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelDestroyed)) == null) - return; - string title; - if (ch is IVoiceChannel) + try { - title = GetText(logChannel.Guild, "voice_chan_destroyed"); + var ch = ich as IGuildChannel; + if (ch == null) + return; + + if (!GuildLogSettings.TryGetValue(ch.Guild.Id, out LogSetting logSetting) + || (logSetting.ChannelDestroyedId == null) + || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == ch.Id)) + return; + + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelDestroyed)) == null) + return; + string title; + if (ch is IVoiceChannel) + { + title = GetText(logChannel.Guild, "voice_chan_destroyed"); + } + else + title = GetText(logChannel.Guild, "text_chan_destroyed"); + await logChannel.EmbedAsync(new EmbedBuilder() + .WithOkColor() + .WithTitle("🆕 " + title) + .WithDescription($"{ch.Name} | {ch.Id}") + .WithFooter(efb => efb.WithText(CurrentTime))).ConfigureAwait(false); } - else - title = GetText(logChannel.Guild, "text_chan_destroyed"); - await logChannel.EmbedAsync(new EmbedBuilder() - .WithOkColor() - .WithTitle("🆕 " + title) - .WithDescription($"{ch.Name} | {ch.Id}") - .WithFooter(efb => efb.WithText(CurrentTime))).ConfigureAwait(false); - } - catch - { - // ignored - } + catch + { + // ignored + } + }); } private async Task _client_ChannelCreated(IChannel ich) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - var ch = ich as IGuildChannel; - if (ch == null) - return; - - if (!GuildLogSettings.TryGetValue(ch.Guild.Id, out LogSetting logSetting) - || (logSetting.ChannelCreatedId == null)) - return; - - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelCreated)) == null) - return; - string title; - if (ch is IVoiceChannel) + try { - title = GetText(logChannel.Guild, "voice_chan_created"); + var ch = ich as IGuildChannel; + if (ch == null) + return; + + if (!GuildLogSettings.TryGetValue(ch.Guild.Id, out LogSetting logSetting) + || (logSetting.ChannelCreatedId == null)) + return; + + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelCreated)) == null) + return; + string title; + if (ch is IVoiceChannel) + { + title = GetText(logChannel.Guild, "voice_chan_created"); + } + else + title = GetText(logChannel.Guild, "text_chan_created"); + await logChannel.EmbedAsync(new EmbedBuilder() + .WithOkColor() + .WithTitle("🆕 " + title) + .WithDescription($"{ch.Name} | {ch.Id}") + .WithFooter(efb => efb.WithText(CurrentTime))).ConfigureAwait(false); } - else - title = GetText(logChannel.Guild, "text_chan_created"); - await logChannel.EmbedAsync(new EmbedBuilder() - .WithOkColor() - .WithTitle("🆕 " + title) - .WithDescription($"{ch.Name} | {ch.Id}") - .WithFooter(efb => efb.WithText(CurrentTime))).ConfigureAwait(false); - } - catch (Exception ex) { _log.Warn(ex); } + catch (Exception ex) { _log.Warn(ex); } + }); } private async Task _client_UserVoiceStateUpdated(SocketUser iusr, SocketVoiceState before, SocketVoiceState after) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - var usr = iusr as IGuildUser; - if (usr == null) - return; - - var beforeVch = before.VoiceChannel; - var afterVch = after.VoiceChannel; - - if (beforeVch == afterVch) - return; - - if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out LogSetting logSetting) - || (logSetting.LogVoicePresenceId == null)) - return; - - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresence)) == null) - return; - - string str = null; - if (beforeVch?.Guild == afterVch?.Guild) + try { - str = "🎙" + Format.Code(PrettyCurrentTime) + GetText(logChannel.Guild, "user_vmoved", - "👤" + Format.Bold(usr.Username + "#" + usr.Discriminator), - Format.Bold(beforeVch?.Name ?? ""), Format.Bold(afterVch?.Name ?? "")); + var usr = iusr as IGuildUser; + if (usr == null) + return; + + var beforeVch = before.VoiceChannel; + var afterVch = after.VoiceChannel; + + if (beforeVch == afterVch) + return; + + if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out LogSetting logSetting) + || (logSetting.LogVoicePresenceId == null)) + return; + + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresence)) == null) + return; + + string str = null; + if (beforeVch?.Guild == afterVch?.Guild) + { + str = "🎙" + Format.Code(PrettyCurrentTime) + GetText(logChannel.Guild, "user_vmoved", + "👤" + Format.Bold(usr.Username + "#" + usr.Discriminator), + Format.Bold(beforeVch?.Name ?? ""), Format.Bold(afterVch?.Name ?? "")); + } + else if (beforeVch == null) + { + str = "🎙" + Format.Code(PrettyCurrentTime) + GetText(logChannel.Guild, "user_vjoined", + "👤" + Format.Bold(usr.Username + "#" + usr.Discriminator), + Format.Bold(afterVch.Name ?? "")); + } + else if (afterVch == null) + { + str = "🎙" + Format.Code(PrettyCurrentTime) + GetText(logChannel.Guild, "user_vleft", + "👤" + Format.Bold(usr.Username + "#" + usr.Discriminator), + Format.Bold(beforeVch.Name ?? "")); + } + if (str != null) + PresenceUpdates.AddOrUpdate(logChannel, new List() { str }, (id, list) => { list.Add(str); return list; }); } - else if (beforeVch == null) + catch { - str = "🎙" + Format.Code(PrettyCurrentTime) + GetText(logChannel.Guild, "user_vjoined", - "👤" + Format.Bold(usr.Username + "#" + usr.Discriminator), - Format.Bold(afterVch.Name ?? "")); + // ignored } - else if (afterVch == null) - { - str = "🎙" + Format.Code(PrettyCurrentTime) + GetText(logChannel.Guild, "user_vleft", - "👤" + Format.Bold(usr.Username + "#" + usr.Discriminator), - Format.Bold(beforeVch.Name ?? "")); - } - if (str != null) - PresenceUpdates.AddOrUpdate(logChannel, new List() { str }, (id, list) => { list.Add(str); return list; }); - } - catch - { - // ignored - } + }); } private async Task _client_UserPresenceUpdated(Optional optGuild, SocketUser usr, SocketPresence before, SocketPresence after) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - var guild = optGuild.GetValueOrDefault() ?? (usr as SocketGuildUser)?.Guild; + try + { + var guild = optGuild.GetValueOrDefault() ?? (usr as SocketGuildUser)?.Guild; - if (guild == null) - return; + if (guild == null) + return; - if (!GuildLogSettings.TryGetValue(guild.Id, out LogSetting logSetting) - || (logSetting.LogUserPresenceId == null) - || before.Status == after.Status) - return; + if (!GuildLogSettings.TryGetValue(guild.Id, out LogSetting logSetting) + || (logSetting.LogUserPresenceId == null) + || before.Status == after.Status) + return; - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserPresence)) == null) - return; - string str = ""; - if (before.Status != after.Status) - str = "🎭" + Format.Code(PrettyCurrentTime) + - GetText(logChannel.Guild, "user_status_change", - "👤" + Format.Bold(usr.Username), - Format.Bold(after.Status.ToString())); + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserPresence)) == null) + return; + string str = ""; + if (before.Status != after.Status) + str = "🎭" + Format.Code(PrettyCurrentTime) + + GetText(logChannel.Guild, "user_status_change", + "👤" + Format.Bold(usr.Username), + Format.Bold(after.Status.ToString())); - //if (before.Game?.Name != after.Game?.Name) - //{ - // if (str != "") - // str += "\n"; - // str += $"👾`{prettyCurrentTime}`👤__**{usr.Username}**__ is now playing **{after.Game?.Name}**."; - //} + //if (before.Game?.Name != after.Game?.Name) + //{ + // if (str != "") + // str += "\n"; + // str += $"👾`{prettyCurrentTime}`👤__**{usr.Username}**__ is now playing **{after.Game?.Name}**."; + //} - PresenceUpdates.AddOrUpdate(logChannel, new List() { str }, (id, list) => { list.Add(str); return list; }); - } - catch - { - // ignored - } + PresenceUpdates.AddOrUpdate(logChannel, new List() { str }, (id, list) => { list.Add(str); return list; }); + } + catch + { + // ignored + } + }); } private async Task _client_UserLeft(IGuildUser usr) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out LogSetting logSetting) - || (logSetting.UserLeftId == null)) - return; + try + { + if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out LogSetting logSetting) + || (logSetting.UserLeftId == null)) + return; - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserLeft)) == null) - return; + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserLeft)) == null) + return; - await logChannel.EmbedAsync(new EmbedBuilder() - .WithOkColor() - .WithTitle("❌ " + GetText(logChannel.Guild, "user_left")) - .WithThumbnailUrl(usr.GetAvatarUrl()) - .WithDescription(usr.ToString()) - .AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString())) - .WithFooter(efb => efb.WithText(CurrentTime))).ConfigureAwait(false); - } - catch - { - // ignored - } + await logChannel.EmbedAsync(new EmbedBuilder() + .WithOkColor() + .WithTitle("❌ " + GetText(logChannel.Guild, "user_left")) + .WithThumbnailUrl(usr.GetAvatarUrl()) + .WithDescription(usr.ToString()) + .AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString())) + .WithFooter(efb => efb.WithText(CurrentTime))).ConfigureAwait(false); + } + catch + { + // ignored + } + }); } - private async Task _client_UserJoined(IGuildUser usr) + private Task _client_UserJoined(IGuildUser usr) { - try + var _ = Task.Run(async () => { - if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out LogSetting logSetting) - || (logSetting.UserJoinedId == null)) - return; + try + { + if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out LogSetting logSetting) + || (logSetting.UserJoinedId == null)) + return; - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserJoined)) == null) - return; + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserJoined)) == null) + return; - await logChannel.EmbedAsync(new EmbedBuilder() - .WithOkColor() - .WithTitle("✅ " + GetText(logChannel.Guild, "user_joined")) - .WithThumbnailUrl(usr.GetAvatarUrl()) - .WithDescription($"{usr}") - .AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString())) - .WithFooter(efb => efb.WithText(CurrentTime))).ConfigureAwait(false); - } - catch (Exception ex) { _log.Warn(ex); } + await logChannel.EmbedAsync(new EmbedBuilder() + .WithOkColor() + .WithTitle("✅ " + GetText(logChannel.Guild, "user_joined")) + .WithThumbnailUrl(usr.GetAvatarUrl()) + .WithDescription($"{usr}") + .AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString())) + .WithFooter(efb => efb.WithText(CurrentTime))).ConfigureAwait(false); + } + catch (Exception ex) { _log.Warn(ex); } + }); + return Task.CompletedTask; } private async Task _client_UserUnbanned(IUser usr, IGuild guild) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - if (!GuildLogSettings.TryGetValue(guild.Id, out LogSetting logSetting) - || (logSetting.UserUnbannedId == null)) - return; + try + { + if (!GuildLogSettings.TryGetValue(guild.Id, out LogSetting logSetting) + || (logSetting.UserUnbannedId == null)) + return; - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserUnbanned)) == null) - return; + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserUnbanned)) == null) + return; - await logChannel.EmbedAsync(new EmbedBuilder() - .WithOkColor() - .WithTitle("♻️ " + GetText(logChannel.Guild, "user_unbanned")) - .WithThumbnailUrl(usr.GetAvatarUrl()) - .WithDescription(usr.ToString()) - .AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString())) - .WithFooter(efb => efb.WithText(CurrentTime))).ConfigureAwait(false); - } - catch (Exception ex) { _log.Warn(ex); } + await logChannel.EmbedAsync(new EmbedBuilder() + .WithOkColor() + .WithTitle("♻️ " + GetText(logChannel.Guild, "user_unbanned")) + .WithThumbnailUrl(usr.GetAvatarUrl()) + .WithDescription(usr.ToString()) + .AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString())) + .WithFooter(efb => efb.WithText(CurrentTime))).ConfigureAwait(false); + } + catch (Exception ex) { _log.Warn(ex); } + }); } private async Task _client_UserBanned(IUser usr, IGuild guild) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - if (!GuildLogSettings.TryGetValue(guild.Id, out LogSetting logSetting) - || (logSetting.UserBannedId == null)) - return; + try + { + if (!GuildLogSettings.TryGetValue(guild.Id, out LogSetting logSetting) + || (logSetting.UserBannedId == null)) + return; - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserBanned)) == null) - return; - await logChannel.EmbedAsync(new EmbedBuilder() - .WithOkColor() - .WithTitle("🚫 " + GetText(logChannel.Guild, "user_banned")) - .WithThumbnailUrl(usr.GetAvatarUrl()) - .WithDescription(usr.ToString()) - .AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString())) - .WithFooter(efb => efb.WithText(CurrentTime))).ConfigureAwait(false); - } - catch (Exception ex) { _log.Warn(ex); } + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserBanned)) == null) + return; + await logChannel.EmbedAsync(new EmbedBuilder() + .WithOkColor() + .WithTitle("🚫 " + GetText(logChannel.Guild, "user_banned")) + .WithThumbnailUrl(usr.GetAvatarUrl()) + .WithDescription(usr.ToString()) + .AddField(efb => efb.WithName("Id").WithValue(usr.Id.ToString())) + .WithFooter(efb => efb.WithText(CurrentTime))).ConfigureAwait(false); + } + catch (Exception ex) { _log.Warn(ex); } + }); } private async Task _client_MessageDeleted(Cacheable optMsg, ISocketMessageChannel ch) { - - try + await Task.Yield(); + var _ = Task.Run(async () => { - var msg = (optMsg.HasValue ? optMsg.Value : null) as IUserMessage; - if (msg == null || msg.IsAuthor(_client)) - return; + try + { + var msg = (optMsg.HasValue ? optMsg.Value : null) as IUserMessage; + if (msg == null || msg.IsAuthor(_client)) + return; - var channel = ch as ITextChannel; - if (channel == null) - return; + var channel = ch as ITextChannel; + if (channel == null) + return; - if (!GuildLogSettings.TryGetValue(channel.Guild.Id, out LogSetting logSetting) - || (logSetting.MessageDeletedId == null) - || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == channel.Id)) - return; + if (!GuildLogSettings.TryGetValue(channel.Guild.Id, out LogSetting logSetting) + || (logSetting.MessageDeletedId == null) + || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == channel.Id)) + return; - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(channel.Guild, logSetting, LogType.MessageDeleted)) == null || logChannel.Id == msg.Id) - return; - var embed = new EmbedBuilder() - .WithOkColor() - .WithTitle("🗑 " + GetText(logChannel.Guild, "msg_del", ((ITextChannel)msg.Channel).Name)) - .WithDescription(msg.Author.ToString()) - .AddField(efb => efb.WithName(GetText(logChannel.Guild, "content")).WithValue(string.IsNullOrWhiteSpace(msg.Content) ? "-" : msg.Resolve(userHandling: TagHandling.FullName)).WithIsInline(false)) - .AddField(efb => efb.WithName("Id").WithValue(msg.Id.ToString()).WithIsInline(false)) - .WithFooter(efb => efb.WithText(CurrentTime)); - if (msg.Attachments.Any()) - embed.AddField(efb => efb.WithName(GetText(logChannel.Guild, "attachments")).WithValue(string.Join(", ", msg.Attachments.Select(a => a.Url))).WithIsInline(false)); + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(channel.Guild, logSetting, LogType.MessageDeleted)) == null || logChannel.Id == msg.Id) + return; + var embed = new EmbedBuilder() + .WithOkColor() + .WithTitle("🗑 " + GetText(logChannel.Guild, "msg_del", ((ITextChannel)msg.Channel).Name)) + .WithDescription(msg.Author.ToString()) + .AddField(efb => efb.WithName(GetText(logChannel.Guild, "content")).WithValue(string.IsNullOrWhiteSpace(msg.Content) ? "-" : msg.Resolve(userHandling: TagHandling.FullName)).WithIsInline(false)) + .AddField(efb => efb.WithName("Id").WithValue(msg.Id.ToString()).WithIsInline(false)) + .WithFooter(efb => efb.WithText(CurrentTime)); + if (msg.Attachments.Any()) + embed.AddField(efb => efb.WithName(GetText(logChannel.Guild, "attachments")).WithValue(string.Join(", ", msg.Attachments.Select(a => a.Url))).WithIsInline(false)); - await logChannel.EmbedAsync(embed).ConfigureAwait(false); - } - catch (Exception ex) - { - _log.Warn(ex); - // ignored - } + await logChannel.EmbedAsync(embed).ConfigureAwait(false); + } + catch (Exception ex) + { + _log.Warn(ex); + // ignored + } + }); } private async Task _client_MessageUpdated(Cacheable optmsg, SocketMessage imsg2, ISocketMessageChannel ch) { - try + await Task.Yield(); + var _ = Task.Run(async () => { - var after = imsg2 as IUserMessage; - if (after == null || after.IsAuthor(_client)) - return; + try + { + var after = imsg2 as IUserMessage; + if (after == null || after.IsAuthor(_client)) + return; - var before = (optmsg.HasValue ? optmsg.Value : null) as IUserMessage; - if (before == null) - return; + var before = (optmsg.HasValue ? optmsg.Value : null) as IUserMessage; + if (before == null) + return; - var channel = ch as ITextChannel; - if (channel == null) - return; + var channel = ch as ITextChannel; + if (channel == null) + return; - if (before.Content == after.Content) - return; + if (before.Content == after.Content) + return; - if (!GuildLogSettings.TryGetValue(channel.Guild.Id, out LogSetting logSetting) - || (logSetting.MessageUpdatedId == null) - || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == channel.Id)) - return; + if (!GuildLogSettings.TryGetValue(channel.Guild.Id, out LogSetting logSetting) + || (logSetting.MessageUpdatedId == null) + || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == channel.Id)) + return; - ITextChannel logChannel; - if ((logChannel = await TryGetLogChannel(channel.Guild, logSetting, LogType.MessageUpdated)) == null || logChannel.Id == after.Channel.Id) - return; + ITextChannel logChannel; + if ((logChannel = await TryGetLogChannel(channel.Guild, logSetting, LogType.MessageUpdated)) == null || logChannel.Id == after.Channel.Id) + return; - var embed = new EmbedBuilder() - .WithOkColor() - .WithTitle("📝 " + GetText(logChannel.Guild, "msg_update", ((ITextChannel)after.Channel).Name)) - .WithDescription(after.Author.ToString()) - .AddField(efb => efb.WithName(GetText(logChannel.Guild, "old_msg")).WithValue(string.IsNullOrWhiteSpace(before.Content) ? "-" : before.Resolve(userHandling: TagHandling.FullName)).WithIsInline(false)) - .AddField(efb => efb.WithName(GetText(logChannel.Guild, "new_msg")).WithValue(string.IsNullOrWhiteSpace(after.Content) ? "-" : after.Resolve(userHandling: TagHandling.FullName)).WithIsInline(false)) - .AddField(efb => efb.WithName("Id").WithValue(after.Id.ToString()).WithIsInline(false)) - .WithFooter(efb => efb.WithText(CurrentTime)); + var embed = new EmbedBuilder() + .WithOkColor() + .WithTitle("📝 " + GetText(logChannel.Guild, "msg_update", ((ITextChannel)after.Channel).Name)) + .WithDescription(after.Author.ToString()) + .AddField(efb => efb.WithName(GetText(logChannel.Guild, "old_msg")).WithValue(string.IsNullOrWhiteSpace(before.Content) ? "-" : before.Resolve(userHandling: TagHandling.FullName)).WithIsInline(false)) + .AddField(efb => efb.WithName(GetText(logChannel.Guild, "new_msg")).WithValue(string.IsNullOrWhiteSpace(after.Content) ? "-" : after.Resolve(userHandling: TagHandling.FullName)).WithIsInline(false)) + .AddField(efb => efb.WithName("Id").WithValue(after.Id.ToString()).WithIsInline(false)) + .WithFooter(efb => efb.WithText(CurrentTime)); - await logChannel.EmbedAsync(embed).ConfigureAwait(false); - } - catch - { - // ignored - } + await logChannel.EmbedAsync(embed).ConfigureAwait(false); + } + catch + { + // ignored + } + }); } public enum LogType diff --git a/src/NadekoBot/Services/Administration/MuteService.cs b/src/NadekoBot/Services/Administration/MuteService.cs index 8d454ab1..01b29d34 100644 --- a/src/NadekoBot/Services/Administration/MuteService.cs +++ b/src/NadekoBot/Services/Administration/MuteService.cs @@ -71,20 +71,21 @@ namespace NadekoBot.Services.Administration _client.UserJoined += Client_UserJoined; } - private async Task Client_UserJoined(IGuildUser usr) + private Task Client_UserJoined(IGuildUser usr) { try { MutedUsers.TryGetValue(usr.Guild.Id, out ConcurrentHashSet muted); if (muted == null || !muted.Contains(usr.Id)) - return; - await MuteUser(usr).ConfigureAwait(false); + return Task.CompletedTask; + Task.Run(() => MuteUser(usr).ConfigureAwait(false)); } catch (Exception ex) { - LogManager.GetCurrentClassLogger().Warn(ex); + _log.Warn(ex); } + return Task.CompletedTask; } public async Task MuteUser(IGuildUser usr, MuteType type = MuteType.All) diff --git a/src/NadekoBot/Services/CommandHandler.cs b/src/NadekoBot/Services/CommandHandler.cs index dec52f6a..725b94d8 100644 --- a/src/NadekoBot/Services/CommandHandler.cs +++ b/src/NadekoBot/Services/CommandHandler.cs @@ -258,7 +258,7 @@ namespace NadekoBot.Services break; } } - var prefix = GetPrefix(guild.Id); + var prefix = GetPrefix(guild?.Id); // execute the command and measure the time it took if (messageContent.StartsWith(prefix)) { diff --git a/src/NadekoBot/Services/Games/GamesService.cs b/src/NadekoBot/Services/Games/GamesService.cs index 2b5b4579..213ede37 100644 --- a/src/NadekoBot/Services/Games/GamesService.cs +++ b/src/NadekoBot/Services/Games/GamesService.cs @@ -99,6 +99,7 @@ namespace NadekoBot.Services.Games private async Task PotentialFlowerGeneration(SocketMessage imsg) { + await Task.Yield(); var msg = imsg as SocketUserMessage; if (msg == null || msg.Author.IsBot) return; @@ -109,48 +110,51 @@ namespace NadekoBot.Services.Games if (!GenerationChannels.Contains(channel.Id)) return; - - try + + var _ = Task.Run(async () => { - var lastGeneration = LastGenerations.GetOrAdd(channel.Id, DateTime.MinValue); - var rng = new NadekoRandom(); - - if (DateTime.Now - TimeSpan.FromSeconds(_bc.CurrencyGenerationCooldown) < lastGeneration) //recently generated in this channel, don't generate again - return; - - var num = rng.Next(1, 101) + _bc.CurrencyGenerationChance * 100; - if (num > 100 && LastGenerations.TryUpdate(channel.Id, DateTime.Now, lastGeneration)) + try { - var dropAmount = _bc.CurrencyDropAmount; + var lastGeneration = LastGenerations.GetOrAdd(channel.Id, DateTime.MinValue); + var rng = new NadekoRandom(); - if (dropAmount > 0) + if (DateTime.Now - TimeSpan.FromSeconds(_bc.CurrencyGenerationCooldown) < lastGeneration) //recently generated in this channel, don't generate again + return; + + var num = rng.Next(1, 101) + _bc.CurrencyGenerationChance * 100; + if (num > 100 && LastGenerations.TryUpdate(channel.Id, DateTime.Now, lastGeneration)) { - var msgs = new IUserMessage[dropAmount]; - var prefix = _cmdHandler.GetPrefix(channel.Guild.Id); - var toSend = dropAmount == 1 - ? GetText(channel, "curgen_sn", _bc.CurrencySign) - + " " + GetText(channel, "pick_sn", prefix) - : GetText(channel, "curgen_pl", dropAmount, _bc.CurrencySign) - + " " + GetText(channel, "pick_pl", prefix); - var file = GetRandomCurrencyImage(); - using (var fileStream = file.Data.ToStream()) + var dropAmount = _bc.CurrencyDropAmount; + + if (dropAmount > 0) { - var sent = await channel.SendFileAsync( - fileStream, - file.Name, - toSend).ConfigureAwait(false); + var msgs = new IUserMessage[dropAmount]; + var prefix = _cmdHandler.GetPrefix(channel.Guild.Id); + var toSend = dropAmount == 1 + ? GetText(channel, "curgen_sn", _bc.CurrencySign) + + " " + GetText(channel, "pick_sn", prefix) + : GetText(channel, "curgen_pl", dropAmount, _bc.CurrencySign) + + " " + GetText(channel, "pick_pl", prefix); + var file = GetRandomCurrencyImage(); + using (var fileStream = file.Data.ToStream()) + { + var sent = await channel.SendFileAsync( + fileStream, + file.Name, + toSend).ConfigureAwait(false); - msgs[0] = sent; + msgs[0] = sent; + } + + PlantedFlowers.AddOrUpdate(channel.Id, msgs.ToList(), (id, old) => { old.AddRange(msgs); return old; }); } - - PlantedFlowers.AddOrUpdate(channel.Id, msgs.ToList(), (id, old) => { old.AddRange(msgs); return old; }); } } - } - catch (Exception ex) - { - LogManager.GetCurrentClassLogger().Warn(ex); - } + catch (Exception ex) + { + LogManager.GetCurrentClassLogger().Warn(ex); + } + }); return; } } diff --git a/src/NadekoBot/Services/Searches/AnimeSearchService.cs b/src/NadekoBot/Services/Searches/AnimeSearchService.cs new file mode 100644 index 00000000..71820506 --- /dev/null +++ b/src/NadekoBot/Services/Searches/AnimeSearchService.cs @@ -0,0 +1,98 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using NLog; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace NadekoBot.Services.Searches +{ + public class AnimeSearchService + { + private readonly Timer _anilistTokenRefresher; + private readonly Logger _log; + + private static string anilistToken { get; set; } + + public AnimeSearchService() + { + _log = LogManager.GetCurrentClassLogger(); + _anilistTokenRefresher = new Timer(async (state) => + { + try + { + var headers = new Dictionary + { + {"grant_type", "client_credentials"}, + {"client_id", "kwoth-w0ki9"}, + {"client_secret", "Qd6j4FIAi1ZK6Pc7N7V4Z"}, + }; + + using (var http = new HttpClient()) + { + //http.AddFakeHeaders(); + http.DefaultRequestHeaders.Clear(); + var formContent = new FormUrlEncodedContent(headers); + var response = await http.PostAsync("https://anilist.co/api/auth/access_token", formContent).ConfigureAwait(false); + var stringContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + anilistToken = JObject.Parse(stringContent)["access_token"].ToString(); + } + } + catch + { + // ignored + } + }, null, TimeSpan.FromSeconds(0), TimeSpan.FromMinutes(29)); + } + + public async Task GetAnimeData(string query) + { + if (string.IsNullOrWhiteSpace(query)) + throw new ArgumentNullException(nameof(query)); + try + { + + var link = "http://anilist.co/api/anime/search/" + Uri.EscapeUriString(query); + using (var http = new HttpClient()) + { + var res = await http.GetStringAsync(link + $"?access_token={anilistToken}").ConfigureAwait(false); + var smallObj = JArray.Parse(res)[0]; + var aniData = await http.GetStringAsync("http://anilist.co/api/anime/" + smallObj["id"] + $"?access_token={anilistToken}").ConfigureAwait(false); + + return await Task.Run(() => { try { return JsonConvert.DeserializeObject(aniData); } catch { return null; } }).ConfigureAwait(false); + } + } + catch (Exception ex) + { + _log.Warn(ex, "Failed anime search for {0}", query); + return null; + } + } + + public async Task GetMangaData(string query) + { + if (string.IsNullOrWhiteSpace(query)) + throw new ArgumentNullException(nameof(query)); + try + { + using (var http = new HttpClient()) + { + var res = await http.GetStringAsync("http://anilist.co/api/manga/search/" + Uri.EscapeUriString(query) + $"?access_token={anilistToken}").ConfigureAwait(false); + var smallObj = JArray.Parse(res)[0]; + var aniData = await http.GetStringAsync("http://anilist.co/api/manga/" + smallObj["id"] + $"?access_token={anilistToken}").ConfigureAwait(false); + + return await Task.Run(() => { try { return JsonConvert.DeserializeObject(aniData); } catch { return null; } }).ConfigureAwait(false); + } + } + catch (Exception ex) + { + _log.Warn(ex, "Failed anime search for {0}", query); + return null; + } + } + } +} diff --git a/src/NadekoBot/Modules/Searches/Commands/Models/AnimeResult.cs b/src/NadekoBot/Services/Searches/Models/AnimeResult.cs similarity index 93% rename from src/NadekoBot/Modules/Searches/Commands/Models/AnimeResult.cs rename to src/NadekoBot/Services/Searches/Models/AnimeResult.cs index 114515ad..626421d2 100644 --- a/src/NadekoBot/Modules/Searches/Commands/Models/AnimeResult.cs +++ b/src/NadekoBot/Services/Searches/Models/AnimeResult.cs @@ -1,6 +1,6 @@ using NadekoBot.Extensions; -namespace NadekoBot.Modules.Searches.Models +namespace NadekoBot.Services.Searches { public class AnimeResult { diff --git a/src/NadekoBot/Services/Searches/MagicItem.cs b/src/NadekoBot/Services/Searches/Models/MagicItem.cs similarity index 100% rename from src/NadekoBot/Services/Searches/MagicItem.cs rename to src/NadekoBot/Services/Searches/Models/MagicItem.cs diff --git a/src/NadekoBot/Modules/Searches/Commands/Models/MangaResult.cs b/src/NadekoBot/Services/Searches/Models/MangaResult.cs similarity index 92% rename from src/NadekoBot/Modules/Searches/Commands/Models/MangaResult.cs rename to src/NadekoBot/Services/Searches/Models/MangaResult.cs index a0d47962..3109b940 100644 --- a/src/NadekoBot/Modules/Searches/Commands/Models/MangaResult.cs +++ b/src/NadekoBot/Services/Searches/Models/MangaResult.cs @@ -1,4 +1,4 @@ -namespace NadekoBot.Modules.Searches.Models +namespace NadekoBot.Services.Searches { public class MangaResult { diff --git a/src/NadekoBot/Services/Searches/SearchPokemon.cs b/src/NadekoBot/Services/Searches/Models/SearchPokemon.cs similarity index 100% rename from src/NadekoBot/Services/Searches/SearchPokemon.cs rename to src/NadekoBot/Services/Searches/Models/SearchPokemon.cs diff --git a/src/NadekoBot/Services/Searches/StreamResponses.cs b/src/NadekoBot/Services/Searches/Models/StreamResponses.cs similarity index 100% rename from src/NadekoBot/Services/Searches/StreamResponses.cs rename to src/NadekoBot/Services/Searches/Models/StreamResponses.cs diff --git a/src/NadekoBot/Services/Searches/WoWJoke.cs b/src/NadekoBot/Services/Searches/Models/WoWJoke.cs similarity index 100% rename from src/NadekoBot/Services/Searches/WoWJoke.cs rename to src/NadekoBot/Services/Searches/Models/WoWJoke.cs diff --git a/src/NadekoBot/Services/Searches/SearchesService.cs b/src/NadekoBot/Services/Searches/SearchesService.cs index 951b01da..f37f9ec4 100644 --- a/src/NadekoBot/Services/Searches/SearchesService.cs +++ b/src/NadekoBot/Services/Searches/SearchesService.cs @@ -41,32 +41,35 @@ namespace NadekoBot.Services.Searches //translate commands _client.MessageReceived += async (msg) => { - try + await Task.Yield(); + var _ = Task.Run(async () => { - var umsg = msg as SocketUserMessage; - if (umsg == null) - return; - - if (!TranslatedChannels.TryGetValue(umsg.Channel.Id, out var autoDelete)) - return; - - var key = new UserChannelPair() + try { - UserId = umsg.Author.Id, - ChannelId = umsg.Channel.Id, - }; + var umsg = msg as SocketUserMessage; + if (umsg == null) + return; - string langs; - if (!UserLanguages.TryGetValue(key, out langs)) - return; + if (!TranslatedChannels.TryGetValue(umsg.Channel.Id, out var autoDelete)) + return; - var text = await Translate(langs, umsg.Resolve(TagHandling.Ignore)) - .ConfigureAwait(false); - if (autoDelete) - try { await umsg.DeleteAsync().ConfigureAwait(false); } catch { } - await umsg.Channel.SendConfirmAsync($"{umsg.Author.Mention} `:` " + text.Replace("<@ ", "<@").Replace("<@! ", "<@!")).ConfigureAwait(false); - } - catch { } + var key = new UserChannelPair() + { + UserId = umsg.Author.Id, + ChannelId = umsg.Channel.Id, + }; + + if (!UserLanguages.TryGetValue(key, out string langs)) + return; + + var text = await Translate(langs, umsg.Resolve(TagHandling.Ignore)) + .ConfigureAwait(false); + if (autoDelete) + try { await umsg.DeleteAsync().ConfigureAwait(false); } catch { } + await umsg.Channel.SendConfirmAsync($"{umsg.Author.Mention} `:` " + text.Replace("<@ ", "<@").Replace("<@! ", "<@!")).ConfigureAwait(false); + } + catch { } + }); }; //pokemon commands diff --git a/src/NadekoBot/Services/Utility/UtilityService.cs b/src/NadekoBot/Services/Utility/UtilityService.cs index 46b52d21..660984b2 100644 --- a/src/NadekoBot/Services/Utility/UtilityService.cs +++ b/src/NadekoBot/Services/Utility/UtilityService.cs @@ -21,42 +21,46 @@ namespace NadekoBot.Services.Utility _client.MessageReceived += Client_MessageReceived; } - private async Task Client_MessageReceived(SocketMessage imsg) + private Task Client_MessageReceived(SocketMessage imsg) { - try - { - if (imsg.Author.IsBot) - return; - var msg = imsg as IUserMessage; - if (msg == null) - return; - var channel = imsg.Channel as ITextChannel; - if (channel == null) - return; - if (msg.Author.Id == _client.CurrentUser.Id) return; - foreach (var subscriber in Subscribers) + var _ = Task.Run(async () => { + try { - var set = subscriber.Value; - if (!set.Contains(channel)) - continue; - foreach (var chan in set.Except(new[] { channel })) + if (imsg.Author.IsBot) + return; + var msg = imsg as IUserMessage; + if (msg == null) + return; + var channel = imsg.Channel as ITextChannel; + if (channel == null) + return; + if (msg.Author.Id == _client.CurrentUser.Id) return; + foreach (var subscriber in Subscribers) { - try + var set = subscriber.Value; + if (!set.Contains(channel)) + continue; + foreach (var chan in set.Except(new[] { channel })) { - await chan.SendMessageAsync(GetMessage(channel, (IGuildUser)msg.Author, - msg)).ConfigureAwait(false); - } - catch - { - // ignored + try + { + await chan.SendMessageAsync(GetMessage(channel, (IGuildUser)msg.Author, + msg)).ConfigureAwait(false); + } + catch + { + // ignored + } } } } - } - catch - { - // ignored - } + catch + { + // ignored + } + }); + + return Task.CompletedTask; } private string GetMessage(ITextChannel channel, IGuildUser user, IUserMessage message) =>