.define slightly improved and refactored

This commit is contained in:
Toastie 2024-08-01 13:41:30 +12:00
parent fe5c8622dd
commit 3e73dc8ba5
Signed by: toastie_t0ast
GPG key ID: 27F3B6855AFD40A4
3 changed files with 100 additions and 64 deletions

View file

@ -327,71 +327,35 @@ public partial class Searches : EllieModule<SearchesService>
if (!await ValidateQuery(word))
return;
using var http = _httpFactory.CreateClient();
string res;
try
var maybeItems = await _service.GetDefinitionsAsync(word);
if (!maybeItems.TryPickT0(out var defs, out var error))
{
res = await _cache.GetOrCreateAsync($"define_{word}",
e =>
{
e.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
return http.GetStringAsync("https://api.pearson.com/v2/dictionaries/entries?headword="
+ WebUtility.UrlEncode(word));
});
var responseModel = JsonConvert.DeserializeObject<DefineModel>(res);
var data = responseModel.Results
.Where(x => x.Senses is not null
&& x.Senses.Count > 0
&& x.Senses[0].Definition is not null)
.Select(x => (Sense: x.Senses[0], x.PartOfSpeech))
.ToList();
if (!data.Any())
{
Log.Warning("Definition not found: {Word}", word);
await Response().Error(strs.define_unknown).SendAsync();
}
var col = data.Select(x => (
Definition: x.Sense.Definition is string
? x.Sense.Definition.ToString()
: ((JArray)JToken.Parse(x.Sense.Definition.ToString())).First.ToString(),
Example: x.Sense.Examples is null || x.Sense.Examples.Count == 0
? string.Empty
: x.Sense.Examples[0].Text, Word: word,
WordType: string.IsNullOrWhiteSpace(x.PartOfSpeech) ? "-" : x.PartOfSpeech))
.ToList();
Log.Information("Sending {Count} definition for: {Word}", col.Count, word);
await Response()
.Paginated()
.Items(col)
.PageSize(1)
.Page((items, _) =>
{
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();
if (!string.IsNullOrWhiteSpace(model.Example))
embed.AddField(GetText(strs.example), model.Example);
return embed;
})
.SendAsync();
}
catch (Exception ex)
{
Log.Error(ex, "Error retrieving definition data for: {Word}", word);
await HandleErrorAsync(error);
return;
}
await Response()
.Paginated()
.Items(defs)
.PageSize(1)
.Page((items, _) =>
{
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();
if (!string.IsNullOrWhiteSpace(model.Example))
embed.AddField(GetText(strs.example), model.Example);
return embed;
})
.SendAsync();
}
[Cmd]

View file

@ -399,7 +399,7 @@ public class SearchesService : IEService
return gamesMap[key];
}
public async Task<OneOf.OneOf<WikipediaReply, ErrorType>> GetWikipediaPageAsync(string query)
public async Task<OneOf<WikipediaReply, ErrorType>> GetWikipediaPageAsync(string query)
{
query = query.Trim();
if (string.IsNullOrEmpty(query))
@ -516,4 +516,66 @@ public class SearchesService : IEService
return ErrorType.Unknown;
}
}
private static TypedKey<string> GetDefineKey(string query)
=> new TypedKey<string>($"define_{query}");
public async Task<OneOf<List<DefineData>, ErrorType>> GetDefinitionsAsync(string query)
{
if (string.IsNullOrEmpty(query))
{
return ErrorType.InvalidInput;
}
query = Uri.EscapeDataString(query);
using var http = _httpFactory.CreateClient();
string res;
try
{
res = await _c.GetOrAddAsync(GetDefineKey(query),
async () => await http.GetStringAsync(
$"https://api.pearson.com/v2/dictionaries/entries?headword={query}"),
TimeSpan.FromHours(12));
var responseModel = JsonConvert.DeserializeObject<DefineModel>(res);
var data = responseModel.Results
.Where(x => x.Senses is not null
&& x.Senses.Count > 0
&& x.Senses[0].Definition is not null)
.Select(x => (Sense: x.Senses[0], x.PartOfSpeech))
.ToList();
if (!data.Any())
{
Log.Warning("Definition not found: {Word}", query);
return ErrorType.NotFound;
}
var items = new List<DefineData>();
foreach (var d in data)
{
items.Add(new DefineData
{
Definition = d.Sense.Definition is JArray { Count: > 0 } defs
? defs[0].ToString()
: d.Sense.Definition.ToString(),
Example = d.Sense.Examples is null || d.Sense.Examples.Count == 0
? string.Empty
: d.Sense.Examples[0].Text,
WordType = string.IsNullOrWhiteSpace(d.PartOfSpeech) ? "-" : d.PartOfSpeech,
Word = query,
});
}
return items.OrderByDescending(x => !string.IsNullOrWhiteSpace(x.Example)).ToList();
}
catch (Exception ex)
{
Log.Error(ex, "Error retrieving definition data for: {Word}", query);
return ErrorType.Unknown;
}
}
}

View file

@ -0,0 +1,10 @@
#nullable disable
namespace EllieBot.Modules.Searches.Services;
public sealed class DefineData
{
public required string Definition { get; init; }
public required string Example { get; init; }
public required string WordType { get; init; }
public required string Word { get; init; }
}