diff --git a/VkNet.Tests/Categories/Ads/GetMusiciansByIdsTest.cs b/VkNet.Tests/Categories/Ads/GetMusiciansByIdsTest.cs new file mode 100644 index 000000000..096a74151 --- /dev/null +++ b/VkNet.Tests/Categories/Ads/GetMusiciansByIdsTest.cs @@ -0,0 +1,25 @@ +using NUnit.Framework; +using VkNet.Tests.Infrastructure; + +namespace VkNet.Tests.Categories.Ads +{ + [TestFixture] + public class GetMusiciansByIdsTest : CategoryBaseTest + { + protected override string Folder => "Ads"; + + [Test] + public void GetMusiciansByIds() + { + Url = "https://api.vk.com/method/ads.getMusiciansByIds"; + + ReadCategoryJsonPath(nameof(Api.Ads.GetMusiciansByIds)); + + var result = Api.Ads.GetMusiciansByIds("1, 2, 3"); + Assert.That(result[0].Name, Is.EqualTo("UGLYBOY")); + Assert.That(result[1].Name, Is.EqualTo("Rudesarcasmov")); + Assert.That(result[2].Name, Is.EqualTo("Santiz")); + Assert.That(result[1].Id, Is.EqualTo(2)); + } + } +} \ No newline at end of file diff --git a/VkNet.Tests/Categories/Ads/GetMusiciansTest.cs b/VkNet.Tests/Categories/Ads/GetMusiciansTest.cs new file mode 100644 index 000000000..97b7b31dc --- /dev/null +++ b/VkNet.Tests/Categories/Ads/GetMusiciansTest.cs @@ -0,0 +1,28 @@ +using System; +using NUnit.Framework; +using VkNet.Enums; +using VkNet.Enums.SafetyEnums; +using VkNet.Model; +using VkNet.Model.RequestParams.Ads; +using VkNet.Tests.Infrastructure; + +namespace VkNet.Tests.Categories.Ads +{ + [TestFixture] + public class GetMusiciansTest : CategoryBaseTest + { + protected override string Folder => "Ads"; + + [Test] + public void GetMusicians() + { + Url = "https://api.vk.com/method/ads.getMusicians"; + + ReadCategoryJsonPath(nameof(Api.Ads.GetMusicians)); + + var result = Api.Ads.GetMusicians("Alan Walker"); + Assert.That(result[0].Name, Is.EqualTo("Alan Walker")); + Assert.That(result[0].Id, Is.EqualTo(32697)); + } + } +} \ No newline at end of file diff --git a/VkNet.Tests/Categories/Ads/UpdateOfficeUsersTest.cs b/VkNet.Tests/Categories/Ads/UpdateOfficeUsersTest.cs new file mode 100644 index 000000000..d0e31973b --- /dev/null +++ b/VkNet.Tests/Categories/Ads/UpdateOfficeUsersTest.cs @@ -0,0 +1,66 @@ +using NUnit.Framework; +using VkNet.Enums.SafetyEnums; +using VkNet.Model; +using VkNet.Model.RequestParams.Ads; +using VkNet.Tests.Infrastructure; + +namespace VkNet.Tests.Categories.Ads +{ + [TestFixture] + public class UpdateOfficeUsersTest : CategoryBaseTest + { + protected override string Folder => "Ads"; + + [Test] + public void UpdateOfficeUsers() + { + Url = "https://api.vk.com/method/ads.updateOfficeUsers"; + + ReadCategoryJsonPath(nameof(Api.Ads.UpdateOfficeUsers)); + + OfficeUsersSpecification officeUsersSpecification1 = new OfficeUsersSpecification + { + UserId = 12423, + Role = AccessRole.Reports, + ClientsIds = new int[] + { + 1245, + 566, + 323 + }, + GrantAccessToAllClients = true, + ViewBudget = true + }; + + OfficeUsersSpecification officeUsersSpecification2 = new OfficeUsersSpecification + { + UserId = 4324432, + Role = AccessRole.Manager, + ClientsIds = new int[] + { + 567357, + 566566, + 3645623 + }, + GrantAccessToAllClients = false, + ViewBudget = false + }; + + OfficeUsersSpecification[] data = + { + officeUsersSpecification1, + officeUsersSpecification2 + }; + + var result = Api.Ads.UpdateOfficeUsers(new AdsDataSpecificationParams + { + AccountId = 1605245430, + Data = data + }); + + Assert.That(result[0].UserId, Is.EqualTo(1567)); + Assert.That(result[0].IsSuccess, Is.False); + Assert.That(result[0].Error.ErrorCode, Is.EqualTo(100)); + } + } +} \ No newline at end of file diff --git a/VkNet.Tests/TestData/Categories/Ads/GetMusicians.json b/VkNet.Tests/TestData/Categories/Ads/GetMusicians.json new file mode 100644 index 000000000..84b275b2e --- /dev/null +++ b/VkNet.Tests/TestData/Categories/Ads/GetMusicians.json @@ -0,0 +1,7 @@ +{ + "response": [{ + "id": 32697, + "name": "Alan Walker", + "avatar": "https://sun9-24.u...-e7E&type=audio" + }] +} \ No newline at end of file diff --git a/VkNet.Tests/TestData/Categories/Ads/GetMusiciansByIds.json b/VkNet.Tests/TestData/Categories/Ads/GetMusiciansByIds.json new file mode 100644 index 000000000..6c062279a --- /dev/null +++ b/VkNet.Tests/TestData/Categories/Ads/GetMusiciansByIds.json @@ -0,0 +1,13 @@ +{ + "response": [{ + "id": 1, + "name": "UGLYBOY", + "avatar": "https://sun9-11.u...FeTk&type=audio" + }, { + "id": 2, + "name": "Rudesarcasmov" + }, { + "id": 3, + "name": "Santiz" + }] +} \ No newline at end of file diff --git a/VkNet.Tests/TestData/Categories/Ads/UpdateOfficeUsers.json b/VkNet.Tests/TestData/Categories/Ads/UpdateOfficeUsers.json new file mode 100644 index 000000000..74131ead0 --- /dev/null +++ b/VkNet.Tests/TestData/Categories/Ads/UpdateOfficeUsers.json @@ -0,0 +1,10 @@ +{ + "response": [{ + "user_id": 1567, + "is_success": false, + "error": { + "error_code": 100, + "error_msg": "One of the parameters specified was missing or invalid: account_id is undefined" + } + }] +} \ No newline at end of file diff --git a/VkNet/Abstractions/Category/Async/IAdsCategoryAsync.cs b/VkNet/Abstractions/Category/Async/IAdsCategoryAsync.cs index 55290c2d1..faabaa418 100644 --- a/VkNet/Abstractions/Category/Async/IAdsCategoryAsync.cs +++ b/VkNet/Abstractions/Category/Async/IAdsCategoryAsync.cs @@ -862,5 +862,37 @@ public interface IAdsCategoryAsync /// Страница документации ВКонтакте http://vk.com/dev/ads.updateTargetPixel /// Task UpdateTargetPixelAsync(UpdateTargetPixelParams updateTargetPixelParams); + + /// + /// Возвращает информацию о музыкантах (по имени музыканта), на слушателей которых доступно таргетирование. + /// + /// + /// Возвращает массив всех подходящих под запрос artistName музыкантов. + /// + /// Страница документации ВКонтакте http://vk.com/dev/ads.getMusicians + /// + Task> GetMusiciansAsync(string artistName); + + /// + /// Возвращает информацию о музыкантах (по id музыкантов) на слушателей, для которых доступно таргетирование. + /// + /// + /// Возвращает массив музыкантов с соответствующими идентификаторами из запроса. + /// + /// Страница документации ВКонтакте http://vk.com/dev/ads.getMusiciansByIds + /// + Task> GetMusiciansByIdsAsync(string ids); + + /// + /// Добавляет/редактирует администраторов и/или наблюдателей в рекламный кабинет. + /// + /// + /// + /// Возвращает массив значений - ответов на каждый запрос в массиве response + /// + /// + /// Страница документации ВКонтакте http://vk.com/dev/ads.updateOfficeUsers + /// + Task> UpdateOfficeUsersAsync(AdsDataSpecificationParams officeUsersSpecification); } } \ No newline at end of file diff --git a/VkNet/Abstractions/Category/IAdsCategory.cs b/VkNet/Abstractions/Category/IAdsCategory.cs index 2d7cbc49a..c614f5dd3 100644 --- a/VkNet/Abstractions/Category/IAdsCategory.cs +++ b/VkNet/Abstractions/Category/IAdsCategory.cs @@ -141,5 +141,14 @@ public interface IAdsCategory : IAdsCategoryAsync /// bool UpdateTargetPixel(UpdateTargetPixelParams updateTargetPixelParams); + + /// + ReadOnlyCollection GetMusicians(string artistName); + + /// + ReadOnlyCollection GetMusiciansByIds(string ids); + + /// + ReadOnlyCollection UpdateOfficeUsers(AdsDataSpecificationParams officeUsersSpecification); } } \ No newline at end of file diff --git a/VkNet/Categories/AdsCategory.cs b/VkNet/Categories/AdsCategory.cs index 8104f5d50..463083e3c 100644 --- a/VkNet/Categories/AdsCategory.cs +++ b/VkNet/Categories/AdsCategory.cs @@ -482,5 +482,37 @@ public bool UpdateTargetPixel(UpdateTargetPixelParams updateTargetPixelParams) { "category_id", updateTargetPixelParams.CategoryId }, { "client_id", updateTargetPixelParams.ClientId } }); } + + /// + public ReadOnlyCollection GetMusicians(string artistName) + { + return _vk.Call>("ads.getMusicians", + new VkParameters + { + { "artist_name", artistName } + }); + } + + /// + public ReadOnlyCollection GetMusiciansByIds(string ids) + { + return _vk.Call>("ads.getMusiciansByIds", + new VkParameters + { + { "ids", ids } + }); + } + + /// + public ReadOnlyCollection UpdateOfficeUsers( + AdsDataSpecificationParams officeUsersSpecification) + { + return _vk.Call>("ads.updateOfficeUsers", + new VkParameters + { + { "account_id", officeUsersSpecification.AccountId }, + { "data", officeUsersSpecification.Data } + }); + } } } \ No newline at end of file diff --git a/VkNet/Categories/Async/AdsCategoryAsync.cs b/VkNet/Categories/Async/AdsCategoryAsync.cs index 858b72593..804580888 100644 --- a/VkNet/Categories/Async/AdsCategoryAsync.cs +++ b/VkNet/Categories/Async/AdsCategoryAsync.cs @@ -275,5 +275,24 @@ public Task UpdateTargetPixelAsync(UpdateTargetPixelParams updateTargetPix { return TypeHelper.TryInvokeMethodAsync(() => UpdateTargetPixel(updateTargetPixelParams)); } + + /// + public Task> GetMusiciansAsync(string artistName) + { + return TypeHelper.TryInvokeMethodAsync(() => GetMusicians(artistName)); + } + + /// + public Task> GetMusiciansByIdsAsync(string ids) + { + return TypeHelper.TryInvokeMethodAsync(() => GetMusiciansByIds(ids)); + } + + /// + public Task> UpdateOfficeUsersAsync( + AdsDataSpecificationParams officeUsersSpecification) + { + return TypeHelper.TryInvokeMethodAsync(() => UpdateOfficeUsers(officeUsersSpecification)); + } } } \ No newline at end of file diff --git a/VkNet/Model/Ads/OfficeUsersSpecification.cs b/VkNet/Model/Ads/OfficeUsersSpecification.cs new file mode 100644 index 000000000..ea9732291 --- /dev/null +++ b/VkNet/Model/Ads/OfficeUsersSpecification.cs @@ -0,0 +1,59 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using VkNet.Enums; +using VkNet.Enums.SafetyEnums; +using VkNet.Utils; +using VkNet.Utils.JsonConverter; + +namespace VkNet.Model +{ + /// + /// + /// + [Serializable] + public class OfficeUsersSpecification + { + /// + /// Идентификатор пользователя, добавляемого как администратор/наблюдатель. + /// + [JsonProperty("user_id")] + public long UserId { get; set; } + + /// + /// Тип полномочий. + /// + [JsonProperty("role")] + [JsonConverter(typeof(SafetyEnumJsonConverter))] + public AccessRole Role { get; set; } + + /// + /// Массив идентификаторов клиента. + /// + [JsonProperty("clients_ids")] + public int[] ClientsIds { get; set; } + + /// + /// Доступ ко всем текущим и новым клиентам этого кабинета. + /// + [JsonProperty("grant_access_to_all_clients")] + public bool GrantAccessToAllClients { get; set; } + + /// + /// Показывать ли бюджет пользователю. + /// + [JsonProperty("view_budget")] + public bool? ViewBudget { get; set; } + + public OfficeUsersSpecification FromJson(VkResponse response) + { + return new OfficeUsersSpecification + { + UserId = response["user_id"], + Role = response["role"], + ClientsIds = response["client_ids"].ToListOf(x => x).ToArray(), + GrantAccessToAllClients = response["grant_access_to_all_clients"] + }; + } + } +} \ No newline at end of file diff --git a/VkNet/Model/Results/Ads/GetMusiciansByIdsResult.cs b/VkNet/Model/Results/Ads/GetMusiciansByIdsResult.cs new file mode 100644 index 000000000..732e9f8ca --- /dev/null +++ b/VkNet/Model/Results/Ads/GetMusiciansByIdsResult.cs @@ -0,0 +1,46 @@ +using System; +using Newtonsoft.Json; +using VkNet.Utils; + +namespace VkNet.Model +{ + /// + /// + /// + [Serializable] + public class GetMusiciansByIdsResult + { + /// + /// Идентификатор музыканта. + /// + [JsonProperty("id")] + public long Id { get; set; } + + /// + /// Полный псевдоним музыканта. + /// + [JsonProperty("name")] + public string Name { get; set; } + + /// + /// Аватарка музыканта. + /// + [JsonProperty("avatar")] + public string Avatar { get; set; } + + /// + /// Разобрать из json. + /// + /// Ответ сервера. + /// + public static GetMusiciansByIdsResult FromJson(VkResponse response) + { + return new GetMusiciansByIdsResult + { + Id = response["id"], + Name = response["name"], + Avatar = response["avatar"] + }; + } + } +} \ No newline at end of file diff --git a/VkNet/Model/Results/Ads/GetMusiciansResult.cs b/VkNet/Model/Results/Ads/GetMusiciansResult.cs new file mode 100644 index 000000000..c1dde37ae --- /dev/null +++ b/VkNet/Model/Results/Ads/GetMusiciansResult.cs @@ -0,0 +1,46 @@ +using System; +using Newtonsoft.Json; +using VkNet.Utils; + +namespace VkNet.Model +{ + /// + /// + /// + [Serializable] + public class GetMusiciansResult + { + /// + /// Идентификатор музыканта. + /// + [JsonProperty("id")] + public long Id { get; set; } + + /// + /// Полный псевдоним музыканта. + /// + [JsonProperty("name")] + public string Name { get; set; } + + /// + /// Аватарка музыканта. + /// + [JsonProperty("avatar")] + public string Avatar { get; set; } + + /// + /// Разобрать из json. + /// + /// Ответ сервера. + /// + public static GetMusiciansResult FromJson(VkResponse response) + { + return new GetMusiciansResult + { + Id = response["id"], + Name = response["name"], + Avatar = response["avatar"] + }; + } + } +} \ No newline at end of file diff --git a/VkNet/Model/Results/Ads/UpdateOfficeUsersResult.cs b/VkNet/Model/Results/Ads/UpdateOfficeUsersResult.cs new file mode 100644 index 000000000..bdb2c540a --- /dev/null +++ b/VkNet/Model/Results/Ads/UpdateOfficeUsersResult.cs @@ -0,0 +1,33 @@ +using System; +using JetBrains.Annotations; +using Newtonsoft.Json; +using VkNet.Utils; + +namespace VkNet.Model +{ + /// + /// + /// + [Serializable] + public class UpdateOfficeUsersResult + { + /// + /// Идентификатор пользователя, добавляемого как администратор/наблюдатель. + /// + [JsonProperty("user_id")] + public long UserId { get; set; } + + /// + /// Был ли пользователь успешно изменен. + /// + [JsonProperty("is_success")] + public bool IsSuccess { get; set; } + + /// + /// Если IsSuccess=false также возвращается объект error с описанием ошибки. + /// + [JsonProperty("error")] + [CanBeNull] + public VkError Error { get; set; } + } +} \ No newline at end of file