Skip to content

Commit 28f4278

Browse files
authored
Merge pull request #27 from teesofttech/feature/9-insights-api
Implement Insights API support
2 parents ffea699 + 5126ad3 commit 28f4278

16 files changed

Lines changed: 519 additions & 11 deletions

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ var token = await client.Tokens.SendAsync(new SendTokenRequest
8888
});
8989
```
9090

91+
Check account balance:
92+
93+
```csharp
94+
var balance = await client.Insights.GetBalanceAsync();
95+
```
96+
9197
## Examples
9298

9399
Run the examples project after setting your Termii API key:

docs/API_COVERAGE.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,17 @@ The Termii docs describe a REST/JSON API and state that each account has its own
4646
| Messaging | Send WhatsApp conversational message | POST | `/api/sms/send` | JSON body | `TermiiClient.Messaging` | Implemented | #7, PR #21 | Unit tests added |
4747
| Messaging | Send bulk message | POST | `/api/sms/send/bulk` | JSON body | `TermiiClient.Messaging` | Implemented | #7, PR #21 | Unit tests added |
4848
| Messaging | Send via Number API | POST | `/api/sms/number/send` | JSON body | `TermiiClient.Numbers` | Implemented | #5, PR #25 | Unit tests added |
49-
| Token | Send OTP token | POST | `/api/sms/otp/send` | JSON body | `TermiiClient.Tokens` | In progress | #4 | Unit tests added |
50-
| Token | Verify OTP token | POST | `/api/sms/otp/verify` | JSON body | `TermiiClient.Tokens` | In progress | #4 | Unit tests added |
51-
| Token | Generate in-app OTP token | POST | `/api/sms/otp/generate` | JSON body | `TermiiClient.Tokens` | In progress | #4 | Unit tests added |
52-
| Token | Send voice OTP | POST | `/api/sms/otp/send/voice` | JSON body | `TermiiClient.Tokens` | In progress | #4 | Unit tests added |
53-
| Token | Send voice call token | POST | `/api/sms/otp/call` | JSON body | `TermiiClient.Tokens` | In progress | #4 | Unit tests added |
54-
| Token | Send email OTP token | POST | `/api/email/otp/send` | JSON body | `TermiiClient.Tokens` | In progress | #4 | Unit tests added |
55-
| Token | Send WhatsApp OTP token | POST | `/api/sms/send` | JSON body with `channel=whatsapp_otp` | `TermiiClient.Tokens` | In progress | #4 | Unit tests added |
56-
| Insights | Get balance | GET | `/api/get-balance` | Query | `TermiiClient.Insights` | Planned | #9 | Planned unit + optional integration |
57-
| Insights | Search DND/number status | GET | `/api/check/dnd` | Query | `TermiiClient.Insights` | Planned | #9 | Planned unit + optional integration |
58-
| Insights | Query number intelligence/status | GET | `/api/insight/number/query` | Query | `TermiiClient.Insights` | Planned | #9 | Planned unit + optional integration |
59-
| Insights | Fetch message inbox/history | GET | `/api/sms/inbox` | Query | `TermiiClient.Insights` | Planned | #9 | Planned unit + optional integration |
49+
| Token | Send OTP token | POST | `/api/sms/otp/send` | JSON body | `TermiiClient.Tokens` | Implemented | #4, PR #26 | Unit tests added |
50+
| Token | Verify OTP token | POST | `/api/sms/otp/verify` | JSON body | `TermiiClient.Tokens` | Implemented | #4, PR #26 | Unit tests added |
51+
| Token | Generate in-app OTP token | POST | `/api/sms/otp/generate` | JSON body | `TermiiClient.Tokens` | Implemented | #4, PR #26 | Unit tests added |
52+
| Token | Send voice OTP | POST | `/api/sms/otp/send/voice` | JSON body | `TermiiClient.Tokens` | Implemented | #4, PR #26 | Unit tests added |
53+
| Token | Send voice call token | POST | `/api/sms/otp/call` | JSON body | `TermiiClient.Tokens` | Implemented | #4, PR #26 | Unit tests added |
54+
| Token | Send email OTP token | POST | `/api/email/otp/send` | JSON body | `TermiiClient.Tokens` | Implemented | #4, PR #26 | Unit tests added |
55+
| Token | Send WhatsApp OTP token | POST | `/api/sms/send` | JSON body with `channel=whatsapp_otp` | `TermiiClient.Tokens` | Implemented | #4, PR #26 | Unit tests added |
56+
| Insights | Get balance | GET | `/api/get-balance` | Query | `TermiiClient.Insights` | In progress | #9 | Unit tests added |
57+
| Insights | Search DND/number status | GET | `/api/check/dnd` | Query | `TermiiClient.Insights` | In progress | #9 | Unit tests added |
58+
| Insights | Query number intelligence/status | GET | `/api/insight/number/query` | Query | `TermiiClient.Insights` | In progress | #9 | Unit tests added |
59+
| Insights | Fetch message inbox/history | GET | `/api/sms/inbox` | Query | `TermiiClient.Insights` | In progress | #9 | Unit tests added |
6060
| Insights | Fetch message analytics/history | GET | `/api/sms/history/analytics` | Query | `TermiiClient.Insights` | Needs verification | #9 | Planned unit + optional integration |
6161

6262
## Deferred Coverage
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace Termii;
2+
3+
public sealed class CheckDndRequest
4+
{
5+
public string PhoneNumber { get; set; } = string.Empty;
6+
7+
internal string ToPath()
8+
{
9+
TermiiRequestValidation.Required(PhoneNumber, nameof(PhoneNumber));
10+
11+
var query = new List<string>();
12+
TermiiInsightsQueryString.AddIfPresent(query, "phone_number", PhoneNumber);
13+
14+
return TermiiInsightsQueryString.Append("/api/check/dnd", query);
15+
}
16+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System.Text.Json;
2+
using System.Text.Json.Serialization;
3+
4+
namespace Termii;
5+
6+
public sealed class CheckDndResponse
7+
{
8+
[JsonPropertyName("number")]
9+
public string? Number { get; set; }
10+
11+
[JsonPropertyName("phone_number")]
12+
public string? PhoneNumber { get; set; }
13+
14+
[JsonPropertyName("status")]
15+
public string? Status { get; set; }
16+
17+
[JsonPropertyName("network")]
18+
public string? Network { get; set; }
19+
20+
[JsonPropertyName("dnd_active")]
21+
public bool? DndActive { get; set; }
22+
23+
[JsonExtensionData]
24+
public Dictionary<string, JsonElement>? AdditionalData { get; set; }
25+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Text.Json;
2+
using System.Text.Json.Serialization;
3+
4+
namespace Termii;
5+
6+
public sealed class GetBalanceResponse
7+
{
8+
[JsonPropertyName("user")]
9+
public string? User { get; set; }
10+
11+
[JsonPropertyName("balance")]
12+
public decimal? Balance { get; set; }
13+
14+
[JsonPropertyName("currency")]
15+
public string? Currency { get; set; }
16+
17+
[JsonExtensionData]
18+
public Dictionary<string, JsonElement>? AdditionalData { get; set; }
19+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
namespace Termii;
2+
3+
public sealed class GetMessageHistoryRequest
4+
{
5+
public int? Page { get; set; }
6+
7+
public int? Size { get; set; }
8+
9+
public string? Sender { get; set; }
10+
11+
public string? Receiver { get; set; }
12+
13+
public string? MessageId { get; set; }
14+
15+
public string? Status { get; set; }
16+
17+
public string? FromDate { get; set; }
18+
19+
public string? ToDate { get; set; }
20+
21+
internal string ToPath()
22+
{
23+
var query = new List<string>();
24+
TermiiInsightsQueryString.AddIfPresent(query, "page", Page);
25+
TermiiInsightsQueryString.AddIfPresent(query, "size", Size);
26+
TermiiInsightsQueryString.AddIfPresent(query, "sender", Sender);
27+
TermiiInsightsQueryString.AddIfPresent(query, "receiver", Receiver);
28+
TermiiInsightsQueryString.AddIfPresent(query, "message_id", MessageId);
29+
TermiiInsightsQueryString.AddIfPresent(query, "status", Status);
30+
TermiiInsightsQueryString.AddIfPresent(query, "from", FromDate);
31+
TermiiInsightsQueryString.AddIfPresent(query, "to", ToDate);
32+
33+
return TermiiInsightsQueryString.Append("/api/sms/inbox", query);
34+
}
35+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace Termii;
2+
3+
public interface ITermiiInsightsClient
4+
{
5+
Task<GetBalanceResponse> GetBalanceAsync(CancellationToken cancellationToken = default);
6+
7+
Task<CheckDndResponse> CheckDndAsync(
8+
CheckDndRequest request,
9+
CancellationToken cancellationToken = default);
10+
11+
Task<QueryNumberResponse> QueryNumberAsync(
12+
QueryNumberRequest request,
13+
CancellationToken cancellationToken = default);
14+
15+
Task<MessageHistoryResponse> GetMessageHistoryAsync(
16+
GetMessageHistoryRequest? request = null,
17+
CancellationToken cancellationToken = default);
18+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System.Text.Json;
2+
using System.Text.Json.Serialization;
3+
4+
namespace Termii;
5+
6+
public sealed class MessageHistoryRecord
7+
{
8+
[JsonPropertyName("message_id")]
9+
public string? MessageId { get; set; }
10+
11+
[JsonPropertyName("sender")]
12+
public string? Sender { get; set; }
13+
14+
[JsonPropertyName("receiver")]
15+
public string? Receiver { get; set; }
16+
17+
[JsonPropertyName("message")]
18+
public string? Message { get; set; }
19+
20+
[JsonPropertyName("amount")]
21+
public decimal? Amount { get; set; }
22+
23+
[JsonPropertyName("reroute")]
24+
public int? Reroute { get; set; }
25+
26+
[JsonPropertyName("status")]
27+
public string? Status { get; set; }
28+
29+
[JsonPropertyName("sms_type")]
30+
public string? SmsType { get; set; }
31+
32+
[JsonPropertyName("send_by")]
33+
public string? SentBy { get; set; }
34+
35+
[JsonPropertyName("created_at")]
36+
public string? CreatedAt { get; set; }
37+
38+
[JsonPropertyName("updated_at")]
39+
public string? UpdatedAt { get; set; }
40+
41+
[JsonExtensionData]
42+
public Dictionary<string, JsonElement>? AdditionalData { get; set; }
43+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System.Text.Json;
2+
using System.Text.Json.Serialization;
3+
4+
namespace Termii;
5+
6+
public sealed class MessageHistoryResponse
7+
{
8+
[JsonPropertyName("content")]
9+
public IReadOnlyList<MessageHistoryRecord> Content { get; set; } = Array.Empty<MessageHistoryRecord>();
10+
11+
[JsonPropertyName("totalElements")]
12+
public int? TotalElements { get; set; }
13+
14+
[JsonPropertyName("totalPages")]
15+
public int? TotalPages { get; set; }
16+
17+
[JsonPropertyName("last")]
18+
public bool? Last { get; set; }
19+
20+
[JsonPropertyName("size")]
21+
public int? Size { get; set; }
22+
23+
[JsonPropertyName("number")]
24+
public int? Number { get; set; }
25+
26+
[JsonPropertyName("first")]
27+
public bool? First { get; set; }
28+
29+
[JsonPropertyName("empty")]
30+
public bool? Empty { get; set; }
31+
32+
[JsonExtensionData]
33+
public Dictionary<string, JsonElement>? AdditionalData { get; set; }
34+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace Termii;
2+
3+
public sealed class QueryNumberRequest
4+
{
5+
public string PhoneNumber { get; set; } = string.Empty;
6+
7+
public string? CountryCode { get; set; }
8+
9+
internal string ToPath()
10+
{
11+
TermiiRequestValidation.Required(PhoneNumber, nameof(PhoneNumber));
12+
13+
var query = new List<string>();
14+
TermiiInsightsQueryString.AddIfPresent(query, "phone_number", PhoneNumber);
15+
TermiiInsightsQueryString.AddIfPresent(query, "country_code", CountryCode);
16+
17+
return TermiiInsightsQueryString.Append("/api/insight/number/query", query);
18+
}
19+
}

0 commit comments

Comments
 (0)