-
-
Notifications
You must be signed in to change notification settings - Fork 923
feat: add session_id to webhook payloads and jid to API responses #579
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,9 +30,12 @@ func handler(ctx context.Context, instance *DeviceInstance, rawEvt any) { | |
| chatStorageRepo := instance.GetChatStorage() | ||
| client := instance.GetClient() | ||
|
|
||
| sessionID := instance.ID() | ||
| deviceJID := instance.JID() | ||
|
|
||
| switch evt := rawEvt.(type) { | ||
| case *events.DeleteForMe: | ||
| handleDeleteForMe(ctx, evt, chatStorageRepo, instance.JID(), client) | ||
| handleDeleteForMe(ctx, evt, chatStorageRepo, sessionID, deviceJID, client) | ||
| case *events.AppStateSyncComplete: | ||
| handleAppStateSyncComplete(ctx, client, evt) | ||
| case *events.PairSuccess: | ||
|
|
@@ -44,9 +47,9 @@ func handler(ctx context.Context, instance *DeviceInstance, rawEvt any) { | |
| case *events.StreamReplaced: | ||
| handleStreamReplaced(ctx) | ||
| case *events.Message: | ||
| handleMessage(ctx, evt, chatStorageRepo, client) | ||
| handleMessage(ctx, evt, chatStorageRepo, sessionID, client) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistency: For LID-based WhatsApp accounts, Suggestion: Pass |
||
| case *events.Receipt: | ||
| handleReceipt(ctx, evt, instance.JID(), client) | ||
| handleReceipt(ctx, evt, sessionID, deviceJID, client) | ||
| case *events.Archive: | ||
| handleArchive(ctx, evt, chatStorageRepo, client) | ||
| case *events.Presence: | ||
|
|
@@ -58,25 +61,25 @@ func handler(ctx context.Context, instance *DeviceInstance, rawEvt any) { | |
| case *events.AppState: | ||
| handleAppState(ctx, evt) | ||
| case *events.GroupInfo: | ||
| handleGroupInfo(ctx, evt, instance.JID(), client) | ||
| handleGroupInfo(ctx, evt, sessionID, deviceJID, client) | ||
| case *events.JoinedGroup: | ||
| handleJoinedGroup(ctx, evt, instance.JID(), client) | ||
| handleJoinedGroup(ctx, evt, sessionID, deviceJID, client) | ||
| case *events.NewsletterJoin: | ||
| handleNewsletterJoin(ctx, evt, instance.JID(), client) | ||
| handleNewsletterJoin(ctx, evt, sessionID, deviceJID, client) | ||
| case *events.NewsletterLeave: | ||
| handleNewsletterLeave(ctx, evt, instance.JID(), client) | ||
| handleNewsletterLeave(ctx, evt, sessionID, deviceJID, client) | ||
| case *events.NewsletterLiveUpdate: | ||
| handleNewsletterLiveUpdate(ctx, evt, instance.JID(), client) | ||
| handleNewsletterLiveUpdate(ctx, evt, sessionID, deviceJID, client) | ||
| case *events.NewsletterMuteChange: | ||
| handleNewsletterMuteChange(ctx, evt, instance.JID(), client) | ||
| handleNewsletterMuteChange(ctx, evt, sessionID, deviceJID, client) | ||
| case *events.CallOffer: | ||
| handleCallOffer(ctx, evt, chatStorageRepo, instance.JID(), client) | ||
| handleCallOffer(ctx, evt, chatStorageRepo, sessionID, deviceJID, client) | ||
| } | ||
|
|
||
| instance.UpdateStateFromClient() | ||
| } | ||
|
|
||
| func handleDeleteForMe(ctx context.Context, evt *events.DeleteForMe, chatStorageRepo domainChatStorage.IChatStorageRepository, deviceID string, client *whatsmeow.Client) { | ||
| func handleDeleteForMe(ctx context.Context, evt *events.DeleteForMe, chatStorageRepo domainChatStorage.IChatStorageRepository, sessionID string, deviceID string, client *whatsmeow.Client) { | ||
| log.Infof("Deleted message %s for %s", evt.MessageID, evt.SenderJID.String()) | ||
|
|
||
| // Find the message to get its chat JID | ||
|
|
@@ -103,7 +106,7 @@ func handleDeleteForMe(ctx context.Context, evt *events.DeleteForMe, chatStorage | |
| go func(c *whatsmeow.Client) { | ||
| webhookCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | ||
| defer cancel() | ||
| if err := forwardDeleteToWebhook(webhookCtx, evt, message, deviceID, c); err != nil { | ||
| if err := forwardDeleteToWebhook(webhookCtx, evt, message, sessionID, deviceID, c); err != nil { | ||
|
occult marked this conversation as resolved.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistency: go func(e *events.Message, c *whatsmeow.Client, sid string) {While safe here (strings are immutable, pointers are not mutated after launch), the inconsistent pattern is fragile. Consider passing all referenced variables as goroutine arguments for uniformity. |
||
| log.Errorf("Failed to forward delete event to webhook: %v", err) | ||
| } | ||
| }(client) | ||
|
|
@@ -214,7 +217,7 @@ func handleStreamReplaced(_ context.Context) { | |
| os.Exit(0) | ||
| } | ||
|
|
||
| func handleReceipt(ctx context.Context, evt *events.Receipt, deviceID string, client *whatsmeow.Client) { | ||
| func handleReceipt(ctx context.Context, evt *events.Receipt, sessionID string, deviceID string, client *whatsmeow.Client) { | ||
| sendReceipt := false | ||
| switch evt.Type { | ||
| case types.ReceiptTypeRead, types.ReceiptTypeReadSelf: | ||
|
|
@@ -231,7 +234,7 @@ func handleReceipt(ctx context.Context, evt *events.Receipt, deviceID string, cl | |
| go func(e *events.Receipt, c *whatsmeow.Client) { | ||
| webhookCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | ||
| defer cancel() | ||
| if err := forwardReceiptToWebhook(webhookCtx, e, deviceID, c); err != nil { | ||
| if err := forwardReceiptToWebhook(webhookCtx, e, sessionID, deviceID, c); err != nil { | ||
| logrus.Errorf("Failed to forward ack event to webhook: %v", err) | ||
| } | ||
| }(evt, client) | ||
|
|
@@ -254,7 +257,7 @@ func handleAppState(_ context.Context, evt *events.AppState) { | |
| log.Debugf("App state event: %+v / %+v", evt.Index, evt.SyncActionValue) | ||
| } | ||
|
|
||
| func handleGroupInfo(ctx context.Context, evt *events.GroupInfo, deviceID string, client *whatsmeow.Client) { | ||
| func handleGroupInfo(ctx context.Context, evt *events.GroupInfo, sessionID string, deviceID string, client *whatsmeow.Client) { | ||
| // Only process events that have actual changes | ||
| hasChanges := len(evt.Join) > 0 || len(evt.Leave) > 0 || len(evt.Promote) > 0 || len(evt.Demote) > 0 || | ||
| evt.Name != nil || evt.Topic != nil || evt.Locked != nil || evt.Announce != nil | ||
|
|
@@ -282,7 +285,7 @@ func handleGroupInfo(ctx context.Context, evt *events.GroupInfo, deviceID string | |
| go func(e *events.GroupInfo, c *whatsmeow.Client) { | ||
| webhookCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | ||
| defer cancel() | ||
| if err := forwardGroupInfoToWebhook(webhookCtx, e, deviceID, c); err != nil { | ||
| if err := forwardGroupInfoToWebhook(webhookCtx, e, sessionID, deviceID, c); err != nil { | ||
| logrus.Errorf("Failed to forward group info event to webhook: %v", err) | ||
| } | ||
| }(evt, client) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,14 +28,15 @@ const ( | |
|
|
||
| // WebhookEvent is the top-level structure for webhook payloads | ||
| type WebhookEvent struct { | ||
| Event string `json:"event"` | ||
| DeviceID string `json:"device_id"` | ||
| Payload map[string]any `json:"payload"` | ||
| Event string `json:"event"` | ||
| DeviceID string `json:"device_id"` | ||
| SessionID string `json:"session_id,omitempty"` | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: These JSON struct tags are decorative — Consider either marshaling the struct directly, or removing the JSON tags to avoid the false impression that they control serialization. |
||
| Payload map[string]any `json:"payload"` | ||
| } | ||
|
|
||
| // forwardMessageToWebhook is a helper function to forward message event to webhook url | ||
| func forwardMessageToWebhook(ctx context.Context, client *whatsmeow.Client, evt *events.Message) error { | ||
| webhookEvent, err := createWebhookEvent(ctx, client, evt) | ||
| func forwardMessageToWebhook(ctx context.Context, client *whatsmeow.Client, evt *events.Message, sessionID string) error { | ||
| webhookEvent, err := createWebhookEvent(ctx, client, evt, sessionID) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
@@ -45,14 +46,18 @@ func forwardMessageToWebhook(ctx context.Context, client *whatsmeow.Client, evt | |
| "device_id": webhookEvent.DeviceID, | ||
| "payload": webhookEvent.Payload, | ||
| } | ||
| if webhookEvent.SessionID != "" { | ||
| payload["session_id"] = webhookEvent.SessionID | ||
| } | ||
|
|
||
| return forwardPayloadToConfiguredWebhooks(ctx, payload, webhookEvent.Event) | ||
| } | ||
|
|
||
| func createWebhookEvent(ctx context.Context, client *whatsmeow.Client, evt *events.Message) (*WebhookEvent, error) { | ||
| func createWebhookEvent(ctx context.Context, client *whatsmeow.Client, evt *events.Message, sessionID string) (*WebhookEvent, error) { | ||
| webhookEvent := &WebhookEvent{ | ||
| Event: EventTypeMessage, | ||
| Payload: make(map[string]any), | ||
| Event: EventTypeMessage, | ||
| SessionID: sessionID, | ||
| Payload: make(map[string]any), | ||
| } | ||
|
|
||
| // Set device_id | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: This
if sessionID != "" { body["session_id"] = sessionID }pattern is repeated across 9+ webhook functions (call, delete, group, joined-group, newsletter join/leave/update/mute, receipt). Consider extracting a helper:This reduces duplication and ensures any future envelope changes are applied uniformly.