Skip to content

Commit

Permalink
feat: add hooks models (#45)
Browse files Browse the repository at this point in the history
* feat: add hooks models

* feat: add method to validate webhook signature

* feat: add example of validating a callback
  • Loading branch information
Dovchik authored Mar 25, 2024
1 parent 3042176 commit 3b142be
Show file tree
Hide file tree
Showing 67 changed files with 3,057 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.AspNetCore.Mvc;
using Sinch;
using Sinch.Conversation.Hooks;

namespace WebApiExamples.Controllers;

[ApiController]
[Route("event-listener")]
public class ReceiveConversationCallbackController : ControllerBase
{
private readonly ISinchClient _sinch;
private readonly ILogger _logger;
private const string Secret = "1234_my_secret";

public ReceiveConversationCallbackController(ISinchClient sinch, ILogger<ReplyToInboundController> logger)
{
_sinch = sinch;
_logger = logger;
}

[HttpPost(Name = "handle")]
public ActionResult Handle([FromBody] JsonObject json)
{
var headers = Request.Headers.ToDictionary(a => a.Key, a => a.Value);
if (!_sinch.Conversation.Webhooks.ValidateAuthenticationHeader(headers, json,
Secret))
{
_logger?.LogError("Failed to authorize received callback.");
return Unauthorized();
}

var callbackEvent = json.Deserialize<ICallbackEvent>();
// do something with specific event
switch (callbackEvent)
{
case CapabilityEvent capabilityEvent:
break;
case ChannelEvent channelEvent:
break;
case ContactCreateEvent contactCreateEvent:
break;
case ContactDeleteEvent contactDeleteEvent:
break;
case ContactIdentitiesDuplicationEvent contactIdentitiesDuplicationEvent:
break;
case ContactMergeEvent contactMergeEvent:
break;
case ContactUpdateEvent contactUpdateEvent:
break;
case ConversationDeleteEvent conversationDeleteEvent:
break;
case ConversationStartEvent conversationStartEvent:
break;
case ConversationStopEvent conversationStopEvent:
break;
case DeliveryEvent deliveryEvent:
break;
case InboundEvent inboundEvent:
break;
case MessageDeliveryReceiptEvent messageDeliveryReceiptEvent:
break;
case MessageInboundEvent messageInboundEvent:
break;
case MessageInboundSmartConversationRedactionEvent messageInboundSmartConversationRedactionEvent:
break;
case MessageSubmitEvent messageSubmitEvent:
break;
case OptInEvent optInEvent:
break;
case OptOutEvent optOutEvent:
break;
case SmartConversationsEvent smartConversationsEvent:
break;
case UnsupportedCallbackEvent unsupportedCallbackEvent:
break;
default:
throw new ArgumentOutOfRangeException(nameof(callbackEvent));
}

return Ok();
}
}
47 changes: 47 additions & 0 deletions src/Sinch/Conversation/Hooks/CallbackEventBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.Text.Json.Serialization;

namespace Sinch.Conversation.Hooks
{
public abstract class CallbackEventBase : ICallbackEvent
{
/// <summary>
/// Id of the subscribed app.
/// </summary>
[JsonPropertyName("app_id")]
public string AppId { get; set; }

/// <summary>
/// Timestamp marking when the channel callback was accepted/received by the Conversation API.
/// </summary>
[JsonPropertyName("accepted_time")]
public DateTime AcceptedTime { get; set; }


/// <summary>
/// Timestamp of the event as provided by the underlying channels.
/// </summary>
[JsonPropertyName("event_time")]
public DateTime EventTime { get; set; }

/// <summary>
/// The project ID of the app which has subscribed for the callback.
/// </summary>
[JsonPropertyName("project_id")]
public string ProjectId { get; set; }


/// <summary>
/// Context-dependent metadata. Refer to specific callback&#39;s documentation for exact information provided.
/// </summary>
[JsonPropertyName("message_metadata")]
public string MessageMetadata { get; set; }


/// <summary>
/// The value provided in field correlation_id of a send message request.
/// </summary>
[JsonPropertyName("correlation_id")]
public string CorrelationId { get; set; }
}
}
37 changes: 37 additions & 0 deletions src/Sinch/Conversation/Hooks/CapabilityEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Text;
using System.Text.Json.Serialization;
using Sinch.Conversation.Hooks.Models;

namespace Sinch.Conversation.Hooks
{
/// <summary>
/// This callback is used to deliver the results of the asynchronous capability checks.
/// </summary>
public sealed class CapabilityEvent : CallbackEventBase
{
/// <summary>
/// Gets or Sets CapabilityNotification
/// </summary>
[JsonPropertyName("capability_notification")]
public CapabilityNotification CapabilityNotification { get; set; }

/// <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 {nameof(CapabilityEvent)} {{\n");
sb.Append($" {nameof(AppId)}: ").Append(AppId).Append('\n');
sb.Append($" {nameof(AcceptedTime)}: ").Append(AcceptedTime).Append('\n');
sb.Append($" {nameof(EventTime)}: ").Append(EventTime).Append('\n');
sb.Append($" {nameof(ProjectId)}: ").Append(ProjectId).Append('\n');
sb.Append($" {nameof(MessageMetadata)}: ").Append(MessageMetadata).Append('\n');
sb.Append($" {nameof(CorrelationId)}: ").Append(CorrelationId).Append('\n');
sb.Append($" {nameof(CapabilityNotification)}: ").Append(CapabilityNotification).Append('\n');
sb.Append("}\n");
return sb.ToString();
}
}
}
41 changes: 41 additions & 0 deletions src/Sinch/Conversation/Hooks/ChannelEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Text;
using System.Text.Json.Serialization;
using Sinch.Conversation.Hooks.Models;

