Skip to content

Commit

Permalink
Change signature of BingVisualSearch.ReverseImageSearchAsync to ret…
Browse files Browse the repository at this point in the history
…urn `IReadOnlyList` instead
  • Loading branch information
d4n3436 committed Jun 25, 2024
1 parent df29165 commit e4e2f47
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 21 deletions.
17 changes: 8 additions & 9 deletions src/Apis/Bing/BingVisualSearch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public BingVisualSearch(HttpClient httpClient)
}

/// <inheritdoc/>
public async Task<IEnumerable<IBingReverseImageSearchResult>> ReverseImageSearchAsync(string url,
public async Task<IReadOnlyList<IBingReverseImageSearchResult>> ReverseImageSearchAsync(string url,
BingSafeSearchLevel safeSearch = BingSafeSearchLevel.Moderate, string? language = null,
CancellationToken cancellationToken = default)
{
Expand All @@ -83,19 +83,18 @@ public async Task<IEnumerable<IBingReverseImageSearchResult>> ReverseImageSearch
throw new BingException(message, imageCategory);
}

var root = document.RootElement.Clone();

var rawItems = root
return document.RootElement
.GetProperty("tags")
.EnumerateArray()
.Select(x => x.GetPropertyOrDefault("actions"))
.SelectMany(x => x.EnumerateArrayOrEmpty())
.FirstOrDefault(x => x.GetPropertyOrDefault("actionType").GetStringOrDefault() == "VisualSearch")
.FirstOrDefault(x => x.TryGetProperty("actionType", out var actionTye) && actionTye.ValueEquals("VisualSearch"u8))
.GetPropertyOrDefault("data")
.GetPropertyOrDefault("value")
.EnumerateArrayOrEmpty();

return rawItems.Select(item => item.Deserialize<BingReverseImageSearchResult>()!);
.EnumerateArrayOrEmpty()
.Select(item => item.Deserialize<BingReverseImageSearchResult>()!)
.ToArray()
.AsReadOnly();
}

/// <inheritdoc/>
Expand All @@ -112,7 +111,7 @@ public void Dispose()

