From 86b015115a43a03006c96479b7c4718daf62900e Mon Sep 17 00:00:00 2001 From: Toastie Date: Mon, 29 Jul 2024 18:26:18 +1200 Subject: [PATCH] Brough .wiki command to 2018 standards --- src/EllieBot/Modules/Searches/Searches.cs | 108 ++++++++++-------- .../Modules/Searches/SearchesService.cs | 73 ++++++++++++ 2 files changed, 135 insertions(+), 46 deletions(-) diff --git a/src/EllieBot/Modules/Searches/Searches.cs b/src/EllieBot/Modules/Searches/Searches.cs index b085ea6..6de2b01 100644 --- a/src/EllieBot/Modules/Searches/Searches.cs +++ b/src/EllieBot/Modules/Searches/Searches.cs @@ -136,11 +136,11 @@ public partial class Searches : EllieModule } var eb = _sender.CreateEmbed() - .WithOkColor() - .WithTitle(GetText(strs.time_new)) - .WithDescription(Format.Code(data.Time.ToString(Culture))) - .AddField(GetText(strs.location), string.Join('\n', data.Address.Split(", ")), true) - .AddField(GetText(strs.timezone), data.TimeZoneName, true); + .WithOkColor() + .WithTitle(GetText(strs.time_new)) + .WithDescription(Format.Code(data.Time.ToString(Culture))) + .AddField(GetText(strs.location), string.Join('\n', data.Address.Split(", ")), true) + .AddField(GetText(strs.timezone), data.TimeZoneName, true); await Response().Embed(eb).SendAsync(); } @@ -162,14 +162,16 @@ public partial class Searches : EllieModule await Response() .Embed(_sender.CreateEmbed() - .WithOkColor() - .WithTitle(movie.Title) - .WithUrl($"https://www.imdb.com/title/{movie.ImdbId}/") - .WithDescription(movie.Plot.TrimTo(1000)) - .AddField("Rating", movie.ImdbRating, true) - .AddField("Genre", movie.Genre, true) - .AddField("Year", movie.Year, true) - .WithImageUrl(Uri.IsWellFormedUriString(movie.Poster, UriKind.Absolute) ? movie.Poster : null)) + .WithOkColor() + .WithTitle(movie.Title) + .WithUrl($"https://www.imdb.com/title/{movie.ImdbId}/") + .WithDescription(movie.Plot.TrimTo(1000)) + .AddField("Rating", movie.ImdbRating, true) + .AddField("Genre", movie.Genre, true) + .AddField("Year", movie.Year, true) + .WithImageUrl(Uri.IsWellFormedUriString(movie.Poster, UriKind.Absolute) + ? movie.Poster + : null)) .SendAsync(); } @@ -244,9 +246,9 @@ public partial class Searches : EllieModule await Response() .Embed(_sender.CreateEmbed() - .WithOkColor() - .AddField(GetText(strs.original_url), $"<{query}>") - .AddField(GetText(strs.short_url), $"<{shortLink}>")) + .WithOkColor() + .AddField(GetText(strs.original_url), $"<{query}>") + .AddField(GetText(strs.short_url), $"<{shortLink}>")) .SendAsync(); } @@ -266,13 +268,13 @@ public partial class Searches : EllieModule } var embed = _sender.CreateEmbed() - .WithOkColor() - .WithTitle(card.Name) - .WithDescription(card.Description) - .WithImageUrl(card.ImageUrl) - .AddField(GetText(strs.store_url), card.StoreUrl, true) - .AddField(GetText(strs.cost), card.ManaCost, true) - .AddField(GetText(strs.types), card.Types, true); + .WithOkColor() + .WithTitle(card.Name) + .WithDescription(card.Description) + .WithImageUrl(card.ImageUrl) + .AddField(GetText(strs.store_url), card.StoreUrl, true) + .AddField(GetText(strs.cost), card.ManaCost, true) + .AddField(GetText(strs.types), card.Types, true); await Response().Embed(embed).SendAsync(); } @@ -331,10 +333,10 @@ public partial class Searches : EllieModule { var item = items[0]; return _sender.CreateEmbed() - .WithOkColor() - .WithUrl(item.Permalink) - .WithTitle(item.Word) - .WithDescription(item.Definition); + .WithOkColor() + .WithUrl(item.Permalink) + .WithTitle(item.Word) + .WithDescription(item.Definition); }) .SendAsync(); return; @@ -402,11 +404,11 @@ public partial class Searches : EllieModule { var model = items.First(); var embed = _sender.CreateEmbed() - .WithDescription(ctx.User.Mention) - .AddField(GetText(strs.word), model.Word, true) - .AddField(GetText(strs._class), model.WordType, true) - .AddField(GetText(strs.definition), model.Definition) - .WithOkColor(); + .WithDescription(ctx.User.Mention) + .AddField(GetText(strs.word), model.Word, true) + .AddField(GetText(strs._class), model.WordType, true) + .AddField(GetText(strs.definition), model.Definition) + .WithOkColor(); if (!string.IsNullOrWhiteSpace(model.Example)) embed.AddField(GetText(strs.example), model.Example); @@ -432,22 +434,36 @@ public partial class Searches : EllieModule } [Cmd] - public async Task Wiki([Leftover] string query = null) + public async Task Wiki([Leftover] string query) { query = query?.Trim(); if (!await ValidateQuery(query)) return; - using var http = _httpFactory.CreateClient(); - var result = await http.GetStringAsync( - "https://en.wikipedia.org//w/api.php?action=query&format=json&prop=info&redirects=1&formatversion=2&inprop=url&titles=" - + Uri.EscapeDataString(query)); - var data = JsonConvert.DeserializeObject(result); - if (data.Query.Pages[0].Missing || string.IsNullOrWhiteSpace(data.Query.Pages[0].FullUrl)) - await Response().Error(strs.wiki_page_not_found).SendAsync(); - else - await Response().Text(data.Query.Pages[0].FullUrl).SendAsync(); + var maybeRes = await _service.GetWikipediaPageAsync(query); + if (!maybeRes.TryPickT0(out var res, out var error)) + { + await HandleErrorAsync(error); + return; + } + + var data = res.Data; + await Response().Text(data.Url).SendAsync(); + } + + public Task HandleErrorAsync(ErrorType error) + { + var errorKey = error switch + { + ErrorType.ApiKeyMissing => strs.api_key_missing, + ErrorType.InvalidInput => strs.invalid_input, + ErrorType.NotFound => strs.not_found, + ErrorType.Unknown => strs.error_occured, + _ => strs.error_occured, + }; + + return Response().Error(errorKey).SendAsync(); } [Cmd] @@ -481,10 +497,10 @@ public partial class Searches : EllieModule await Response() .Embed( _sender.CreateEmbed() - .WithOkColor() - .AddField("Username", usr.ToString()) - .AddField("Avatar Url", avatarUrl) - .WithThumbnailUrl(avatarUrl.ToString())) + .WithOkColor() + .AddField("Username", usr.ToString()) + .AddField("Avatar Url", avatarUrl) + .WithThumbnailUrl(avatarUrl.ToString())) .SendAsync(); } diff --git a/src/EllieBot/Modules/Searches/SearchesService.cs b/src/EllieBot/Modules/Searches/SearchesService.cs index f5e3be4..742f71c 100644 --- a/src/EllieBot/Modules/Searches/SearchesService.cs +++ b/src/EllieBot/Modules/Searches/SearchesService.cs @@ -2,6 +2,7 @@ using EllieBot.Modules.Searches.Common; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using OneOf.Types; using SixLabors.Fonts; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Drawing.Processing; @@ -454,4 +455,76 @@ public class SearchesService : IEService return gamesMap[key]; } + + public async Task> GetWikipediaPageAsync(string query) + { + query = query.Trim(); + if (string.IsNullOrEmpty(query)) + { + return ErrorType.InvalidInput; + } + + try + { + var result = await _c.GetOrAddAsync($"wikipedia_{query}", + async _ => + { + using var http = _httpFactory.CreateClient(); + http.DefaultRequestHeaders.Clear(); + + return await http.GetStringAsync( + "https://en.wikipedia.org/w/api.php?action=query" + + "&format=json" + + "&prop=info" + + "&redirects=1" + + "&formatversion=2" + + "&inprop=url" + + "&titles=" + + Uri.EscapeDataString(query)); + }, + TimeSpan.FromHours(1)) + .ConfigureAwait(false); + + var data = JsonConvert.DeserializeObject(result); + + if (data.Query.Pages is null || !data.Query.Pages.Any() || data.Query.Pages.First().Missing) + { + return ErrorType.NotFound; + } + + Log.Information("Sending wikipedia url for: {Query}", query); + + return new WikipediaReply + { + Data = new() + { + Url = data.Query.Pages[0].FullUrl, + } + }; + } + catch (Exception ex) + { + Log.Error(ex, "Error retrieving wikipedia data for: '{Query}'", query); + + return ErrorType.Unknown; + } + } +} + +public enum ErrorType +{ + InvalidInput, + NotFound, + Unknown, + ApiKeyMissing +} + +public class WikipediaReply +{ + public class Info + { + public required string Url { get; init; } + } + + public required Info Data { get; init; } } \ No newline at end of file