Skip to content

Commit

Permalink
Feat/conversation webhooks (#39)
Browse files Browse the repository at this point in the history
* refactor: use interface in logger in Messages.cs

* chore: disable CS1570 in GetDeliveryReportResponse.cs

* feat: implement Webhooks
create 
delete
update
list
get

* fix: remove ClientSecret from ToString of ClientCredentials.cs
  • Loading branch information
Dovchik authored Feb 13, 2024
1 parent 0f794f6 commit 1122042
Show file tree
Hide file tree
Showing 10 changed files with 549 additions and 5 deletions.
4 changes: 2 additions & 2 deletions examples/Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Environment.GetEnvironmentVariable("SINCH_KEY_SECRET")!,
Environment.GetEnvironmentVariable("SINCH_PROJECT_ID")!);

var verification = sinch.Verification(Environment.GetEnvironmentVariable("SINCH_APP_KEY")!,
Environment.GetEnvironmentVariable("SINCH_APP_SECRET")!, AuthStrategy.ApplicationSign);
_ = sinch.Verification(Environment.GetEnvironmentVariable("SINCH_APP_KEY")!,
Environment.GetEnvironmentVariable("SINCH_APP_SECRET")!);

Console.ReadLine();
4 changes: 2 additions & 2 deletions src/Sinch/Conversation/Messages/Messages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ internal class Messages : ISinchConversationMessages
{
private readonly Uri _baseAddress;
private readonly IHttp _http;
private readonly ILoggerAdapter<Messages> _logger;
private readonly ILoggerAdapter<ISinchConversationMessages> _logger;
private readonly string _projectId;

public Messages(string projectId, Uri baseAddress, ILoggerAdapter<Messages> logger, IHttp http)
public Messages(string projectId, Uri baseAddress, ILoggerAdapter<ISinchConversationMessages> logger, IHttp http)
{
_projectId = projectId;
_baseAddress = baseAddress;
Expand Down
11 changes: 10 additions & 1 deletion src/Sinch/Conversation/SinchConversationClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Sinch.Conversation.Contacts;
using Sinch.Conversation.Conversations;
using Sinch.Conversation.Messages;
using Sinch.Conversation.Webhooks;
using Sinch.Core;
using Sinch.Logger;

Expand All @@ -27,20 +28,26 @@ public interface ISinchConversation

/// <inheritdoc cref="ISinchConversationConversations" />
ISinchConversationConversations Conversations { get; }

/// <inheritdoc cref="ISinchConversationWebhooks" />
ISinchConversationWebhooks Webhooks { get; }
}

/// <inheritdoc />
internal class SinchConversationClient : ISinchConversation
{
internal SinchConversationClient(string projectId, Uri baseAddress, LoggerFactory loggerFactory, IHttp http)
{
Messages = new Messages.Messages(projectId, baseAddress, loggerFactory?.Create<Messages.Messages>(),
Messages = new Messages.Messages(projectId, baseAddress,
loggerFactory?.Create<ISinchConversationMessages>(),
http);
Apps = new Apps.Apps(projectId, baseAddress, loggerFactory?.Create<Apps.Apps>(), http);
Contacts = new Contacts.Contacts(projectId, baseAddress,
loggerFactory?.Create<ISinchConversationContacts>(), http);
Conversations = new ConversationsClient(projectId, baseAddress,
loggerFactory?.Create<ISinchConversationConversations>(), http);
Webhooks = new Webhooks.Webhooks(projectId, baseAddress,
loggerFactory?.Create<ISinchConversationWebhooks>(), http);
}

/// <inheritdoc />
Expand All @@ -54,5 +61,7 @@ internal SinchConversationClient(string projectId, Uri baseAddress, LoggerFactor

/// <inheritdoc />
public ISinchConversationConversations Conversations { get; }

public ISinchConversationWebhooks Webhooks { get; }
}
}
56 changes: 56 additions & 0 deletions src/Sinch/Conversation/Webhooks/ClientCredentials.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System.Text;

namespace Sinch.Conversation.Webhooks
{
/// <summary>
/// Optional. Used for OAuth2 authentication.
/// </summary>
public sealed class ClientCredentials
{
/// <summary>
/// The Client ID that will be used in the OAuth2 Client Credentials flow.
/// </summary>
#if NET7_0_OR_GREATER
public required string ClientId { get; set; }
#else
public string ClientId { get; set; }
#endif


/// <summary>
/// The Client Secret that will be used in the OAuth2 Client Credentials flow.
/// </summary>
#if NET7_0_OR_GREATER
public required string ClientSecret { get; set; }
#else
public string ClientSecret { get; set; }
#endif


/// <summary>
/// The endpoint that will be used in the OAuth2 Client Credentials flow. Expected to return a JSON with an access
/// token and &#x60;expires_in&#x60; value (in seconds). The &#x60;expires_in&#x60; value, which must be a minimum of
/// 30 seconds and a maximum of 3600 seconds, is how long Sinch will save the access token before asking for a new one.
/// </summary>
#if NET7_0_OR_GREATER
public required string Endpoint { get; set; }
#else
public string Endpoint { get; set; }
#endif


/// <summary>
/// Returns the string presentation of the object
/// </summary>
/// <returns>String presentation of the object</returns>
public override string ToString()
{
var sb = new StringBuilder();
sb.Append("class ClientCredentials {\n");
sb.Append(" ClientId: ").Append(ClientId).Append("\n");
sb.Append(" Endpoint: ").Append(Endpoint).Append("\n");
sb.Append("}\n");
return sb.ToString();
}
}
}
145 changes: 145 additions & 0 deletions src/Sinch/Conversation/Webhooks/Webhook.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
using System.Collections.Generic;
using System.Text;
using Sinch.Core;

namespace Sinch.Conversation.Webhooks
{
/// <summary>
/// Represents a destination for receiving callbacks from the Conversation API.
/// </summary>
public class Webhook : PropertyMaskQuery
{
private WebhookTargetType _targetType;
private string _appId;
private ClientCredentials _clientCredentials;
private string _id;
private string _secret;
private string _target;
private List<WebhookTrigger> _triggers;

/// <summary>
/// Gets or sets the target type.
/// </summary>
public WebhookTargetType TargetType
{
get => _targetType;
set
{
SetFields.Add(nameof(TargetType));
_targetType = value;
}
}

/// <summary>
/// The app that this webhook belongs to.
/// </summary>
#if NET7_0_OR_GREATER
public required string AppId
#else
public string AppId
#endif
{
get => _appId;
set
{
SetFields.Add(nameof(AppId));
_appId = value;
}
}

/// <summary>
/// Gets or sets the client credentials.
/// </summary>
public ClientCredentials ClientCredentials
{
get => _clientCredentials;
set
{
SetFields.Add(nameof(ClientCredentials));
_clientCredentials = value;
}
}

/// <summary>
/// Gets or sets the ID of the webhook.
/// </summary>
public string Id
{
get => _id;
set
{
SetFields.Add(nameof(Id));
_id = value;
}
}

/// <summary>
/// Optional secret to be used to sign contents of webhooks sent by the Conversation API.
/// You can then use the secret to verify the signature.
/// </summary>
public string Secret
{
get => _secret;
set
{
SetFields.Add(nameof(Secret));
_secret = value;
}
}

/// <summary>
/// Gets or sets the target URL where events should be sent to.
/// Maximum URL length is 742. The conversation-api.*.sinch.com subdomains are forbidden.
/// </summary>
#if NET7_0_OR_GREATER
public required string Target
#else
public string Target
#endif
{
get => _target;
set
{
SetFields.Add(nameof(Target));
_target = value;
}
}

/// <summary>
/// An array of triggers that should trigger the webhook and result in an event being sent to the target URL.
/// Refer to the list of [Webhook Triggers](https://developers.sinch.com/docs/conversation/callbacks#webhook-triggers)
/// for a complete list.
/// </summary>
#if NET7_0_OR_GREATER
public required List<WebhookTrigger> Triggers
#else
public List<WebhookTrigger> Triggers
#endif
{
get => _triggers;
set
{
SetFields.Add(nameof(Triggers));
_triggers = value;
}
}

/// <summary>
/// Returns the string presentation of the object.
/// </summary>
/// <returns>String presentation of the object.</returns>
public override string ToString()
{
var sb = new StringBuilder();
sb.Append("class Webhook {\n");
sb.Append(" AppId: ").Append(AppId).Append("\n");
sb.Append(" ClientCredentials: ").Append(ClientCredentials).Append("\n");
sb.Append(" Id: ").Append(Id).Append("\n");
sb.Append(" Target: ").Append(Target).Append("\n");
sb.Append(" TargetType: ").Append(TargetType).Append("\n");
sb.Append(" Triggers: ").Append(Triggers).Append("\n");
sb.Append("}\n");
return sb.ToString();
}
}
}
15 changes: 15 additions & 0 deletions src/Sinch/Conversation/Webhooks/WebhookTargetType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Text.Json.Serialization;
using Sinch.Core;

namespace Sinch.Conversation.Webhooks
{
/// <summary>
/// Defines WebhookTargetType
/// </summary>
[JsonConverter(typeof(EnumRecordJsonConverter<WebhookTargetType>))]
public record WebhookTargetType(string Value) : EnumRecord(Value)
{
public static readonly WebhookTargetType Dismiss = new("DISMISS");
public static readonly WebhookTargetType Http = new("HTTP");
}
}
55 changes: 55 additions & 0 deletions src/Sinch/Conversation/Webhooks/WebhookTrigger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System.Text.Json.Serialization;
using Sinch.Core;

namespace Sinch.Conversation.Webhooks
{
/// <summary>
/// - &#x60;UNSPECIFIED_TRIGGER&#x60;: Using this value will cause errors. - &#x60;MESSAGE_DELIVERY&#x60;: Subscribe to
/// delivery receipts for a message sent. - &#x60;MESSAGE_SUBMIT&#x60;: Subscribe to message submission notifications.
/// - &#x60;EVENT_DELIVERY&#x60;: Subscribe to delivery receipts for a event sent. - &#x60;MESSAGE_INBOUND&#x60;:
/// Subscribe to inbound messages from end users on the underlying channels. - &#x60;SMART_CONVERSATION&#x60;: These
/// triggers allow you to subscribe to payloads that provide machine learning analyses of inbound messages from end
/// users on the underlying channels - &#x60;MESSAGE_INBOUND_SMART_CONVERSATION_REDACTION&#x60;: These triggers allow
/// you to subscribe to payloads that deliver redacted versions of inbound messages - &#x60;EVENT_INBOUND&#x60;:
/// Subscribe to inbound events from end users on the underlying channels. - &#x60;CONVERSATION_START&#x60;: Subscribe
/// to an event that is triggered when a new conversation has been started. - &#x60;CONVERSATION_STOP&#x60;: Subscribe
/// to an event that is triggered when an active conversation has been stopped. - &#x60;CONTACT_CREATE&#x60;: Subscribe
/// to an event that is triggered when a new contact has been created. - &#x60;CONTACT_DELETE&#x60;: Subscribe to an
/// event that is triggered when a contact has been deleted. - &#x60;CONTACT_MERGE&#x60;: Subscribe to an event that is
/// triggered when two contacts are merged. - &#x60;CONTACT_UPDATE&#x60;: Subscribe to an event that is triggered when
/// a contact is updated. - &#x60;UNSUPPORTED&#x60;: Subscribe to callbacks that are not natively supported by the
/// Conversation API. - &#x60;OPT_IN&#x60;: Subscribe to opt_ins. - &#x60;OPT_OUT&#x60;: Subscribe to opt_outs. -
/// &#x60;CAPABILITY&#x60;: Subscribe to see get capability results. - &#x60;CHANNEL_EVENT&#x60;: Subscribe to channel
/// event notifications. - &#x60;CONVERSATION_DELETE&#x60;: Subscribe to get an event when a conversation is deleted. -
/// &#x60;CONTACT_IDENTITIES_DUPLICATION&#x60;: Subscribe to get an event when contact identity duplications are found
/// during message or event processing. - &#x60;SMART_CONVERSATIONS&#x60;: Subscribe to smart conversations callback
/// </summary>
[JsonConverter(typeof(EnumRecordJsonConverter<WebhookTrigger>))]
public record WebhookTrigger(string Value) : EnumRecord(Value)
{
public static readonly WebhookTrigger UnspecifiedTrigger = new("UNSPECIFIED_TRIGGER");
public static readonly WebhookTrigger MessageDelivery = new("MESSAGE_DELIVERY");
public static readonly WebhookTrigger MessageSubmit = new("MESSAGE_SUBMIT");
public static readonly WebhookTrigger EventDelivery = new("EVENT_DELIVERY");
public static readonly WebhookTrigger MessageInbound = new("MESSAGE_INBOUND");
public static readonly WebhookTrigger SmartConversation = new("SMART_CONVERSATION");

public static readonly WebhookTrigger MessageInboundSmartConversationRedaction =
new("MESSAGE_INBOUND_SMART_CONVERSATION_REDACTION");

public static readonly WebhookTrigger EventInbound = new("EVENT_INBOUND");
public static readonly WebhookTrigger ConversationStart = new("CONVERSATION_START");
public static readonly WebhookTrigger ConversationStop = new("CONVERSATION_STOP");
public static readonly WebhookTrigger ContactCreate = new("CONTACT_CREATE");
public static readonly WebhookTrigger ContactDelete = new("CONTACT_DELETE");
public static readonly WebhookTrigger ContactMerge = new("CONTACT_MERGE");
public static readonly WebhookTrigger ContactUpdate = new("CONTACT_UPDATE");
public static readonly WebhookTrigger Unsupported = new("UNSUPPORTED");
public static readonly WebhookTrigger OptIn = new("OPT_IN");
public static readonly WebhookTrigger OptOut = new("OPT_OUT");
public static readonly WebhookTrigger Capability = new("CAPABILITY");
public static readonly WebhookTrigger ChannelEvent = new("CHANNEL_EVENT");
public static readonly WebhookTrigger ConversationDelete = new("CONVERSATION_DELETE");
public static readonly WebhookTrigger ContactIdentitiesDuplication = new("CONTACT_IDENTITIES_DUPLICATION");
}
}
Loading

0 comments on commit 1122042

Please sign in to comment.