private static HttpRequestMessage BuildRequest(string url, string invokedSkill, BingSafeSearchLevel safeSearch = BingSafeSearchLevel.Moderate, string? language = null)
{
string jsonRequest = $$"""{"imageInfo":{"url":"{{url}}","source":"Url"},"knowledgeRequest":{"invokedSkills":["{{invokedSkill}}"]}}""";
string jsonRequest = $$$"""{"imageInfo":{"url":"{{{url}}}","source":"Url"},"knowledgeRequest":{"invokedSkills":["{{{invokedSkill}}}"]}}""";
var content = new MultipartFormDataContent
{
{ new StringContent(jsonRequest), "knowledgeRequest" }
Expand Down
4 changes: 2 additions & 2 deletions src/Apis/Bing/IBingVisualSearch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public interface IBingVisualSearch
/// <param name="safeSearch">The safe search level.</param>
/// <param name="language">The language of the results.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A <see cref="Task{TResult}"/> representing the asynchronous search operation. The result contains an <see cref="IEnumerable{T}"/> of search results.</returns>
Task<IEnumerable<IBingReverseImageSearchResult>> ReverseImageSearchAsync(string url,
/// <returns>A <see cref="Task{TResult}"/> representing the asynchronous search operation. The result contains a read-only list of search results.</returns>
Task<IReadOnlyList<IBingReverseImageSearchResult>> ReverseImageSearchAsync(string url,
BingSafeSearchLevel safeSearch = BingSafeSearchLevel.Moderate, string? language = null,
CancellationToken cancellationToken = default);
}
11 changes: 5 additions & 6 deletions src/Modules/ImageModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -337,29 +337,28 @@ public virtual async Task<RuntimeResult> BingAsync(string url, bool multiImages,
}

bool isNsfw = Context.Channel.IsNsfw();
IBingReverseImageSearchResult[] results;
IReadOnlyList<IBingReverseImageSearchResult> results;

_logger.LogInformation("Sending Bing reverse image search request (URL: {Url}, is NSFW: {IsNsfw}, language: {Language})", url, isNsfw, interaction.GetLanguageCode());
try
{
results = (await _bingVisualSearch.ReverseImageSearchAsync(url, isNsfw ? BingSafeSearchLevel.Off : BingSafeSearchLevel.Strict, interaction.GetLanguageCode()))
.ToArray();
results = await _bingVisualSearch.ReverseImageSearchAsync(url, isNsfw ? BingSafeSearchLevel.Off : BingSafeSearchLevel.Strict, interaction.GetLanguageCode());
}
catch (BingException e)
{
_logger.LogWarning(e, "Failed to perform reverse image search to url {Url}", url);
return FergunResult.FromError(e.ImageCategory is null ? e.Message : _localizer[$"Bing{e.ImageCategory}"], ephemeral, interaction);
}

_logger.LogDebug("Bing reverse image search result count: {Count}", results.Length);
_logger.LogDebug("Bing reverse image search result count: {Count}", results.Count);

if (results.Length == 0)
if (results.Count == 0)
{
return FergunResult.FromError(_localizer["NoResults"], ephemeral, interaction);
}

int count = multiImages ? 4 : 1;
int maxIndex = (int)Math.Ceiling((double)results.Length / count) - 1;
int maxIndex = (int)Math.Ceiling((double)results.Count / count) - 1;

var paginator = new LazyPaginatorBuilder()
.WithPageFactory(GeneratePage)
Expand Down
3 changes: 1 addition & 2 deletions tests/Fergun.Tests/Apis/BingVisualSearchTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Drawing;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Fergun.Apis.Bing;
Expand All @@ -19,7 +18,7 @@ public class BingVisualSearchTests
[InlineData("https://r.bing.com/rp/NFrQjXWivF4omoTPSU03A6aosg0.jpg", BingSafeSearchLevel.Strict, "es")]
public async Task ReverseImageSearchAsync_Returns_Results(string url, BingSafeSearchLevel safeSearch, string? language)
{
var results = (await _bingVisualSearch.ReverseImageSearchAsync(url, safeSearch, language)).ToArray();
var results = await _bingVisualSearch.ReverseImageSearchAsync(url, safeSearch, language);

Assert.NotNull(results);
Assert.NotEmpty(results);
Expand Down
4 changes: 2 additions & 2 deletions tests/Fergun.Tests/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ public static IBingVisualSearch CreateMockedBingVisualSearchApi(Faker? faker = n
faker ??= new Faker();
var bingMock = new Mock<IBingVisualSearch>();

bingMock.Setup(x => x.ReverseImageSearchAsync(It.Is<string>(s => s == string.Empty), It.IsAny<BingSafeSearchLevel>(), It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(Enumerable.Empty<IBingReverseImageSearchResult>);
bingMock.Setup(x => x.ReverseImageSearchAsync(It.Is<string>(s => !string.IsNullOrEmpty(s)), It.IsAny<BingSafeSearchLevel>(), It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(() => faker.MakeLazy(50, () => CreateMockedBingReverseImageSearchResult(faker)));
bingMock.Setup(x => x.ReverseImageSearchAsync(It.Is<string>(s => s == string.Empty), It.IsAny<BingSafeSearchLevel>(), It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(Array.Empty<IBingReverseImageSearchResult>);
bingMock.Setup(x => x.ReverseImageSearchAsync(It.Is<string>(s => !string.IsNullOrEmpty(s)), It.IsAny<BingSafeSearchLevel>(), It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(() => faker.Make(50, () => CreateMockedBingReverseImageSearchResult(faker)).AsReadOnly());
bingMock.Setup(x => x.ReverseImageSearchAsync(It.Is<string>(s => s == "https://example.com/error"), It.IsAny<BingSafeSearchLevel>(), It.IsAny<string>(), It.IsAny<CancellationToken>())).ThrowsAsync(new BingException("Error message."));

return bingMock.Object;
Expand Down

0 comments on commit e4e2f47

Please sign in to comment.