diff --git a/VkNet.Tests/Categories/Calls/CallsCategoryTest.cs b/VkNet.Tests/Categories/Calls/CallsCategoryTest.cs new file mode 100644 index 000000000..93a6dc967 --- /dev/null +++ b/VkNet.Tests/Categories/Calls/CallsCategoryTest.cs @@ -0,0 +1,45 @@ +using FluentAssertions; +using VkNet.Tests.Infrastructure; +using Xunit; + +namespace VkNet.Tests.Categories.Calls; + +public class CallsCategoryTest : CategoryBaseTest +{ + protected override string Folder => "Calls"; + + [Fact] + public void ForceFinish() + { + Url = "https://api.vk.com/method/calls.forceFinish"; + + ReadCategoryJsonPath(nameof(ForceFinish)); + + var result = Api.Calls.ForceFinish(new() + { + CallId = "10c5386e-10cb-43c6-999a-d01a37ee71e0" + }); + + result.Should() + .BeTrue(); + } + + [Fact] + public void Start() + { + Url = "https://api.vk.com/method/calls.start"; + + ReadCategoryJsonPath(nameof(Start)); + + var result = Api.Calls.Start(new()); + + result.JoinLink.Should() + .Be("https://vk.com/call/join/7BIRLBXzMD74J_JGR3G5wNZbZCkAT_ZtNFzJbHhIkMk"); + + result.OkJoinLink.Should() + .Be("7BIRLBXzMD74J_JGR3G5wNZbZCkAT_ZtNFzJbHhIkMk"); + + result.CallId.Should() + .Be("10c5386e-10cb-43c6-999a-d01a37ee71e0"); + } +} \ No newline at end of file diff --git a/VkNet.Tests/TestData/Categories/Calls/ForceFinish.json b/VkNet.Tests/TestData/Categories/Calls/ForceFinish.json new file mode 100644 index 000000000..a318c4360 --- /dev/null +++ b/VkNet.Tests/TestData/Categories/Calls/ForceFinish.json @@ -0,0 +1,3 @@ +{ + "response": 1 +} \ No newline at end of file diff --git a/VkNet.Tests/TestData/Categories/Calls/Start.json b/VkNet.Tests/TestData/Categories/Calls/Start.json new file mode 100644 index 000000000..c5acd6187 --- /dev/null +++ b/VkNet.Tests/TestData/Categories/Calls/Start.json @@ -0,0 +1,7 @@ +{ + "response": { + "join_link": "https://vk.com/call/join/7BIRLBXzMD74J_JGR3G5wNZbZCkAT_ZtNFzJbHhIkMk", + "ok_join_link": "7BIRLBXzMD74J_JGR3G5wNZbZCkAT_ZtNFzJbHhIkMk", + "call_id": "10c5386e-10cb-43c6-999a-d01a37ee71e0" + } +} \ No newline at end of file diff --git a/VkNet/Abstractions/Category/Async/ICallCategoryAsync.cs b/VkNet/Abstractions/Category/Async/ICallCategoryAsync.cs new file mode 100644 index 000000000..2ca35bad0 --- /dev/null +++ b/VkNet/Abstractions/Category/Async/ICallCategoryAsync.cs @@ -0,0 +1,35 @@ +using System.Threading; +using System.Threading.Tasks; +using VkNet.Model; + +namespace VkNet.Abstractions; + +/// +/// Методы для работы со звонками +/// +public interface ICallsCategoryAsync +{ + /// + /// Принудительно завершить звонок + /// + /// Параметры запроса + /// Токен отмены операции + /// После успешного выполнения возвращает true . + /// + /// Страница документации ВКонтакте https://dev.vk.com/ru/method/calls.forceFinish + /// + Task ForceFinishAsync(CallsForceFinishParams @params, + CancellationToken token = default); + + /// + /// Создать новый звонок от имени пользователя или сообщества + /// + /// Параметры запроса + /// Токен отмены операции + /// После успешного выполнения возвращает объект CallStartResult + /// + /// Страница документации ВКонтакте https://dev.vk.com/ru/method/calls.start + /// + Task StartAsync(CallsStartParams @params, + CancellationToken token = default); +} \ No newline at end of file diff --git a/VkNet/Abstractions/Category/ICallsCategory.cs b/VkNet/Abstractions/Category/ICallsCategory.cs new file mode 100644 index 000000000..ea4b48513 --- /dev/null +++ b/VkNet/Abstractions/Category/ICallsCategory.cs @@ -0,0 +1,15 @@ +using VkNet.Model; + +namespace VkNet.Abstractions; + +/// +/// Методы для работы со звонками +/// +public interface ICallsCategory : ICallsCategoryAsync +{ + /// + bool ForceFinish(CallsForceFinishParams @params); + + /// + CallStartResult Start(CallsStartParams @params); +} \ No newline at end of file diff --git a/VkNet/Abstractions/Core/IVkApiCategories.cs b/VkNet/Abstractions/Core/IVkApiCategories.cs index 4c60992ca..ecbae7761 100644 --- a/VkNet/Abstractions/Core/IVkApiCategories.cs +++ b/VkNet/Abstractions/Core/IVkApiCategories.cs @@ -233,4 +233,9 @@ public interface IVkApiCategories /// ShortVideo /// IShortVideoCategory ShortVideo { get; } + + /// + /// Calls + /// + ICallsCategory Calls { get; } } \ No newline at end of file diff --git a/VkNet/Categories/Async/CallsCategoryAsync.cs b/VkNet/Categories/Async/CallsCategoryAsync.cs new file mode 100644 index 000000000..9f43decc2 --- /dev/null +++ b/VkNet/Categories/Async/CallsCategoryAsync.cs @@ -0,0 +1,21 @@ +using System.Threading; +using System.Threading.Tasks; +using VkNet.Abstractions; +using VkNet.Model; +using VkNet.Utils; + +namespace VkNet.Categories; + +/// +public partial class CallsCategory +{ + /// + public Task ForceFinishAsync(CallsForceFinishParams @params, CancellationToken token = default) => + TypeHelper.TryInvokeMethodAsync(() => + ForceFinish(@params), token); + + /// + public Task StartAsync(CallsStartParams @params, CancellationToken token = default) => + TypeHelper.TryInvokeMethodAsync(() => + Start(@params), token); +} \ No newline at end of file diff --git a/VkNet/Categories/CallsCategory.cs b/VkNet/Categories/CallsCategory.cs new file mode 100644 index 000000000..47710a3da --- /dev/null +++ b/VkNet/Categories/CallsCategory.cs @@ -0,0 +1,41 @@ +using VkNet.Abstractions; +using VkNet.Exception; +using VkNet.Model; + +namespace VkNet.Categories; + +/// +public partial class CallsCategory : ICallsCategory +{ + private readonly IVkApiInvoke _vk; + + /// + /// Инициализирует новый экземпляр класса + /// + public CallsCategory(IVkApiInvoke vk) => _vk = vk; + + /// + public bool ForceFinish(CallsForceFinishParams @params) + { + if (@params.CallId.Length is not 36) + { + throw new VkApiException(message: "Параметр call_id обязательный. Макс. длина = 36 Мин. длина = 36"); + } + + return _vk.Call("calls.forceFinish", new() + { + { + "call_id", @params.CallId + } + }); + } + + /// + public CallStartResult Start(CallsStartParams @params) => + _vk.Call("calls.start", new() + { + { + "group_id", @params.GroupId + } + }); +} \ No newline at end of file diff --git a/VkNet/Model/CallStartResult.cs b/VkNet/Model/CallStartResult.cs new file mode 100644 index 000000000..06a749460 --- /dev/null +++ b/VkNet/Model/CallStartResult.cs @@ -0,0 +1,29 @@ +using System; +using Newtonsoft.Json; + +namespace VkNet.Model; + +/// +/// Результат создания нового звонка +/// +[Serializable] +public class CallStartResult +{ + /// + /// Ссылка на звонок + /// + [JsonProperty("join_link")] + public string JoinLink { get; set; } + + /// + /// Ссылка на звонок (Ok) + /// + [JsonProperty("ok_join_link")] + public string OkJoinLink { get; set; } + + /// + /// Идентификатор созданного звонка + /// + [JsonProperty("call_id")] + public string CallId { get; set; } +} \ No newline at end of file diff --git a/VkNet/Model/RequestParams/Calls/CallsForceFinishParams.cs b/VkNet/Model/RequestParams/Calls/CallsForceFinishParams.cs new file mode 100644 index 000000000..a61e7b1a8 --- /dev/null +++ b/VkNet/Model/RequestParams/Calls/CallsForceFinishParams.cs @@ -0,0 +1,16 @@ +using System; + +namespace VkNet.Model; + +/// +/// Список параметров для метода calls.forceFinish +/// +[Serializable] +public class CallsForceFinishParams +{ + /// + /// Идентификатор звонка + /// + /// Обязательный параметр Макс. длина = 36 Мин. длина = 36 + public string CallId { get; set; } +} \ No newline at end of file diff --git a/VkNet/Model/RequestParams/Calls/CallsStartParams.cs b/VkNet/Model/RequestParams/Calls/CallsStartParams.cs new file mode 100644 index 000000000..4138dc3d5 --- /dev/null +++ b/VkNet/Model/RequestParams/Calls/CallsStartParams.cs @@ -0,0 +1,14 @@ +using System; + +namespace VkNet.Model; +/// +/// Список параметров для метода calls.start +/// +[Serializable] +public class CallsStartParams +{ + /// + /// Идентификатор сообщества + /// + public int? GroupId { get; set; } +} \ No newline at end of file diff --git a/VkNet/VkApi.cs b/VkNet/VkApi.cs index c1783dcee..5c441b5aa 100644 --- a/VkNet/VkApi.cs +++ b/VkNet/VkApi.cs @@ -791,6 +791,9 @@ public int MaxCaptchaRecognitionCount /// public IShortVideoCategory ShortVideo { get; set; } + /// + public ICallsCategory Calls { get; set; } + #endregion #region private @@ -1084,6 +1087,7 @@ private void Initialization(IServiceProvider serviceProvider) DownloadedGames = new DownloadedGamesCategory(this); Asr = new AsrCategory(this); ShortVideo = new ShortVideoCategory(this); + Calls = new CallsCategory(this); RequestsPerSecond = 3;