-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathSopranoProvider.cs
More file actions
87 lines (81 loc) · 3.59 KB
/
Copy pathSopranoProvider.cs
File metadata and controls
87 lines (81 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
using System.Text.Json;
using System.Text.RegularExpressions;
namespace Epp.Otp.Providers;
public sealed class SopranoProvider : IProviderAdapter
{
private const string DefaultVoiceLanguage = "en-US";
private const int VoiceGender = 1;
private const int VoiceLoop = 2;
public ProviderManifest Manifest { get; } = new(
Id: "soprano",
Auth: new AuthConfig("oauth"),
ResponseMapping: new Dictionary<string, Outcome>
{
["ENROUTE"] = Outcome.Continue,
["ACCEPTED"] = Outcome.Continue,
["SUBMITTED"] = Outcome.Continue,
["SENT"] = Outcome.Continue,
["DELIVERED"] = Outcome.Continue,
["QUEUED"] = Outcome.Continue,
["FAILED"] = Outcome.Fail,
["REJECTED"] = Outcome.Fail,
["FILTERED"] = Outcome.Fail,
["BLOCKED"] = Outcome.Block,
["default"] = Outcome.Fail,
});
public ProviderHttpRequest BuildRequest(string channel, string endpoint, DispatchRequest dispatch, ProviderCredential credential, IEnv env)
{
var headers = new Dictionary<string, string>
{
["Content-Type"] = "application/json",
["Accept"] = "application/json",
["Authorization"] = "Bearer " + credential.AccessToken,
};
var body = new Dictionary<string, object?>
{
["destination"] = dispatch.Destination.TrimStart('+'),
["messageTypes"] = new[] { channel == "voice" ? "voice" : "sms" },
["correlationId"] = dispatch.CorrelationId ?? dispatch.MessageId,
["shutterMode"] = false,
};
if (channel == "voice")
{
var message = dispatch.Message ?? string.Empty;
var passcode = Regex.Match(message, "[0-9]{6}");
if (!passcode.Success)
throw new InvalidOperationException("voice message does not contain a six-digit passcode");
body["voice"] = new
{
text2voice = new
{
beforePasswordText = message[..passcode.Index],
password = passcode.Value,
afterPasswordText = message[(passcode.Index + passcode.Length)..],
language = string.IsNullOrWhiteSpace(dispatch.Locale) ? DefaultVoiceLanguage : dispatch.Locale,
gender = VoiceGender,
loop = VoiceLoop,
},
};
}
else
{
body["text"] = dispatch.Message;
}
return new ProviderHttpRequest(endpoint, "POST", headers, JsonSerializer.Serialize(body));
}
public ParsedResponse ParseResponse(int httpStatus, bool ok, JsonElement json)
{
var payload = json.ValueKind == JsonValueKind.Array && json.GetArrayLength() > 0 ? json[0] : json;
string? id = null, status = null;
if (payload.ValueKind == JsonValueKind.Object)
{
if (payload.TryGetProperty("id", out var idElement)) id = idElement.ToString();
else if (payload.TryGetProperty("messageId", out var messageIdElement)) id = messageIdElement.ToString();
if (!payload.TryGetProperty("status", out var statusElement) || statusElement.ValueKind == JsonValueKind.Null)
payload.TryGetProperty("state", out statusElement);
if (statusElement.ValueKind == JsonValueKind.String) status = statusElement.GetString();
}
status = string.IsNullOrWhiteSpace(status) ? "UNKNOWN" : status.ToUpperInvariant();
return new ParsedResponse(ok, httpStatus, id, status);
}
}