private async Task <Response> BuildMemeAsync(Languages language, IMessageDetail m) { string[] urls = m.URLs; Response response = null; for (int i = 0; i < urls.Length; i++) { string url = urls[i]; try { // Check if the url is a file if (WebHelper.IsImageUrl(url)) { // It is, download and perform meme var tuple = await WebHelper.DownloadFile(url); if (tuple.Item2 != null) { response = DoBuildMemeImage(language, tuple.Item2); } else { // We failed, return a response indicating the failure. string err = Emojis.NoEntrySign + " " + tuple.Item1.ReasonPhrase; response = new Response { Embed = EmbedUtility.ToEmbed(err), Message = err, ResponseType = ResponseType.Default }; } break; } } catch (HttpRequestException ex) { errorLogger.LogDebug($"HttpRequestException exception downloading file: {url}. Assuming file too big.", true); errorLogger.LogException(ex, ErrorSeverity.Information); string err = ($"{Emojis.NoEntry} {languageHandler.GetPhrase(language, "Error_NotAFile")}"); response = new Response { Embed = EmbedUtility.ToEmbed(err), Message = err, ResponseType = ResponseType.Default }; break; } catch (Exception ex) { errorLogger.LogDebug($"Exception downloading or handling meme file: {url}", true); errorLogger.LogException(ex, ErrorSeverity.Information); // try other urls } } return(response); }
public override IList <Response> Execute(SenderSettings senderDetail, IMessageDetail args) { ServerSettings serverSettings = senderDetail.ServerSettings; CultureInfo cultureInfo = languageHandler.GetCultureInfo(serverSettings.Language); CommandMessageHelper command = new CommandMessageHelper(serverSettings.CommandSymbol, args.Message); Discord.Color responseColor = Discord.Color.Green; // First, check the cache if we already have this pokémon. string query = command.CommandDetail; if (args.URLs.Length > 0) { var response = new[] { waitHandler.CreatePleaseWaitResponse(senderDetail.ServerSettings.Language) }; Task.Run(async() => { Response asyncResponse = await CorrelatePokemonAsync(senderDetail.ServerSettings.Language, args); if (asyncResponse == null) { string err = ($"{Emojis.NoEntry} {languageHandler.GetPhrase(senderDetail.ServerSettings.Language, "Error_NoImageMessages")}"); asyncResponse = new Response { Embed = EmbedUtility.ToEmbed(err), Message = err, ResponseType = ResponseType.Default }; } await asyncResponder.SendResponseAsync(args, asyncResponse); waitHandler.PopPleaseWaitMessage(); }); return(response); } query = query.Replace("(Pokemon)", "").Replace("(Pokémon)", "").Trim(); query = query.Replace("(move)", "").Trim(); StringBuilder output = new StringBuilder(); Pokemon pokemon = KnowledgeBase.GetPokémon(query); string imageUrl = null; bool isCached = (pokemon != null); try { // For now, assume that it is a Pokémon. string url = "https://bulbapedia.bulbagarden.net/wiki/" + query.Capitalize() + "_(Pokémon)"; string urlRaw = url + "?action=raw"; if (!isCached) { // Assume correct URL pokemon = Pokemon.ParsePage(urlRaw); } if (pokemon != null) { string p = pokemon.Name + "_(Pokémon)"; dynamic imageJson = null; output .Append("https://bulbapedia.bulbagarden.net/wiki/") .Append(p) .AppendLine("#") // # is for mobile where () is not correctly parsed in the URL parser .AppendLine(MakeAPokemonString(pokemon, cultureInfo, serverSettings.Language)); try { cancellationTokenSource.CancelAfter(300000); Task.Run(async() => { imageJson = await JSONHelper.GetJsonAsync(Uri.EscapeUriString("https://bulbapedia.bulbagarden.net/w/api.php?action=query&format=json&prop=pageimages&titles=" + p)).ConfigureAwait(false); }, cancellationTokenSource.Token).Wait(); JToken token = imageJson["query"]["pages"]; token = token.First.First; imageUrl = token["thumbnail"]["source"]?.ToString(); } catch (TaskCanceledException tcex) { errorLogger.LogDebug("Did not query Bulbapedia in time to retrieve the Pokemon image.", true); errorLogger.LogException(tcex, ErrorSeverity.Warning); } catch (Exception ex) { errorLogger.LogDebug($"Exception occurred retrieving the Pokemon image for {pokemon?.Name}.\n" + $"imageUrl: {imageUrl}\n" + $"imageJson: {imageJson}", true); errorLogger.LogException(ex, ErrorSeverity.Error); } } else { output.AppendLine($"{Emojis.ExclamationSymbol} {languageHandler.GetPhrase(senderDetail.ServerSettings.Language, "Error_PokemonNotFound")}: {urlRaw}"); } } catch (WebException) { output.AppendLine($"{Emojis.CrossSymbol} {languageHandler.GetPhrase(senderDetail.ServerSettings.Language, "Error_PokemonNotFound")}: {query}"); } catch (Exception ex) { output.AppendLine($"{languageHandler.GetPhrase(senderDetail.ServerSettings.Language, "Error_Oops")}: {ex.Message}"); } return(Response.CreateArrayFromString(output.ToString(), responseColor, pokemon.Name, imageUrl)); }
public override IList <Response> Execute(SenderSettings senderDetail, IMessageDetail args) { ServerSettings serverSettings = senderDetail.ServerSettings; CommandMessageHelper command = new CommandMessageHelper(serverSettings.CommandSymbol, args.Message); // Verify command. string[] splitCommand = command.CommandLower.Split('>', StringSplitOptions.RemoveEmptyEntries); if (splitCommand.Length == 2) { var sourceLanguage = splitCommand[0]; if (!translateCodes.Contains(sourceLanguage)) { if (string.Equals(sourceLanguage, "?") || sourceLanguage.Equals("auto", StringComparison.OrdinalIgnoreCase)) { sourceLanguage = "auto"; } else { // If the source language is not found, then assume the command is not for us. return(Response.NoResponse); } } // Command verified, continue with the translation. var targetLanguage = splitCommand[1]; var toTranslate = command.CommandDetail; if (string.IsNullOrWhiteSpace(toTranslate)) { return(Response.CreateArrayFromString(TRANSLATE_HOMEPAGE)); } else if (!translateCodes.Contains(targetLanguage)) { string err = ($"{Emojis.CrossSymbol} {languageHandler.GetPhrase(senderDetail.ServerSettings.Language, "Error_IncorrectParameter")}: {targetLanguage}"); return(Response.CreateArrayFromString(err)); } string query = Uri.EscapeDataString(toTranslate); string request = "https://translate.googleapis.com/translate_a/single?client=gtx&dt=t" + $"&ie=UTF-8" + $"&oe=UTF-8" + $"&sl={sourceLanguage}" + $"&tl={targetLanguage}" + $"&q={query}"; errorLogger.LogDebug(request, false); // Responds asynchronously. Task.Run(async() => { JContainer json; string message = null; try { json = (JContainer)await JSONHelper.GetJsonAsync(request).ConfigureAwait(false); } catch (Exception) { json = null; message = ($"{Emojis.NoEntry} {languageHandler.GetPhrase(senderDetail.ServerSettings.Language, "Error_ServerNotFound")}"); } try { dynamic outer = json[0]; if (outer.Count > 0) { StringBuilder translation = new StringBuilder(); for (int i = 0; i < outer.Count; i++) { string translatedLine = outer[i][0]?.ToString(); if (translatedLine != null) { translation.AppendLine(translatedLine); } } if (translation.Length <= 0) { message = ($"{Emojis.Warning} {languageHandler.GetPhrase(senderDetail.ServerSettings.Language, "Error_NoResults")}"); } else { message = translation.ToString(); } } else { message = ($"{Emojis.Warning} {languageHandler.GetPhrase(senderDetail.ServerSettings.Language, "Error_NoResults")}"); } } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex) { // Extra information for debugging. errorLogger.LogException(ex, ErrorSeverity.Error); errorLogger.LogDebug("Unable to process the translation response: " + ex, true); errorLogger.LogDebug("Request: " + request, true); errorLogger.LogDebug("Response: " + json, true); // Let the usual error handling kick in. throw; } Response asyncResponse = Response.CreateFromString(message); await asyncResponder.SendResponseAsync(args, asyncResponse).ConfigureAwait(false); }); // Return out the lifecycle with no response. return(new[] { Response.WaitForAsync }); } else { return(Response.NoResponse); } }
public override IList <Response> Execute(SenderSettings senderDetail, IMessageDetail args) { // Responds asynchronously. Task.Run(async() => { CommandMessageHelper command = new CommandMessageHelper(senderDetail.ServerSettings.CommandSymbol, args.Message); string manualUrl = "http://minecraft.gamepedia.com/index.php?search=" + command.EscapedCommandDetail + "&title=Special%3ASearch&go=Go"; StringBuilder output = new StringBuilder(manualUrl + " \n"); string[] craftingTemplateParams = new string[] { "\n", "|" }; string query = command.EscapedCommandDetail; string json = ""; try { bool redirectResolved = true; // Resolve redirects do { json = await WebHelper.GetTextAsync($"http://minecraft.gamepedia.com/api.php?format=json&action=query&titles={query}&prop=revisions&rvprop=content&callback=?"); if (json.Contains(RedirectString)) { // Resolve redirect TextParser parser = new TextParser(json); parser.MovePast(RedirectString, true); parser.MovePast("[[", true); string article = parser.ExtractUntil("]]", false, true); string newQuery = Uri.EscapeDataString(article); if (query == newQuery) { output.AppendLine(Emojis.ExclamationSymbol + " infinite recursion error on: " + query); redirectResolved = false; break; } else { query = newQuery; } } }while (json.Contains(RedirectString)); if (redirectResolved) { string url = "http://minecraft.gamepedia.com/" + query; // Get the recipe. if (!json.ContainsIgnore(CraftingString, StringComparison.OrdinalIgnoreCase, " ", "\n", "\r")) { string error = Emojis.InfoSymbol + " " + languageHandler.GetPhrase(senderDetail.ServerSettings.Language, "Error_UnknownRecipe"); output.AppendLine(error + " " + command.CommandDetail + ": " + url); } else { // We're in business. TextParser parser = new TextParser(json); parser.MovePast(CraftingString, true); string recipeTemplate = parser.ExtractUntil("}}", false, true).Replace("|head=0", "").Replace("|head=1", "").Replace("|showdescription=0", "").Replace("|showdescription=1", "").Replace("|showname=0", "").Replace("|showname=1", ""); parser = new TextParser(recipeTemplate); parser.MovePast("|", true); // First parameter is template name string[,] recipe = new string[3, 3]; // Initialise all elements with an empty string. for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { recipe[x, y] = ""; } } if (recipeTemplate.Contains("A2") || recipeTemplate.Contains("B2") || recipeTemplate.Contains("C2")) { // Method 1, cells specified string a1Cell = parser.ExtractBetween("A1", craftingTemplateParams, true); recipe[0, 0] = TidyRecipeParameter(a1Cell); string b1Cell = parser.ExtractBetween("B1", craftingTemplateParams, true); recipe[1, 0] = TidyRecipeParameter(b1Cell); string c1Cell = parser.ExtractBetween("C1", craftingTemplateParams, true); recipe[2, 0] = TidyRecipeParameter(c1Cell); string a2Cell = parser.ExtractBetween("A2", craftingTemplateParams, true); recipe[0, 1] = TidyRecipeParameter(a2Cell); string b2Cell = parser.ExtractBetween("B2", craftingTemplateParams, true); recipe[1, 1] = TidyRecipeParameter(b2Cell); string c2Cell = parser.ExtractBetween("C2", craftingTemplateParams, true); recipe[2, 1] = TidyRecipeParameter(c2Cell); string a3Cell = parser.ExtractBetween("A3", craftingTemplateParams, true); recipe[0, 2] = TidyRecipeParameter(a3Cell); string b3Cell = parser.ExtractBetween("B3", craftingTemplateParams, true); recipe[1, 2] = TidyRecipeParameter(b3Cell); string c3Cell = parser.ExtractBetween("C3", craftingTemplateParams, true); recipe[2, 2] = TidyRecipeParameter(c3Cell); } else { // Method 2, all fields present -OR- clockwise layout. List <string> items = new List <string>(); for (int i = 0; i < 9; i++) { string candidateItem = TidyRecipeParameter(parser.ExtractUntil(craftingTemplateParams, false, true)); if (candidateItem.Contains("output", StringComparison.OrdinalIgnoreCase)) { break; } else { items.Add(candidateItem); parser.MovePast("|"); } } // If we have less than 4, then it's constructed in a clockwise fashion. switch (items.Count) { case 0: break; case 1: recipe[0, 1] = items[0]; break; case 2: recipe[0, 1] = items[0]; recipe[1, 1] = items[1]; break; case 3: recipe[0, 1] = items[0]; recipe[1, 1] = items[1]; recipe[1, 2] = items[2]; break; case 4: recipe[0, 1] = items[0]; recipe[1, 1] = items[1]; recipe[1, 2] = items[2]; recipe[0, 2] = items[3]; break; default: { recipe[0, 1] = items[0]; recipe[1, 1] = items[1]; recipe[1, 2] = items[2]; recipe[0, 2] = items[3]; break; } case 9: // Otherwise, all parameters are specified and just go from top left to bottom right. for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { recipe[x, y] = items[(x * 3) + y]; } } break; } } parser.MovePast(OutputNameString, true); string outputName = TidyRecipeParameter(parser.ExtractUntil(craftingTemplateParams, false, true)); if (string.IsNullOrWhiteSpace(outputName)) { string error = Emojis.ExclamationSymbol + " " + languageHandler.GetPhrase(senderDetail.ServerSettings.Language, "Error_UnknownRecipe"); output.AppendLine($"{error}{command.CommandDetail}: " + url); } else { const int pad = 14; output.AppendLine($"```"); // Mono-space engage! output.AppendLine($"|--------------|--------------|--------------|"); output.AppendLine($"|{recipe[0, 0].CentreString(pad)}|{recipe[1, 0].CentreString(pad)}|{recipe[2, 0].CentreString(pad)}|"); output.AppendLine($"|--------------|--------------|--------------|"); output.AppendLine($"|{recipe[0, 1].CentreString(pad)}|{recipe[1, 1].CentreString(pad)}|{recipe[2, 1].CentreString(pad)}|"); output.AppendLine($"|--------------|--------------|--------------|"); output.AppendLine($"|{recipe[0, 2].CentreString(pad)}|{recipe[1, 2].CentreString(pad)}|{recipe[2, 2].CentreString(pad)}|"); output.AppendLine($"|--------------|--------------|--------------|"); output.AppendLine($"```"); output.AppendLine($"{outputName}"); } } } } catch (Exception ex) { string error = Emojis.CrossSymbol + " " + languageHandler.GetPhrase(senderDetail.ServerSettings.Language, "Error_Oops"); output.AppendLine(error + " " + command.CommandDetail); errorLogger.LogDebug("Query: " + query, true); errorLogger.LogDebug("JSON: " + json, true); errorLogger.LogDebug(ex.ToString(), true); } Response asyncResponse = new Response { ResponseType = ResponseType.Default, Embed = EmbedUtility.ToEmbed(output.ToString(), null), Message = output.ToString() }; await asyncResponder.SendResponseAsync(args, asyncResponse); }); // Return out the lifecycle with no response. return(new[] { Response.WaitForAsync }); }