Commit 6376a6d
Review fix (#273)
* feat(whatsapp): Part 1 — GreenAPI setup + test-send page
Track-management messaging will run over WhatsApp via GreenAPI. This
first part wires the plumbing:
- Event gains greenApiInstanceId / greenApiToken (persisted through
mapEventDevSettingsFormToMutateObject, guarded so other forms don't
wipe them)
- New admin page /whatsapp: save GreenAPI credentials, and once set,
send a single test message to validate the setup
- Reachable from the Integration & API page via an "Open" link
- Backend POST /v1/:eventId/whatsapp/send-test (apiKey-protected) calls
GreenAPI server-side so the token never reaches the browser
Part 2 will add the per-track "ready" -> overall GO flow on top of this.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(whatsapp): Part 2 — interactive track buttons, ready loop, GO
Drive track management over GreenAPI interactive buttons:
- SendInteractiveButtonsReply with a 3-button-per-message limit; tracks
are split across as many messages as needed
- A GreenAPI incoming webhook (/v1/whatsapp/webhook, mapped to the event
by instance id) receives a button tap, marks that track ready, edits
the now-button-less message to a status recap, and re-offers buttons
for the tracks still pending in that group
- When every track is ready, a GO message is sent to the same chat (once)
- Readiness is persisted per event (events/{id}/whatsapp/current) so the
admin page can poll a status endpoint and show progress
Flow logic lives in trackFlow.ts with injected senders and is covered by
unit tests (chunking, ready/edit/re-offer, single GO, idempotent press).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(whatsapp): guard undefined tracks in track management status
status?.tracks could be undefined (optional chaining stopped at status),
crashing on .filter. Default to an empty list before reading it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(whatsapp): correct webhook URL formatting + clarify chat format
- normalise API_URL trailing slash so the webhook URL isn't mangled
(was producing "...frv1/whatsapp/webhook")
- guide the shared chat input toward a chatId ending with @c.us / @g.us
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(whatsapp): drop unsupported 'type' field on interactive buttons
GreenAPI sendInteractiveButtonsReply rejects buttons[].type
("'buttons[0].type' is not allowed"); send only buttonId + buttonText.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(whatsapp): persist shared chat + authorize the webhook
- Prefill the shared chat input from the stored session chatId so the
operator doesn't retype it each time.
- Require an Authorization header on the incoming GreenAPI webhook,
matched against the event apiKey (raw or "Bearer <key>"); reject forged
button presses with 401. The page shows the value to configure in
GreenAPI alongside the webhook URL.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(whatsapp): make button-tap webhook actually reachable
Presses did nothing because GreenAPI was never reliably calling our
webhook (URL/token not set), and the new auth check then rejected any
call lacking the token.
- Add an "auto-configure" path: POST .../whatsapp/configure-webhook sets
the instance webhookUrl + webhookUrlToken (= event apiKey, sent back as
"Authorization: Bearer <key>") + incomingWebhook=yes via GreenAPI
setSettings. Frontend button passes the computed webhook URL.
- Log every webhook call (typeWebhook, typeMessage, extracted button id,
auth presence) so "press did nothing" is traceable in function logs.
- Keep manual URL + token display as a fallback.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(whatsapp): persist the shared chat id on the event
The shared chat was only kept inside the session (written on send), so it
looked unsaved. Store whatsappSharedChatId on the event doc, seed the
input from it, add an explicit "Save chat" button, and also persist it
when sending track buttons.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(whatsapp): status route returned {} due to Type.Any() reply schema
fast-json-stringify with a bare Type.Any() response schema strips every
field, so the status endpoint always returned an empty object. Give it an
explicit schema (chatId/tracks/messages/goSent).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(whatsapp): use a poll instead of interactive buttons + event-scoped webhook
Interactive/reply buttons don't reliably produce incoming webhooks on
standard WhatsApp, so taps were never received. Switch to a WhatsApp poll
(sendPoll), whose votes DO arrive as pollUpdateMessage webhooks.
- One poll lists the tracks as options (up to 12 per poll, split beyond
that). A vote marks the matching track ready (by option name, sticky);
GO is sent once all are ready.
- Webhook is now event-scoped: POST /v1/:eventId/whatsapp/webhook, so it
starts with the API base + event id and needs no instance->event lookup.
Auth via Authorization header == event apiKey (raw or Bearer).
- configure-webhook enables pollMessageWebhook too; the page shows/sets the
event-scoped URL.
- Drop button send/edit/re-offer logic and findEventByInstanceId; tests
updated for the poll flow.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat: Add automation of track panel after go
* refacto: Rework the panels infos feedback on track mngt
* Improve whatsapp UI, add schedule tasks and upcoming session date
* Changew message if not all rdy
* feta: Change panel configuration for track auto messages on GO
* refacto: Set real production times for automatic panel talk configuration
* Improve ui
* Add cancel support
* Review fixes
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: fteychene <francois.teychene@gmail.com>1 parent 31d85bd commit 6376a6d
3 files changed
Lines changed: 51 additions & 45 deletions
File tree
- functions/src/api/routes/whatsapp
- src/services/hooks
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
34 | 38 | | |
35 | 39 | | |
36 | 40 | | |
| |||
46 | 50 | | |
47 | 51 | | |
48 | 52 | | |
49 | | - | |
50 | | - | |
| 53 | + | |
| 54 | + | |
51 | 55 | | |
52 | 56 | | |
53 | 57 | | |
| |||
57 | 61 | | |
58 | 62 | | |
59 | 63 | | |
60 | | - | |
| 64 | + | |
61 | 65 | | |
62 | 66 | | |
63 | 67 | | |
64 | 68 | | |
65 | | - | |
| 69 | + | |
66 | 70 | | |
67 | 71 | | |
68 | 72 | | |
69 | 73 | | |
70 | 74 | | |
71 | 75 | | |
72 | | - | |
| 76 | + | |
73 | 77 | | |
74 | 78 | | |
75 | 79 | | |
| |||
85 | 89 | | |
86 | 90 | | |
87 | 91 | | |
88 | | - | |
89 | | - | |
| 92 | + | |
| 93 | + | |
90 | 94 | | |
91 | 95 | | |
92 | 96 | | |
| |||
97 | 101 | | |
98 | 102 | | |
99 | 103 | | |
100 | | - | |
| 104 | + | |
101 | 105 | | |
102 | 106 | | |
103 | 107 | | |
104 | 108 | | |
105 | | - | |
| 109 | + | |
106 | 110 | | |
107 | 111 | | |
108 | 112 | | |
| |||
111 | 115 | | |
112 | 116 | | |
113 | 117 | | |
114 | | - | |
| 118 | + | |
115 | 119 | | |
116 | 120 | | |
117 | 121 | | |
| |||
134 | 138 | | |
135 | 139 | | |
136 | 140 | | |
137 | | - | |
138 | | - | |
| 141 | + | |
| 142 | + | |
139 | 143 | | |
140 | 144 | | |
141 | 145 | | |
| |||
145 | 149 | | |
146 | 150 | | |
147 | 151 | | |
148 | | - | |
| 152 | + | |
149 | 153 | | |
150 | 154 | | |
151 | 155 | | |
152 | 156 | | |
153 | 157 | | |
154 | 158 | | |
155 | | - | |
156 | | - | |
157 | | - | |
| 159 | + | |
158 | 160 | | |
159 | 161 | | |
160 | 162 | | |
| |||
168 | 170 | | |
169 | 171 | | |
170 | 172 | | |
171 | | - | |
| 173 | + | |
172 | 174 | | |
173 | 175 | | |
174 | 176 | | |
| |||
177 | 179 | | |
178 | 180 | | |
179 | 181 | | |
180 | | - | |
| 182 | + | |
181 | 183 | | |
182 | 184 | | |
183 | 185 | | |
184 | | - | |
185 | | - | |
186 | | - | |
| 186 | + | |
187 | 187 | | |
188 | 188 | | |
189 | 189 | | |
190 | 190 | | |
191 | 191 | | |
192 | 192 | | |
193 | | - | |
194 | | - | |
195 | | - | |
| 193 | + | |
196 | 194 | | |
197 | 195 | | |
198 | 196 | | |
| |||
205 | 203 | | |
206 | 204 | | |
207 | 205 | | |
208 | | - | |
| 206 | + | |
209 | 207 | | |
210 | 208 | | |
211 | 209 | | |
| |||
244 | 242 | | |
245 | 243 | | |
246 | 244 | | |
247 | | - | |
| 245 | + | |
248 | 246 | | |
249 | 247 | | |
250 | 248 | | |
| |||
254 | 252 | | |
255 | 253 | | |
256 | 254 | | |
257 | | - | |
| 255 | + | |
258 | 256 | | |
259 | 257 | | |
260 | 258 | | |
261 | 259 | | |
262 | | - | |
| 260 | + | |
263 | 261 | | |
264 | 262 | | |
265 | 263 | | |
266 | | - | |
| 264 | + | |
267 | 265 | | |
268 | 266 | | |
269 | 267 | | |
270 | | - | |
| 268 | + | |
271 | 269 | | |
272 | 270 | | |
273 | 271 | | |
274 | 272 | | |
275 | 273 | | |
276 | | - | |
277 | 274 | | |
278 | | - | |
| 275 | + | |
279 | 276 | | |
280 | 277 | | |
281 | 278 | | |
282 | | - | |
283 | | - | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
284 | 282 | | |
285 | 283 | | |
286 | 284 | | |
| |||
294 | 292 | | |
295 | 293 | | |
296 | 294 | | |
| 295 | + | |
| 296 | + | |
297 | 297 | | |
298 | 298 | | |
299 | 299 | | |
| |||
315 | 315 | | |
316 | 316 | | |
317 | 317 | | |
318 | | - | |
319 | | - | |
| 318 | + | |
| 319 | + | |
320 | 320 | | |
321 | 321 | | |
322 | 322 | | |
| |||
327 | 327 | | |
328 | 328 | | |
329 | 329 | | |
330 | | - | |
331 | | - | |
332 | | - | |
| 330 | + | |
333 | 331 | | |
334 | 332 | | |
335 | 333 | | |
| |||
343 | 341 | | |
344 | 342 | | |
345 | 343 | | |
346 | | - | |
| 344 | + | |
347 | 345 | | |
348 | 346 | | |
349 | 347 | | |
| |||
352 | 350 | | |
353 | 351 | | |
354 | 352 | | |
355 | | - | |
| 353 | + | |
356 | 354 | | |
357 | 355 | | |
358 | 356 | | |
359 | 357 | | |
360 | | - | |
361 | | - | |
362 | | - | |
| 358 | + | |
363 | 359 | | |
364 | 360 | | |
365 | 361 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
39 | 43 | | |
40 | 44 | | |
41 | 45 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
47 | 47 | | |
48 | 48 | | |
49 | 49 | | |
50 | | - | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
51 | 57 | | |
52 | 58 | | |
53 | 59 | | |
| |||
0 commit comments