forked from EllieBotDevs/elliebot
197 lines
No EOL
6.6 KiB
C#
197 lines
No EOL
6.6 KiB
C#
using EllieBot.Modules.Searches.Youtube;
|
|
|
|
namespace EllieBot.Modules.Searches;
|
|
|
|
public partial class Searches
|
|
{
|
|
public partial class SearchCommands : EllieModule
|
|
{
|
|
private readonly ISearchServiceFactory _searchFactory;
|
|
private readonly IBotCache _cache;
|
|
|
|
public SearchCommands(
|
|
ISearchServiceFactory searchFactory,
|
|
IBotCache cache)
|
|
{
|
|
_searchFactory = searchFactory;
|
|
_cache = cache;
|
|
}
|
|
|
|
[Cmd]
|
|
public async Task Google([Leftover] string? query = null)
|
|
{
|
|
query = query?.Trim();
|
|
|
|
if (string.IsNullOrWhiteSpace(query))
|
|
{
|
|
await Response().Error(strs.specify_search_params).SendAsync();
|
|
return;
|
|
}
|
|
|
|
_ = ctx.Channel.TriggerTypingAsync();
|
|
|
|
var search = _searchFactory.GetSearchService();
|
|
var data = await search.SearchAsync(query);
|
|
|
|
if (data is null or { Entries: null or { Count: 0 } })
|
|
{
|
|
await Response().Error(strs.no_results).SendAsync();
|
|
return;
|
|
}
|
|
|
|
// 3 with an answer
|
|
// 4 without an answer
|
|
// 5 is ideal but it lookes horrible on mobile
|
|
|
|
var takeCount = string.IsNullOrWhiteSpace(data.Answer)
|
|
? 4
|
|
: 3;
|
|
|
|
var descStr = data.Entries
|
|
.Take(takeCount)
|
|
.Select(static res => $@"**[{Format.Sanitize(res.Title)}]({res.Url})**
|
|
*{Format.EscapeUrl(res.DisplayUrl)}*
|
|
{Format.Sanitize(res.Description ?? "-")}")
|
|
.Join("\n\n");
|
|
|
|
if (!string.IsNullOrWhiteSpace(data.Answer))
|
|
descStr = Format.Code(data.Answer) + "\n\n" + descStr;
|
|
|
|
descStr = descStr.TrimTo(4096);
|
|
|
|
var embed = CreateEmbed()
|
|
.WithOkColor()
|
|
.WithAuthor(ctx.User)
|
|
.WithTitle(query.TrimTo(64)!)
|
|
.WithDescription(descStr)
|
|
.WithFooter(
|
|
GetText(strs.results_in(data.Info.TotalResults, data.Info.SearchTime)),
|
|
"https://i.imgur.com/G46fm8J.png");
|
|
|
|
await Response().Embed(embed).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
public async Task Image([Leftover] string query)
|
|
{
|
|
query = query.Trim();
|
|
|
|
if (string.IsNullOrWhiteSpace(query))
|
|
{
|
|
await Response().Error(strs.specify_search_params).SendAsync();
|
|
return;
|
|
}
|
|
|
|
_ = ctx.Channel.TriggerTypingAsync();
|
|
|
|
var search = _searchFactory.GetImageSearchService();
|
|
var data = await search.SearchImagesAsync(query);
|
|
|
|
if (data is null or { Entries: null or { Count: 0 } })
|
|
{
|
|
await Response().Error(strs.no_search_results).SendAsync();
|
|
return;
|
|
}
|
|
|
|
EmbedBuilder CreateImageEmbed(IImageSearchResultEntry entry)
|
|
{
|
|
return CreateEmbed()
|
|
.WithOkColor()
|
|
.WithAuthor(ctx.User)
|
|
.WithTitle(query)
|
|
.WithImageUrl(entry.Link);
|
|
}
|
|
|
|
await Response()
|
|
.Paginated()
|
|
.Items(data.Entries)
|
|
.PageSize(1)
|
|
.AddFooter(false)
|
|
.Page((items, _) =>
|
|
{
|
|
var item = items.FirstOrDefault();
|
|
|
|
if (item is null)
|
|
return CreateEmbed()
|
|
.WithPendingColor()
|
|
.WithDescription(GetText(strs.no_search_results));
|
|
|
|
var embed = CreateImageEmbed(item);
|
|
|
|
return embed;
|
|
})
|
|
.SendAsync();
|
|
}
|
|
|
|
private TypedKey<string[]> GetYtCacheKey(string query)
|
|
=> new($"search:yt:{query}");
|
|
|
|
private async Task AddYoutubeUrlToCacheAsync(string query, string[] url)
|
|
=> await _cache.AddAsync(GetYtCacheKey(query), url, expiry: 1.Hours());
|
|
|
|
private async Task<VideoInfo[]?> GetYoutubeUrlFromCacheAsync(string query)
|
|
{
|
|
var result = await _cache.GetAsync(GetYtCacheKey(query));
|
|
|
|
if (!result.TryGetValue(out var urls) || urls.Length == 0)
|
|
return null;
|
|
|
|
return urls.Map(url => new VideoInfo()
|
|
{
|
|
Url = url
|
|
});
|
|
}
|
|
|
|
[Cmd]
|
|
public async Task Youtube([Leftover] string query)
|
|
{
|
|
query = query.Trim();
|
|
|
|
_ = ctx.Channel.TriggerTypingAsync();
|
|
|
|
var maybeResults = await GetYoutubeUrlFromCacheAsync(query)
|
|
?? await _searchFactory.GetYoutubeSearchService().SearchAsync(query);
|
|
|
|
if (maybeResults is not { } result || result.Length == 0)
|
|
{
|
|
await Response().Error(strs.no_results).SendAsync();
|
|
return;
|
|
}
|
|
|
|
await AddYoutubeUrlToCacheAsync(query, result.Map(x => x.Url));
|
|
|
|
await Response().Text(result[0].Url).SendAsync();
|
|
}
|
|
|
|
// [Cmd]
|
|
// public async Task DuckDuckGo([Leftover] string query = null)
|
|
// {
|
|
// query = query?.Trim();
|
|
// if (!await ValidateQuery(query))
|
|
// return;
|
|
//
|
|
// _ = ctx.Channel.TriggerTypingAsync();
|
|
//
|
|
// var data = await _service.DuckDuckGoSearchAsync(query);
|
|
// if (data is null)
|
|
// {
|
|
// await Response().Error(strs.no_results).SendAsync();
|
|
// return;
|
|
// }
|
|
//
|
|
// var desc = data.Results.Take(5)
|
|
// .Select(res => $@"[**{res.Title}**]({res.Link})
|
|
// {res.Text.TrimTo(380 - res.Title.Length - res.Link.Length)}");
|
|
//
|
|
// var descStr = string.Join("\n\n", desc);
|
|
//
|
|
// var embed = CreateEmbed()
|
|
// .WithAuthor(ctx.User.ToString(),
|
|
// "https://upload.wikimedia.org/wikipedia/en/9/90/The_DuckDuckGo_Duck.png")
|
|
// .WithDescription($"{GetText(strs.search_for)} **{query}**\n\n" + descStr)
|
|
// .WithOkColor();
|
|
//
|
|
// await Response().Embed(embed).SendAsync();
|
|
// }
|
|
}
|
|
} |