Skip to content

Commit fc952b9

Browse files
committed
implement-typing-indication
1 parent abf0abf commit fc952b9

File tree

1 file changed

+63
-37
lines changed

1 file changed

+63
-37
lines changed

src/whatsapp.ts

Lines changed: 63 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ import {
88
injectReferenceId,
99
injectReply,
1010
injectSpinner,
11+
injectTyping,
1112
injectUserId,
1213
} from "./api.ts";
1314
import type { ConversationEvent, TaskHandler } from "./index.ts";
1415
import type { Endpoint } from "./taskBouncer.ts";
1516

17+
const apiVersion = "v21.0";
18+
1619
const {
1720
anymap,
1821
filter,
@@ -44,7 +47,7 @@ export const sendWhatsappMessage =
4447
(accessToken: string, fromNumberId: string) => (to: string) =>
4548
pipe(convertToWhatsAppFormat, (body: string) =>
4649
fetch(
47-
`https://graph.facebook.com/v20.0/${fromNumberId}/messages`,
50+
`https://graph.facebook.com/${apiVersion}/${fromNumberId}/messages`,
4851
{
4952
method: "POST",
5053
body: JSON.stringify({
@@ -54,10 +57,7 @@ export const sendWhatsappMessage =
5457
to,
5558
text: { preview_url: false, body },
5659
}),
57-
headers: {
58-
"Authorization": `Bearer ${accessToken}`,
59-
"Content-Type": "application/json",
60-
},
60+
headers: makeHeaders(accessToken),
6161
},
6262
).then(async (response) => {
6363
if (!response.ok) throw new Error(await response.text());
@@ -84,34 +84,34 @@ export const sendWhatsappTemplate =
8484
langCode: string,
8585
components: Component[],
8686
) =>
87-
fetch(`https://graph.facebook.com/v20.0/${fromNumberId}/messages`, {
88-
method: "POST",
89-
body: JSON.stringify({
90-
recipient_type: "individual",
91-
messaging_product: "whatsapp",
92-
to,
93-
type: "template",
94-
template: {
95-
name,
96-
language: { code: langCode },
97-
components: components.map((c) => ({
98-
...c,
99-
parameters: c.parameters.map((p) =>
100-
p.type === "text"
101-
? ({
102-
type: "text",
103-
text: templateTextParamConstraints(p.text),
104-
})
105-
: p
106-
),
107-
})),
108-
},
109-
}),
110-
headers: {
111-
Authorization: `Bearer ${accessToken}`,
112-
"Content-Type": "application/json",
87+
fetch(
88+
`https://graph.facebook.com/${apiVersion}/${fromNumberId}/messages`,
89+
{
90+
method: "POST",
91+
body: JSON.stringify({
92+
recipient_type: "individual",
93+
messaging_product: "whatsapp",
94+
to,
95+
type: "template",
96+
template: {
97+
name,
98+
language: { code: langCode },
99+
components: components.map((c) => ({
100+
...c,
101+
parameters: c.parameters.map((p) =>
102+
p.type === "text"
103+
? ({
104+
type: "text",
105+
text: templateTextParamConstraints(p.text),
106+
})
107+
: p
108+
),
109+
})),
110+
},
111+
}),
112+
headers: makeHeaders(accessToken),
113113
},
114-
}).then(async (response) => {
114+
).then(async (response) => {
115115
if (!response.ok) throw new Error(await response.text());
116116
return (await response.json()) as SentMessageResponse;
117117
});
@@ -327,12 +327,9 @@ type MediaGetResponse = {
327327
};
328328

329329
const getMediaFromId = (accessToken: string) => (id: string): Promise<string> =>
330-
fetch(`https://graph.facebook.com/v21.0/${id}`, {
330+
fetch(`https://graph.facebook.com/${apiVersion}/${id}`, {
331331
method: "GET",
332-
headers: {
333-
"Authorization": `Bearer ${accessToken}`,
334-
"Content-Type": "application/json",
335-
},
332+
headers: makeHeaders(accessToken),
336333
})
337334
.then((response) => response.json() as Promise<MediaGetResponse>)
338335
.then(({ url }) =>
@@ -385,13 +382,23 @@ export const whatsappForBusinessInjectDepsAndRun =
385382
injectUserId(() => coerce(fromNumber(msg))),
386383
injectSpinner(pipe(send, (_) => () => Promise.resolve())),
387384
injectReply(send),
385+
injectTyping(() =>
386+
sendWhatsappTypingIndicator(token, toNumberId(msg))(
387+
messageId(msg),
388+
)
389+
),
388390
referenceId(msg)
389391
? injectReferenceId(() => referenceId(msg))
390392
: identity,
391393
)(doTask)(),
392394
)
393395
: Promise.resolve();
394396

397+
const makeHeaders = (accessToken: string) => ({
398+
"Authorization": `Bearer ${accessToken}`,
399+
"Content-Type": "application/json",
400+
});
401+
395402
export const whatsappBusinessHandler = (
396403
token: string,
397404
path: string,
@@ -401,3 +408,22 @@ export const whatsappBusinessHandler = (
401408
predicate: ({ url, method }) => url === path && method === "POST",
402409
handler: whatsappForBusinessInjectDepsAndRun(token, doTask),
403410
});
411+
412+
export const sendWhatsappTypingIndicator =
413+
(accessToken: string, fromNumberId: string) => (messageId: string) =>
414+
fetch(
415+
`https://graph.facebook.com/${apiVersion}/${fromNumberId}/messages`,
416+
{
417+
method: "POST",
418+
body: JSON.stringify({
419+
messaging_product: "whatsapp",
420+
status: "read",
421+
message_id: messageId,
422+
typing_indicator: { type: "text" },
423+
}),
424+
headers: makeHeaders(accessToken),
425+
},
426+
).then(async (response) => {
427+
if (!response.ok) throw new Error(await response.text());
428+
return response.json();
429+
});

0 commit comments

Comments
 (0)