Skip to content

Commit 061fcae

Browse files
committed
Return message identifier from send/reply
This can be useful to keep track of conversations with the user.
1 parent d6e35dc commit 061fcae

File tree

5 files changed

+83
-18
lines changed

5 files changed

+83
-18
lines changed

src/Tests/WhatsAppClientTests.cs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,49 @@ public async Task SendsMessageAsync()
2626
{
2727
var (configuration, client) = Initialize();
2828

29-
await client.SendAsync(configuration["SendFrom"]!, configuration["SendTo"]!, "Hi there!");
29+
var id = await client.SendAsync(configuration["SendFrom"]!, configuration["SendTo"]!, "Hi there!");
30+
31+
Assert.NotNull(id);
32+
Assert.NotEmpty(id);
33+
}
34+
35+
[SecretsFact("Meta:VerifyToken", "SendFrom", "SendTo")]
36+
public async Task ReactToSentMessageAsync()
37+
{
38+
var (configuration, client) = Initialize();
39+
40+
var id = await client.SendAsync(configuration["SendFrom"]!, configuration["SendTo"]!, "Hi there!");
41+
42+
Assert.NotNull(id);
43+
Assert.NotEmpty(id);
44+
45+
await client.ReactAsync(configuration["SendFrom"]!, configuration["SendTo"]!, id, "🙏");
46+
}
47+
48+
[SecretsFact("Meta:VerifyToken", "SendFrom", "SendTo")]
49+
public async Task ReplyToSentMessageAsync()
50+
{
51+
var (configuration, client) = Initialize();
52+
var from = configuration["SendFrom"]!;
53+
var to = configuration["SendTo"]!;
54+
55+
var id = await client.SendAsync(configuration["SendFrom"]!, configuration["SendTo"]!, "Hi there!");
56+
57+
Assert.NotNull(id);
58+
Assert.NotEmpty(id);
59+
60+
var reply = await client.ReplyAsync(
61+
new ContentMessage(id,
62+
new Service(from, from),
63+
new User(to, to),
64+
DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
65+
new TextContent("Hi there!")),
66+
"Reply here!");
67+
68+
Assert.NotNull(reply);
69+
Assert.NotEmpty(reply);
70+
71+
Assert.NotEqual(id, reply);
3072
}
3173

3274
[SecretsFact("Meta:VerifyToken", "SendFrom", "SendTo")]

src/WhatsApp/IWhatsAppClient.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ public interface IWhatsAppClient
2222
/// </summary>
2323
/// <param name="numberId">The phone identifier to send the message from, which must be configured via <see cref="MetaOptions.Numbers"/>.</param>
2424
/// <param name="payload">The message payload.</param>
25-
/// <returns>Whether the message was successfully sent.</returns>
25+
/// <returns>The message id that was sent/reacted/marked, if any.</returns>
2626
/// <see cref="https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages"/>
2727
/// <exception cref="ArgumentException">The number <paramref name="numberId"/> is not registered in <see cref="MetaOptions"/>.</exception>
2828
/// <exception cref="HttpRequestException">The HTTP request failed. Exception message contains the error response body from WhatsApp.</exception>
2929
[Description(nameof(Devlooped) + nameof(WhatsApp) + nameof(IWhatsAppClient) + nameof(SendAsync))]
30-
Task SendAsync(string numberId, object payload);
30+
Task<string?> SendAsync(string numberId, object payload);
3131
}

src/WhatsApp/WhatsAppClient.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public HttpClient CreateHttp(string numberId)
4141
}
4242

4343
/// <inheritdoc />
44-
public async Task SendAsync(string numberId, object payload)
44+
public async Task<string?> SendAsync(string numberId, object payload)
4545
{
4646
if (!options.Numbers.TryGetValue(numberId, out var token))
4747
throw new ArgumentException($"The number '{numberId}' is not registered in the options.", nameof(numberId));
@@ -59,5 +59,9 @@ public async Task SendAsync(string numberId, object payload)
5959
logger.LogError("Failed to send WhatsApp message from {From}: {Error}", numberId, error);
6060
throw new HttpRequestException(error, null, result.StatusCode);
6161
}
62+
63+
var response = await result.Content.ReadFromJsonAsync(WhatsAppSerializerContext.Default.SendResponse);
64+
65+
return response?.Messages.FirstOrDefault()?.Id;
6266
}
6367
}

