From ff53bbec1659f05144d736ce18fcbb15fa263e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=A4felfinger?= Date: Fri, 21 Oct 2022 00:23:54 +0200 Subject: [PATCH] adds first get images implementation with image type not complete yet --- .../Piwigo.Client.Tests/AlbumApiTests.cs | 2 +- .../Piwigo.Client.Tests/ApiTestsBase.cs | 14 + .../ImageApi.getImages.json | 285 ++++++++++++++++++ .../Piwigo.Client.Tests/ImageApiTests.cs | 36 +++ .../Piwigo.Client.Tests.csproj | 6 + PiwigoDotnet/Piwigo.Client/Contract/Image.cs | 20 ++ .../Piwigo.Client/Contract/ImageFilter.cs | 34 +++ .../Piwigo.Client/Contract/PagedImages.cs | 22 ++ .../Piwigo.Client/Contract/PagingInfo.cs | 5 + PiwigoDotnet/Piwigo.Client/IImageApi.cs | 8 +- PiwigoDotnet/Piwigo.Client/ImageApi.cs | 101 +++++++ PiwigoDotnet/Piwigo.Client/ImageOrder.cs | 13 + 12 files changed, 544 insertions(+), 2 deletions(-) create mode 100644 PiwigoDotnet/Piwigo.Client.Tests/ImageApi.getImages.json create mode 100644 PiwigoDotnet/Piwigo.Client.Tests/ImageApiTests.cs create mode 100644 PiwigoDotnet/Piwigo.Client/Contract/Image.cs create mode 100644 PiwigoDotnet/Piwigo.Client/Contract/ImageFilter.cs create mode 100644 PiwigoDotnet/Piwigo.Client/Contract/PagedImages.cs create mode 100644 PiwigoDotnet/Piwigo.Client/Contract/PagingInfo.cs create mode 100644 PiwigoDotnet/Piwigo.Client/ImageApi.cs create mode 100644 PiwigoDotnet/Piwigo.Client/ImageOrder.cs diff --git a/PiwigoDotnet/Piwigo.Client.Tests/AlbumApiTests.cs b/PiwigoDotnet/Piwigo.Client.Tests/AlbumApiTests.cs index 91efd70..34e9f45 100644 --- a/PiwigoDotnet/Piwigo.Client.Tests/AlbumApiTests.cs +++ b/PiwigoDotnet/Piwigo.Client.Tests/AlbumApiTests.cs @@ -6,7 +6,7 @@ namespace Piwigo.Client.Tests; [TestFixture] public class AlbumApiTests : ApiTestsBase { - private AlbumApi _albumApi = null!; + private IAlbumApi _albumApi = null!; protected override void OnSetUp() { diff --git a/PiwigoDotnet/Piwigo.Client.Tests/ApiTestsBase.cs b/PiwigoDotnet/Piwigo.Client.Tests/ApiTestsBase.cs index 88f719d..32594a5 100644 --- a/PiwigoDotnet/Piwigo.Client.Tests/ApiTestsBase.cs +++ b/PiwigoDotnet/Piwigo.Client.Tests/ApiTestsBase.cs @@ -1,3 +1,4 @@ +using System.Reflection; using Flurl.Http.Configuration; using Flurl.Http.Content; using Flurl.Http.Testing; @@ -43,6 +44,19 @@ public class ApiTestsBase SetJsonResult(@"{stat: ""ok"", result: null}"); } + internal async Task SetJsonResultFromFileAsync(string fileName) + { + var assemblyLocation = Assembly.GetExecutingAssembly().Location; + var directory = Path.GetDirectoryName(assemblyLocation) ?? Environment.CurrentDirectory; + var path = Path.Combine(directory, fileName); + + using var reader = File.OpenText(path); + + var fileContent = await reader.ReadToEndAsync(); + + SetJsonResult(fileContent); + } + internal void SetJsonResult(string json) { HttpTest?.RespondWith(json); diff --git a/PiwigoDotnet/Piwigo.Client.Tests/ImageApi.getImages.json b/PiwigoDotnet/Piwigo.Client.Tests/ImageApi.getImages.json new file mode 100644 index 0000000..76380b0 --- /dev/null +++ b/PiwigoDotnet/Piwigo.Client.Tests/ImageApi.getImages.json @@ -0,0 +1,285 @@ +{ + stat: "ok", + result: { + paging: { + page: 0, + per_page: 100, + count: 4, + total_count: "1" + }, + images: [ + { + is_favorite: false, + id: 4, + width: 4452, + height: 2968, + hit: 2, + file: "2017-08-30-20-38-c7d_7682.jpg", + name: "2017-08-30-20-38-c7d 7682", + comment: null, + date_creation: "2017-08-30 20:38:47", + date_available: "2022-10-20 22:01:32", + page_url: "http://localhost:8080/picture.php?/4", + element_url: "http://localhost:8080/upload/2022/10/20/20221020220132-2c6d9eab.jpg", + derivatives: { + square: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220132-2c6d9eab-sq.jpg", + width: 120, + height: 120 + }, + thumb: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220132-2c6d9eab-th.jpg", + width: 144, + height: 96 + }, + 2small: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220132-2c6d9eab-2s.jpg", + width: 240, + height: 160 + }, + xsmall: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220132-2c6d9eab-xs.jpg", + width: 432, + height: 288 + }, + small: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220132-2c6d9eab-sm.jpg", + width: 576, + height: 384 + }, + medium: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220132-2c6d9eab-me.jpg", + width: 792, + height: 528 + }, + large: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220132-2c6d9eab-la.jpg", + width: 1008, + height: 672 + }, + xlarge: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220132-2c6d9eab-xl.jpg", + width: 1224, + height: 816 + }, + xxlarge: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220132-2c6d9eab-xx.jpg", + width: 1656, + height: 1104 + } + }, + categories: [ + { + id: 7, + url: "http://localhost:8080/index.php?/category/7", + page_url: "http://localhost:8080/picture.php?/4/category/7" + } + ] + }, + { + is_favorite: false, + id: 3, + width: 3961, + height: 2641, + hit: 4, + file: "2017-05-24-20-35-c7d_6283.jpg", + name: "2017-05-24-20-35-c7d 6283", + comment: null, + date_creation: "2017-05-24 20:35:44", + date_available: "2022-10-20 22:01:31", + page_url: "http://localhost:8080/picture.php?/3", + element_url: "http://localhost:8080/upload/2022/10/20/20221020220131-9a567bdb.jpg", + derivatives: { + square: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220131-9a567bdb-sq.jpg", + width: 120, + height: 120 + }, + thumb: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220131-9a567bdb-th.jpg", + width: 144, + height: 96 + }, + 2small: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220131-9a567bdb-2s.jpg", + width: 240, + height: 160 + }, + xsmall: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220131-9a567bdb-xs.jpg", + width: 432, + height: 288 + }, + small: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220131-9a567bdb-sm.jpg", + width: 576, + height: 384 + }, + medium: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220131-9a567bdb-me.jpg", + width: 792, + height: 528 + }, + large: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220131-9a567bdb-la.jpg", + width: 1008, + height: 672 + }, + xlarge: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220131-9a567bdb-xl.jpg", + width: 1224, + height: 816 + }, + xxlarge: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220131-9a567bdb-xx.jpg", + width: 1656, + height: 1104 + } + }, + categories: [ + { + id: 7, + url: "http://localhost:8080/index.php?/category/7", + page_url: "http://localhost:8080/picture.php?/3/category/7" + } + ] + }, + { + is_favorite: false, + id: 2, + width: 3107, + height: 4660, + hit: 4, + file: "2017-04-21-11-53-C7D_4469.jpg", + name: "2017-04-21-11-53-C7D 4469", + comment: null, + date_creation: "2017-04-21 11:53:28", + date_available: "2022-10-20 22:01:30", + page_url: "http://localhost:8080/picture.php?/2", + element_url: "http://localhost:8080/upload/2022/10/20/20221020220130-8e50dbd3.jpg", + derivatives: { + square: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220130-8e50dbd3-sq.jpg", + width: 120, + height: 120 + }, + thumb: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220130-8e50dbd3-th.jpg", + width: 96, + height: 144 + }, + 2small: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220130-8e50dbd3-2s.jpg", + width: 160, + height: 240 + }, + xsmall: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220130-8e50dbd3-xs.jpg", + width: 216, + height: 324 + }, + small: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220130-8e50dbd3-sm.jpg", + width: 288, + height: 432 + }, + medium: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220130-8e50dbd3-me.jpg", + width: 396, + height: 594 + }, + large: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220130-8e50dbd3-la.jpg", + width: 504, + height: 756 + }, + xlarge: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220130-8e50dbd3-xl.jpg", + width: 612, + height: 918 + }, + xxlarge: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220130-8e50dbd3-xx.jpg", + width: 828, + height: 1242 + } + }, + categories: [ + { + id: 7, + url: "http://localhost:8080/index.php?/category/7", + page_url: "http://localhost:8080/picture.php?/2/category/7" + } + ] + }, + { + is_favorite: false, + id: 1, + width: 5184, + height: 3456, + hit: 2, + file: "2017-01-05-11-25-c7d_2770.jpg", + name: "2017-01-05-11-25-c7d 2770", + comment: null, + date_creation: "2017-01-05 11:25:34", + date_available: "2022-10-20 22:01:29", + page_url: "http://localhost:8080/picture.php?/1", + element_url: "http://localhost:8080/upload/2022/10/20/20221020220129-6b8c2a7d.jpg", + derivatives: { + square: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220129-6b8c2a7d-sq.jpg", + width: 120, + height: 120 + }, + thumb: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220129-6b8c2a7d-th.jpg", + width: 144, + height: 96 + }, + 2small: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220129-6b8c2a7d-2s.jpg", + width: 240, + height: 160 + }, + xsmall: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220129-6b8c2a7d-xs.jpg", + width: 432, + height: 288 + }, + small: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220129-6b8c2a7d-sm.jpg", + width: 576, + height: 384 + }, + medium: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220129-6b8c2a7d-me.jpg", + width: 792, + height: 528 + }, + large: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220129-6b8c2a7d-la.jpg", + width: 1008, + height: 672 + }, + xlarge: { + url: "http://localhost:8080/i.php?/upload/2022/10/20/20221020220129-6b8c2a7d-xl.jpg", + width: 1224, + height: 816 + }, + xxlarge: { + url: "http://localhost:8080/_data/i/upload/2022/10/20/20221020220129-6b8c2a7d-xx.jpg", + width: 1656, + height: 1104 + } + }, + categories: [ + { + id: 7, + url: "http://localhost:8080/index.php?/category/7", + page_url: "http://localhost:8080/picture.php?/1/category/7" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/PiwigoDotnet/Piwigo.Client.Tests/ImageApiTests.cs b/PiwigoDotnet/Piwigo.Client.Tests/ImageApiTests.cs new file mode 100644 index 0000000..90fe964 --- /dev/null +++ b/PiwigoDotnet/Piwigo.Client.Tests/ImageApiTests.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Logging.Abstractions; +using Piwigo.Client.Contract; + +namespace Piwigo.Client.Tests; + +[TestFixture] +public class ImageApiTests : ApiTestsBase +{ + private IImageApi _imageApi = null!; + + protected override void OnSetUp() + { + base.OnSetUp(); + _imageApi = new ImageApi(Context, new NullLogger()); + } + + [Test] + public async Task GetImages_should_return_expected_images() + { + await SetJsonResultFromFileAsync("ImageApi.getImages.json"); + + var result = await _imageApi.GetImages(7, true, new PagingInfo(0, 100, 0), ImageFilter.Empty); + + CorrectMethodShouldGetCalled("pwg.categories.getImages"); + CorrectParamShouldGetSent("cat_id", "7"); + CorrectParamShouldGetSent("recursive", "true"); + CorrectParamShouldGetSent("per_page", "100"); + CorrectParamShouldGetSent("page", "0"); + + result.Images.Should().HaveCount(4); + result.Images.First().Id.Should().Be(4); + result.Paging.Page.Should().Be(0); + result.Paging.PageSize.Should().Be(100); + result.Paging.TotalItems.Should().Be(4); + } +} \ No newline at end of file diff --git a/PiwigoDotnet/Piwigo.Client.Tests/Piwigo.Client.Tests.csproj b/PiwigoDotnet/Piwigo.Client.Tests/Piwigo.Client.Tests.csproj index 9bf5783..124decf 100644 --- a/PiwigoDotnet/Piwigo.Client.Tests/Piwigo.Client.Tests.csproj +++ b/PiwigoDotnet/Piwigo.Client.Tests/Piwigo.Client.Tests.csproj @@ -21,4 +21,10 @@ + + + Always + + + diff --git a/PiwigoDotnet/Piwigo.Client/Contract/Image.cs b/PiwigoDotnet/Piwigo.Client/Contract/Image.cs new file mode 100644 index 0000000..bffee8b --- /dev/null +++ b/PiwigoDotnet/Piwigo.Client/Contract/Image.cs @@ -0,0 +1,20 @@ +using Newtonsoft.Json; + +namespace Piwigo.Client.Contract; + +public class Image +{ + [JsonProperty("id")] + public int Id { get; init; } + + [JsonProperty("width")] + public int Width { get; init; } + + [JsonProperty("height")] + public int Height { get; init; } + + [JsonProperty("hit")] + public int Hit { get; init; } + + //TODO: add additional fields +} \ No newline at end of file diff --git a/PiwigoDotnet/Piwigo.Client/Contract/ImageFilter.cs b/PiwigoDotnet/Piwigo.Client/Contract/ImageFilter.cs new file mode 100644 index 0000000..73a4afe --- /dev/null +++ b/PiwigoDotnet/Piwigo.Client/Contract/ImageFilter.cs @@ -0,0 +1,34 @@ +using System.Diagnostics.CodeAnalysis; + +namespace Piwigo.Client.Contract; + +[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] +public record ImageFilter +{ + public static ImageFilter Empty => new() + { + MinRate = null, + MaxRate = null, + MinHit = null, + MaxHit = null, + MinRatio = null, + MaxRatio = null, + MaxLevel = null, + MinDateAvailable = null, + MaxDataAvailable = null, + MinDateCreated = null, + MaxDateCreated = null + }; + + public float? MinRate { get; init; } + public float? MaxRate { get; init; } + public int? MinHit { get; init; } + public int? MaxHit { get; init; } + public float? MinRatio { get; init; } + public float? MaxRatio { get; init; } + public int? MaxLevel { get; init; } + public DateTime? MinDateAvailable { get; init; } + public DateTime? MaxDataAvailable { get; init; } + public DateTime? MinDateCreated { get; init; } + public DateTime? MaxDateCreated { get; init; } +} \ No newline at end of file diff --git a/PiwigoDotnet/Piwigo.Client/Contract/PagedImages.cs b/PiwigoDotnet/Piwigo.Client/Contract/PagedImages.cs new file mode 100644 index 0000000..7aa4998 --- /dev/null +++ b/PiwigoDotnet/Piwigo.Client/Contract/PagedImages.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; + +namespace Piwigo.Client.Contract; + +public class PagedImages +{ + protected PagedImages() + { + } + + public PagedImages(PagingInfo paging, IReadOnlyCollection images) + { + Paging = paging ?? throw new ArgumentNullException(nameof(paging)); + Images = images ?? throw new ArgumentNullException(nameof(images)); + } + + [JsonProperty("paging")] + public PagingInfo Paging { get; init; } = null!; + + [JsonProperty("images")] + public IReadOnlyCollection Images { get; init; } = null!; +} \ No newline at end of file diff --git a/PiwigoDotnet/Piwigo.Client/Contract/PagingInfo.cs b/PiwigoDotnet/Piwigo.Client/Contract/PagingInfo.cs new file mode 100644 index 0000000..731c645 --- /dev/null +++ b/PiwigoDotnet/Piwigo.Client/Contract/PagingInfo.cs @@ -0,0 +1,5 @@ +using Newtonsoft.Json; + +namespace Piwigo.Client.Contract; + +public record PagingInfo([property: JsonProperty("page")] int Page, [property: JsonProperty("per_page")] int PageSize, [property: JsonProperty("count")] int TotalItems); \ No newline at end of file diff --git a/PiwigoDotnet/Piwigo.Client/IImageApi.cs b/PiwigoDotnet/Piwigo.Client/IImageApi.cs index 9ba4ce2..60236aa 100644 --- a/PiwigoDotnet/Piwigo.Client/IImageApi.cs +++ b/PiwigoDotnet/Piwigo.Client/IImageApi.cs @@ -1,3 +1,9 @@ +using Piwigo.Client.Contract; + namespace Piwigo.Client; -public interface IImageApi {} \ No newline at end of file +public interface IImageApi +{ + Task GetImages(int albumId, bool recursive, PagingInfo page, ImageFilter filter, ImageOrder order = ImageOrder.Name, + CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/PiwigoDotnet/Piwigo.Client/ImageApi.cs b/PiwigoDotnet/Piwigo.Client/ImageApi.cs new file mode 100644 index 0000000..0299592 --- /dev/null +++ b/PiwigoDotnet/Piwigo.Client/ImageApi.cs @@ -0,0 +1,101 @@ +using System.Globalization; +using Microsoft.Extensions.Logging; +using Piwigo.Client.Contract; + +namespace Piwigo.Client; + +public class ImageApi : IImageApi +{ + private readonly IPiwigoContext _context; + private readonly ILogger _logger; + + public ImageApi(IPiwigoContext context, ILogger logger) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + public async Task GetImages(int albumId, bool recursive, PagingInfo page, ImageFilter filter, ImageOrder order = ImageOrder.Name, + CancellationToken cancellationToken = default) + { + var orderValue = order switch + { + ImageOrder.Id => "id", + ImageOrder.File => "file", + ImageOrder.Name => "name", + ImageOrder.Hit => "hit", + ImageOrder.RatingScore => "rating_score", + ImageOrder.DateCreation => "date_creation", + ImageOrder.DateAvailable => "date_available", + ImageOrder.Random => "random", + _ => throw new ArgumentOutOfRangeException(nameof(order), order, null) + }; + + var formParams = new Dictionary + { + { "cat_id", albumId.ToString() }, + { "recursive", recursive.ToString() }, + { "per_page", page.PageSize.ToString() }, + { "page", page.Page.ToString() }, + { "order", orderValue } + }; + + if (filter.MinRate.HasValue) + { + formParams.Add("f_min_rate", filter.MinRate.Value.ToString(CultureInfo.InvariantCulture)); + } + + if (filter.MaxRate.HasValue) + { + formParams.Add("f_max_rate", filter.MaxRate.Value.ToString(CultureInfo.InvariantCulture)); + } + + if (filter.MinHit.HasValue) + { + formParams.Add("f_min_hit", filter.MinHit.Value.ToString()); + } + + if (filter.MaxHit.HasValue) + { + formParams.Add("f_max_hit", filter.MaxHit.Value.ToString()); + } + + if (filter.MinRatio.HasValue) + { + formParams.Add("f_min_ratio", filter.MinRatio.Value.ToString(CultureInfo.InvariantCulture)); + } + + if (filter.MaxRatio.HasValue) + { + formParams.Add("f_max_ratio", filter.MaxRatio.Value.ToString(CultureInfo.InvariantCulture)); + } + + if (filter.MaxLevel.HasValue) + { + formParams.Add("f_max_level", filter.MaxLevel.Value.ToString()); + } + + if (filter.MinDateAvailable.HasValue) + { + formParams.Add("f_min_date_available", filter.MinDateAvailable.Value.ToString("yyyy-MM-dd")); + } + + if (filter.MaxDataAvailable.HasValue) + { + formParams.Add("f_max_date_available", filter.MaxDataAvailable.Value.ToString("yyyy-MM-dd")); + } + + if (filter.MinDateCreated.HasValue) + { + formParams.Add("f_min_date_created", filter.MinDateCreated.Value.ToString("yyyy-MM-dd")); + } + + if (filter.MaxDateCreated.HasValue) + { + formParams.Add("f_max_date_created", filter.MaxDateCreated.Value.ToString("yyyy-MM-dd")); + } + + var response = await _context.PostAsync>(_logger, "pwg.categories.getImages", formParams, cancellationToken); + return response.Result; + } +} \ No newline at end of file diff --git a/PiwigoDotnet/Piwigo.Client/ImageOrder.cs b/PiwigoDotnet/Piwigo.Client/ImageOrder.cs new file mode 100644 index 0000000..deddde0 --- /dev/null +++ b/PiwigoDotnet/Piwigo.Client/ImageOrder.cs @@ -0,0 +1,13 @@ +namespace Piwigo.Client; + +public enum ImageOrder +{ + Id = 0, + File, + Name, + Hit, + RatingScore, + DateCreation, + DateAvailable, + Random +} \ No newline at end of file