Skip to content

Commit

Permalink
Refactor/unify oneofs (#68)
Browse files Browse the repository at this point in the history
* refactor(sms): inbounds as IInbound

* refactor(verification): make specific request by type

Update report response model with new data

* refactor(verification): update models to split verification status and report responses

* fix: rename flashCall to flashcall

* chore: remove obsolete test

* chore(sms): remove Type prop, add serde based on json value
  • Loading branch information
Dovchik authored May 6, 2024
1 parent 8bd781b commit b737280
Show file tree
Hide file tree
Showing 24 changed files with 602 additions and 242 deletions.
87 changes: 87 additions & 0 deletions src/Sinch/SMS/Inbounds/BinaryInbound.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using System.Text.Json.Serialization;

namespace Sinch.SMS.Inbounds
{
public class BinaryInbound : IInbound
{
/// <summary>
/// The ID of this inbound message.
/// </summary>
#if NET7_0_OR_GREATER
public required string Id { get; set; }

#else
public string Id { get; set; } = null!;

#endif

/// <summary>
/// The phone number that sent the message.
/// </summary>
#if NET7_0_OR_GREATER
public required string From { get; set; }
#else
public string From { get; set; } = null!;
#endif


/// <summary>
/// The Sinch phone number or short code to which the message was sent.
/// </summary>
#if NET7_0_OR_GREATER
public required string To { get; set; }
#else
public string To { get; set; } = null!;
#endif

/// <summary>
/// The message content Base64 encoded. <br/><br/>
/// Max 140 bytes together with udh.
/// </summary>
#if NET7_0_OR_GREATER
public required string Body { get; set; }
#else
public string Body { get; set; } = null!;
#endif


/// <summary>
/// If this inbound message is in response to a previously sent message that contained a client reference,
/// then this field contains that client reference.<br /><br />
/// Utilizing this feature requires additional setup on your account.
/// Contact your <see href="https://dashboard.sinch.com/settings/account-details">account manager</see>
/// to enable this feature.
/// </summary>
public string? ClientReference { get; set; }

/// <summary>
/// The MCC/MNC of the sender's operator if known.
/// </summary>
public string? OperatorId { get; set; }

/// <summary>
/// When the message left the originating device. Only available if provided by operator.
/// </summary>
public DateTime? SendAt { get; set; }

/// <summary>
/// When the system received the message.
/// </summary>
#if NET7_0_OR_GREATER
public required DateTime ReceivedAt { get; set; }
#else
public DateTime ReceivedAt { get; set; }
#endif

/// <summary>
/// The UDH header of a binary message HEX encoded. Max 140 bytes together with body.
/// </summary>

#if NET7_0_OR_GREATER
public required string Udh { get; set; }
#else
public string Udh { get; set; } = null!;
#endif
}
}
54 changes: 54 additions & 0 deletions src/Sinch/SMS/Inbounds/IInbound.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Sinch.Core;

namespace Sinch.SMS.Inbounds
{
/// <summary>
/// Marker interface for Inbound types
/// </summary>
[JsonInterfaceConverter(typeof(InboundJsonConverter))]
public interface IInbound
{
}

public class InboundJsonConverter : JsonConverter<IInbound>
{
public override IInbound? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var elem = JsonElement.ParseValue(ref reader);
var descriptor = elem.EnumerateObject().FirstOrDefault(x => x.Name == "type");
var method = descriptor.Value.GetString();

if (SmsType.Text.Value == method)
return elem.Deserialize<SmsInbound>(options);

if (SmsType.Binary.Value == method)
return elem.Deserialize<BinaryInbound>(options);

throw new JsonException(
$"Failed to match verification method object, got prop `{descriptor.Name}` with value `{method}`");
}

public override void Write(Utf8JsonWriter writer, IInbound value, JsonSerializerOptions options)
{
var type = value.GetType();
if (type == typeof(SmsInbound))
{
JsonSerializer.Serialize(writer, value as SmsInbound, options);
}

if (type == typeof(BinaryInbound))
{
JsonSerializer.Serialize(writer, value as BinaryInbound, options);
}
else
{
throw new InvalidOperationException(
$"Cannot serialize unknown type of {nameof(IInbound)}");
}
}
}
}
10 changes: 5 additions & 5 deletions src/Sinch/SMS/Inbounds/Inbounds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ Task<ListInboundsResponse> List(ListInboundsRequest request,
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
IAsyncEnumerable<Inbound> ListAuto(ListInboundsRequest request, CancellationToken cancellationToken = default);
IAsyncEnumerable<IInbound> ListAuto(ListInboundsRequest request, CancellationToken cancellationToken = default);

/// <summary>
/// This operation retrieves a specific inbound message with the provided inbound ID.
/// </summary>
/// <param name="inboundId">The Inbound ID found when listing inbound messages</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<Inbound> Get(string inboundId, CancellationToken cancellationToken = default);
Task<IInbound> Get(string inboundId, CancellationToken cancellationToken = default);
}

