@@ -53,7 +53,9 @@ export class ChatwootService {
5353 private readonly cache : CacheService ,
5454 ) { }
5555
56- private pgClient = postgresClient . getChatwootConnection ( ) ;
56+ private async getPgClient ( ) {
57+ return postgresClient . getChatwootConnection ( ) ;
58+ }
5759
5860 private async getProvider ( instance : InstanceDto ) : Promise < ChatwootModel | null > {
5961 const cacheKey = `${ instance . instanceName } :getProvider` ;
@@ -382,7 +384,8 @@ export class ChatwootService {
382384 if ( ! uri ) return false ;
383385
384386 const sqlTags = `SELECT id, taggings_count FROM tags WHERE name = $1 LIMIT 1` ;
385- const tagData = ( await this . pgClient . query ( sqlTags , [ nameInbox ] ) ) ?. rows [ 0 ] ;
387+ const pgClient = await this . getPgClient ( ) ;
388+ const tagData = ( await pgClient . query ( sqlTags , [ nameInbox ] ) ) ?. rows [ 0 ] ;
386389 let tagId = tagData ?. id ;
387390 const taggingsCount = tagData ?. taggings_count || 0 ;
388391
@@ -392,18 +395,18 @@ export class ChatwootService {
392395 DO UPDATE SET taggings_count = tags.taggings_count + 1
393396 RETURNING id` ;
394397
395- tagId = ( await this . pgClient . query ( sqlTag , [ nameInbox , taggingsCount + 1 ] ) ) ?. rows [ 0 ] ?. id ;
398+ tagId = ( await pgClient . query ( sqlTag , [ nameInbox , taggingsCount + 1 ] ) ) ?. rows [ 0 ] ?. id ;
396399
397400 const sqlCheckTagging = `SELECT 1 FROM taggings
398401 WHERE tag_id = $1 AND taggable_type = 'Contact' AND taggable_id = $2 AND context = 'labels' LIMIT 1` ;
399402
400- const taggingExists = ( await this . pgClient . query ( sqlCheckTagging , [ tagId , contactId ] ) ) ?. rowCount > 0 ;
403+ const taggingExists = ( await pgClient . query ( sqlCheckTagging , [ tagId , contactId ] ) ) ?. rowCount > 0 ;
401404
402405 if ( ! taggingExists ) {
403406 const sqlInsertLabel = `INSERT INTO taggings (tag_id, taggable_type, taggable_id, context, created_at)
404407 VALUES ($1, 'Contact', $2, 'labels', NOW())` ;
405408
406- await this . pgClient . query ( sqlInsertLabel , [ tagId , contactId ] ) ;
409+ await pgClient . query ( sqlInsertLabel , [ tagId , contactId ] ) ;
407410 }
408411
409412 return true ;
@@ -861,6 +864,7 @@ export class ChatwootService {
861864 messageBody ?: any ,
862865 sourceId ?: string ,
863866 quotedMsg ?: MessageModel ,
867+ messageBodyForRetry ?: any ,
864868 ) {
865869 const client = await this . clientCw ( instance ) ;
866870
@@ -869,32 +873,66 @@ export class ChatwootService {
869873 return null ;
870874 }
871875
872- const replyToIds = await this . getReplyToIds ( messageBody , instance ) ;
876+ const doCreateMessage = async ( convId : number ) => {
877+ const replyToIds = await this . getReplyToIds ( messageBody , instance ) ;
873878
874- const sourceReplyId = quotedMsg ?. chatwootMessageId || null ;
879+ const sourceReplyId = quotedMsg ?. chatwootMessageId || null ;
875880
876- const message = await client . messages . create ( {
877- accountId : this . provider . accountId ,
878- conversationId : conversationId ,
879- data : {
880- content : content ,
881- message_type : messageType ,
882- attachments : attachments ,
883- private : privateMessage || false ,
884- source_id : sourceId ,
885- content_attributes : {
886- ...replyToIds ,
881+ const message = await client . messages . create ( {
882+ accountId : this . provider . accountId ,
883+ conversationId : convId ,
884+ data : {
885+ content : content ,
886+ message_type : messageType ,
887+ attachments : attachments ,
888+ private : privateMessage || false ,
889+ source_id : sourceId ,
890+ content_attributes : {
891+ ...replyToIds ,
892+ } ,
893+ source_reply_id : sourceReplyId ? sourceReplyId . toString ( ) : null ,
887894 } ,
888- source_reply_id : sourceReplyId ? sourceReplyId . toString ( ) : null ,
889- } ,
890- } ) ;
895+ } ) ;
891896
892- if ( ! message ) {
893- this . logger . warn ( 'message not found' ) ;
894- return null ;
895- }
897+ if ( ! message ) {
898+ this . logger . warn ( 'message not found' ) ;
899+ return null ;
900+ }
896901
897- return message ;
902+ return message ;
903+ } ;
904+
905+ try {
906+ return await doCreateMessage ( conversationId ) ;
907+ } catch ( error ) {
908+ const errorMessage = error . toString ( ) . toLowerCase ( ) ;
909+ const status = error . response ?. status ;
910+ if ( errorMessage . includes ( 'not found' ) || status === 404 ) {
911+ this . logger . warn ( `Conversation ${ conversationId } not found. Retrying...` ) ;
912+ const bodyForRetry = messageBodyForRetry || messageBody ;
913+
914+ if ( ! bodyForRetry ) {
915+ this . logger . error ( 'Cannot retry createMessage without a message body for context.' ) ;
916+ return null ;
917+ }
918+
919+ const remoteJid = bodyForRetry . key . remoteJid ;
920+ const cacheKey = `${ instance . instanceName } :createConversation-${ remoteJid } ` ;
921+ await this . cache . delete ( cacheKey ) ;
922+
923+ const newConversationId = await this . createConversation ( instance , bodyForRetry ) ;
924+ if ( ! newConversationId ) {
925+ this . logger . error ( `Failed to create new conversation for ${ remoteJid } ` ) ;
926+ return null ;
927+ }
928+
929+ this . logger . log ( `Retrying message creation for ${ remoteJid } with new conversation ${ newConversationId } ` ) ;
930+ return await doCreateMessage ( newConversationId ) ;
931+ } else {
932+ this . logger . error ( `Error creating message: ${ error } ` ) ;
933+ throw error ;
934+ }
935+ }
898936 }
899937
900938 public async getOpenConversationByContact (
@@ -987,6 +1025,7 @@ export class ChatwootService {
9871025 messageBody ?: any ,
9881026 sourceId ?: string ,
9891027 quotedMsg ?: MessageModel ,
1028+ messageBodyForRetry ?: any ,
9901029 ) {
9911030 if ( sourceId && this . isImportHistoryAvailable ( ) ) {
9921031 const messageAlreadySaved = await chatwootImport . getExistingSourceIds ( [ sourceId ] , conversationId ) ;
@@ -997,54 +1036,84 @@ export class ChatwootService {
9971036 }
9981037 }
9991038 }
1000- const data = new FormData ( ) ;
1039+ const doSendData = async ( convId : number ) => {
1040+ const data = new FormData ( ) ;
10011041
1002- if ( content ) {
1003- data . append ( 'content' , content ) ;
1004- }
1042+ if ( content ) {
1043+ data . append ( 'content' , content ) ;
1044+ }
10051045
1006- data . append ( 'message_type' , messageType ) ;
1046+ data . append ( 'message_type' , messageType ) ;
10071047
1008- data . append ( 'attachments[]' , fileStream , { filename : fileName } ) ;
1048+ data . append ( 'attachments[]' , fileStream , { filename : fileName } ) ;
10091049
1010- const sourceReplyId = quotedMsg ?. chatwootMessageId || null ;
1050+ const sourceReplyId = quotedMsg ?. chatwootMessageId || null ;
10111051
1012- if ( messageBody && instance ) {
1013- const replyToIds = await this . getReplyToIds ( messageBody , instance ) ;
1052+ if ( messageBody && instance ) {
1053+ const replyToIds = await this . getReplyToIds ( messageBody , instance ) ;
10141054
1015- if ( replyToIds . in_reply_to || replyToIds . in_reply_to_external_id ) {
1016- const content = JSON . stringify ( {
1017- ...replyToIds ,
1018- } ) ;
1019- data . append ( 'content_attributes' , content ) ;
1055+ if ( replyToIds . in_reply_to || replyToIds . in_reply_to_external_id ) {
1056+ const content = JSON . stringify ( {
1057+ ...replyToIds ,
1058+ } ) ;
1059+ data . append ( 'content_attributes' , content ) ;
1060+ }
10201061 }
1021- }
10221062
1023- if ( sourceReplyId ) {
1024- data . append ( 'source_reply_id' , sourceReplyId . toString ( ) ) ;
1025- }
1063+ if ( sourceReplyId ) {
1064+ data . append ( 'source_reply_id' , sourceReplyId . toString ( ) ) ;
1065+ }
10261066
1027- if ( sourceId ) {
1028- data . append ( 'source_id' , sourceId ) ;
1029- }
1067+ if ( sourceId ) {
1068+ data . append ( 'source_id' , sourceId ) ;
1069+ }
10301070
1031- const config = {
1032- method : 'post' ,
1033- maxBodyLength : Infinity ,
1034- url : `${ this . provider . url } /api/v1/accounts/${ this . provider . accountId } /conversations/${ conversationId } /messages` ,
1035- headers : {
1036- api_access_token : this . provider . token ,
1037- ...data . getHeaders ( ) ,
1038- } ,
1039- data : data ,
1071+ const config = {
1072+ method : 'post' ,
1073+ maxBodyLength : Infinity ,
1074+ url : `${ this . provider . url } /api/v1/accounts/${ this . provider . accountId } /conversations/${ convId } /messages` ,
1075+ headers : {
1076+ api_access_token : this . provider . token ,
1077+ ...data . getHeaders ( ) ,
1078+ } ,
1079+ data : data ,
1080+ } ;
1081+
1082+ const { data : responseData } = await axios . request ( config ) ;
1083+ return responseData ;
10401084 } ;
10411085
10421086 try {
1043- const { data } = await axios . request ( config ) ;
1044-
1045- return data ;
1087+ return await doSendData ( conversationId ) ;
10461088 } catch ( error ) {
1047- this . logger . error ( error ) ;
1089+ const errorMessage = error . toString ( ) . toLowerCase ( ) ;
1090+ const status = error . response ?. status ;
1091+
1092+ if ( errorMessage . includes ( 'not found' ) || status === 404 ) {
1093+ this . logger . warn ( `Conversation ${ conversationId } not found. Retrying...` ) ;
1094+ const bodyForRetry = messageBodyForRetry || messageBody ;
1095+
1096+ if ( ! bodyForRetry ) {
1097+ this . logger . error ( 'Cannot retry sendData without a message body for context.' ) ;
1098+ return null ;
1099+ }
1100+
1101+ const remoteJid = bodyForRetry . key . remoteJid ;
1102+ const cacheKey = `${ instance . instanceName } :createConversation-${ remoteJid } ` ;
1103+ await this . cache . delete ( cacheKey ) ;
1104+
1105+ const newConversationId = await this . createConversation ( instance , bodyForRetry ) ;
1106+ if ( ! newConversationId ) {
1107+ this . logger . error ( `Failed to create new conversation for ${ remoteJid } ` ) ;
1108+ return null ;
1109+ }
1110+
1111+ this . logger . log ( `Retrying sendData for ${ remoteJid } with new conversation ${ newConversationId } ` ) ;
1112+ return await doSendData ( newConversationId ) ;
1113+ } else {
1114+ this . logger . error ( error ) ;
1115+ return null ;
1116+ }
10481117 }
10491118 }
10501119
@@ -2032,6 +2101,7 @@ export class ChatwootService {
20322101 body ,
20332102 'WAID:' + body . key . id ,
20342103 quotedMsg ,
2104+ null ,
20352105 ) ;
20362106
20372107 if ( ! send ) {
@@ -2051,6 +2121,7 @@ export class ChatwootService {
20512121 body ,
20522122 'WAID:' + body . key . id ,
20532123 quotedMsg ,
2124+ null ,
20542125 ) ;
20552126
20562127 if ( ! send ) {
@@ -2076,6 +2147,7 @@ export class ChatwootService {
20762147 } ,
20772148 'WAID:' + body . key . id ,
20782149 quotedMsg ,
2150+ body ,
20792151 ) ;
20802152 if ( ! send ) {
20812153 this . logger . warn ( 'message not sent' ) ;
@@ -2132,6 +2204,8 @@ export class ChatwootService {
21322204 instance ,
21332205 body ,
21342206 'WAID:' + body . key . id ,
2207+ quotedMsg ,
2208+ null ,
21352209 ) ;
21362210
21372211 if ( ! send ) {
@@ -2173,6 +2247,7 @@ export class ChatwootService {
21732247 body ,
21742248 'WAID:' + body . key . id ,
21752249 quotedMsg ,
2250+ null ,
21762251 ) ;
21772252
21782253 if ( ! send ) {
@@ -2192,6 +2267,7 @@ export class ChatwootService {
21922267 body ,
21932268 'WAID:' + body . key . id ,
21942269 quotedMsg ,
2270+ null ,
21952271 ) ;
21962272
21972273 if ( ! send ) {
@@ -2262,6 +2338,7 @@ export class ChatwootService {
22622338 } ,
22632339 'WAID:' + body . key . id ,
22642340 null ,
2341+ body ,
22652342 ) ;
22662343 if ( ! send ) {
22672344 this . logger . warn ( 'edited message not sent' ) ;
@@ -2515,7 +2592,8 @@ export class ChatwootService {
25152592 and created_at >= now() - interval '6h'
25162593 order by created_at desc` ;
25172594
2518- const messagesData = ( await this . pgClient . query ( sqlMessages ) ) ?. rows ;
2595+ const pgClient = await this . getPgClient ( ) ;
2596+ const messagesData = ( await pgClient . query ( sqlMessages ) ) ?. rows ;
25192597 const ids : string [ ] = messagesData
25202598 . filter ( ( message ) => ! ! message . source_id )
25212599 . map ( ( message ) => message . source_id . replace ( 'WAID:' , '' ) ) ;
0 commit comments