src/WhatsApp/WhatsAppClientExtensions.cs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ public static Task ReactAsync(this IWhatsAppClient client, string from, string t
7373
/// <param name="client">The WhatsApp client.</param>
7474
/// <param name="message">The message to reply to.</param>
7575
/// <param name="reply">The text message to respond with.</param>
76-
public static Task ReplyAsync(this IWhatsAppClient client, UserMessage message, string reply)
76+
/// <returns>The identifier of the reply.</returns>
77+
public static Task<string?> ReplyAsync(this IWhatsAppClient client, UserMessage message, string reply)
7778
=> client.SendAsync(message.To.Id, new
7879
{
7980
messaging_product = "whatsapp",
@@ -98,7 +99,8 @@ public static Task ReplyAsync(this IWhatsAppClient client, UserMessage message,
9899
/// <param name="message">The message to reply to.</param>
99100
/// <param name="reply">The text message to respond with.</param>
100101
/// <param name="button">Interactive button for users to reply.</param>
101-
public static Task ReplyAsync(this IWhatsAppClient client, UserMessage message, string reply, Button button)
102+
/// <returns>The identifier of the reply message.</returns>
103+
public static Task<string?> ReplyAsync(this IWhatsAppClient client, UserMessage message, string reply, Button button)
102104
=> client.SendAsync(message.To.Id, new
103105
{
104106
messaging_product = "whatsapp",
@@ -135,7 +137,8 @@ public static Task ReplyAsync(this IWhatsAppClient client, UserMessage message,
135137
/// <param name="reply">The text message to respond with.</param>
136138
/// <param name="button1">Interactive button for a user choice.</param>
137139
/// <param name="button2">Interactive button for a user choice.</param>
138-
public static Task ReplyAsync(this IWhatsAppClient client, UserMessage message, string reply, Button button1, Button button2)
140+
/// <returns>The identifier of the reply message.</returns>
141+
public static Task<string?> ReplyAsync(this IWhatsAppClient client, UserMessage message, string reply, Button button1, Button button2)
139142
=> client.SendAsync(message.To.Id, new
140143
{
141144
messaging_product = "whatsapp",
@@ -174,7 +177,8 @@ public static Task ReplyAsync(this IWhatsAppClient client, UserMessage message,
174177
/// <param name="button1">Interactive button for a user choice.</param>
175178
/// <param name="button2">Interactive button for a user choice.</param>
176179
/// <param name="button3">Interactive button for a user choice.</param>
177-
public static Task ReplyAsync(this IWhatsAppClient client, UserMessage message, string reply, Button button1, Button button2, Button button3)
180+
/// <returns>The identifier of the reply message.</returns>
181+
public static Task<string?> ReplyAsync(this IWhatsAppClient client, UserMessage message, string reply, Button button1, Button button2, Button button3)
178182
=> client.SendAsync(message.To.Id, new
179183
{
180184
messaging_product = "whatsapp",
@@ -211,7 +215,8 @@ public static Task ReplyAsync(this IWhatsAppClient client, UserMessage message,
211215
/// <param name="client">The WhatsApp client.</param>
212216
/// <param name="reaction">The reaction from the user.</param>
213217
/// <param name="reply">The text message to respond with.</param>
214-
public static Task ReplyAsync(this IWhatsAppClient client, ReactionMessage message, string reply)
218+
/// <returns>The identifier of the reply message.</returns>
219+
public static Task<string?> ReplyAsync(this IWhatsAppClient client, ReactionMessage message, string reply)
215220
=> client.SendAsync(message.To.Id, new
216221
{
217222
messaging_product = "whatsapp",
@@ -235,7 +240,8 @@ public static Task ReplyAsync(this IWhatsAppClient client, ReactionMessage messa
235240
/// <param name="client">The WhatsApp client.</param>
236241
/// <param name="to">The originating user to send a message to.</param>
237242
/// <param name="message">The text message to send.</param>
238-
public static Task SendAsync(this IWhatsAppClient client, Message to, string message)
243+
/// <returns>The identifier of the sent message.</returns>
244+
public static Task<string?> SendAsync(this IWhatsAppClient client, Message to, string message)
239245
=> SendAsync(client, to.To.Id, to.From.Number, message);
240246

241247
/// <summary>
@@ -245,7 +251,8 @@ public static Task SendAsync(this IWhatsAppClient client, Message to, string mes
245251
/// <param name="to">The originating user to send a message to.</param>
246252
/// <param name="message">The text message to send.</param>
247253
/// <param name="button">Interactive button for users to reply.</param>
248-
public static Task SendAsync(this IWhatsAppClient client, Message to, string message, Button button)
254+
/// <returns>The identifier of the sent message.</returns>
255+
public static Task<string?> SendAsync(this IWhatsAppClient client, Message to, string message, Button button)
249256
=> SendAsync(client, to.To.Id, to.From.Number, message, button);
250257

251258
/// <summary>
@@ -256,7 +263,8 @@ public static Task SendAsync(this IWhatsAppClient client, Message to, string mes
256263
/// <param name="message">The text message to send.</param>
257264
/// <param name="button1">Interactive button for a user choice.</param>
258265
/// <param name="button2">Interactive button for a user choice.</param>
259-
public static Task SendAsync(this IWhatsAppClient client, Message to, string message, Button button1, Button button2)
266+
/// <returns>The identifier of the sent message.</returns>
267+
public static Task<string?> SendAsync(this IWhatsAppClient client, Message to, string message, Button button1, Button button2)
260268
=> SendAsync(client, to.To.Id, to.From.Number, message, button1, button2);
261269

262270
/// <summary>
@@ -268,7 +276,8 @@ public static Task SendAsync(this IWhatsAppClient client, Message to, string mes
268276
/// <param name="button1">Interactive button for a user choice.</param>
269277
/// <param name="button2">Interactive button for a user choice.</param>
270278
/// <param name="button3">Interactive button for a user choice.</param>
271-
public static Task SendAsync(this IWhatsAppClient client, Message to, string message, Button button1, Button button2, Button button3)
279+
/// <returns>The identifier of the sent message.</returns>
280+
public static Task<string?> SendAsync(this IWhatsAppClient client, Message to, string message, Button button1, Button button2, Button button3)
272281
=> SendAsync(client, to.To.Id, to.From.Number, message, button1, button2, button3);
273282

274283
/// <summary>
@@ -278,7 +287,8 @@ public static Task SendAsync(this IWhatsAppClient client, Message to, string mes
278287
/// <param name="from">The service number to send the message through.</param>
279288
/// <param name="to">The user phone number to send the message to.</param>
280289
/// <param name="message">The text message to send.</param>
281-
public static Task SendAsync(this IWhatsAppClient client, string from, string to, string message)
290+
/// <returns>The identifier of the sent message.</returns>
291+
public static Task<string?> SendAsync(this IWhatsAppClient client, string from, string to, string message)
282292
=> client.SendAsync(from, new
283293
{
284294
messaging_product = "whatsapp",
@@ -300,7 +310,8 @@ public static Task SendAsync(this IWhatsAppClient client, string from, string to
300310
/// <param name="to">The user phone number to send the message to.</param>
301311
/// <param name="message">The text message to send.</param>
302312
/// <param name="button">Interactive button for users to reply.</param>
303-
public static Task SendAsync(this IWhatsAppClient client, string from, string to, string message, Button button)
313+
/// <returns>The identifier of the sent message.</returns>
314+
public static Task<string?> SendAsync(this IWhatsAppClient client, string from, string to, string message, Button button)
304315
=> client.SendAsync(from, new
305316
{
306317
messaging_product = "whatsapp",
@@ -334,7 +345,8 @@ public static Task SendAsync(this IWhatsAppClient client, string from, string to
334345
/// <param name="message">The text message to send.</param>
335346
/// <param name="button1">Interactive button for a user choice.</param>
336347
/// <param name="button2">Interactive button for a user choice.</param>
337-
public static Task SendAsync(this IWhatsAppClient client, string from, string to, string message, Button button1, Button button2)
348+
/// <returns>The identifier of the sent message.</returns>
349+
public static Task<string?> SendAsync(this IWhatsAppClient client, string from, string to, string message, Button button1, Button button2)
338350
=> client.SendAsync(from, new
339351
{
340352
messaging_product = "whatsapp",
@@ -370,7 +382,8 @@ public static Task SendAsync(this IWhatsAppClient client, string from, string to
370382
/// <param name="button1">Interactive button for a user choice.</param>
371383
/// <param name="button2">Interactive button for a user choice.</param>
372384
/// <param name="button3">Interactive button for a user choice.</param>
373-
public static Task SendAsync(this IWhatsAppClient client, string from, string to, string message, Button button1, Button button2, Button button3)
385+
/// <returns>The identifier of the sent message.</returns>
386+
public static Task<string?> SendAsync(this IWhatsAppClient client, string from, string to, string message, Button button1, Button button2, Button button3)
374387
=> client.SendAsync(from, new
375388
{
376389
messaging_product = "whatsapp",

src/WhatsApp/WhatsAppSerializerContext.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ namespace Devlooped.WhatsApp;
2121
[JsonSerializable(typeof(MediaReference))]
2222
[JsonSerializable(typeof(GraphMethodException))]
2323
[JsonSerializable(typeof(ErrorResponse))]
24+
[JsonSerializable(typeof(SendResponse))]
25+
[JsonSerializable(typeof(MessageId))]
2426
partial class WhatsAppSerializerContext : JsonSerializerContext { }
2527

26-
record ErrorResponse(GraphMethodException Error);
28+
record ErrorResponse(GraphMethodException Error);
29+
30+
record SendResponse(MessageId[] Messages);
31+
32+
record MessageId(string Id);

0 commit comments

Comments
 (0)