public class Inbounds : ISinchSmsInbounds
Expand All @@ -62,7 +62,7 @@ public Task<ListInboundsResponse> List(ListInboundsRequest request, Cancellation
return _http.Send<ListInboundsResponse>(uri, HttpMethod.Get, cancellationToken);
}

public async IAsyncEnumerable<Inbound> ListAuto(ListInboundsRequest request, [EnumeratorCancellation] CancellationToken cancellationToken = default)
public async IAsyncEnumerable<IInbound> ListAuto(ListInboundsRequest request, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
_logger?.LogDebug("Auto listing inbounds...");
bool isLastPage;
Expand All @@ -83,11 +83,11 @@ public async IAsyncEnumerable<Inbound> ListAuto(ListInboundsRequest request, [En
}


public Task<Inbound> Get(string inboundId, CancellationToken cancellationToken = default)
public Task<IInbound> Get(string inboundId, CancellationToken cancellationToken = default)
{
var uri = new Uri(_baseAddress, $"xms/v1/{_projectOrServicePlanId}/inbounds/{inboundId}");
_logger?.LogDebug("Getting inbound with {id}", inboundId);
return _http.Send<Inbound>(uri, HttpMethod.Get, cancellationToken);
return _http.Send<IInbound>(uri, HttpMethod.Get, cancellationToken);
}
}
}
2 changes: 1 addition & 1 deletion src/Sinch/SMS/Inbounds/List/ListInboundsResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ public sealed class ListInboundsResponse

public int Count { get; set; }

