@@ -49,7 +49,7 @@ async function retryWithBackoff<T>(
4949 maxAttempts : number = 5 ,
5050 operationName : string = 'Operação' ,
5151 baseDelayMs : number = 3000 ,
52- ) : Promise < T | null > {
52+ ) : Promise < T > {
5353 const logger = new Logger ( 'RetryHelper' ) ;
5454
5555 for ( let attempt = 1 ; attempt <= maxAttempts ; attempt ++ ) {
@@ -66,7 +66,7 @@ async function retryWithBackoff<T>(
6666
6767 if ( attempt === maxAttempts ) {
6868 logger . error ( `❌ ${ operationName } falhou após ${ maxAttempts } tentativas: ${ errorMsg } ` ) ;
69- return null ;
69+ throw new Error ( `Failed after ${ maxAttempts } attempts: ${ operationName } - ${ errorMsg } ` ) ;
7070 }
7171
7272 // Exponential backoff: 3s, 6s, 12s, 24s...
@@ -81,7 +81,7 @@ async function retryWithBackoff<T>(
8181 }
8282 }
8383
84- return null ;
84+ throw new Error ( `Failed after ${ maxAttempts } attempts: ${ operationName } ` ) ;
8585}
8686
8787/**
@@ -935,16 +935,15 @@ export class ChatwootService {
935935
936936 // ✅ Retry ao buscar inbox (45 segundos)
937937 const filterInbox = await retryWithBackoff (
938- async ( ) => await this . getInbox ( instance ) ,
938+ async ( ) => {
939+ const inbox = await this . getInbox ( instance ) ;
940+ if ( ! inbox ) throw new Error ( 'Inbox not found' ) ;
941+ return inbox ;
942+ } ,
939943 5 ,
940944 `Buscar inbox no Chatwoot (instance: ${ instance . instanceName } )` ,
941945 ) ;
942946
943- if ( ! filterInbox ) {
944- this . logger . error ( 'Failed to get inbox after retry' ) ;
945- return null ;
946- }
947-
948947 // 🔧 FIX: Verifica se já existe conversação pelo número de telefone (unifica LID e JID)
949948 if ( ! isGroup && phoneNumber ) {
950949 const existingConversationId = await this . findExistingConversationByPhone (
@@ -1064,20 +1063,19 @@ export class ChatwootService {
10641063 // ✅ Retry ao listar conversações do contato (45 segundos)
10651064 const contactConversations = await retryWithBackoff (
10661065 async ( ) => {
1067- return ( await client . contacts . listConversations ( {
1066+ const conversations = ( await client . contacts . listConversations ( {
10681067 accountId : this . provider . accountId ,
10691068 id : contactId ,
10701069 } ) ) as any ;
1070+ if ( ! conversations || ! conversations . payload ) {
1071+ throw new Error ( 'No conversations found or payload is undefined' ) ;
1072+ }
1073+ return conversations ;
10711074 } ,
10721075 5 ,
10731076 `Listar conversações do contato no Chatwoot (contactId: ${ contactId } )` ,
10741077 ) ;
10751078
1076- if ( ! contactConversations || ! contactConversations . payload ) {
1077- this . logger . error ( `No conversations found or payload is undefined` ) ;
1078- return null ;
1079- }
1080-
10811079 let inboxConversation = contactConversations . payload . find (
10821080 ( conversation ) => conversation . inbox_id == filterInbox . id ,
10831081 ) ;
@@ -1122,21 +1120,17 @@ export class ChatwootService {
11221120 // ✅ Retry ao criar conversação (45 segundos)
11231121 const conversation = await retryWithBackoff (
11241122 async ( ) => {
1125- return await client . conversations . create ( {
1123+ const conv = await client . conversations . create ( {
11261124 accountId : this . provider . accountId ,
11271125 data,
11281126 } ) ;
1127+ if ( ! conv ) throw new Error ( 'Failed to create conversation' ) ;
1128+ return conv ;
11291129 } ,
11301130 5 ,
11311131 `Criar conversação no Chatwoot (remoteJid: ${ remoteJid } )` ,
11321132 ) ;
11331133
1134- // ❌ Se falhou após 45 segundos, será recuperado pelo cron
1135- if ( ! conversation ) {
1136- this . logger . warn ( `⚠️ Falha ao criar conversação (remoteJid: ${ remoteJid } ) - será recuperada pelo cron` ) ;
1137- return null ;
1138- }
1139-
11401134 this . logger . verbose ( `New conversation created of ${ remoteJid } with ID: ${ conversation . id } ` ) ;
11411135 this . cache . set ( cacheKey , conversation . id , 1800 ) ;
11421136 return conversation . id ;
@@ -1208,7 +1202,6 @@ export class ChatwootService {
12081202 messageBody ?: any ,
12091203 sourceId ?: string ,
12101204 quotedMsg ?: MessageModel ,
1211- timestamp ?: number , // Timestamp em segundos (Unix timestamp)
12121205 ) {
12131206 const client = await this . clientCw ( instance ) ;
12141207
@@ -1224,7 +1217,7 @@ export class ChatwootService {
12241217 // ✅ Retry com backoff exponencial (45 segundos)
12251218 const message = await retryWithBackoff (
12261219 async ( ) => {
1227- return await client . messages . create ( {
1220+ const msg = await client . messages . create ( {
12281221 accountId : this . provider . accountId ,
12291222 conversationId : conversationId ,
12301223 data : {
@@ -1239,17 +1232,13 @@ export class ChatwootService {
12391232 source_reply_id : sourceReplyId ? sourceReplyId . toString ( ) : null ,
12401233 } ,
12411234 } ) ;
1235+ if ( ! msg ) throw new Error ( 'Failed to create message' ) ;
1236+ return msg ;
12421237 } ,
12431238 5 ,
12441239 `Criar mensagem no Chatwoot (conversationId: ${ conversationId } )` ,
12451240 ) ;
12461241
1247- // ❌ Se falhou após 45 segundos, será recuperado pelo cron
1248- if ( ! message ) {
1249- this . logger . warn ( `⚠️ Falha ao enviar mensagem (conversationId: ${ conversationId } ) - será recuperada pelo cron` ) ;
1250- return null ;
1251- }
1252-
12531242 return message ;
12541243 }
12551244
@@ -1400,18 +1389,13 @@ export class ChatwootService {
14001389 const result = await retryWithBackoff (
14011390 async ( ) => {
14021391 const response = await axios . request ( config ) ;
1392+ if ( ! response . data ) throw new Error ( 'No data in response' ) ;
14031393 return response . data ;
14041394 } ,
14051395 5 ,
14061396 `Enviar mídia ao Chatwoot (conversationId: ${ conversationId } )` ,
14071397 ) ;
14081398
1409- // ❌ Se falhou após 45 segundos, envia pro RabbitMQ
1410- if ( ! result ) {
1411- this . logger . warn ( `⚠️ Falha ao enviar mídia (conversationId: ${ conversationId } ) - será recuperada pelo cron` ) ;
1412- return null ;
1413- }
1414-
14151399 return result ;
14161400 }
14171401
@@ -1887,31 +1871,24 @@ export class ChatwootService {
18871871 quoted : await this . getQuotedMessage ( body , instance ) ,
18881872 } ;
18891873
1890- // 🛡️ Proteção anti-duplicação para anexos
1891- const cacheKey = `cw_sending_${ body . id } _${ attachment . id || Date . now ( ) } ` ;
1892- const alreadySending = await this . cache . get ( cacheKey ) ;
1893-
1894- if ( alreadySending ) {
1895- this . logger . warn (
1896- `[CHATWOOT→WA] Anexo da mensagem ${ body . id } já está sendo enviado, ignorando duplicata` ,
1897- ) ;
1898- continue ;
1899- }
1900-
1901- await this . cache . set ( cacheKey , true , 30 ) ;
1902-
19031874 let messageSent : any ;
19041875 try {
1905- // 🔄 Retry automático para anexos
1876+ // 🔄 Retry automático para anexos (5 tentativas = ~93 segundos)
19061877 messageSent = await retryWithBackoff (
19071878 async ( ) => {
1908- const result = await this . sendAttachment ( waInstance , chatId , attachment . data_url , formatText , options ) ;
1879+ const result = await this . sendAttachment (
1880+ waInstance ,
1881+ chatId ,
1882+ attachment . data_url ,
1883+ formatText ,
1884+ options ,
1885+ ) ;
19091886 if ( ! result ) {
19101887 throw new Error ( 'Attachment not sent' ) ;
19111888 }
19121889 return result ;
19131890 } ,
1914- 3 ,
1891+ 5 ,
19151892 `Enviar anexo do Chatwoot para WhatsApp (${ chatId } )` ,
19161893 ) ;
19171894
@@ -1927,16 +1904,11 @@ export class ChatwootService {
19271904 } ,
19281905 instance ,
19291906 ) ;
1930-
1931- // ✅ Sucesso! Remove do cache
1932- await this . cache . delete ( cacheKey ) ;
19331907 } catch ( error ) {
1934- // ❌ Falhou! Remove do cache
1935- await this . cache . delete ( cacheKey ) ;
1936-
19371908 if ( ! messageSent && body . conversation ?. id ) {
19381909 this . onSendMessageError ( instance , body . conversation ?. id , error ) ;
19391910 }
1911+ throw error ;
19401912 }
19411913 }
19421914 } else {
@@ -1949,21 +1921,9 @@ export class ChatwootService {
19491921
19501922 sendTelemetry ( '/message/sendText' ) ;
19511923
1952- // 🛡️ Proteção anti-duplicação
1953- const cacheKey = `cw_sending_${ body . id } ` ;
1954- const alreadySending = await this . cache . get ( cacheKey ) ;
1955-
1956- if ( alreadySending ) {
1957- this . logger . warn ( `[CHATWOOT→WA] Mensagem ${ body . id } já está sendo enviada, ignorando duplicata` ) ;
1958- return { message : 'already_sending' } ;
1959- }
1960-
1961- // Marca como "enviando" por 30 segundos
1962- await this . cache . set ( cacheKey , true , 30 ) ;
1963-
19641924 let messageSent : any ;
19651925 try {
1966- // 🔄 Retry automático: 3 tentativas (~6 segundos total)
1926+ // 🔄 Retry automático: 5 tentativas (~93 segundos total)
19671927 messageSent = await retryWithBackoff (
19681928 async ( ) => {
19691929 const result = await waInstance ?. textMessage ( data , true ) ;
@@ -1972,7 +1932,7 @@ export class ChatwootService {
19721932 }
19731933 return result ;
19741934 } ,
1975- 3 ,
1935+ 5 ,
19761936 `Enviar mensagem do Chatwoot para WhatsApp (${ chatId } )` ,
19771937 ) ;
19781938
@@ -1992,13 +1952,7 @@ export class ChatwootService {
19921952 } ,
19931953 instance ,
19941954 ) ;
1995-
1996- // ✅ Sucesso! Remove do cache
1997- await this . cache . delete ( cacheKey ) ;
19981955 } catch ( error ) {
1999- // ❌ Falhou após 3 tentativas! Remove do cache para poder tentar depois
2000- await this . cache . delete ( cacheKey ) ;
2001-
20021956 if ( ! messageSent && body . conversation ?. id ) {
20031957 this . onSendMessageError ( instance , body . conversation ?. id , error ) ;
20041958 }
@@ -2331,7 +2285,7 @@ export class ChatwootService {
23312285
23322286 // Generic interactive message
23332287 return '📱 *Mensagem interativa*\n\n_Esta mensagem contém botões ou elementos interativos. Visualize no celular para interagir._' ;
2334- } catch ( error ) {
2288+ } catch {
23352289 return '📱 *Mensagem interativa*\n\n_Esta mensagem contém elementos interativos. Visualize no celular._' ;
23362290 }
23372291 }
@@ -3415,7 +3369,7 @@ export class ChatwootService {
34153369 const totalImported = await chatwootImport . importHistoryMessages ( instance , this , inbox , this . provider , false ) ; // 🔧 Não mostra mensagens do bot no cron (silencioso)
34163370 const waInstance = this . waMonitor . waInstances [ instance . instanceName ] ;
34173371 waInstance . clearCacheChatwoot ( ) ;
3418-
3372+
34193373 return totalImported || 0 ;
34203374 } catch {
34213375 return 0 ;
0 commit comments