namespace Sinch.Conversation.Hooks
{
/// <summary>
/// This callback is used to deliver notifications regarding channel-specific information and updates. For example, if your are using the WhatsApp channel of the Conversation API, and your quality rating has been changed to GREEN, a POST would be made to the CHANNEL_EVENT webhook.
/// </summary>
public sealed class ChannelEvent : CallbackEventBase
{
/// <summary>
/// Gets or Sets ChannelEventNotification
/// </summary>
[JsonPropertyName("channel_event_notification")]
public EventNotification EventNotification { get; set; }


/// <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 {nameof(ChannelEvent)} {{\n");
sb.Append($" {nameof(AppId)}: ").Append(AppId).Append('\n');
sb.Append($" {nameof(AcceptedTime)}: ").Append(AcceptedTime).Append('\n');
sb.Append($" {nameof(EventTime)}: ").Append(EventTime).Append('\n');
sb.Append($" {nameof(ProjectId)}: ").Append(ProjectId).Append('\n');
sb.Append($" {nameof(MessageMetadata)}: ").Append(MessageMetadata).Append('\n');
sb.Append($" {nameof(CorrelationId)}: ").Append(CorrelationId).Append('\n');
sb.Append($" {nameof(EventNotification)}: ").Append(EventNotification).Append('\n');
sb.Append("}\n");
return sb.ToString();
}

}

}
39 changes: 39 additions & 0 deletions src/Sinch/Conversation/Hooks/ContactCreateEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Text;
using System.Text.Json.Serialization;
using Sinch.Conversation.Hooks.Models;

namespace Sinch.Conversation.Hooks
{
/// <summary>
/// This callback is sent when a new contact is created.
/// </summary>
public sealed class ContactCreateEvent : CallbackEventBase
{
/// <summary>
/// Gets or Sets ContactCreateNotification
/// </summary>
[JsonPropertyName("contact_create_notification")]
public ContactNotification ContactCreateNotification { get; set; }


/// <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 {nameof(ContactCreateEvent)} {{\n");
sb.Append($" {nameof(AppId)}: ").Append(AppId).Append('\n');
sb.Append($" {nameof(AcceptedTime)}: ").Append(AcceptedTime).Append('\n');
sb.Append($" {nameof(EventTime)}: ").Append(EventTime).Append('\n');
sb.Append($" {nameof(ProjectId)}: ").Append(ProjectId).Append('\n');
sb.Append($" {nameof(MessageMetadata)}: ").Append(MessageMetadata).Append('\n');
sb.Append($" {nameof(CorrelationId)}: ").Append(CorrelationId).Append('\n');
sb.Append($" {nameof(ContactCreateNotification)}: ").Append(ContactCreateNotification).Append('\n');
sb.Append("}\n");
return sb.ToString();
}
}
}
39 changes: 39 additions & 0 deletions src/Sinch/Conversation/Hooks/ContactDeleteEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Text;
using System.Text.Json.Serialization;
using Sinch.Conversation.Hooks.Models;

