diff --git a/Vonage.Test/Conversations/GetConversations/SerializationTest.cs b/Vonage.Test/Conversations/GetConversations/SerializationTest.cs index cea841670..79cde9781 100644 --- a/Vonage.Test/Conversations/GetConversations/SerializationTest.cs +++ b/Vonage.Test/Conversations/GetConversations/SerializationTest.cs @@ -43,7 +43,7 @@ internal static void VerifyExpectedResponse(GetConversationsResponse response) Maybe.None, new Links(new HalLink(new Uri( "https://api.nexmo.com/v1/conversations/CON-d66d47de-5bcb-4300-94f0-0c9d4b948e9a"))), - Maybe.None), + Maybe.None), }); response.Links.First.Href.Should() .Be(new Uri("https://api.nexmo.com/v1/conversations?order=desc&page_size=10")); diff --git a/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeAudioMessage-response.json b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeAudioMessage-response.json new file mode 100644 index 000000000..3bd31dee9 --- /dev/null +++ b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeAudioMessage-response.json @@ -0,0 +1,29 @@ +{ + "id": 100, + "type": "message", + "from": "string", + "body": { + "message_type": "audio", + "audio": { + "url": "https://example.com/audio.mp3" + } + }, + "timestamp": "2020-01-01T14:00:00.00Z", + "_embedded": { + "from_user": { + "id": "USR-82e028d9-5201-4f1e-8188-604b2d3471ec", + "name": "my_user_name", + "display_name": "My User Name", + "image_url": "https://example.com/image.png", + "custom_data": {} + }, + "from_member": { + "id": "string" + } + }, + "_links": { + "self": { + "href": "https://api.nexmo.com/v0.1/conversations/CON-1234/events/100" + } + } +} \ No newline at end of file diff --git a/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeCustomMessage-response.json b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeCustomMessage-response.json new file mode 100644 index 000000000..b23eab7a8 --- /dev/null +++ b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeCustomMessage-response.json @@ -0,0 +1,27 @@ +{ + "id": 100, + "type": "message", + "from": "string", + "body": { + "message_type": "custom", + "custom": {} + }, + "timestamp": "2020-01-01T14:00:00.00Z", + "_embedded": { + "from_user": { + "id": "USR-82e028d9-5201-4f1e-8188-604b2d3471ec", + "name": "my_user_name", + "display_name": "My User Name", + "image_url": "https://example.com/image.png", + "custom_data": {} + }, + "from_member": { + "id": "string" + } + }, + "_links": { + "self": { + "href": "https://api.nexmo.com/v0.1/conversations/CON-1234/events/100" + } + } +} \ No newline at end of file diff --git a/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeFileMessage-response.json b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeFileMessage-response.json new file mode 100644 index 000000000..67f55ac47 --- /dev/null +++ b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeFileMessage-response.json @@ -0,0 +1,29 @@ +{ + "id": 100, + "type": "message", + "from": "string", + "body": { + "message_type": "file", + "file": { + "url": "https://example.com/file.txt" + } + }, + "timestamp": "2020-01-01T14:00:00.00Z", + "_embedded": { + "from_user": { + "id": "USR-82e028d9-5201-4f1e-8188-604b2d3471ec", + "name": "my_user_name", + "display_name": "My User Name", + "image_url": "https://example.com/image.png", + "custom_data": {} + }, + "from_member": { + "id": "string" + } + }, + "_links": { + "self": { + "href": "https://api.nexmo.com/v0.1/conversations/CON-1234/events/100" + } + } +} \ No newline at end of file diff --git a/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeImageMessage-response.json b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeImageMessage-response.json new file mode 100644 index 000000000..4221eb884 --- /dev/null +++ b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeImageMessage-response.json @@ -0,0 +1,29 @@ +{ + "id": 100, + "type": "message", + "from": "string", + "body": { + "message_type": "image", + "image": { + "url": "https://example.com/image.png" + } + }, + "timestamp": "2020-01-01T14:00:00.00Z", + "_embedded": { + "from_user": { + "id": "USR-82e028d9-5201-4f1e-8188-604b2d3471ec", + "name": "my_user_name", + "display_name": "My User Name", + "image_url": "https://example.com/image.png", + "custom_data": {} + }, + "from_member": { + "id": "string" + } + }, + "_links": { + "self": { + "href": "https://api.nexmo.com/v0.1/conversations/CON-1234/events/100" + } + } +} \ No newline at end of file diff --git a/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeLocationMessage-response.json b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeLocationMessage-response.json new file mode 100644 index 000000000..fc1e7856c --- /dev/null +++ b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeLocationMessage-response.json @@ -0,0 +1,32 @@ +{ + "id": 100, + "type": "message", + "from": "string", + "body": { + "message_type": "location", + "location": { + "longitude": "Longitude", + "latitude": "Latitude", + "name": "Name", + "address": "Address" + } + }, + "timestamp": "2020-01-01T14:00:00.00Z", + "_embedded": { + "from_user": { + "id": "USR-82e028d9-5201-4f1e-8188-604b2d3471ec", + "name": "my_user_name", + "display_name": "My User Name", + "image_url": "https://example.com/image.png", + "custom_data": {} + }, + "from_member": { + "id": "string" + } + }, + "_links": { + "self": { + "href": "https://api.nexmo.com/v0.1/conversations/CON-1234/events/100" + } + } +} \ No newline at end of file diff --git a/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeTemplateMessage-response.json b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeTemplateMessage-response.json new file mode 100644 index 000000000..6b6446d07 --- /dev/null +++ b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeTemplateMessage-response.json @@ -0,0 +1,34 @@ +{ + "id": 100, + "type": "message", + "from": "string", + "body": { + "message_type": "template", + "template": { + "name": "Template", + "parameters": [], + "whatsapp": { + "policy": "deterministic", + "locale": "en-US" + } + } + }, + "timestamp": "2020-01-01T14:00:00.00Z", + "_embedded": { + "from_user": { + "id": "USR-82e028d9-5201-4f1e-8188-604b2d3471ec", + "name": "my_user_name", + "display_name": "My User Name", + "image_url": "https://example.com/image.png", + "custom_data": {} + }, + "from_member": { + "id": "string" + } + }, + "_links": { + "self": { + "href": "https://api.nexmo.com/v0.1/conversations/CON-1234/events/100" + } + } +} \ No newline at end of file diff --git a/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeTextMessage-response.json b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeTextMessage-response.json new file mode 100644 index 000000000..dbc3cc430 --- /dev/null +++ b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeTextMessage-response.json @@ -0,0 +1,27 @@ +{ + "id": 100, + "type": "message", + "from": "string", + "body": { + "message_type": "text", + "text": "string" + }, + "timestamp": "2020-01-01T14:00:00.00Z", + "_embedded": { + "from_user": { + "id": "USR-82e028d9-5201-4f1e-8188-604b2d3471ec", + "name": "my_user_name", + "display_name": "My User Name", + "image_url": "https://example.com/image.png", + "custom_data": {} + }, + "from_member": { + "id": "string" + } + }, + "_links": { + "self": { + "href": "https://api.nexmo.com/v0.1/conversations/CON-1234/events/100" + } + } +} \ No newline at end of file diff --git a/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeVcardMessage-response.json b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeVcardMessage-response.json new file mode 100644 index 000000000..705a4f432 --- /dev/null +++ b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeVcardMessage-response.json @@ -0,0 +1,32 @@ +{ + "id": 100, + "type": "message", + "from": "string", + "body": { + "message_type": "vcard", + "vcard": { + "url": "https://example.com/file.txt" + }, + "image": { + "url": "https://example.com/image.png" + } + }, + "timestamp": "2020-01-01T14:00:00.00Z", + "_embedded": { + "from_user": { + "id": "USR-82e028d9-5201-4f1e-8188-604b2d3471ec", + "name": "my_user_name", + "display_name": "My User Name", + "image_url": "https://example.com/image.png", + "custom_data": {} + }, + "from_member": { + "id": "string" + } + }, + "_links": { + "self": { + "href": "https://api.nexmo.com/v0.1/conversations/CON-1234/events/100" + } + } +} \ No newline at end of file diff --git a/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeVideoMessage-response.json b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeVideoMessage-response.json new file mode 100644 index 000000000..7a48762f2 --- /dev/null +++ b/Vonage.Test/Conversations/GetEvent/Data/ShouldDeserializeVideoMessage-response.json @@ -0,0 +1,29 @@ +{ + "id": 100, + "type": "message", + "from": "string", + "body": { + "message_type": "video", + "video": { + "url": "https://example.com/video.mkv" + } + }, + "timestamp": "2020-01-01T14:00:00.00Z", + "_embedded": { + "from_user": { + "id": "USR-82e028d9-5201-4f1e-8188-604b2d3471ec", + "name": "my_user_name", + "display_name": "My User Name", + "image_url": "https://example.com/image.png", + "custom_data": {} + }, + "from_member": { + "id": "string" + } + }, + "_links": { + "self": { + "href": "https://api.nexmo.com/v0.1/conversations/CON-1234/events/100" + } + } +} \ No newline at end of file diff --git a/Vonage.Test/Conversations/GetEvent/RequestTest.cs b/Vonage.Test/Conversations/GetEvent/RequestTest.cs new file mode 100644 index 000000000..f4894b1e7 --- /dev/null +++ b/Vonage.Test/Conversations/GetEvent/RequestTest.cs @@ -0,0 +1,48 @@ +using Vonage.Conversations.GetEvent; +using Vonage.Test.Common.Extensions; +using Xunit; + +namespace Vonage.Test.Conversations.GetEvent; + +[Trait("Category", "Request")] +public class RequestTest +{ + [Fact] + public void GetEndpointPath_ShouldReturnApiEndpoint() => + GetEventRequest.Parse("CON-123", "EVE-123") + .Map(request => request.GetEndpointPath()) + .Should() + .BeSuccess("/v1/conversations/CON-123/events/EVE-123"); + + [Theory] + [InlineData("")] + [InlineData(" ")] + [InlineData(null)] + public void Parse_ShouldReturnFailure_GivenConversationIdIsEmpty(string invalidId) => + GetEventRequest.Parse(invalidId, "MEM-123") + .Should() + .BeParsingFailure("ConversationId cannot be null or whitespace."); + + [Theory] + [InlineData("")] + [InlineData(" ")] + [InlineData(null)] + public void Parse_ShouldReturnFailure_GivenEventIdIsEmpty(string invalidId) => + GetEventRequest.Parse("CON-123", invalidId) + .Should() + .BeParsingFailure("EventId cannot be null or whitespace."); + + [Fact] + public void Parse_ShouldSetConversationId() => + GetEventRequest.Parse("CON-123", "EVE-123") + .Map(request => request.ConversationId) + .Should() + .BeSuccess("CON-123"); + + [Fact] + public void Parse_ShouldSetMemberId() => + GetEventRequest.Parse("CON-123", "EVE-123") + .Map(request => request.EventId) + .Should() + .BeSuccess("EVE-123"); +} \ No newline at end of file diff --git a/Vonage.Test/Conversations/GetEvent/SerializationTest.cs b/Vonage.Test/Conversations/GetEvent/SerializationTest.cs new file mode 100644 index 000000000..839ec7962 --- /dev/null +++ b/Vonage.Test/Conversations/GetEvent/SerializationTest.cs @@ -0,0 +1,84 @@ +using System; +using Vonage.Common; +using Vonage.Conversations; +using Vonage.Serialization; +using Vonage.Test.Common; +using Vonage.Test.Common.Extensions; +using Xunit; + +namespace Vonage.Test.Conversations.GetEvent; + +[Trait("Category", "Serialization")] +public class SerializationTest +{ + private readonly SerializationTestHelper helper = new SerializationTestHelper( + typeof(SerializationTest).Namespace, + JsonSerializerBuilder.BuildWithSnakeCase()); + + [Fact] + public void ShouldDeserializeTextMessage() => this.helper.Serializer + .DeserializeObject(this.helper.GetResponseJson()) + .Should() + .BeSuccess(BuildExpectedEvent(new EventBodyTextMessage("string"))); + + private static Event BuildExpectedEvent(EventBodyBase body) => new Event(100, "message", "string", body, + DateTimeOffset.Parse("2020-01-01T14:00:00.00Z"), + new EmbeddedEventData( + new EmbeddedEventUser("USR-82e028d9-5201-4f1e-8188-604b2d3471ec", "my_user_name", "My User Name", + "https://example.com/image.png", new { }), new EmbeddedEventMember("string")), + new Links(new HalLink(new Uri("https://api.nexmo.com/v0.1/conversations/CON-1234/events/100")))); + + [Fact] + public void ShouldDeserializeImageMessage() => this.helper.Serializer + .DeserializeObject(this.helper.GetResponseJson()) + .Should() + .BeSuccess( + BuildExpectedEvent(new EventBodyImageMessage(new EventBodyImageUrl("https://example.com/image.png")))); + + [Fact] + public void ShouldDeserializeAudioMessage() => this.helper.Serializer + .DeserializeObject(this.helper.GetResponseJson()) + .Should() + .BeSuccess( + BuildExpectedEvent(new EventBodyAudioMessage(new EventBodyAudioUrl("https://example.com/audio.mp3")))); + + [Fact] + public void ShouldDeserializeVideoMessage() => this.helper.Serializer + .DeserializeObject(this.helper.GetResponseJson()) + .Should() + .BeSuccess( + BuildExpectedEvent(new EventBodyVideoMessage(new EventBodyVideoUrl("https://example.com/video.mkv")))); + + [Fact] + public void ShouldDeserializeFileMessage() => this.helper.Serializer + .DeserializeObject(this.helper.GetResponseJson()) + .Should() + .BeSuccess(BuildExpectedEvent(new EventBodyFileMessage(new EventBodyFileUrl("https://example.com/file.txt")))); + + [Fact] + public void ShouldDeserializeTemplateMessage() => this.helper.Serializer + .DeserializeObject(this.helper.GetResponseJson()) + .Should() + .BeSuccess(BuildExpectedEvent(new EventBodyTemplateMessage("Template", Array.Empty(), + new EventBodyTemplateWhatsApp("Deterministic", "en-US")))); + + [Fact] + public void ShouldDeserializeCustomMessage() => this.helper.Serializer + .DeserializeObject(this.helper.GetResponseJson()) + .Should() + .BeSuccess(BuildExpectedEvent(new EventBodyCustomMessage(new { }))); + + [Fact] + public void ShouldDeserializeVcardMessage() => this.helper.Serializer + .DeserializeObject(this.helper.GetResponseJson()) + .Should() + .BeSuccess(BuildExpectedEvent(new EventBodyVcardMessage(new EventBodyVcardUrl("https://example.com/file.txt"), + new EventBodyImageUrl("https://example.com/image.png")))); + + [Fact] + public void ShouldDeserializeLocationMessage() => this.helper.Serializer + .DeserializeObject(this.helper.GetResponseJson()) + .Should() + .BeSuccess(BuildExpectedEvent( + new EventBodyLocationMessage(new EventBodyLocation("Longitude", "Latitude", "Name", "Address")))); +} \ No newline at end of file diff --git a/Vonage.Test/Conversations/GetUserConversations/SerializationTest.cs b/Vonage.Test/Conversations/GetUserConversations/SerializationTest.cs index 4900fe939..5e8f2af8b 100644 --- a/Vonage.Test/Conversations/GetUserConversations/SerializationTest.cs +++ b/Vonage.Test/Conversations/GetUserConversations/SerializationTest.cs @@ -30,7 +30,7 @@ internal static void VerifyExpectedResponse(GetUserConversationsResponse respons var conversation = response.Embedded.Conversations.First(); ConversationTests.VerifyExpectedResponse(conversation); conversation.Embedded.Should() - .Be(new EmbeddedData("MEM-63f61863-4a51-4f6b-86e1-46edebio0391", MemberState.Left)); + .Be(new EmbeddedConversationData("MEM-63f61863-4a51-4f6b-86e1-46edebio0391", MemberState.Left)); response.Links.First.Href.Should() .Be(new Uri( "https://api.nexmo.com/v1/users/USR-82e028d9-5201-4f1e-8188-604b2d3471ec/conversations?order=desc&page_size=10")); diff --git a/Vonage.Test/Vonage.Test.csproj b/Vonage.Test/Vonage.Test.csproj index da7632618..b3b949430 100644 --- a/Vonage.Test/Vonage.Test.csproj +++ b/Vonage.Test/Vonage.Test.csproj @@ -1197,6 +1197,33 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + diff --git a/Vonage/Conversations/Conversation.cs b/Vonage/Conversations/Conversation.cs index a138634a8..89f24cae6 100644 --- a/Vonage/Conversations/Conversation.cs +++ b/Vonage/Conversations/Conversation.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.ComponentModel; using System.Text.Json.Serialization; -using Vonage.Common; using Vonage.Common.Monads; using Vonage.Common.Serialization; @@ -34,8 +33,8 @@ public record Conversation( Maybe Properties, [property: JsonPropertyName("_links")] Links Links, [property: JsonPropertyName("_embedded")] - [property: JsonConverter(typeof(MaybeJsonConverter))] - Maybe Embedded); + [property: JsonConverter(typeof(MaybeJsonConverter))] + Maybe Embedded); /// /// Represents the conversation history @@ -50,12 +49,6 @@ public record Timestamp( [property: JsonConverter(typeof(MaybeJsonConverter))] Maybe Destroyed); -/// -/// Represents additional links. -/// -/// The link to the conversation -public record Links(HalLink Self); - /// /// Represents the Conversation Properties. /// @@ -82,7 +75,7 @@ public record Properties( /// /// The Member Id. /// The state that the member is in. -public record EmbeddedData( +public record EmbeddedConversationData( [property: JsonPropertyName("id")] [property: JsonPropertyOrder(0)] string MemberId, diff --git a/Vonage/Conversations/ConversationsClient.cs b/Vonage/Conversations/ConversationsClient.cs index 52439ce32..f286472b2 100644 --- a/Vonage/Conversations/ConversationsClient.cs +++ b/Vonage/Conversations/ConversationsClient.cs @@ -7,6 +7,7 @@ using Vonage.Conversations.DeleteEvent; using Vonage.Conversations.GetConversation; using Vonage.Conversations.GetConversations; +using Vonage.Conversations.GetEvent; using Vonage.Conversations.GetMember; using Vonage.Conversations.GetMembers; using Vonage.Conversations.GetUserConversations; @@ -19,56 +20,60 @@ namespace Vonage.Conversations; internal class ConversationsClient : IConversationsClient { private readonly VonageHttpClient vonageClient; - + /// /// Creates a new client. /// /// The client configuration. internal ConversationsClient(VonageHttpClientConfiguration configuration) => this.vonageClient = new VonageHttpClient(configuration, JsonSerializerBuilder.BuildWithSnakeCase()); - + /// public Task> CreateConversationAsync(Result request) => this.vonageClient.SendWithResponseAsync(request); - + /// public Task> DeleteConversationAsync(Result request) => this.vonageClient.SendAsync(request); - + /// public Task> DeleteEventAsync(Result request) => this.vonageClient.SendAsync(request); - + /// public Task> GetConversationAsync(Result request) => this.vonageClient.SendWithResponseAsync(request); - + + /// + public Task> GetEventAsync(Result request) => + this.vonageClient.SendWithResponseAsync(request); + /// public Task> CreateMemberAsync(Result request) => this.vonageClient.SendWithResponseAsync(request); - + /// public Task> UpdateMemberAsync(Result request) => this.vonageClient.SendWithResponseAsync(request); - + /// public Task> GetMemberAsync(Result request) => this.vonageClient.SendWithResponseAsync(request); - + /// public Task> GetConversationsAsync(Result request) => this.vonageClient.SendWithResponseAsync(request); - + /// public Task> GetMembersAsync(Result request) => this.vonageClient.SendWithResponseAsync(request); - + /// public Task> GetUserConversationsAsync( Result request) => this.vonageClient.SendWithResponseAsync(request); - + /// public Task> UpdateConversationAsync(Result request) => this.vonageClient.SendWithResponseAsync(request); diff --git a/Vonage/Conversations/Event.cs b/Vonage/Conversations/Event.cs new file mode 100644 index 000000000..897826c98 --- /dev/null +++ b/Vonage/Conversations/Event.cs @@ -0,0 +1,66 @@ +using System; +using System.Text.Json.Serialization; + +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + +namespace Vonage.Conversations; + +public record Event( + int Id, + string Type, + string From, + EventBodyBase Body, + DateTimeOffset Timestamp, + [property: JsonPropertyName("_embedded")] + EmbeddedEventData Embedded, + [property: JsonPropertyName("_links")] Links Links); + +public record EmbeddedEventData( + [property: JsonPropertyName("from_user")] + EmbeddedEventUser User, + [property: JsonPropertyName("from_member")] + EmbeddedEventMember Member); + +public record EmbeddedEventUser( + string Id, + string Name, + [property: JsonPropertyName("display_name")] + string DisplayName, + [property: JsonPropertyName("image_url")] + string ImageUrl, + object CustomData); + +public record EmbeddedEventMember(string Id); + +[JsonPolymorphic(TypeDiscriminatorPropertyName = "message_type")] +[JsonDerivedType(typeof(EventBodyBase))] +[JsonDerivedType(typeof(EventBodyTextMessage), "text")] +[JsonDerivedType(typeof(EventBodyImageMessage), "image")] +[JsonDerivedType(typeof(EventBodyAudioMessage), "audio")] +[JsonDerivedType(typeof(EventBodyVideoMessage), "video")] +[JsonDerivedType(typeof(EventBodyFileMessage), "file")] +[JsonDerivedType(typeof(EventBodyTemplateMessage), "template")] +[JsonDerivedType(typeof(EventBodyCustomMessage), "custom")] +[JsonDerivedType(typeof(EventBodyVcardMessage), "vcard")] +[JsonDerivedType(typeof(EventBodyLocationMessage), "location")] +public record EventBodyBase; + +public record EventBodyTextMessage(string Text) : EventBodyBase; +public record EventBodyImageMessage(EventBodyImageUrl Image) : EventBodyBase; +public record EventBodyImageUrl(string Url); +public record EventBodyAudioMessage(EventBodyAudioUrl Audio) : EventBodyBase; +public record EventBodyAudioUrl(string Url); +public record EventBodyVideoMessage(EventBodyVideoUrl Video) : EventBodyBase; +public record EventBodyVideoUrl(string Url); +public record EventBodyFileMessage(EventBodyFileUrl File) : EventBodyBase; +public record EventBodyFileUrl(string Url); + +public record EventBodyTemplateMessage(string Name, object[] Parameters, EventBodyTemplateWhatsApp WhatsApp) + : EventBodyBase; + +public record EventBodyTemplateWhatsApp(string Policy, string Locale); +public record EventBodyCustomMessage(object Custom) : EventBodyBase; +public record EventBodyVcardMessage(EventBodyVcardUrl Vcard, EventBodyImageUrl Image) : EventBodyBase; +public record EventBodyVcardUrl(string Url); +public record EventBodyLocationMessage(EventBodyLocation File) : EventBodyBase; +public record EventBodyLocation(string Longitude, string Latitude, string Name, string Address); \ No newline at end of file diff --git a/Vonage/Conversations/GetEvent/GetEventRequest.cs b/Vonage/Conversations/GetEvent/GetEventRequest.cs new file mode 100644 index 000000000..6393d62a5 --- /dev/null +++ b/Vonage/Conversations/GetEvent/GetEventRequest.cs @@ -0,0 +1,46 @@ +using System.Net.Http; +using Vonage.Common.Client; +using Vonage.Common.Monads; +using Vonage.Common.Validation; + +namespace Vonage.Conversations.GetEvent; + +/// +public readonly struct GetEventRequest : IVonageRequest +{ + /// + /// The conversation Id. + /// + public string ConversationId { get; private init; } + + /// + /// The event Id. + /// + public string EventId { get; private init; } + + /// + public HttpRequestMessage BuildRequestMessage() => VonageRequestBuilder + .Initialize(HttpMethod.Get, this.GetEndpointPath()) + .Build(); + + /// + public string GetEndpointPath() => $"/v1/conversations/{this.ConversationId}/events/{this.EventId}"; + + /// + /// Parses the input into a GetEventRequest. + /// + /// The conversation Id. + /// The event Id. + /// A success state with the request if the parsing succeeded. A failure state with an error if it failed. + public static Result Parse(string conversationId, string eventId) => + Result + .FromSuccess(new GetEventRequest {ConversationId = conversationId, EventId = eventId}) + .Map(InputEvaluation.Evaluate) + .Bind(evaluation => evaluation.WithRules(VerifyConversationId, VerifyEventId)); + + private static Result VerifyConversationId(GetEventRequest request) => + InputValidation.VerifyNotEmpty(request, request.ConversationId, nameof(ConversationId)); + + private static Result VerifyEventId(GetEventRequest request) => + InputValidation.VerifyNotEmpty(request, request.EventId, nameof(EventId)); +} \ No newline at end of file diff --git a/Vonage/Conversations/IConversationsClient.cs b/Vonage/Conversations/IConversationsClient.cs index 0c621b441..61b5fbc2f 100644 --- a/Vonage/Conversations/IConversationsClient.cs +++ b/Vonage/Conversations/IConversationsClient.cs @@ -6,6 +6,7 @@ using Vonage.Conversations.DeleteEvent; using Vonage.Conversations.GetConversation; using Vonage.Conversations.GetConversations; +using Vonage.Conversations.GetEvent; using Vonage.Conversations.GetMember; using Vonage.Conversations.GetMembers; using Vonage.Conversations.GetUserConversations; @@ -25,70 +26,77 @@ public interface IConversationsClient /// The request. /// Success or Failure. Task> CreateConversationAsync(Result request); - + /// /// Deletes a conversation. /// /// The request. /// Success or Failure. Task> DeleteConversationAsync(Result request); - + /// /// Deletes an event. /// /// The request. /// Success or Failure. Task> DeleteEventAsync(Result request); - + /// /// Retrieves a conversation. /// /// The request. /// Success or Failure. Task> GetConversationAsync(Result request); - + + /// + /// Retrieves an event. + /// + /// The request. + /// Success or Failure. + Task> GetEventAsync(Result request); + /// /// Creates a member. /// /// The request. /// Success or Failure. Task> CreateMemberAsync(Result request); - + /// /// Updates a member. /// /// The request. /// Success or Failure. Task> UpdateMemberAsync(Result request); - + /// /// Retrieves a member. /// /// The request. /// Success or Failure. Task> GetMemberAsync(Result request); - + /// /// Retrieves conversations. /// /// The request. /// Success or Failure. Task> GetConversationsAsync(Result request); - + /// /// Retrieves members. /// /// The request. /// Success or Failure. Task> GetMembersAsync(Result request); - + /// /// Retrieves conversations for a user. /// /// The request. /// Success or Failure. Task> GetUserConversationsAsync(Result request); - + /// /// Updates a conversation. /// diff --git a/Vonage/Conversations/Links.cs b/Vonage/Conversations/Links.cs new file mode 100644 index 000000000..626913781 --- /dev/null +++ b/Vonage/Conversations/Links.cs @@ -0,0 +1,9 @@ +using Vonage.Common; + +namespace Vonage.Conversations; + +/// +/// Represents additional links. +/// +/// The link to the resource. +public record Links(HalLink Self); \ No newline at end of file