Hi again,
I am currently creating a webhook to receive whatsapp messages. I wish to test the webhook by creating a new line with the content of the message in the UI. I read it is possible that consumers can execute commands. How do I establish my code to execute a command whenever a message is received via the webhook?
- Application
'Test Webhook': collection ['Index'] {
'Index': text // @default: auto-increment || "001"
'Content': text
'Webhook tester': command @hidden {
'Content': text
} as $ => update ^ .'Test Webhook' = create (
'Index' = "1"
'Content' = $ .'Content'
)
}
- Implementation
'Webhook': collection = (
'Test Webhook' = $ .'Test Webhook'* as $'webhook' (
'Content': text = $'webhook'.'Content'
'Webhook tester': command as $ => execute $^ $'webhook'.'Webhook tester' (
'Content': text = $ .'Content'
)
)
)
- Interface
'Webhook': collection ['Key'] {
'Key': text
'Content': text
'Webhook tester': command {
'Content': text
}
}
- Processor
consumer ( )
add-hook 'network'::'webserver' "/echo"
do (
'status' = 200
'headers' = create [ "content-type" ] "application/json"
'content' = $'request' => serialize as JSON => call 'unicode'::'as binary' with ( )
)
Ok, so it looks like you need something like this:
- Find the correct webhook entry based on a key.
- Invoke the command.
- Send a reply to the other party.
You can reuse/adapt some ideas from this code:
add-hook 'network'::'webserver' "/callback"
do {
let $'key' = "key" // <-- get this from request data, e.g. from a header, query parameter or posted data
switch $ .'Webhook'[ $'key' ] (
| value as $ => {
execute $ command 'Webhook tester' with (
'Content' = "content" // <-- also get this from request data
)
(
'status' = 200
'headers' = no-op
'content' = "OK" => call 'unicode'::'as binary' with ( )
)
}
| error => (
'status' = 500
'headers' = no-op
'content' = "Webhook key not found" => call 'unicode'::'as binary' with ( )
)
)
}
Using the switch
statement, you will be able do determine whether the provided key exists or not.
Please let me know if this helps.
1 Like
Thank you!
I am figuring out how to put the data received through the webhook in variables. execute $ command 'Webhook tester' with ( 'Content' = $'request'.'content' => serialize as JSON
does not give any syntax error, however let $'Data' = $'request'.'content' => serialize as JSON
does.
add-hook 'network'::'webserver' "/callback"
do {
let $'Data' = $'request'.'content' => serialize as JSON
execute $ command 'Webhook tester' with (
'Content' = $'request'.'content' => serialize as JSON
)
(
'status' = 200
'headers' = create [ "content-type" ] "application/json"
'content' = $'request' => serialize as JSON => call 'unicode'::'as binary' with ( )
)
The request content is defined as an optional field of the binary type:
define 'network request' as @API {
'method': 'network method'
'parameters': optional 'key value list'
'headers': optional 'key value list'
'content': optional binary
}
To read this field, it should be guarded to provide a fallback in case it is missing, like this:
let $'request content' = $'request'.'content' get || throw "Missing network content"
That results in a binary
type value in $'request content'
. If you then want to convert to a text
type value, for example to parse it as JSON later, you can do:
let $'request text' = $'request content' => call 'unicode'::'import' with ( $'encoding' = "UTF-8" ) || throw "Invalid content"
You can add further steps to parse JSON using ... => parse as JSON
and convert it to a typed data structure using ... => decorate as ...
.
1 Like
It should be noted that you can chain several operations with the =>
operator to avoid creating temporary variables, if you’re only interested in the end result. The binary to text conversion, JSON parsing and decoration as a typed data structure are often combined in a single statement:
let $'data' = ^ $'request'.'content' get => call 'unicode'::'import' with ( $'encoding' = "UTF-8" ) => parse as JSON => decorate as {
// <-- here you specify the schema of your data structure
} || throw "unable to parse request data"
1 Like