feat: add generateMessageID method and support for messageId in sendM…#2361
Open
JefersonRamos wants to merge 6 commits intoEvolutionAPI:developfrom
Open
feat: add generateMessageID method and support for messageId in sendM…#2361JefersonRamos wants to merge 6 commits intoEvolutionAPI:developfrom
JefersonRamos wants to merge 6 commits intoEvolutionAPI:developfrom
Conversation
Contributor
Reviewer's GuideAdds support for externally generated WhatsApp/Baileys message IDs, including a new internal API endpoint to pre-generate Baileys-compatible message IDs and wiring the optional messageId through DTOs, controllers, services, and the send pipeline so it overrides default ID generation when provided. Sequence diagram for the new generateMessageID API flowsequenceDiagram
actor Integrator
participant HTTP_API as HTTP_API
participant BaileysRouter as BaileysRouter
participant BaileysController as BaileysController
participant BaileysStartupService as BaileysStartupService
participant BaileysSock as BaileysSock
Integrator->>HTTP_API: GET /baileys/generateMessageID/{instance}
HTTP_API->>BaileysRouter: routeRequest
BaileysRouter->>BaileysController: generateMessageID(instanceDto)
BaileysController->>BaileysStartupService: generateMessageID()
BaileysStartupService->>BaileysSock: generateMessageIDV2(userId)
BaileysSock-->>BaileysStartupService: messageId
BaileysStartupService-->>BaileysController: { id: messageId }
BaileysController-->>BaileysRouter: { id: messageId }
BaileysRouter-->>HTTP_API: HTTP 200 { id: messageId }
HTTP_API-->>Integrator: returns preGenerated messageId
Sequence diagram for sending messages with optional external messageIdsequenceDiagram
actor Integrator
participant EvolutionAPI as EvolutionAPI
participant EvolutionStartupService as EvolutionStartupService
participant BaileysStartupService as BaileysStartupService
participant BaileysSock as BaileysSock
participant WhatsAppServer as WhatsAppServer
Integrator->>EvolutionAPI: POST /sendMessage with options.messageId?
EvolutionAPI->>EvolutionStartupService: sendMessage(sender, message, options)
EvolutionStartupService->>EvolutionStartupService: messageId = options.messageId || v4()
EvolutionStartupService->>BaileysStartupService: sendMessage(sender, message, optionsWithMessageId)
BaileysStartupService->>BaileysStartupService: use options.messageId when calling sock.sendMessage
BaileysStartupService->>BaileysSock: sendMessage(jid, content, options.messageId)
BaileysSock->>WhatsAppServer: sendMessage with provided messageId
WhatsAppServer-->>BaileysSock: ack using same messageId
BaileysSock-->>BaileysStartupService: send result
BaileysStartupService-->>EvolutionStartupService: send result
EvolutionStartupService-->>Integrator: HTTP 200 with tracking using messageId
Updated class diagram for Baileys and Evolution messaging structuresclassDiagram
class BaileysStartupService {
- client
+ sendMessage(sender, message, options, isIntegration)
- generateMessageID() Promise
}
class EvolutionStartupService {
+ sendMessage(sender, message, options, file, isIntegration)
- createAudioMessage(sender, options)
}
class BaileysController {
- waMonitor
+ baileysOnWhatsapp(jid)
+ generateMessageID(instanceDto)
+ profilePictureUrl(instanceDto, body)
}
class Options {
+ delay: number
+ presence: string
+ linkPreview: boolean
+ mentionsEveryOne: boolean
+ mentioned: string[]
+ webhookUrl: string
+ messageId: string
}
class Metadata {
+ delay: number
+ presence: string
+ linkPreview: boolean
+ mentionsEveryOne: boolean
+ mentioned: string[]
+ encoding: boolean
+ notConvertSticker: boolean
+ messageId: string
}
class SendTextDto {
}
class InstanceDto {
+ instanceName: string
}
class WaMonitor {
+ waInstances: Map
}
class BaileysSock {
+ user: any
+ generateMessageIDV2(userId)
+ sendMessage(jid, content, messageId)
}
Metadata <|-- SendTextDto
Options o-- EvolutionStartupService
Options o-- BaileysStartupService
BaileysController o-- WaMonitor
WaMonitor o-- BaileysStartupService
BaileysStartupService o-- BaileysSock
BaileysController ..> InstanceDto
EvolutionStartupService ..> Options
BaileysStartupService ..> Options
Metadata ..> Options
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Contributor
There was a problem hiding this comment.
Hey - I've found 3 issues, and left some high level feedback:
- In
sendMessage, the change fromnulltooptions.messageIdassumesoptionsis always defined; consider usingoptions?.messageId(or a default) to avoid runtime errors whenoptionsis undefined. - The new
generateMessageIDmethod is declaredprivateinBaileysStartupServicebut is invoked fromBaileysControllerviainstance.generateMessageID(); either make it public or expose it via a dedicated public wrapper to avoid TypeScript access violations and clarify its intended usage. - In
generateMessageID, you’re callinggenerateMessageIDV2(this.client.user?.id)without checking thatthis.client.user?.idexists; adding a guard or clear error when the instance is not connected would make the behavior more predictable.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `sendMessage`, the change from `null` to `options.messageId` assumes `options` is always defined; consider using `options?.messageId` (or a default) to avoid runtime errors when `options` is undefined.
- The new `generateMessageID` method is declared `private` in `BaileysStartupService` but is invoked from `BaileysController` via `instance.generateMessageID()`; either make it public or expose it via a dedicated public wrapper to avoid TypeScript access violations and clarify its intended usage.
- In `generateMessageID`, you’re calling `generateMessageIDV2(this.client.user?.id)` without checking that `this.client.user?.id` exists; adding a guard or clear error when the instance is not connected would make the behavior more predictable.
## Individual Comments
### Comment 1
<location> `src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts:1983-1988` </location>
<code_context>
}
}
+ private async generateMessageID() {
+
+ return {
+ id: generateMessageIDV2(this.client.user?.id)
+ };
+ }
</code_context>
<issue_to_address>
**suggestion:** Consider making `generateMessageID` synchronous and/or public if it's part of the controller surface.
This method doesn’t `await` anything, so it can be made synchronous to avoid unnecessary promise wrapping. Since it’s called externally via `instance.generateMessageID(...)`, treating it as `public` would also better reflect its actual usage and improve typings and maintainability.
```suggestion
public generateMessageID() {
return {
id: generateMessageIDV2(this.client.user?.id)
};
}
```
</issue_to_address>
### Comment 2
<location> `src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts:2253` </location>
<code_context>
linkPreview,
quoted,
- null,
+ options.messageId,
group?.ephemeralDuration,
// group?.participants,
</code_context>
<issue_to_address>
**issue (bug_risk):** Passing `undefined` instead of `null` for `messageId` may subtly change behavior; consider preserving the old null semantics.
To keep the old behavior while allowing explicit IDs, you can pass `options?.messageId ?? null` here (and in the other similar call).
</issue_to_address>
### Comment 3
<location> `src/api/integrations/channel/evolution/evolution.channel.service.ts:321` </location>
<code_context>
let audioFile;
- const messageId = v4();
+ const messageId = options?.messageId || v4();
let messageRaw: any;
</code_context>
<issue_to_address>
**suggestion:** Prefer nullish coalescing over `||` when choosing between provided and generated message IDs.
`options?.messageId || v4()` will replace any falsy `messageId` (like an empty string) with a new ID. If the intent is to only fall back when `messageId` is `null` or `undefined`, use `const messageId = options?.messageId ?? v4();` to preserve valid-but-falsy IDs.
```suggestion
const messageId = options?.messageId ?? v4();
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
Outdated
Show resolved
Hide resolved
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
Outdated
Show resolved
Hide resolved
src/api/integrations/channel/evolution/evolution.channel.service.ts
Outdated
Show resolved
Hide resolved
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
…ce.ts Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…essage DTO
📋 Description
Em cenários de alto volume de envio de mensagens via Evolution API, chamadas HTTP síncronas podem sofrer timeout, fazendo com que o backend do integrador perca a referência do msg.key.id, apesar da mensagem já ter sido gerada/enviada pelo Baileys.
Como o messageId é gerado localmente pelo Baileys antes do envio, adotei uma abordagem que permite pré-gerar esse identificador no mesmo contexto da sessão, eliminando a dependência da resposta HTTP para rastreamento.
Criada uma nova API interna:
POST /baileys/generateMessageID/{instance}Essa API:
Ajustado o fluxo de envio para:
Benefícios:
Observações importantes:
🔗 Related Issue
Closes #(issue_number)
🧪 Type of Change
🧪 Testing
📸 Screenshots (if applicable)
✅ Checklist
📝 Additional Notes
Summary by Sourcery
Add support for externally supplied WhatsApp message IDs and expose an internal API to pre-generate protocol-compatible message IDs per instance.
New Features:
Enhancements: