@@ -3311,91 +3311,46 @@ export class BaileysStartupService extends ChannelStartupService {
33113311 ] ) ;
33123312
33133313 public async buttonMessage ( data : SendButtonsDto ) {
3314- if ( data . buttons . length === 0 ) {
3315- throw new BadRequestException ( 'At least one button is required' ) ;
3316- }
3317-
3318- const hasReplyButtons = data . buttons . some ( ( btn ) => btn . type === 'reply' ) ;
3319-
3320- const hasPixButton = data . buttons . some ( ( btn ) => btn . type === 'pix' ) ;
3314+ if ( data . buttons . length === 0 ) {
3315+ throw new BadRequestException ( 'At least one button is required' ) ;
3316+ }
33213317
3322- const hasOtherButtons = data . buttons . some ( ( btn ) => btn . type !== 'reply' && btn . type !== 'pix' ) ;
3318+ const hasReplyButtons = data . buttons . some ( ( btn ) => btn . type === 'reply' ) ;
3319+ const hasPixButton = data . buttons . some ( ( btn ) => btn . type === 'pix' ) ;
3320+ const hasOtherButtons = data . buttons . some ( ( btn ) => btn . type !== 'reply' && btn . type !== 'pix' ) ;
33233321
3324- if ( hasReplyButtons ) {
3325- if ( data . buttons . length > 3 ) {
3326- throw new BadRequestException ( 'Maximum of 3 reply buttons allowed' ) ;
3327- }
3328- if ( hasOtherButtons ) {
3329- throw new BadRequestException ( 'Reply buttons cannot be mixed with other button types' ) ;
3330- }
3322+ // Reply rules
3323+ if ( hasReplyButtons ) {
3324+ if ( data . buttons . length > 3 ) {
3325+ throw new BadRequestException ( 'Maximum of 3 reply buttons allowed' ) ;
33313326 }
3332-
3333- if ( hasPixButton ) {
3334- if ( data . buttons . length > 1 ) {
3335- throw new BadRequestException ( 'Only one PIX button is allowed' ) ;
3336- }
3337- if ( hasOtherButtons ) {
3338- throw new BadRequestException ( 'PIX button cannot be mixed with other button types' ) ;
3339- }
3340-
3341- const message : proto . IMessage = {
3342- viewOnceMessage : {
3343- message : {
3344- interactiveMessage : {
3345- nativeFlowMessage : {
3346- buttons : [ { name : this . mapType . get ( 'pix' ) , buttonParamsJson : this . toJSONString ( data . buttons [ 0 ] ) } ] ,
3347- messageParamsJson : JSON . stringify ( { from : 'api' , templateId : v4 ( ) } ) ,
3348- } ,
3349- } ,
3350- } ,
3351- } ,
3352- } ;
3353-
3354- return await this . sendMessageWithTyping ( data . number , message , {
3355- delay : data ?. delay ,
3356- presence : 'composing' ,
3357- quoted : data ?. quoted ,
3358- mentionsEveryOne : data ?. mentionsEveryOne ,
3359- mentioned : data ?. mentioned ,
3360- } ) ;
3327+ if ( hasOtherButtons ) {
3328+ throw new BadRequestException ( 'Reply buttons cannot be mixed with other button types' ) ;
33613329 }
3330+ }
33623331
3363- const generate = await ( async ( ) => {
3364- if ( data ?. thumbnailUrl ) {
3365- return await this . prepareMediaMessage ( { mediatype : 'image' , media : data . thumbnailUrl } ) ;
3366- }
3367- } ) ( ) ;
3332+ // CTA rules (url/call/copy) - WhatsApp limits to 2 CTAs
3333+ if ( hasOtherButtons && ! hasReplyButtons && ! hasPixButton ) {
3334+ if ( data . buttons . length > 2 ) {
3335+ throw new BadRequestException ( 'Maximum of 2 CTA buttons allowed (url/call/copy)' ) ;
3336+ }
3337+ }
33683338
3369- const buttons = data . buttons . map ( ( value ) => {
3370- return { name : this . mapType . get ( value . type ) , buttonParamsJson : this . toJSONString ( value ) } ;
3371- } ) ;
3339+ // PIX rules
3340+ if ( hasPixButton ) {
3341+ if ( data . buttons . length > 1 ) {
3342+ throw new BadRequestException ( 'Only one PIX button is allowed' ) ;
3343+ }
3344+ if ( hasOtherButtons ) {
3345+ throw new BadRequestException ( 'PIX button cannot be mixed with other button types' ) ;
3346+ }
33723347
33733348 const message : proto . IMessage = {
3374- viewOnceMessage : {
3349+ deviceSentMessage : {
33753350 message : {
33763351 interactiveMessage : {
3377- body : {
3378- text : ( ( ) => {
3379- let t = '*' + data . title + '*' ;
3380- if ( data ?. description ) {
3381- t += '\n\n' ;
3382- t += data . description ;
3383- t += '\n' ;
3384- }
3385- return t ;
3386- } ) ( ) ,
3387- } ,
3388- footer : { text : data ?. footer } ,
3389- header : ( ( ) => {
3390- if ( generate ?. message ?. imageMessage ) {
3391- return {
3392- hasMediaAttachment : ! ! generate . message . imageMessage ,
3393- imageMessage : generate . message . imageMessage ,
3394- } ;
3395- }
3396- } ) ( ) ,
33973352 nativeFlowMessage : {
3398- buttons : buttons ,
3353+ buttons : [ { name : this . mapType . get ( 'pix' ) , buttonParamsJson : this . toJSONString ( data . buttons [ 0 ] ) } ] ,
33993354 messageParamsJson : JSON . stringify ( { from : 'api' , templateId : v4 ( ) } ) ,
34003355 } ,
34013356 } ,
@@ -3412,6 +3367,58 @@ export class BaileysStartupService extends ChannelStartupService {
34123367 } ) ;
34133368 }
34143369
3370+ const generate = await ( async ( ) => {
3371+ if ( data ?. thumbnailUrl ) {
3372+ return await this . prepareMediaMessage ( { mediatype : 'image' , media : data . thumbnailUrl } ) ;
3373+ }
3374+ } ) ( ) ;
3375+
3376+ const buttons = data . buttons . map ( ( value ) => {
3377+ return { name : this . mapType . get ( value . type ) , buttonParamsJson : this . toJSONString ( value ) } ;
3378+ } ) ;
3379+
3380+ const message : proto . IMessage = {
3381+ deviceSentMessage : {
3382+ message : {
3383+ interactiveMessage : {
3384+ body : {
3385+ text : ( ( ) => {
3386+ let t = '*' + data . title + '*' ;
3387+ if ( data ?. description ) {
3388+ t += '\n\n' ;
3389+ t += data . description ;
3390+ t += '\n' ;
3391+ }
3392+ return t ;
3393+ } ) ( ) ,
3394+ } ,
3395+ footer : { text : data ?. footer } ,
3396+ header : ( ( ) => {
3397+ if ( generate ?. message ?. imageMessage ) {
3398+ return {
3399+ hasMediaAttachment : ! ! generate . message . imageMessage ,
3400+ imageMessage : generate . message . imageMessage ,
3401+ } ;
3402+ }
3403+ } ) ( ) ,
3404+ nativeFlowMessage : {
3405+ buttons,
3406+ messageParamsJson : JSON . stringify ( { from : 'api' , templateId : v4 ( ) } ) ,
3407+ } ,
3408+ } ,
3409+ } ,
3410+ } ,
3411+ } ;
3412+
3413+ return await this . sendMessageWithTyping ( data . number , message , {
3414+ delay : data ?. delay ,
3415+ presence : 'composing' ,
3416+ quoted : data ?. quoted ,
3417+ mentionsEveryOne : data ?. mentionsEveryOne ,
3418+ mentioned : data ?. mentioned ,
3419+ } ) ;
3420+ }
3421+
34153422 public async locationMessage ( data : SendLocationDto ) {
34163423 return await this . sendMessageWithTyping (
34173424 data . number ,
0 commit comments