Made events run async where needed, fixed .startevent flowerreaction and running commands in DMs
This commit is contained in:
		
							
								
								
									
										34
									
								
								src/NadekoBot/Command Errors 2017-06-05.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/NadekoBot/Command Errors 2017-06-05.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -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.<StartRequest>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.<FinishSendAsync>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.<GetContentAsync>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.<Randjoke>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.<<BuildCommand>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.<ExecuteAsyncInternal>d__38.MoveNext() | ||||
| --- End of stack trace from previous location where exception was thrown --- | ||||
|    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() | ||||
|    at Discord.Commands.CommandInfo.<ExecuteAsyncInternal>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.<ExecuteAsync>d__37.MoveNext() | ||||
| ------ | ||||
| @@ -16,8 +16,6 @@ namespace NadekoBot.Modules.Administration | ||||
|         [Group] | ||||
|         public class LocalizationCommands : NadekoSubmodule | ||||
|         { | ||||
|             //Română, România | ||||
|             //Bahasa Indonesia, Indonesia | ||||
|             private static ImmutableDictionary<string, string> supportedLocales { get; } = new Dictionary<string, string>() | ||||
|             { | ||||
|                 {"ar", "العربية" }, | ||||
|   | ||||
| @@ -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; | ||||
|                 } | ||||
|  | ||||
|   | ||||
| @@ -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); } | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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() => $@". ┌─────┐ | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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 () => | ||||
|                 { | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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<string, string> | ||||
|                         { | ||||
|                             {"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<AnimeResult> 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<AnimeResult>(aniData); } catch { return null; } }).ConfigureAwait(false); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
|                 { | ||||
|                     _log.Warn(ex, "Failed anime search for {0}", query); | ||||
|                     return null; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             private async Task<MangaResult> 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<MangaResult>(aniData); } catch { return null; } }).ConfigureAwait(false); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
|                 { | ||||
|                     _log.Warn(ex, "Failed anime search for {0}", query); | ||||
|                     return null; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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>(searchesService) | ||||
|                     .Add(streamNotificationService) | ||||
|                     .Add(animeSearchService) | ||||
|                 .Add<ClashOfClansService>(clashService) | ||||
|                 .Add<MusicService>(musicService) | ||||
|                 .Add<GreetSettingsService>(greetSettingsService) | ||||
|   | ||||
| @@ -31,6 +31,9 @@ | ||||
|    | ||||
|   <ItemGroup> | ||||
|     <Compile Remove="data\**\*;credentials.json" /> | ||||
|     <Compile Remove="Modules\Utility\Models\**" /> | ||||
|     <EmbeddedResource Remove="Modules\Utility\Models\**" /> | ||||
|     <None Remove="Modules\Utility\Models\**" /> | ||||
|     <None Update="credentials_example.json"> | ||||
|       <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
|     </None> | ||||
| @@ -87,6 +90,5 @@ | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <Folder Include="Modules\Music\Classes\" /> | ||||
|     <Folder Include="Modules\Utility\Models\" /> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
|   | ||||
| @@ -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; | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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<ulong> 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) | ||||
|   | ||||
| @@ -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)) | ||||
|             { | ||||
|   | ||||
| @@ -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; | ||||
|         } | ||||
|     } | ||||
|   | ||||
							
								
								
									
										98
									
								
								src/NadekoBot/Services/Searches/AnimeSearchService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/NadekoBot/Services/Searches/AnimeSearchService.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -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<string, string> | ||||
|                         { | ||||
|                             {"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<AnimeResult> 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<AnimeResult>(aniData); } catch { return null; } }).ConfigureAwait(false); | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 _log.Warn(ex, "Failed anime search for {0}", query); | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public async Task<MangaResult> 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<MangaResult>(aniData); } catch { return null; } }).ConfigureAwait(false); | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 _log.Warn(ex, "Failed anime search for {0}", query); | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| using NadekoBot.Extensions; | ||||
| 
 | ||||
| namespace NadekoBot.Modules.Searches.Models | ||||
| namespace NadekoBot.Services.Searches | ||||
| { | ||||
|     public class AnimeResult | ||||
|     { | ||||
| @@ -1,4 +1,4 @@ | ||||
| namespace NadekoBot.Modules.Searches.Models | ||||
| namespace NadekoBot.Services.Searches | ||||
| { | ||||
|     public class MangaResult | ||||
|     { | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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) => | ||||
|   | ||||
		Reference in New Issue
	
	Block a user