Repository navigation
feat(webhooks): normalize call, group and membership events - #23
Conversation
|
Ready to act? Review this PR in Change Stack to turn feedback into patch suggestions you can inspect and refine. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughAdds four normalized engine event kinds—call, group_participants, group_update, membership_request—by extending Zod types and webhook enums, implementing mappers for Baileys and Zapo with unit tests, wiring event listeners in both engines, and updating OpenAPI webhook schema, examples, and description. ChangesNormalized event types across engines
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
packages/types/src/engine.ts (1)
102-110: ⚡ Quick winConsider adding a minimum length constraint on
participantsarray.The
participantsfield accepts an empty array. Looking at the test file (line 177-180), the test expectsparticipants: []to fail, but that's only becauseaction: 'modify'is invalid. An empty array with a valid action like'add'would currently pass validation, which may not be semantically correct for a participant update event.If empty participant arrays should be rejected, add
.min(1):export const groupParticipantsEventSchema = z.object({ type: z.literal('group_participants'), chat: z.string(), action: participantActionSchema, - participants: z.array(z.string()), + participants: z.array(z.string()).min(1), author: z.string().optional(), authorAlt: z.string().optional(), timestamp: z.number().optional() })🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/types/src/engine.ts` around lines 102 - 110, The participants array in groupParticipantsEventSchema currently allows empty arrays; update the participants field (in groupParticipantsEventSchema) to require at least one entry by applying a minimum-length constraint (e.g., change participants: z.array(z.string()) to participants: z.array(z.string()).min(1)) so events like 'add' cannot validate with an empty participants list.packages/engine-zapo/src/events.test.ts (1)
539-549: ⚡ Quick winAdd regression cases for missing
enabled/expirationSecondsin metadata actions.Please add assertions that
mapZapoGroupreturns[]whenactionisannounce/restrictwithoutenabled, andephemeralwithoutexpirationSeconds, so partial-update behavior is enforced by tests.Suggested test additions
it('routes metadata actions to group_update', () => { @@ expect( mapZapoGroup({ action: 'ephemeral', groupJid: 'g@g.us', expirationSeconds: 604800 }) ).toEqual([{ type: 'group_update', chat: 'g@g.us', ephemeralSeconds: 604800 }]) + expect(mapZapoGroup({ action: 'announce', groupJid: 'g@g.us' })).toEqual([]) + expect(mapZapoGroup({ action: 'restrict', groupJid: 'g@g.us' })).toEqual([]) + expect(mapZapoGroup({ action: 'ephemeral', groupJid: 'g@g.us' })).toEqual([]) })🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/engine-zapo/src/events.test.ts` around lines 539 - 549, Add regression assertions to ensure mapZapoGroup enforces partial-update behavior: add tests that when calling mapZapoGroup({ action: 'announce', groupJid: 'g@g.us' }) and mapZapoGroup({ action: 'restrict', groupJid: 'g@g.us' }) (i.e., missing enabled) it returns [], and that mapZapoGroup({ action: 'ephemeral', groupJid: 'g@g.us' }) (missing expirationSeconds) also returns []; update the existing test block that covers metadata actions (which currently checks subject/announce/ephemeral with fields present) to include these extra expect(...).toEqual([]) assertions referencing mapZapoGroup so the behavior is covered.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/engine-baileys/src/events.ts`:
- Around line 396-402: The function mapBaileysCall currently drops Baileys v7's
"timeout" status because CALL_STATUSES only allows
'offer'|'accept'|'reject'|'terminate'; update mapBaileysCall to translate a
call.status === 'timeout' to 'terminate' (before checking CALL_STATUSES) so that
timeout events are normalized to CallStatus. Modify the logic around
CALL_STATUSES and the initial guard in mapBaileysCall (referencing
BaileysCallInput, CALL_STATUSES and the returned CallStatus) to perform the
mapping first, then apply the allow-list and return the normalized status.
In `@packages/engine-zapo/src/events.ts`:
- Around line 410-426: The code is fabricating group_update fields by coercing
missing event.enabled/event.expirationSeconds into false/0; in the
ZAPO_UPDATE_ACTIONS branch (where GroupUpdateEvent update is built) only assign
update.announce, update.restrict, and update.ephemeralSeconds when the
corresponding source properties are actually present (e.g., event.enabled !==
undefined and event.expirationSeconds !== undefined/null) instead of using the
nullish coalescing defaults (?? false/0); preserve the existing
subject/description checks and the hasField existence test so the function
returns an update only when at least one real source field was provided.
---
Nitpick comments:
In `@packages/engine-zapo/src/events.test.ts`:
- Around line 539-549: Add regression assertions to ensure mapZapoGroup enforces
partial-update behavior: add tests that when calling mapZapoGroup({ action:
'announce', groupJid: 'g@g.us' }) and mapZapoGroup({ action: 'restrict',
groupJid: 'g@g.us' }) (i.e., missing enabled) it returns [], and that
mapZapoGroup({ action: 'ephemeral', groupJid: 'g@g.us' }) (missing
expirationSeconds) also returns []; update the existing test block that covers
metadata actions (which currently checks subject/announce/ephemeral with fields
present) to include these extra expect(...).toEqual([]) assertions referencing
mapZapoGroup so the behavior is covered.
In `@packages/types/src/engine.ts`:
- Around line 102-110: The participants array in groupParticipantsEventSchema
currently allows empty arrays; update the participants field (in
groupParticipantsEventSchema) to require at least one entry by applying a
minimum-length constraint (e.g., change participants: z.array(z.string()) to
participants: z.array(z.string()).min(1)) so events like 'add' cannot validate
with an empty participants list.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e1d65ae0-9f9b-4c61-8e98-c0198eb78062
📒 Files selected for processing (11)
apps/api/src/http/openapi.tspackages/engine-baileys/src/engine.tspackages/engine-baileys/src/events.test.tspackages/engine-baileys/src/events.tspackages/engine-zapo/src/engine.tspackages/engine-zapo/src/events.test.tspackages/engine-zapo/src/events.tspackages/types/src/engine.tspackages/types/src/schemas.test.tspackages/types/src/webhook.tsvitest.config.ts
Resumo
Normaliza 4 novos eventos no contrato engine-agnostico
EngineEvent, identicos entre as enginesbaileysezapo:call,group_participants,group_updateemembership_request. Inclui o enderecamento alternativo lid<->pn (fromAlt/authorAlt/participantAlt) nesses eventos, espelhando ofromAltdas mensagens (#19). 6 commits.Closes #7.
Contrato (@multi-wa/types)
EngineEvent:callEventSchema,groupParticipantsEventSchema,groupUpdateEventSchema,membershipRequestEventSchema(reusaparticipantActionSchema).call.status:offer|accept|reject|terminate(intersecao neutra; "perdida" =offersemacceptseguido determinate).membership_request.action:created|revoked(ambas engines) +rejected(so-baileys).*Altopcionais (lid<->pn) nos jids principais.webhookEventTypeSchemaestendido com os 4 tipos.Engines
mapBaileysCall/mapBaileysGroupParticipants/mapBaileysGroupUpdate/mapBaileysMembershipRequest+ listeners (call,group-participants.update,groups.update,group.join-request).*AltviacallerPn/authorPn/participantPn.mapZapoCall+ roteadormapZapoGroup(despacha o evento unicogroupporaction, com fan-out de membership) + listeners (call,group).fromAltdo call viasenderLidJid/callCreatorJid;participantAltviaphoneJid.API / OpenAPI
WebhookDelivery: 4 branches novos nooneOf+ exemplos + descricao (incl. nota lid<->pn).Fora de escopo
newsletterebusinessadiados (sem paridade entre engines).participantsdogroup_participants.Plano de teste
pnpm lint,pnpm typecheck,pnpm buildepnpm test:allterminam zerados (188 testes).events.test.ts) e o contrato emschemas.test.ts.call(offer/accept/reject/terminate); add/remove/promote/demote emitegroup_participants; mudanca de assunto/descricao/announce/restrict/ephemeral emitegroup_update; solicitacao de entrada emitemembership_request.Summary by CodeRabbit
New Features
Documentation