public IEnumerable<Inbound>? Inbounds { get; set; }
public IEnumerable<IInbound>? Inbounds { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,44 @@

namespace Sinch.SMS.Inbounds
{
public class Inbound
public class SmsInbound : IInbound
{
/// <summary>
/// The ID of this inbound message.
/// </summary>
public string? Id { get; set; }
#if NET7_0_OR_GREATER
public required string Id { get; set; }

/// <summary>
/// The object type.
/// </summary>
public SmsType? Type { get; set; }
#else
public string Id { get; set; } = null!;

#endif

/// <summary>
/// The phone number that sent the message.
/// </summary>
public string? From { get; set; }
#if NET7_0_OR_GREATER
public required string From { get; set; }
#else
public string From { get; set; } = null!;
#endif


/// <summary>
/// The Sinch phone number or short code to which the message was sent.
/// </summary>
public string? To { get; set; }
#if NET7_0_OR_GREATER
public required string To { get; set; }
#else
public string To { get; set; } = null!;
#endif

#if NET7_0_OR_GREATER
public required string Body { get; set; }
#else
public string Body { get; set; } = null!;
#endif

/// <summary>
/// The message body. Base64 encoded if type is mo_binary.
/// </summary>
public string? Body { get; set; }

/// <summary>
/// If this inbound message is in response to a previously sent message that contained a client reference,
Expand All @@ -46,11 +58,15 @@ public class Inbound
/// <summary>
/// When the message left the originating device. Only available if provided by operator.
/// </summary>
public DateTime SendAt { get; set; }
public DateTime? SendAt { get; set; }

/// <summary>
/// When the system received the message.
/// </summary>
#if NET7_0_OR_GREATER
public required DateTime ReceivedAt { get; set; }
#else
public DateTime ReceivedAt { get; set; }
#endif
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Sinch.Verification.Common;

namespace Sinch.Verification.Report.Response
namespace Sinch.Verification.Common
{
public class PriceBase
{
Expand Down
4 changes: 2 additions & 2 deletions src/Sinch/Verification/Common/VerificationMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Sinch.Verification.Common
public record VerificationMethod(string Value) : EnumRecord(Value)
{
public static readonly VerificationMethod Sms = new("sms");
public static readonly VerificationMethod FlashCall = new("flashCall");
public static readonly VerificationMethod FlashCall = new("flashcall");
public static readonly VerificationMethod Callout = new("callout");
}

Expand All @@ -23,7 +23,7 @@ public record VerificationMethod(string Value) : EnumRecord(Value)
public record VerificationMethodEx(string Value) : EnumRecord(Value)
{
public static readonly VerificationMethodEx Sms = new("sms");
public static readonly VerificationMethodEx FlashCall = new("flashCall");
public static readonly VerificationMethodEx FlashCall = new("flashcall");
public static readonly VerificationMethodEx Callout = new("callout");
public static readonly VerificationMethodEx Seamless = new("seamless");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Text.Json.Serialization;
using Sinch.Verification.Common;

namespace Sinch.Verification.Report.Request
Expand All @@ -10,6 +11,7 @@ public class ReportFlashCallVerificationRequest : VerifyReportRequest
/// <summary>
/// A configuration object containing settings specific to FlashCall verifications.
/// </summary>
[JsonPropertyName("flashcall")]
#if NET7_0_OR_GREATER
public required FlashCall FlashCall { get; set; }
#else
Expand All @@ -19,7 +21,6 @@ public class ReportFlashCallVerificationRequest : VerifyReportRequest

public class FlashCall
{

/// <summary>
/// The caller ID of the FlashCall.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
using Sinch.Verification.Common;

namespace Sinch.Verification.Report.Response
{
public class ReportCalloutVerificationResponse : VerificationReportResponseBase, IVerificationReportResponse
{
/// <summary>
/// Shows whether the call is complete or not.
/// </summary>
public bool CallComplete { get; set; }
public override VerificationMethod Method { get; protected set; } = VerificationMethod.Callout;

/// <summary>
/// Prices associated with this verification
/// Shows whether the call is complete or not.
/// </summary>
public Price? Price { get; set; }
public bool? CallComplete { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
using System.Text.Json.Serialization;
using Sinch.Verification.Common;

namespace Sinch.Verification.Report.Response
{
public class ReportFlashCallVerificationResponse : VerificationReportResponseBase, IVerificationReportResponse
{
/// <summary>
/// Free text that the client is sending, used to show if the call/SMS was intercepted or not.
/// </summary>
public Source? Source { get; set; }
[JsonInclude]
public override VerificationMethod Method { get; protected set; } = VerificationMethod.FlashCall;

/// <summary>
/// Prices associated with this verification
/// Shows whether the call is complete or not.
/// </summary>
public Price? Price { get; set; }
public bool? CallComplete { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,6 @@ namespace Sinch.Verification.Report.Response
{
public class ReportSmsVerificationResponse : VerificationReportResponseBase, IVerificationReportResponse
{
/// <summary>
/// Free text that the client is sending, used to show if the call/SMS was intercepted or not.
/// </summary>
public Source? Source { get; set; }

/// <summary>
/// Prices associated with this verification
/// </summary>
public PriceBase? Price { get; set; }
public override VerificationMethod Method { get; protected set; } = VerificationMethod.Sms;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public abstract class VerificationReportResponseBase
/// <summary>
/// The method of the verification request.
/// </summary>
public VerificationMethod? Method { get; set; }
[JsonInclude]
public abstract VerificationMethod Method { get; protected set; }

/// <summary>
/// The status of the verification request.
Expand All @@ -32,6 +33,16 @@ public abstract class VerificationReportResponseBase
/// The reference ID that was optionally passed together with the verification request.
/// </summary>
public string? Reference { get; set; }

/// <summary>
/// Free text that the client is sending, used to show if the call/SMS was intercepted or not.
/// </summary>
public Source? Source { get; set; }

/// <summary>
/// Specifies the type of endpoint that will be verified and the particular endpoint. number is currently the only supported endpoint type.
/// </summary>
public Identity? Identity { get; set; }
}

[JsonConverter(typeof(VerificationReportResponseConverter))]
Expand Down
Loading

0 comments on commit b737280

Please sign in to comment.