-
Notifications
You must be signed in to change notification settings - Fork 6.1k
fix(api): add support for WhatsApp Business tokens exceeding 255 char… #2310
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
Changes from 1 commit
9699eed
cb8eda2
4dcbb3a
0230669
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 |
|---|---|---|
|
|
@@ -239,26 +239,37 @@ export class WAMonitoringService { | |
| } | ||
|
|
||
| public async saveInstance(data: any) { | ||
| const truncate = (str: string | null | undefined, maxLength: number): string | null => { | ||
| if (!str) return null; | ||
| return str.length > maxLength ? str.substring(0, maxLength) : str; | ||
| }; | ||
|
|
||
| try { | ||
| const clientName = await this.configService.get<Database>('DATABASE').CONNECTION.CLIENT_NAME; | ||
| const instanceName = truncate(data.instanceName, 255); | ||
| if (!instanceName || instanceName.trim().length === 0) { | ||
| throw new Error('instanceName is required and cannot be empty'); | ||
| } | ||
|
|
||
| const clientName = this.configService.get<Database>('DATABASE').CONNECTION.CLIENT_NAME; | ||
| await this.prismaRepository.instance.create({ | ||
| data: { | ||
| id: data.instanceId, | ||
| name: data.instanceName, | ||
| ownerJid: data.ownerJid, | ||
| profileName: data.profileName, | ||
| profilePicUrl: data.profilePicUrl, | ||
| name: instanceName, | ||
| ownerJid: truncate(data.ownerJid, 100), | ||
| profileName: truncate(data.profileName, 100), | ||
| profilePicUrl: truncate(data.profilePicUrl, 500), | ||
| connectionStatus: | ||
| data.integration && data.integration === Integration.WHATSAPP_BAILEYS ? 'close' : (data.status ?? 'open'), | ||
| number: data.number, | ||
| integration: data.integration || Integration.WHATSAPP_BAILEYS, | ||
| token: data.hash, | ||
| clientName: clientName, | ||
| businessId: data.businessId, | ||
| number: truncate(data.number, 100), | ||
| integration: truncate(data.integration || Integration.WHATSAPP_BAILEYS, 100), | ||
| token: truncate(data.hash, 255), | ||
| clientName: truncate(clientName, 100), | ||
| businessId: truncate(data.businessId, 100), | ||
| }, | ||
| }); | ||
| } catch (error) { | ||
| this.logger.error(error); | ||
| throw error; | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -283,15 +294,31 @@ export class WAMonitoringService { | |
|
|
||
| if (!instance) return; | ||
|
|
||
| instance.setInstance({ | ||
| instanceId: instanceData.instanceId, | ||
| instanceName: instanceData.instanceName, | ||
| integration: instanceData.integration, | ||
| token: instanceData.token, | ||
| number: instanceData.number, | ||
| businessId: instanceData.businessId, | ||
| ownerJid: instanceData.ownerJid, | ||
| }); | ||
| // Para WhatsApp Business, setInstance é async e precisa ser aguardado | ||
| if (instanceData.integration === Integration.WHATSAPP_BUSINESS) { | ||
| const setInstanceResult = (instance as any).setInstance({ | ||
| instanceId: instanceData.instanceId, | ||
| instanceName: instanceData.instanceName, | ||
| integration: instanceData.integration, | ||
| token: instanceData.token, | ||
| number: instanceData.number, | ||
| businessId: instanceData.businessId, | ||
| ownerJid: instanceData.ownerJid, | ||
|
Comment on lines
+321
to
+330
Contributor
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. suggestion: The Promise detection around setInstance can be simplified and made more robust. You can drop the const maybePromise = (instance as any).setInstance({ ... });
await maybePromise;This also handles non-native thenables and matches the controller’s |
||
| }); | ||
| if (setInstanceResult instanceof Promise) { | ||
| await setInstanceResult; | ||
| } | ||
| } else { | ||
| instance.setInstance({ | ||
| instanceId: instanceData.instanceId, | ||
| instanceName: instanceData.instanceName, | ||
| integration: instanceData.integration, | ||
| token: instanceData.token, | ||
| number: instanceData.number, | ||
| businessId: instanceData.businessId, | ||
| ownerJid: instanceData.ownerJid, | ||
| }); | ||
| } | ||
|
|
||
| if (instanceData.connectionStatus === 'open' || instanceData.connectionStatus === 'connecting') { | ||
| this.logger.info( | ||
|
|
@@ -321,11 +348,21 @@ export class WAMonitoringService { | |
| return; | ||
| } | ||
|
|
||
| // Para WhatsApp Business, tenta carregar token completo do cache | ||
| let token = instanceData.token; | ||
| if (instanceData.integration === Integration.WHATSAPP_BUSINESS) { | ||
| const cacheKey = `instance:${instanceData.name}:fullToken`; | ||
|
Comment on lines
+375
to
+378
Contributor
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. issue (bug_risk): Cache key uses The cache key here uses |
||
| const fullToken = await this.cache.get(cacheKey); | ||
| if (fullToken) { | ||
| token = fullToken; | ||
| } | ||
| } | ||
|
|
||
| const instance = { | ||
| instanceId: k.split(':')[1], | ||
| instanceName: k.split(':')[2], | ||
| integration: instanceData.integration, | ||
| token: instanceData.token, | ||
| token: token, | ||
| number: instanceData.number, | ||
| businessId: instanceData.businessId, | ||
| connectionStatus: instanceData.connectionStatus as any, // Pass connection status | ||
|
|
@@ -350,11 +387,21 @@ export class WAMonitoringService { | |
|
|
||
| await Promise.all( | ||
| instances.map(async (instance) => { | ||
| // Para WhatsApp Business, tenta carregar token completo do cache | ||
| let token = instance.token; | ||
| if (instance.integration === Integration.WHATSAPP_BUSINESS) { | ||
| const cacheKey = `instance:${instance.name}:fullToken`; | ||
| const fullToken = await this.cache.get(cacheKey); | ||
| if (fullToken) { | ||
| token = fullToken; | ||
| } | ||
| } | ||
|
|
||
| this.setInstance({ | ||
| instanceId: instance.id, | ||
| instanceName: instance.name, | ||
| integration: instance.integration, | ||
| token: instance.token, | ||
| token: token, | ||
| number: instance.number, | ||
| businessId: instance.businessId, | ||
| ownerJid: instance.ownerJid, | ||
|
|
@@ -377,11 +424,21 @@ export class WAMonitoringService { | |
| where: { id: instanceId }, | ||
| }); | ||
|
|
||
| // Para WhatsApp Business, tenta carregar token completo do cache | ||
| let token = instance.token; | ||
| if (instance.integration === Integration.WHATSAPP_BUSINESS) { | ||
| const cacheKey = `instance:${instance.name}:fullToken`; | ||
| const fullToken = await this.cache.get(cacheKey); | ||
| if (fullToken) { | ||
| token = fullToken; | ||
| } | ||
| } | ||
|
|
||
| this.setInstance({ | ||
| instanceId: instance.id, | ||
| instanceName: instance.name, | ||
| integration: instance.integration, | ||
| token: instance.token, | ||
| token: token, | ||
| businessId: instance.businessId, | ||
| connectionStatus: instance.connectionStatus as any, // Pass connection status | ||
| }); | ||
|
|
||
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 (bug_risk): Consider making the async contract of setInstance explicit and consistent with the base class.
Here
setInstanceis nowasyncand some callers are awaiting it, but the baseChannelStartupService.setInstanceis still effectively synchronous. This split contract can be confusing and lead to timing issues around whenfullTokenis available.I’d suggest either:
Promise<void>) so it’s clear this is part of the instance lifecycle, orawaitit when they depend on cache state (e.g.tokengetter, connection startup).Suggested implementation:
Para tornar o contrato assíncrono explícito e consistente com a classe base, também será necessário:
Atualizar a assinatura de
setInstancena classe base (provavelmenteChannelStartupServiceou similar), por exemplo emsrc/api/integrations/channel/...:public setInstance(instance: any) { ... }parapublic async setInstance(instance: any): Promise<void> { ... }.async/Promise<void>.Verificar todos os locais onde
setInstance(...)é chamado:setInstance(como acesso atokenou início de conexão), garantir que a chamada sejaawait this.setInstance(...)e que o contexto seja assíncrono.setInstanceé chamado mas o resultado não é relevante (fire-and-forget), decidir explicitamente se:await, ouawait, mas com comentários deixando claro que a inicialização é assíncrona e não é necessária imediatamente.Atualizar qualquer interface/abstração que declare
setInstance(por exemplo, uma interface de serviço de canal) para usar a assinaturasetInstance(instance: any): Promise<void>;para manter o contrato de tipo consistente.