namespace Sinch.Conversation.Hooks
{
/// <summary>
/// This callback is sent when a new contact is deleted.
/// </summary>
public sealed class ContactDeleteEvent : CallbackEventBase
{
/// <summary>
/// Gets or Sets ContactDeleteNotification
/// </summary>
[JsonPropertyName("contact_delete_notification")]
public ContactNotification ContactDeleteNotification { get; set; }


/// <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 {nameof(ContactDeleteEvent)} {{\n");
sb.Append($" {nameof(AppId)}: ").Append(AppId).Append('\n');
sb.Append($" {nameof(AcceptedTime)}: ").Append(AcceptedTime).Append('\n');
sb.Append($" {nameof(EventTime)}: ").Append(EventTime).Append('\n');
sb.Append($" {nameof(ProjectId)}: ").Append(ProjectId).Append('\n');
sb.Append($" {nameof(MessageMetadata)}: ").Append(MessageMetadata).Append('\n');
sb.Append($" {nameof(CorrelationId)}: ").Append(CorrelationId).Append('\n');
sb.Append($" {nameof(ContactDeleteNotification)}: ").Append(ContactDeleteNotification).Append('\n');
sb.Append("}\n");
return sb.ToString();
}
}
}
41 changes: 41 additions & 0 deletions src/Sinch/Conversation/Hooks/ContactIdentitiesDuplicationEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Text;
using System.Text.Json.Serialization;
using Sinch.Conversation.Hooks.Models;

namespace Sinch.Conversation.Hooks
{
/// <summary>
/// This callback is sent when duplicates of channel identities are found between multiple contacts in the contact database during message and event processing.
/// </summary>
public sealed class ContactIdentitiesDuplicationEvent : CallbackEventBase
{
/// <summary>
/// Gets or Sets DuplicatedContactIdentitiesNotification
/// </summary>
[JsonPropertyName("duplicated_contact_identities_notification")]
public DuplicatedIdentitiesEvent DuplicatedContactIdentitiesNotification { get; set; }


/// <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 {nameof(ContactIdentitiesDuplicationEvent)} {{\n");
sb.Append($" {nameof(AppId)}: ").Append(AppId).Append('\n');
sb.Append($" {nameof(AcceptedTime)}: ").Append(AcceptedTime).Append('\n');
sb.Append($" {nameof(EventTime)}: ").Append(EventTime).Append('\n');
sb.Append($" {nameof(ProjectId)}: ").Append(ProjectId).Append('\n');
sb.Append($" {nameof(MessageMetadata)}: ").Append(MessageMetadata).Append('\n');
sb.Append($" {nameof(CorrelationId)}: ").Append(CorrelationId).Append('\n');
sb.Append($" {nameof(DuplicatedContactIdentitiesNotification)}: ").Append(DuplicatedContactIdentitiesNotification).Append('\n');
sb.Append("}\n");
return sb.ToString();
}

}

}
38 changes: 38 additions & 0 deletions src/Sinch/Conversation/Hooks/ContactMergeEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Text;
using System.Text.Json.Serialization;
using Sinch.Conversation.Hooks.Models;

namespace Sinch.Conversation.Hooks
{
/// <summary>
/// This callback is sent when two contacts are merged.
/// </summary>
public sealed class ContactMergeEvent : CallbackEventBase
{
/// <summary>
/// Gets or Sets ContactMergeNotification
/// </summary>
[JsonPropertyName("contact_merge_notification")]
public ContactMergeNotification ContactMergeNotification { get; set; }


/// <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 {nameof(ContactMergeEvent)} {{\n");
sb.Append($" {nameof(AppId)}: ").Append(AppId).Append('\n');
sb.Append($" {nameof(AcceptedTime)}: ").Append(AcceptedTime).Append('\n');
sb.Append($" {nameof(EventTime)}: ").Append(EventTime).Append('\n');
sb.Append($" {nameof(ProjectId)}: ").Append(ProjectId).Append('\n');
sb.Append($" {nameof(MessageMetadata)}: ").Append(MessageMetadata).Append('\n');
sb.Append($" {nameof(CorrelationId)}: ").Append(CorrelationId).Append('\n');
sb.Append($" {nameof(ContactMergeNotification)}: ").Append(ContactMergeNotification).Append('\n');
sb.Append("}\n");
return sb.ToString();
}
}
}
Loading

0 comments on commit 3b142be

Please sign in to comment.