diff --git a/Bynder/Sample/ApiSample.cs b/Bynder/Sample/ApiSample.cs index 6c566c9..cc22626 100644 --- a/Bynder/Sample/ApiSample.cs +++ b/Bynder/Sample/ApiSample.cs @@ -48,6 +48,14 @@ public static async Task Main(string[] args) await MetapropertiesSample.MetapropertiesSampleAsync(); return; } + + // Run samples related to the relation between metaproperties and media items + if (args[0].Equals("MetapropertyToMediaSample")) { + Console.WriteLine("Running samples for metaproperties and related media..."); + await MetaPropertyToMediaSample.MetaPropertyToMediaSampleAsync(); + return; + } + // Run samples related to media if (args[0].Equals("MediaSample")) { Console.WriteLine("Running samples for media..."); diff --git a/Bynder/Sample/MediaSample.cs b/Bynder/Sample/MediaSample.cs index bfd3dd3..ed92cad 100644 --- a/Bynder/Sample/MediaSample.cs +++ b/Bynder/Sample/MediaSample.cs @@ -40,6 +40,10 @@ private async Task RunMediaSampleAsync() Console.WriteLine($"Media Name: {media.Name}"); } + // Get ths same list as a full result + var mediaFullResult = await _bynderClient.GetAssetService().GetMediaFullResultAsync(new MediaQuery { Limit = 10 }); + Console.WriteLine($"Retrieving full result based on same query, total number of matching assets is {mediaFullResult.Total.Count}"); + // Get the media info Console.WriteLine("Enter the media ID to get the media info for: "); var mediaIdForInfo = Console.ReadLine(); diff --git a/Bynder/Sample/MetaPropertyToMediaSample.cs b/Bynder/Sample/MetaPropertyToMediaSample.cs new file mode 100644 index 0000000..bbaa232 --- /dev/null +++ b/Bynder/Sample/MetaPropertyToMediaSample.cs @@ -0,0 +1,118 @@ +// Copyright (c) Bynder. All rights reserved. +// Licensed under the MIT License. See LICENSE file in the project root for full license information. + +using System; +using Bynder.Sdk.Service; +using Bynder.Sample.Utils; +using Bynder.Sdk.Settings; +using System.Threading.Tasks; +using System.Linq; +using Bynder.Sdk.Query.Asset; +using Bynder.Sdk.Model; +using System.Collections.Generic; +using Newtonsoft.Json.Linq; +using System.Text; + +namespace Bynder.Sample +{ + public class MetaPropertyToMediaSample + { + private IBynderClient _bynderClient; + + public static async Task MetaPropertyToMediaSampleAsync() + { + var configuration = Configuration.FromJson("Config.json"); + Console.WriteLine($"BaseUrl: {configuration.BaseUrl}"); + var apiSample = new MetaPropertyToMediaSample(configuration); + await apiSample.AuthenticateWithOAuth2Async( + useClientCredentials: configuration.RedirectUri == null + ); + await apiSample.RunMetaPropertyToMediaSampleAsync(); + } + + private MetaPropertyToMediaSample(Configuration configuration) { + _bynderClient = ClientFactory.Create(configuration); + } + + private async Task RunMetaPropertyToMediaSampleAsync() + { + var assetService = _bynderClient.GetAssetService(); + // Get a list of media with limit 10 + Console.WriteLine("Available metaproperties: "); + var metaProperties = await assetService.GetMetapropertiesAsync(); + int i = 0; + foreach(var metaProperty in metaProperties.Values) { + Console.WriteLine($"({++i}) MetaProperty {metaProperty.Name} ({metaProperty.Id})"); + } + Console.WriteLine("Enter number of the metaProperty to search by"); + var metaPropertyNr = Convert.ToInt32(Console.ReadLine()); + var metaPropertySelected = metaProperties.Skip(metaPropertyNr - 1).FirstOrDefault().Value; + i = 0; + foreach (var option in metaPropertySelected.Options) + { + Console.WriteLine($"({++i}) Option {option.Name} ({option.Id})"); + } + Console.WriteLine("Enter number of the option to search by, or a text value"); + var optionSearchText = Console.ReadLine(); + if (Int32.TryParse(optionSearchText, out int optionNr)) + { + var optionSelected = metaPropertySelected.Options.Skip(optionNr - 1).FirstOrDefault(); + optionSearchText = optionSelected.Name; + } + + // Get matching media (assets) + var mediaQuery = new MediaQuery() + { + MetaProperties = new Dictionary> { { metaPropertySelected.Name, [optionSearchText] } }, + Limit = 10 + }; + var mediaList = await _bynderClient.GetAssetService().GetMediaListAsync(mediaQuery); + foreach (var media in mediaList) + { + Console.WriteLine($"ID: {media.Id}"); + Console.WriteLine($"Name: {media.Name}"); + Console.WriteLine($"Meta properties: {ShowMetaProperties(media.PropertyOptionsDictionary)}"); + Console.WriteLine("-----------------"); + } + } + + private string ShowMetaProperties(Dictionary propertyOptionsDictionary) + { + if (propertyOptionsDictionary == null) + { + return ""; + } + StringBuilder sb = new StringBuilder(); + bool first = true; + foreach (var key in propertyOptionsDictionary.Keys) + { + if (first) + { + first = false; + } + else + { + sb.Append("|"); + } + sb.Append($"{key.Replace("property_","")}:{string.Join(',', propertyOptionsDictionary[key].Select(a => a.ToString()))}"); + } + return sb.ToString(); + } + + private async Task AuthenticateWithOAuth2Async(bool useClientCredentials) + { + if (useClientCredentials) + { + await _bynderClient.GetOAuthService().GetAccessTokenAsync(); + } + else + { + Browser.Launch(_bynderClient.GetOAuthService().GetAuthorisationUrl("state example")); + Console.WriteLine("Insert the code: "); + var code = Console.ReadLine(); + await _bynderClient.GetOAuthService().GetAccessTokenAsync(code); + } + } + + } +} diff --git a/Bynder/Sample/UploadSample.cs b/Bynder/Sample/UploadSample.cs index 826279f..21a054a 100644 --- a/Bynder/Sample/UploadSample.cs +++ b/Bynder/Sample/UploadSample.cs @@ -8,6 +8,8 @@ using System.Threading.Tasks; using System.Linq; using Bynder.Sdk.Query.Upload; +using System.Collections.Generic; +using System.IO; namespace Bynder.Sample { public class UploadSample @@ -41,9 +43,77 @@ private async Task RunUploadSampleAsync() return; } - await assetService.UploadFileAsync(new UploadQuery { Filepath = uploadPath, BrandId = brands.First().Id }); + Console.WriteLine("Name of the media item after upload: "); + var name = Console.ReadLine(); + if (string.IsNullOrEmpty(name)) + { + name = null; + } + + Console.WriteLine("Override original filename (leave empty to use the actual filename): "); + var filename = Console.ReadLine(); + + Console.WriteLine("Description (leave empty to use default): "); + var description = Console.ReadLine(); + + var customParameters = GetCustomParameters(); + + Console.WriteLine("Do you want to pass a file stream to the SDK?: (y/n)"); + var passAsStream = Console.ReadLine().ToLower().StartsWith("y"); + + + var query = new UploadQuery + { + Filepath = uploadPath, + BrandId = brands.First().Id, + Name = name, + CustomParameters = customParameters + }; + if (!string.IsNullOrEmpty(filename)) + { + query.OriginalFileName = filename; + } + if (!string.IsNullOrEmpty(description)) + { + query.Description = description; + } + + FileStream fileStream = null; + if (passAsStream) + { + fileStream = File.Open(query.Filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); + } + var before = DateTime.Now; + var response = passAsStream ? await assetService.UploadFileAsync(fileStream, query) : await assetService.UploadFileAsync(query); + var ms = Math.Round((DateTime.Now - before).TotalMilliseconds); + Console.WriteLine($"Uploaded file as media with id {response.MediaId} (time elapsed: {ms})"); + } - + + private Dictionary GetCustomParameters() + { + Console.WriteLine("Do you want to add custom parameters during the upload? (y/n)"); + var input = Console.ReadLine(); + + if (!input.ToString().ToLower().StartsWith("y")) + { + return null; + } + + Dictionary parameters = new Dictionary(); + while (input.ToString().ToLower().StartsWith("y")) + { + Console.WriteLine("Parameter name: "); + var paramName = Console.ReadLine(); + Console.WriteLine("Parameter value: "); + var paramValue = Console.ReadLine(); + parameters.Add(paramName, paramValue); + Console.WriteLine("Do you want to add another custom parameter? (y/n)"); + input = Console.ReadLine(); + } + return parameters; + } + private async Task AuthenticateWithOAuth2Async(bool useClientCredentials) { if (useClientCredentials) diff --git a/Bynder/Sdk/Model/MediaFullResult.cs b/Bynder/Sdk/Model/MediaFullResult.cs new file mode 100644 index 0000000..463bb08 --- /dev/null +++ b/Bynder/Sdk/Model/MediaFullResult.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bynder.Sdk.Model +{ + public class MediaFullResult + { + [JsonProperty("total")] + public Total Total { get; set; } + + [JsonProperty("media")] + public IList Media { get; set; } + } + public class Total + { + public long Count { get; set; } + } +} diff --git a/Bynder/Sdk/Query/Asset/MediaQuery.cs b/Bynder/Sdk/Query/Asset/MediaQuery.cs index 8f40145..09b0869 100644 --- a/Bynder/Sdk/Query/Asset/MediaQuery.cs +++ b/Bynder/Sdk/Query/Asset/MediaQuery.cs @@ -72,5 +72,20 @@ public class MediaQuery /// [ApiField("propertyOptionId", Converter = typeof(ListConverter))] public IList PropertyOptionId { get; set; } = new List(); + + /// + /// Metaproperties + /// Look for assets by specifying meta properties and values by name + /// e.g. City: Amsterdam + /// + /// + /// - Use the database names of the metaproperties, not the IDs + /// - If the metaproperty is of type single/multiple select, the values should be the database names of the option(s) + /// - If the metaproperty is of type text, the values refer to the text itself + /// + /// + [ApiField("property_", Converter = typeof(MetapropertyOptionsConverter))] + public IDictionary> MetaProperties { get; set; } + } } diff --git a/Bynder/Sdk/Query/Asset/MediaQueryFull.cs b/Bynder/Sdk/Query/Asset/MediaQueryFull.cs new file mode 100644 index 0000000..550184e --- /dev/null +++ b/Bynder/Sdk/Query/Asset/MediaQueryFull.cs @@ -0,0 +1,19 @@ +// Copyright (c) Bynder. All rights reserved. +// Licensed under the MIT License. See LICENSE file in the project root for full license information. + +using System.Collections.Generic; +using Bynder.Sdk.Model; +using Bynder.Sdk.Api.Converters; +using Bynder.Sdk.Query.Decoder; + +namespace Bynder.Sdk.Query.Asset +{ + /// + /// Query to filter media results, including the option to see the total number of results + /// + public class MediaQueryFull : MediaQuery + { + [ApiField("total")] + public bool Total { get; set; } + } +} diff --git a/Bynder/Sdk/Query/Decoder/QueryDecoder.cs b/Bynder/Sdk/Query/Decoder/QueryDecoder.cs index 345219b..c65dfce 100644 --- a/Bynder/Sdk/Query/Decoder/QueryDecoder.cs +++ b/Bynder/Sdk/Query/Decoder/QueryDecoder.cs @@ -1,4 +1,4 @@ -// Copyright (c) Bynder. All rights reserved. +// Copyright (c) Bynder. All rights reserved. // Licensed under the MIT License. See LICENSE file in the project root for full license information. using System; @@ -67,7 +67,7 @@ private void ConvertProperty(PropertyInfo propertyInfo, object query, IDictionar { foreach (var item in dictConverter.Convert(value)) { - AddParam(parameters, $"{apiField.ApiName}.{item.Key}", item.Value); + AddParam(parameters, $"{apiField.ApiName}{item.Key}", item.Value); } } @@ -77,6 +77,7 @@ private void ConvertProperty(PropertyInfo propertyInfo, object query, IDictionar } } + private void AddParam(IDictionary parameters, string key, string value) { if (!string.IsNullOrEmpty(value)) diff --git a/Bynder/Sdk/Query/Upload/SaveMediaQuery.cs b/Bynder/Sdk/Query/Upload/SaveMediaQuery.cs index 0d8e01b..8e241fb 100644 --- a/Bynder/Sdk/Query/Upload/SaveMediaQuery.cs +++ b/Bynder/Sdk/Query/Upload/SaveMediaQuery.cs @@ -1,4 +1,4 @@ -// Copyright (c) Bynder. All rights reserved. +// Copyright (c) Bynder. All rights reserved. // Licensed under the MIT License. See LICENSE file in the project root for full license information. using System.Collections.Generic; @@ -43,6 +43,31 @@ internal class SaveMediaQuery [ApiField("tags", Converter = typeof(ListConverter))] public IList Tags { get; set; } + + /// + /// Description of the media + /// + [ApiField("description")] + public string Description { get; set; } + + /// + /// Published date of the media + /// + [ApiField("ISOPublicationDate")] + public string PublishedDate { get; set; } + + /// + /// Copyright information for the media + /// + [ApiField("copyright")] + public string Copyright { get; set; } + + /// + /// Indicates if the media is public + /// + [ApiField("isPublic")] + public bool IsPublic { get; set; } + /// /// Metaproperty options to set on the asset. /// diff --git a/Bynder/Sdk/Query/Upload/UploadQuery.cs b/Bynder/Sdk/Query/Upload/UploadQuery.cs index df69753..c3e2205 100644 --- a/Bynder/Sdk/Query/Upload/UploadQuery.cs +++ b/Bynder/Sdk/Query/Upload/UploadQuery.cs @@ -1,4 +1,4 @@ -// Copyright (c) Bynder. All rights reserved. +// Copyright (c) Bynder. All rights reserved. // Licensed under the MIT License. See LICENSE file in the project root for full license information. using System.Collections.Generic; @@ -15,6 +15,16 @@ public class UploadQuery /// public string Filepath { get; set; } + /// + /// Name the media will have. + /// + public string Name { get; set; } + + /// + /// Original file name the media will have. + /// + public string OriginalFileName { get; set; } + /// /// Brand id where we want to store the file /// @@ -31,5 +41,37 @@ public class UploadQuery /// Tags of the file that we want to update /// public IList Tags { get; set; } + + /// + /// Description of the media + /// + public string Description { get; set; } + + /// + /// Copyright information for the media + /// + public string Copyright { get; set; } + + /// + /// Indicates if the media is public + /// + public bool IsPublic { get; set; } + + /// + /// Metaproperties the media will have + /// + public IDictionary> MetapropertyOptions { get; set; } = new Dictionary>(); + + /// + /// Published date the media will have. + /// + public string PublishedDate { get; set; } + + /// + /// Custom parameters to add to the upload endpoint + /// + public IEnumerable> CustomParameters { get; set; } + + } } diff --git a/Bynder/Sdk/Service/Asset/AssetService.cs b/Bynder/Sdk/Service/Asset/AssetService.cs index d5e15ba..8a958cb 100644 --- a/Bynder/Sdk/Service/Asset/AssetService.cs +++ b/Bynder/Sdk/Service/Asset/AssetService.cs @@ -11,6 +11,7 @@ using Bynder.Sdk.Model; using Bynder.Sdk.Query.Asset; using Bynder.Sdk.Query.Upload; +using System.IO; namespace Bynder.Sdk.Service.Asset { @@ -143,6 +144,18 @@ public async Task UploadFileAsync(UploadQuery query) return await _uploader.UploadFileAsync(query).ConfigureAwait(false); } + /// + /// Check for more information + /// + /// Check for more information + /// Check for more information + /// Check for more information + public async Task UploadFileAsync(FileStream fileStream, UploadQuery query) + { + return await _uploader.UploadFileAsync(fileStream, query).ConfigureAwait(false); + } + + /// /// Check for more information /// @@ -237,6 +250,35 @@ public async Task DeleteAssetUsage(AssetUsageQuery query) /// Check for more information /// /// Check for more information + public async Task GetMediaFullResultAsync(MediaQuery query) + { + var mediaQueryFull = query is MediaQueryFull ? query as MediaQueryFull : CloneIntoFullMediaQuery(query); + return await _requestSender.SendRequestAsync(new ApiRequest + { + Path = "/api/v4/media/", + HTTPMethod = HttpMethod.Get, + Query = mediaQueryFull, + }).ConfigureAwait(false); + } + + private static MediaQueryFull CloneIntoFullMediaQuery(MediaQuery query) + { + return new MediaQueryFull() + { + BrandId = query.BrandId, + CategoryId = query.CategoryId, + CollectionId = query.CollectionId, + Ids = query.Ids, + Keyword = query.Keyword, + Limit = query.Limit, + MetaProperties = query.MetaProperties, + Page = query.Page, + PropertyOptionId = query.PropertyOptionId, + SubBrandId = query.SubBrandId, + Type = query.Type, + Total = true + }; + } public async Task DeleteAssetAsync(string assetId) { return await _requestSender.SendRequestAsync(new ApiRequest diff --git a/Bynder/Sdk/Service/Asset/IAssetService.cs b/Bynder/Sdk/Service/Asset/IAssetService.cs index 17b687a..1d1b0ab 100644 --- a/Bynder/Sdk/Service/Asset/IAssetService.cs +++ b/Bynder/Sdk/Service/Asset/IAssetService.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Threading.Tasks; using Bynder.Sdk.Model; using Bynder.Sdk.Query.Asset; @@ -74,7 +75,7 @@ public interface IAssetService Task> GetMediaListAsync(MediaQuery query); /// - /// Uploads a file async. + /// Uploads a file based on a filepath in the query /// /// Information to upload a file /// Task representing the upload @@ -82,6 +83,18 @@ public interface IAssetService /// Can be thrown when upload does not finish within expected time Task UploadFileAsync(UploadQuery query); + /// + /// Uploads a file as a stream + /// + /// Stream representing the file to be uploaded + /// Information to upload a file + /// Task representing the upload + /// Can be thrown when requests to server can't be completed or HTTP code returned by server is an error + /// Can be thrown when upload does not finish within expected time + + Task UploadFileAsync(FileStream fileStream, UploadQuery query); + + /// /// Modifies a media /// @@ -123,12 +136,19 @@ public interface IAssetService Task DeleteAssetUsage(AssetUsageQuery query); /// + /// Get a full list of Bynder assets including the total number of matching results + /// + /// Information to correctly filter/paginate media + /// Task representing the full result, including the total number of matches + /// Can be thrown when requests to server can't be completed or HTTP code returned by server is an error + /// This method can be used to implement pagination in your app. The MediaFullResult that gets returned has a Total.Count property, which contains the total number of matching assets, not just the number of assets in the current result page + Task GetMediaFullResultAsync(MediaQuery query); + /// Delete an asset /// /// Id of the asset to remove /// Task representing the operation /// Can be thrown when requests to server can't be completed or HTTP code returned by server is an error Task DeleteAssetAsync(string assetId); - } } diff --git a/Bynder/Sdk/Service/Upload/FileUploader.cs b/Bynder/Sdk/Service/Upload/FileUploader.cs index cccc5fb..58b4aad 100644 --- a/Bynder/Sdk/Service/Upload/FileUploader.cs +++ b/Bynder/Sdk/Service/Upload/FileUploader.cs @@ -10,6 +10,8 @@ using Bynder.Sdk.Api.RequestSender; using Bynder.Sdk.Model; using Bynder.Sdk.Query.Upload; +using System.Linq; +using System.Web; namespace Bynder.Sdk.Service.Upload { @@ -69,6 +71,17 @@ public static FileUploader Create(IApiRequestSender requestSender) return new FileUploader(requestSender, new AmazonApi()); } + /// + /// Uploads a file with the data specified in query parameter + /// + /// Stream of the file to upload + /// Upload query information to upload a file + /// Task representing the upload + public async Task UploadFileAsync(Stream fileStream, UploadQuery query) + { + return await UploadFileAsync(fileStream, query, query.OriginalFileName ?? Path.GetFileName(query.Filepath)); + } + /// /// Uploads a file with the data specified in query parameter /// @@ -76,44 +89,66 @@ public static FileUploader Create(IApiRequestSender requestSender) /// Task representing the upload public async Task UploadFileAsync(UploadQuery query) { - var uploadRequest = await RequestUploadInformationAsync(new RequestUploadQuery { Filename = query.Filepath }).ConfigureAwait(false); + var filename = !string.IsNullOrEmpty(query.OriginalFileName) ? query.OriginalFileName : Path.GetFileName(query.Filepath); + var uploadRequest = await RequestUploadInformationAsync(new RequestUploadQuery { Filename = filename }).ConfigureAwait(false); uint chunkNumber = 0; - using (var file = File.Open(query.Filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) + var fileStream = File.Open(query.Filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); + return await UploadFileAsync(fileStream, query, filename); + + + } + + private async Task GetUploadRequest(string fileName) + { + return await RequestUploadInformationAsync(new RequestUploadQuery { Filename = fileName }).ConfigureAwait(false); + } + + + private async Task UploadFileAsync(Stream fileStream, UploadQuery query, string filename) + { + uint chunkNumber = 0; + var uploadRequest = await GetUploadRequest(filename); + using (fileStream) { int bytesRead = 0; var buffer = new byte[CHUNK_SIZE]; - long numberOfChunks = (file.Length + CHUNK_SIZE - 1) / CHUNK_SIZE; + long numberOfChunks = (fileStream.Length + CHUNK_SIZE - 1) / CHUNK_SIZE; - while ((bytesRead = file.Read(buffer, 0, buffer.Length)) > 0) + while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0) { ++chunkNumber; await UploadPartAsync(Path.GetFileName(query.Filepath), buffer, bytesRead, chunkNumber, uploadRequest, (uint)numberOfChunks).ConfigureAwait(false); } } - var finalizeResponse = await FinalizeUploadAsync(uploadRequest, chunkNumber).ConfigureAwait(false); + var finalizeResponse = await FinalizeUploadAsync(uploadRequest, chunkNumber, query.CustomParameters).ConfigureAwait(false); if (await HasFinishedSuccessfullyAsync(finalizeResponse).ConfigureAwait(false)) { return await SaveMediaAsync(new SaveMediaQuery { - Filename = query.Filepath, + Filename = query.Name ?? query.Filepath, BrandId = query.BrandId, ImportId = finalizeResponse.ImportId, MediaId = query.MediaId, - Tags = query.Tags + Tags = query.Tags, + Description = query.Description, + Copyright = query.Copyright, + IsPublic = query.IsPublic, + MetapropertyOptions = query.MetapropertyOptions, + PublishedDate = query.PublishedDate }).ConfigureAwait(false); } else { - throw new BynderUploadException("Converter did not finished. Upload not completed"); + throw new BynderUploadException("Converter did not finish. Upload not completed"); } } /// - /// Gets the closes s3 endpoint. This is needed to know to which bucket Url it uploads chunks + /// Gets the closest s3 endpoint. This is needed to know to which bucket Url it uploads chunks /// /// Task containting string with the Url private async Task GetClosestS3EndpointAsync() @@ -243,7 +278,7 @@ private async Task HasFinishedSuccessfullyAsync(FinalizeResponse finalizeR } /// - /// Registers a chunk in Bynder using . + /// Registers a chunk in Bynder using . /// /// Upload request information /// Current chunk number @@ -274,7 +309,7 @@ private async Task RegisterChunkAsync(UploadRequest uploadRequest, uint chunkNum /// Requests information to start a new upload /// /// Contains the information needed to request upload information - /// Task containing information + /// Task containing information private async Task RequestUploadInformationAsync(RequestUploadQuery query) { var request = new ApiRequest @@ -288,12 +323,12 @@ private async Task RequestUploadInformationAsync(RequestUploadQue } /// - /// Finalizes an upload using . + /// Finalizes an upload using . /// /// Upload request information /// chunk number /// Task with information - private async Task FinalizeUploadAsync(UploadRequest uploadRequest, uint chunkNumber) + private async Task FinalizeUploadAsync(UploadRequest uploadRequest, uint chunkNumber, IEnumerable> customParameters) { var query = new FinalizeUploadQuery { @@ -302,9 +337,18 @@ private async Task FinalizeUploadAsync(UploadRequest uploadReq S3Filename = $"{uploadRequest.S3Filename}/p{chunkNumber}", Chunks = chunkNumber.ToString() }; + var requestParameters = ""; + if (customParameters != null) + { + requestParameters = string.Join('&', customParameters.Select(p => HttpUtility.UrlEncode(p.Key) + "=" + HttpUtility.UrlEncode(p.Value))); + if (!string.IsNullOrEmpty(requestParameters)) + { + requestParameters = "?" + requestParameters; + } + } var request = new ApiRequest { - Path = $"/api/v4/upload/{query.UploadId}/", + Path = $"/api/v4/upload/{query.UploadId}/{requestParameters}", HTTPMethod = HttpMethod.Post, Query = query }; diff --git a/Bynder/Sdk/Settings/Configuration.cs b/Bynder/Sdk/Settings/Configuration.cs index 9635042..cf8a355 100644 --- a/Bynder/Sdk/Settings/Configuration.cs +++ b/Bynder/Sdk/Settings/Configuration.cs @@ -54,6 +54,7 @@ public class Configuration /// instance public static Configuration FromJson(string filepath) { + Console.WriteLine("Read config from " + filepath); return JsonConvert.DeserializeObject(File.ReadAllText(filepath)); } } diff --git a/Bynder/Test/Service/Asset/AssetServiceTest.cs b/Bynder/Test/Service/Asset/AssetServiceTest.cs index 4b633c8..c89cb43 100644 --- a/Bynder/Test/Service/Asset/AssetServiceTest.cs +++ b/Bynder/Test/Service/Asset/AssetServiceTest.cs @@ -3,12 +3,14 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Bynder.Sdk.Api.Requests; using Bynder.Sdk.Api.RequestSender; using Bynder.Sdk.Model; using Bynder.Sdk.Query.Asset; +using Bynder.Sdk.Query.Decoder; using Bynder.Sdk.Service.Asset; using Moq; using Xunit; @@ -124,6 +126,46 @@ public async Task GetMediaListCallsRequestSenderWithValidRequest() Assert.Equal(result, mediaList); } + [Fact] + public async Task GetMediaListWithMetaPropertiesCallsRequestSenderWithValidRequest() + { + var result = new List(); + _apiRequestSenderMock.Setup(sender => sender.SendRequestAsync(It.IsAny>>())) + .ReturnsAsync(result); + var mediaQuery = new MediaQuery() { + MetaProperties = new Dictionary> { { "City", new[] { "Amsterdam", "Rotterdam" } } } + }; + var mediaList = await _assetService.GetMediaListAsync(mediaQuery); + + _apiRequestSenderMock.Verify(sender => sender.SendRequestAsync( + It.Is>>( + req => req.Path == "/api/v4/media/" + && req.HTTPMethod == HttpMethod.Get + && req.Query == mediaQuery + ) + )); + + Assert.Equal(result, mediaList); + } + + [Fact] + public async Task GetMediaListWithMetaPropertiesHasCorrectParameters() + { + var mediaQuery = new MediaQuery() + { + MetaProperties = new Dictionary> { { "City", new[] { "Amsterdam", "Rotterdam" } } } + }; + var mediaList = await _assetService.GetMediaListAsync(mediaQuery); + + QueryDecoder queryDecoder = new QueryDecoder(); + var parameters = queryDecoder.GetParameters(mediaQuery); + + Assert.True(parameters.ContainsKey("property_City")); + Assert.DoesNotContain(".", parameters["property_City"]); + Assert.Equal("Rotterdam", parameters["property_City"].Split(',').Last()); + } + + [Fact] public async Task GetDownloadFileUrlCallsRequestSenderWithValidRequest() { @@ -221,6 +263,28 @@ public async Task AddTagToMediaCallsRequestSenderWithValidRequest() )); } + [Fact] + public async Task GetMediaFullResultAsyncCallsRequestSenderWithValidRequest() + { + var result = new MediaFullResult() { Media = [ new Media() { Id = "SomeId", Name = "SomeName"} ] }; + _apiRequestSenderMock.Setup(sender => sender.SendRequestAsync(It.IsAny>())) + .ReturnsAsync(() => + { + return result; + }); + var mediaQuery = new MediaQuery(); + var mediaFullResult = await _assetService.GetMediaFullResultAsync(mediaQuery); + + _apiRequestSenderMock.Verify(sender => sender.SendRequestAsync( + It.Is>( + req => req.Path == "/api/v4/media/" + && req.HTTPMethod == HttpMethod.Get + && req.Query is MediaQueryFull + ) + )); + Assert.Equal(result, mediaFullResult); + } + [Fact] public async Task CreateAssetUsageCallsRequestSenderWithValidRequest() {