|
1 | | - WhatsApp agents for Azure Functions |
| 1 | + WhatsApp agents for Azure Functions |
2 | 2 | ============ |
3 | 3 |
|
| 4 | +[](https://www.nuget.org/packages/Devlooped.WhatsApp) |
| 5 | +[](https://www.nuget.org/packages/Devlooped.WhatsApp) |
| 6 | +[](https://github.com//devlooped/WhatsApp/blob/main/license.txt) |
| 7 | +[](https://github.com/devlooped/WhatsApp/actions/workflows/build.yml) |
| 8 | + |
4 | 9 | Create agents for WhatsApp using Azure Functions. |
5 | 10 |
|
| 11 | +## Usage |
| 12 | + |
| 13 | +```csharp |
| 14 | +var builder = FunctionsApplication.CreateBuilder(args); |
| 15 | +builder.ConfigureFunctionsWebApplication(); |
| 16 | + |
| 17 | +builder.UseWhatsApp<MyWhatsAppHandler>(); |
| 18 | + |
| 19 | +builder.Build().Run(); |
| 20 | +``` |
| 21 | + |
| 22 | +Instead of providing an `IWhatsAppHandler` implementation, you can also |
| 23 | +register an inline handler using minimal API style: |
| 24 | + |
| 25 | +```csharp |
| 26 | +builder.UseWhatsApp(message => |
| 27 | +{ |
| 28 | + // MessageType: Content | Error | Interactive | Status |
| 29 | + Console.WriteLine($"Got message type {message.Type}"); |
| 30 | + switch (message) |
| 31 | + { |
| 32 | + case ContentMessage content: |
| 33 | + // ContentType = Text | Contact | Document | Image | Audio | Video | Location | Unknown (raw JSON) |
| 34 | + Console.WriteLine($"Got content type {content.Content.Type}"); |
| 35 | + break; |
| 36 | + case ErrorMessage error: |
| 37 | + Console.WriteLine($"Error: {error.Error.Message} ({error.Error.Code})"); |
| 38 | + break; |
| 39 | + case InteractiveMessage interactive: |
| 40 | + Console.WriteLine($"Interactive: {interactive.Button.Title} ({interactive.Button.Id})"); |
| 41 | + break; |
| 42 | + case StatusMessage status: |
| 43 | + Console.WriteLine($"Status: {status.Status}"); |
| 44 | + break; |
| 45 | + } |
| 46 | + return Task.CompletedTask; |
| 47 | +}); |
| 48 | +``` |
| 49 | + |
| 50 | +If the handler needs additional services, they can be provided directly |
| 51 | +as generic parameters of the `UseWhatsApp` method, such as: |
| 52 | + |
| 53 | +```csharp |
| 54 | +builder.UseWhatsApp<IWhatsAppClient, ILogger<Program>>(async (client, logger, message) => |
| 55 | +{ |
| 56 | + logger.LogInformation($"Got message type {message.Type}"); |
| 57 | + // Reply to an incoming content message, for example. |
| 58 | + if (message is ContentMessage content) |
| 59 | + await client.SendTextAync(message.To.Id, message.From.Number, $"Got your {content.}"); |
| 60 | +} |
| 61 | +``` |
| 62 | + |
| 63 | +You can also specify the parameter types in the delegate itself and avoid the |
| 64 | +generic parameters: |
| 65 | + |
| 66 | +```csharp |
| 67 | +builder.UseWhatsApp(async (IWhatsAppClient client, ILogger<Program> logger, Message message) => |
| 68 | +``` |
| 69 | + |
| 70 | +The provided `IWhatsAppClient` provides a very thin abstraction allowing you to send |
| 71 | +arbitrary payloads to WhatsApp for Business: |
| 72 | + |
| 73 | +```csharp |
| 74 | +public interface IWhatsAppClient |
| 75 | +{ |
| 76 | + /// Payloads from https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages |
| 77 | + Task SendAync(string from, object payload); |
| 78 | +} |
| 79 | +``` |
| 80 | + |
| 81 | +Extensions methods for this interface take care of simplifying usage for some |
| 82 | +common scenarios, such as reacting to a message and replying with plain text: |
| 83 | + |
| 84 | +```csharp |
| 85 | +if (message is ContentMessage content) |
| 86 | +{ |
| 87 | + await client.ReactAsync(from: message.To.Id, to: message.From.Number, message.Id, "🧠"); |
| 88 | + // simulate some hard work at hand, like doing some LLM-stuff :) |
| 89 | + await Task.Delay(2000); |
| 90 | + await client.SendTextAync(message.To.Id, message.From.Number, $"☑️ Processed your {content.Type}"); |
| 91 | +} |
| 92 | +``` |
| 93 | + |
| 94 | +## Configuration |
| 95 | + |
| 96 | +You need to register an app in the Meta [App Dashboard](https://developers.facebook.com/apps/]. |
| 97 | +The app must then be configured to use the WhatsApp Business API, and the webhook and |
| 98 | +verification token (an arbitrary value) must be set up in the app settings under WhatsApp. |
| 99 | +The webhook URL is `/whatsapp` under your Azure Functions app. |
| 100 | + |
| 101 | +Make sure you subscribe the webhook to the `messages` field, with API version `v22.0` or later. |
| 102 | + |
| 103 | +Configuration on the Azure Functions side is done via the |
| 104 | +[ASP.NET options pattern](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options) |
| 105 | +and the `MetaOptions` type. When you call `UseWhatsApp`, the options will be bound by |
| 106 | +default to the `Meta` section in the configuration. You can also configure it programmatically |
| 107 | +as follows: |
| 108 | + |
| 109 | +```csharp |
| 110 | +builder.Services.Configure<MetaOptions>(options => |
| 111 | +{ |
| 112 | + options.VerifyToken = "my-webhook-1234"; |
| 113 | + options.Numbers["12345678"] = "asff="; |
| 114 | +}); |
| 115 | +``` |
| 116 | + |
| 117 | +Via configuration: |
| 118 | + |
| 119 | +```json |
| 120 | +{ |
| 121 | + "Meta": { |
| 122 | + "VerifyToken": "my-webhook-1234", |
| 123 | + "Numbers": { |
| 124 | + "12345678": "asff=" |
| 125 | + } |
| 126 | + } |
| 127 | +} |
| 128 | +``` |
| 129 | + |
| 130 | +The `Numbers` dictionary is a map of WhatsApp phone identifiers and the |
| 131 | +corresponding access token for it. To get a permanent access token for |
| 132 | +use, you'd need to create a [system user](https://business.facebook.com/latest/settings/system_users) |
| 133 | +with full control permissions to the WhatsApp Business API (app). |
| 134 | + |
6 | 135 | ## License |
7 | 136 |
|
8 | 137 | We offer this project under a dual licensing model, tailored to the needs |
|
0 commit comments