diff --git a/src/Sinch/Conversation/SinchConversationClient.cs b/src/Sinch/Conversation/SinchConversationClient.cs index 11d622db..4a81ea1d 100644 --- a/src/Sinch/Conversation/SinchConversationClient.cs +++ b/src/Sinch/Conversation/SinchConversationClient.cs @@ -6,6 +6,7 @@ using Sinch.Conversation.Events; using Sinch.Conversation.Messages; using Sinch.Conversation.Transcoding; +using Sinch.Conversation.TemplatesV2; using Sinch.Conversation.Webhooks; using Sinch.Core; using Sinch.Logger; @@ -43,28 +44,34 @@ public interface ISinchConversation /// ISinchConversationCapabilities Capabilities { get; } + + /// + ISinchConversationTemplatesV2 TemplatesV2 { get; } } /// internal class SinchConversationClient : ISinchConversation { - internal SinchConversationClient(string projectId, Uri baseAddress, LoggerFactory loggerFactory, IHttp http) + internal SinchConversationClient(string projectId, Uri conversationBaseAddress, Uri templatesBaseAddress + , LoggerFactory loggerFactory, IHttp http) { - Messages = new Messages.Messages(projectId, baseAddress, + Messages = new Messages.Messages(projectId, conversationBaseAddress, loggerFactory?.Create(), http); - Apps = new Apps.Apps(projectId, baseAddress, loggerFactory?.Create(), http); - Contacts = new Contacts.Contacts(projectId, baseAddress, + Apps = new Apps.Apps(projectId, conversationBaseAddress, loggerFactory?.Create(), http); + Contacts = new Contacts.Contacts(projectId, conversationBaseAddress, loggerFactory?.Create(), http); - Conversations = new ConversationsClient(projectId, baseAddress, + Conversations = new ConversationsClient(projectId, conversationBaseAddress, loggerFactory?.Create(), http); - Webhooks = new Webhooks.Webhooks(projectId, baseAddress, + Webhooks = new Webhooks.Webhooks(projectId, conversationBaseAddress, loggerFactory?.Create(), http); - Events = new Events.Events(projectId, baseAddress, loggerFactory?.Create(), http); - Transcoding = new Transcoding.Transcoding(projectId, baseAddress, + Events = new Events.Events(projectId, conversationBaseAddress, loggerFactory?.Create(), http); + Transcoding = new Transcoding.Transcoding(projectId, conversationBaseAddress, loggerFactory?.Create(), http); - Capabilities = new Capabilities(projectId, baseAddress, + Capabilities = new Capabilities(projectId, conversationBaseAddress, loggerFactory?.Create(), http); + TemplatesV2 = new TemplatesV2.TemplatesV2(projectId, templatesBaseAddress, + loggerFactory?.Create(), http); } /// @@ -90,5 +97,8 @@ internal SinchConversationClient(string projectId, Uri baseAddress, LoggerFactor /// public ISinchConversationCapabilities Capabilities { get; } + + /// + public ISinchConversationTemplatesV2 TemplatesV2 { get; } } } diff --git a/src/Sinch/Conversation/TemplatesV2/ChannelTemplateOverride.cs b/src/Sinch/Conversation/TemplatesV2/ChannelTemplateOverride.cs new file mode 100644 index 00000000..641fd1c8 --- /dev/null +++ b/src/Sinch/Conversation/TemplatesV2/ChannelTemplateOverride.cs @@ -0,0 +1,41 @@ +using System.Text; +using System.Text.Json.Serialization; +using Sinch.Conversation.Messages.Message; + +namespace Sinch.Conversation.TemplatesV2 +{ + /// + /// Optional field to override the omnichannel template by referring to a channel-specific template. + /// + public sealed class ChannelTemplateOverride + { + /// + /// Gets or Sets Whatsapp + /// + [JsonPropertyName("WHATSAPP")] + public OverrideTemplateReference WhatsApp { get; set; } + + + /// + /// Gets or Sets Kakaotalk + /// + [JsonPropertyName("KAKAOTALK")] + public OverrideTemplateReference KakaoTalk { get; set; } + + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class ChannelTemplateOverride {\n"); + sb.Append(" WHATSAPP: ").Append(WhatsApp).Append("\n"); + sb.Append(" KAKOTALK: ").Append(KakaoTalk).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + } +} diff --git a/src/Sinch/Conversation/TemplatesV2/CreateTemplateRequest.cs b/src/Sinch/Conversation/TemplatesV2/CreateTemplateRequest.cs new file mode 100644 index 00000000..7151e90a --- /dev/null +++ b/src/Sinch/Conversation/TemplatesV2/CreateTemplateRequest.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Sinch.Conversation.TemplatesV2 +{ + public class CreateTemplateRequest + { + /// + /// The default translation to use if translation not specified. Specified as a BCP-47 `language_code` and the `language_code` must exist in the translations list. + /// +#if NET7_0_OR_GREATER + public required string DefaultTranslation { get; set; } +#else + public string DefaultTranslation { get; set; } +#endif + + /// + /// Gets or Sets Translations + /// +#if NET7_0_OR_GREATER + public required List Translations { get; set; } +#else + public List Translations { get; set; } +#endif + + + /// + /// The description of the template. + /// + public string Description { get; set; } + + + /// + /// The version of the template. While creating a template, this will be defaulted to 1. When updating a template, you must supply the latest version of the template in order for the update to be successful. + /// + public int Version { get; set; } + + + /// + /// Timestamp when the template was created. + /// + public DateTime CreateTime { get; set; } + + + /// + /// Timestamp when the template was updated. + /// + public DateTime UpdateTime { get; set; } + + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class V2TemplateResponse {\n"); + sb.Append(" Description: ").Append(Description).Append("\n"); + sb.Append(" Version: ").Append(Version).Append("\n"); + sb.Append(" DefaultTranslation: ").Append(DefaultTranslation).Append("\n"); + sb.Append(" Translations: ").Append(Translations).Append("\n"); + sb.Append(" CreateTime: ").Append(CreateTime).Append("\n"); + sb.Append(" UpdateTime: ").Append(UpdateTime).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + } +} diff --git a/src/Sinch/Conversation/TemplatesV2/OverrideTemplateReference.cs b/src/Sinch/Conversation/TemplatesV2/OverrideTemplateReference.cs new file mode 100644 index 00000000..11e24aec --- /dev/null +++ b/src/Sinch/Conversation/TemplatesV2/OverrideTemplateReference.cs @@ -0,0 +1,32 @@ +using System.Text; +using Sinch.Conversation.Messages.Message; + +namespace Sinch.Conversation.TemplatesV2 +{ + public class OverrideTemplateReference + { + /// + /// The referenced template can be an omnichannel template stored in Conversation API Template Store as AppMessage or it can reference external channel-specific template such as WhatsApp Business Template. + /// + public TemplateReference TemplateReference { get; set; } + + /// + /// Gets or Sets ParameterMappings + /// + public TemplateReferenceParameterMappings ParameterMappings { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class TemplateReference {\n"); + sb.Append(" TemplateReference: ").Append(TemplateReference).Append("\n"); + sb.Append(" ParameterMappings: ").Append(ParameterMappings).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + } +} diff --git a/src/Sinch/Conversation/TemplatesV2/Template.cs b/src/Sinch/Conversation/TemplatesV2/Template.cs new file mode 100644 index 00000000..c2d85a19 --- /dev/null +++ b/src/Sinch/Conversation/TemplatesV2/Template.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Sinch.Conversation.TemplatesV2 +{ + public class Template + { + /// + /// The id of the template. Specify this yourself during creation. Otherwise, we will generate an ID for you. This must + /// be unique for a given project. + /// + public string Id { get; set; } + + + /// + /// The description of the template. + /// + public string Description { get; set; } + + + /// + /// The version of the template. While creating a template, this will be defaulted to 1. When updating a template, you + /// must supply the latest version of the template in order for the update to be successful. + /// + public int Version { get; set; } + + + /// + /// The default translation to use if translation not specified. Specified as a BCP-47 `language_code` and + /// the `language_code` must exist in the translations list. + /// + public string DefaultTranslation { get; set; } + + + /// + /// Gets or Sets Translations + /// + public List Translations { get; set; } + + + /// + /// Timestamp when the template was created. + /// + public DateTime CreateTime { get; set; } + + + /// + /// Timestamp when the template was updated. + /// + public DateTime UpdateTime { get; set; } + + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class V2TemplateResponse {\n"); + sb.Append(" Id: ").Append(Id).Append("\n"); + sb.Append(" Description: ").Append(Description).Append("\n"); + sb.Append(" Version: ").Append(Version).Append("\n"); + sb.Append(" DefaultTranslation: ").Append(DefaultTranslation).Append("\n"); + sb.Append(" Translations: ").Append(Translations).Append("\n"); + sb.Append(" CreateTime: ").Append(CreateTime).Append("\n"); + sb.Append(" UpdateTime: ").Append(UpdateTime).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + } +} diff --git a/src/Sinch/Conversation/TemplatesV2/TemplateReferenceParameterMappings.cs b/src/Sinch/Conversation/TemplatesV2/TemplateReferenceParameterMappings.cs new file mode 100644 index 00000000..b5fa6841 --- /dev/null +++ b/src/Sinch/Conversation/TemplatesV2/TemplateReferenceParameterMappings.cs @@ -0,0 +1,31 @@ +using System.Text; + +namespace Sinch.Conversation.TemplatesV2 +{ + /// + /// A mapping between omni-template variables and the channel specific parameters. + /// + public sealed class TemplateReferenceParameterMappings + { + /// + /// The mapping between the omni-template variable and the channel specific parameter. + /// + public string Name { get; set; } + + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class TemplateReferenceParameterMappings {\n"); + sb.Append(" Name: ").Append(Name).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + } + +} diff --git a/src/Sinch/Conversation/TemplatesV2/TemplateTranslation.cs b/src/Sinch/Conversation/TemplatesV2/TemplateTranslation.cs new file mode 100644 index 00000000..f7a1f0e5 --- /dev/null +++ b/src/Sinch/Conversation/TemplatesV2/TemplateTranslation.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json.Serialization; +using Sinch.Conversation.Messages.Message; + +namespace Sinch.Conversation.TemplatesV2 +{ + public class TemplateTranslation + { + // Thank you System.Text.Json -_- + [JsonConstructor] + [Obsolete("Needed for System.Text.Json", true)] + public TemplateTranslation() + { + } + + public TemplateTranslation(ChoiceMessage choiceMessage) + { + ChoiceMessage = choiceMessage; + } + + public TemplateTranslation(LocationMessage locationMessage) + { + LocationMessage = locationMessage; + } + + public TemplateTranslation(MediaMessage mediaMessage) + { + MediaMessage = mediaMessage; + } + + public TemplateTranslation(TemplateMessage templateMessage) + { + TemplateMessage = templateMessage; + } + + public TemplateTranslation(ListMessage listMessage) + { + ListMessage = listMessage; + } + + public TemplateTranslation(TextMessage textMessage) + { + TextMessage = textMessage; + } + + public TemplateTranslation(CardMessage cardMessage) + { + CardMessage = cardMessage; + } + + public TemplateTranslation(CarouselMessage carouselMessage) + { + CarouselMessage = carouselMessage; + } + + [JsonInclude] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public TextMessage TextMessage { get; private set; } + + [JsonInclude] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public CardMessage CardMessage { get; private set; } + + [JsonInclude] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public CarouselMessage CarouselMessage { get; private set; } + + [JsonInclude] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public ChoiceMessage ChoiceMessage { get; private set; } + + [JsonInclude] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public LocationMessage LocationMessage { get; private set; } + + [JsonInclude] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public MediaMessage MediaMessage { get; private set; } + + [JsonInclude] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public TemplateMessage TemplateMessage { get; private set; } + + [JsonInclude] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public ListMessage ListMessage { get; private set; } + + /// + /// The BCP-47 language code, such as `en-US` or `sr-Latn`. For more information, see http://www.unicode.org/reports/tr35/#Unicode_locale_identifier. + /// +#if NET7_0_OR_GREATER + public required string LanguageCode { get; set; } +#else + public string LanguageCode { get; set; } +#endif + + /// + /// The version of the translation. + /// + public string Version { get; set; } + + + /// + /// Gets or Sets ChannelTemplateOverrides + /// + public ChannelTemplateOverride ChannelTemplateOverrides { get; set; } + + + /// + /// List of expected variables. Can be used for request validation. + /// + public List Variables { get; set; } + + + /// + /// Timestamp when the translation was created. + /// + public DateTime CreateTime { get; set; } + + + /// + /// Timestamp of when the translation was updated. + /// + public DateTime UpdateTime { get; set; } + + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class V2TemplateTranslation {\n"); + sb.Append(" LanguageCode: ").Append(LanguageCode).Append("\n"); + sb.Append(" Version: ").Append(Version).Append("\n"); + sb.Append(" TextMessage: ").Append(TextMessage).Append("\n"); + sb.Append(" CardMessage: ").Append(CardMessage).Append("\n"); + sb.Append(" CarouselMessage: ").Append(CarouselMessage).Append("\n"); + sb.Append(" ChoiceMessage: ").Append(ChoiceMessage).Append("\n"); + sb.Append(" LocationMessage: ").Append(LocationMessage).Append("\n"); + sb.Append(" MediaMessage: ").Append(MediaMessage).Append("\n"); + sb.Append(" TemplateMessage: ").Append(TemplateMessage).Append("\n"); + sb.Append(" ListMessage: ").Append(ListMessage).Append("\n"); + sb.Append(" ChannelTemplateOverrides: ").Append(ChannelTemplateOverrides).Append("\n"); + sb.Append(" Variables: ").Append(Variables).Append("\n"); + sb.Append(" CreateTime: ").Append(CreateTime).Append("\n"); + sb.Append(" UpdateTime: ").Append(UpdateTime).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + } +} diff --git a/src/Sinch/Conversation/TemplatesV2/TemplatesV2.cs b/src/Sinch/Conversation/TemplatesV2/TemplatesV2.cs new file mode 100644 index 00000000..756a9878 --- /dev/null +++ b/src/Sinch/Conversation/TemplatesV2/TemplatesV2.cs @@ -0,0 +1,190 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using Sinch.Core; +using Sinch.Logger; + +namespace Sinch.Conversation.TemplatesV2 +{ + /// + /// The Template Management API offers a way to manage templates that can be used together with the Conversation API. + /// Note that you may also use the Message Composer tool on the [Sinch Customer + /// Dashboard](https://dashboard.sinch.com/convapi/message-composer) to [manage + /// templates](https://community.sinch.com/t5/Conversation-API/How-do-I-use-Message-Composer-to-create-omni-channel-message/ta-p/9890). + /// One can view a template as a pre-defined message that can optionally contain some parameters to facilitate some + /// customization of the pre-defined message. This feature can, for instance, be used to construct a generic customer + /// welcome message where the customer's name can be injected via a parameter. It's also possible to provide + /// translations to different languages when creating a template to make it possible to reuse one template for + /// different languages. + /// + public interface ISinchConversationTemplatesV2 + { + /// + /// Get a template + /// + /// + /// + /// + Task