feat(events): forward Picture, UserAbout and BusinessName webhook events#94
Conversation
Reviewer's GuideThis PR wires three previously unhandled Whatsmeow events (Picture, UserAbout, BusinessName) into the existing event dispatching and subscription system so they can be forwarded through webhooks/queues/websockets, mirroring existing PushName-style handling and extending the internal event type registry accordingly. Sequence diagram for forwarding new Picture/UserAbout/BusinessName eventssequenceDiagram
participant WhatsmeowClient as MyClient
participant Service as whatsmeowService
participant Sink as QueueOrWebhook
participant Consumer
WhatsmeowClient->>WhatsmeowClient: myEventHandler(rawEvt *events.Picture)
Note over WhatsmeowClient: doWebhook = true<br/>postMap[event] = Picture<br/>postMap[data] = rawEvt
WhatsmeowClient->>Service: CallWebhook(instance, queueName, jsonData, eventType=Picture)
Service->>Service: contains(subscriptions, PICTURE)
alt [subscription includes PICTURE]
Service->>Sink: sendToQueueOrWebhook(instance, queueName, jsonData)
Sink-->>Consumer: deliver Picture event
else [no PICTURE subscription]
Service-->>WhatsmeowClient: return without forwarding
end
%% The same flow applies to UserAbout/BusinessName with
%% eventType UserAbout/BusinessName and subscriptions USER_ABOUT/BUSINESS_NAME
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The event type strings (
"Picture","UserAbout","BusinessName") are duplicated acrossmyEventHandlerandCallWebhook; consider centralizing them (e.g. constants or a shared mapping) to reduce the risk of future typos or mismatches. - For the new subscription checks in
CallWebhook, you might want to reuse the event type constants frompkg/internal/event_types(or a shared enum-like mapping) instead of hardcoding"PICTURE","USER_ABOUT", and"BUSINESS_NAME"here to keep subscription keys consistent across the codebase.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The event type strings (`"Picture"`, `"UserAbout"`, `"BusinessName"`) are duplicated across `myEventHandler` and `CallWebhook`; consider centralizing them (e.g. constants or a shared mapping) to reduce the risk of future typos or mismatches.
- For the new subscription checks in `CallWebhook`, you might want to reuse the event type constants from `pkg/internal/event_types` (or a shared enum-like mapping) instead of hardcoding `"PICTURE"`, `"USER_ABOUT"`, and `"BUSINESS_NAME"` here to keep subscription keys consistent across the codebase.
## Individual Comments
### Comment 1
<location path="pkg/internal/event_types/event_types.go" line_range="19-21" />
<code_context>
NEWSLETTER = "NEWSLETTER"
QRCODE = "QRCODE"
BUTTON_CLICK = "BUTTON_CLICK"
+ PICTURE = "PICTURE"
+ USER_ABOUT = "USER_ABOUT"
+ BUSINESS_NAME = "BUSINESS_NAME"
)
</code_context>
<issue_to_address>
**🚨 question (security):** Double-check that exposing PICTURE/USER_ABOUT/BUSINESS_NAME as event types aligns with privacy expectations.
Since these fields can now flow through webhooks/queues, please confirm they’re acceptable to treat as event payloads from a privacy/compliance perspective (e.g., sensitivity, redaction needs, integrator consent). It may also be worth checking how we handle similar profile events today and aligning with those safeguards for consistency.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| PICTURE = "PICTURE" | ||
| USER_ABOUT = "USER_ABOUT" | ||
| BUSINESS_NAME = "BUSINESS_NAME" |
There was a problem hiding this comment.
🚨 question (security): Double-check that exposing PICTURE/USER_ABOUT/BUSINESS_NAME as event types aligns with privacy expectations.
Since these fields can now flow through webhooks/queues, please confirm they’re acceptable to treat as event payloads from a privacy/compliance perspective (e.g., sensitivity, redaction needs, integrator consent). It may also be worth checking how we handle similar profile events today and aligning with those safeguards for consistency.
The dispatcher in pkg/whatsmeow/service/whatsmeow.go dropped three events emitted by go.mau.fi/whatsmeow because the central switch had no case for them, logging "Unhandled event" instead of forwarding them: - events.Picture: a user's profile picture or a group's photo changes (JID, Author, Timestamp, Remove, PictureID). - events.UserAbout: a user's about/status text changes (JID, Status, Timestamp). - events.BusinessName: a contact's verified business name changes (JID, OldBusinessName, NewBusinessName). Add the three handler cases in myEventHandler, the matching branches in CallWebhook, and the PICTURE, USER_ABOUT and BUSINESS_NAME subscription categories in pkg/internal/event_types so IsEventType accepts them. The change is additive: existing subscribers are unaffected, and the new events require opting in via the subscribe list (or ALL).
6b73624 to
7f649d6
Compare
|
(Already addressed in #57.) On centralizing the event strings: the whole dispatcher already uses string literals for this, both the On the privacy question: this is the same class of profile data the dispatcher already forwards through |
Description
Three whatsmeow events emitted by
go.mau.fi/whatsmeoware silently dropped by the dispatcher inpkg/whatsmeow/service/whatsmeow.gobecause the central switch has no case for them. They only surface in stdout asUnhandled event *events.Xand never reach consumers.This adds the three missing handlers plus the matching subscribe categories so they can be received via webhook / queue / websocket. It mirrors the existing
*events.PushNamehandling for the three new events.Events
*events.Picturetypes/events/events.goJID,Author,Timestamp,Remove,PictureID.*events.UserAbouttypes/events/events.goJID,Status,Timestamp.*events.BusinessNametypes/events/appstate.goJID,OldBusinessName,NewBusinessName.Changes
pkg/whatsmeow/service/whatsmeow.go(myEventHandler): three new cases mirroring the existing*events.Contact/*events.PushNamehandlers. They setdoWebhook = trueandpostMap["event"]; the raw event is already attached viapostMap["data"] = rawEvt.pkg/whatsmeow/service/whatsmeow.go(CallWebhook): three new branches so consumers can subscribe toPICTURE/USER_ABOUT/BUSINESS_NAMEindependently, following the existing per-category split (e.g.MESSAGEvsSEND_MESSAGEvsREAD_RECEIPT).pkg/internal/event_types/event_types.go: the three new constants in the const block, inAllEventTypes, and invalidEventTypessoIsEventTypeaccepts them.The change is additive: existing subscribers keep receiving exactly what they did before. Consumers wanting the new events opt in by including
PICTURE/USER_ABOUT/BUSINESS_NAME(orALL) in their subscribe list.Use cases
Picture: keep a CRM avatar cache in sync in real time instead of polling/chat/fetchProfilePictureUrl/{instance}per contact, which has no batch endpoint and risks rate-flagging on large sweeps.UserAbout: surface each contact's status text in contact cards / chat lists without polling.BusinessName: reflect a contact's verified business name after they edit it on their phone. Today the only signal is theConnectedre-emit, which carries the user's ownpushName, not the contact's verified business name.Type of Change
Testing
go build ./...passes againstdevelop(whatsmeow-lib pinned at0923702).go vetis clean on the two touched packages.Notes
Reopened against
develop(previously #57, which targetedmain).Summary by Sourcery
Forward additional whatsmeow profile-related events to downstream consumers via existing webhook/queue mechanisms.
New Features: