99 "time"
1010
1111 "go.mau.fi/whatsmeow/proto/waArmadilloApplication"
12+ "go.mau.fi/whatsmeow/proto/waArmadilloXMA"
1213 "go.mau.fi/whatsmeow/proto/waCommon"
1314 "go.mau.fi/whatsmeow/proto/waConsumerApplication"
1415 "go.mau.fi/whatsmeow/types/events"
@@ -628,14 +629,67 @@ func extractE2EEText(e *events.FBMessage) string {
628629 return mt .MessageText .GetText ()
629630 }
630631 if et , ok := c .GetContent ().(* waConsumerApplication.ConsumerApplication_Content_ExtendedTextMessage ); ok {
631- return et .ExtendedTextMessage .GetText ().GetText ()
632+ extMsg := et .ExtendedTextMessage
633+ if extMsg == nil {
634+ return ""
635+ }
636+ // Try GetText().GetText() first
637+ if textMsg := extMsg .GetText (); textMsg != nil {
638+ if text := textMsg .GetText (); text != "" {
639+ return text
640+ }
641+ }
642+ // Fallback to matchedText (the actual URL in the message)
643+ if matched := extMsg .GetMatchedText (); matched != "" {
644+ return matched
645+ }
646+ // Fallback to canonicalURL
647+ if canonical := extMsg .GetCanonicalURL (); canonical != "" {
648+ return canonical
649+ }
632650 }
633651 }
634652 }
635653 }
636654
637- if _ , ok := e .Message .(* waArmadilloApplication.Armadillo ); ok {
638- // Armadillo special messages - could be parsed further
655+ if armadillo , ok := e .Message .(* waArmadilloApplication.Armadillo ); ok {
656+ // Armadillo special messages
657+ if payload := armadillo .GetPayload (); payload != nil {
658+ if content := payload .GetContent (); content != nil {
659+ // ExtendedContentMessage - used for link shares
660+ if extMsg := content .GetExtendedContentMessage (); extMsg != nil {
661+ // Try MessageText first (the actual text the user typed)
662+ if text := extMsg .GetMessageText (); text != "" {
663+ return text
664+ }
665+ // Fallback to TitleText (link title)
666+ if title := extMsg .GetTitleText (); title != "" {
667+ return title
668+ }
669+ // Fallback to ActionURL from CTAs
670+ if ctas := extMsg .GetCtas (); len (ctas ) > 0 {
671+ for _ , cta := range ctas {
672+ if actionURL := cta .GetActionURL (); actionURL != "" {
673+ // Try to extract actual URL from /l.php redirect
674+ if parsedURL := extractURLFromLPHP (actionURL ); parsedURL != "" {
675+ return parsedURL
676+ }
677+ return actionURL
678+ }
679+ if nativeURL := cta .GetNativeURL (); nativeURL != "" {
680+ return nativeURL
681+ }
682+ }
683+ }
684+ }
685+ // ExtendedContentMessageWithSear - extended content with search
686+ if searMsg := content .GetExtendedMessageContentWithSear (); searMsg != nil {
687+ if nativeURL := searMsg .GetNativeURL (); nativeURL != "" {
688+ return nativeURL
689+ }
690+ }
691+ }
692+ }
639693 }
640694
641695 return ""
@@ -893,6 +947,7 @@ func (c *Client) extractE2EEMessage(e *events.FBMessage, senderID int64) *E2EEMe
893947 if ca , ok := e .Message .(* waConsumerApplication.ConsumerApplication ); ok {
894948 if p := ca .GetPayload (); p != nil {
895949 if content := p .GetContent (); content != nil {
950+
896951 // Check for image
897952 if img , ok := content .GetContent ().(* waConsumerApplication.ConsumerApplication_Content_ImageMessage ); ok {
898953 att := c .extractE2EEImageAttachment (img .ImageMessage )
@@ -958,24 +1013,40 @@ func (c *Client) extractE2EEMessage(e *events.FBMessage, senderID int64) *E2EEMe
9581013 // Check for extended text (with URL preview)
9591014 if ext , ok := content .GetContent ().(* waConsumerApplication.ConsumerApplication_Content_ExtendedTextMessage ); ok {
9601015 if extMsg := ext .ExtendedTextMessage ; extMsg != nil {
1016+ var textContent , matchedText , canonicalURL string
9611017 if textMsg := extMsg .GetText (); textMsg != nil {
962- msg .Text = textMsg .GetText ()
1018+ textContent = textMsg .GetText ()
1019+ if textContent != "" {
1020+ msg .Text = textContent
1021+ }
9631022 // Extract mentions from extended text
9641023 if mentions := extractE2EEMentions (textMsg ); mentions != nil {
9651024 msg .Mentions = mentions
9661025 }
9671026 }
968- if extMsg .GetCanonicalURL () != "" || extMsg .GetMatchedText () != "" {
1027+ matchedText = extMsg .GetMatchedText ()
1028+ canonicalURL = extMsg .GetCanonicalURL ()
1029+
1030+ // If text is still empty, use matched text (URL)
1031+ if msg .Text == "" && matchedText != "" {
1032+ msg .Text = matchedText
1033+ }
1034+ // If still empty, use canonical URL
1035+ if msg .Text == "" && canonicalURL != "" {
1036+ msg .Text = canonicalURL
1037+ }
1038+ // Create link attachment if we have a URL
1039+ linkURL := canonicalURL
1040+ if linkURL == "" {
1041+ linkURL = matchedText
1042+ }
1043+ if linkURL != "" {
9691044 att := & Attachment {
9701045 Type : "link" ,
971- URL : extMsg . GetCanonicalURL () ,
1046+ URL : linkURL ,
9721047 FileName : extMsg .GetTitle (),
9731048 Description : extMsg .GetDescription (),
9741049 }
975- // If no canonical URL, use matched text as the URL
976- if att .URL == "" && extMsg .GetMatchedText () != "" {
977- att .URL = extMsg .GetMatchedText ()
978- }
9791050 // Try to decode thumbnail for preview
9801051 if thumb , err := extMsg .DecodeThumbnail (); err == nil && thumb != nil {
9811052 if ancillary := thumb .GetAncillary (); ancillary != nil {
@@ -991,9 +1062,90 @@ func (c *Client) extractE2EEMessage(e *events.FBMessage, senderID int64) *E2EEMe
9911062 }
9921063 }
9931064
1065+ // Extract from Armadillo (special messages like links, payments, etc.)
1066+ if armadillo , ok := e .Message .(* waArmadilloApplication.Armadillo ); ok {
1067+ payload := armadillo .GetPayload ()
1068+ if payload == nil {
1069+ return msg
1070+ }
1071+
1072+ // Try Content first (link shares, etc.)
1073+ if content := payload .GetContent (); content != nil {
1074+ // ExtendedContentMessage - used for link shares
1075+ if extMsg := content .GetExtendedContentMessage (); extMsg != nil {
1076+ att := c .extractArmadilloLinkAttachment (extMsg )
1077+ if att != nil {
1078+ msg .Attachments = append (msg .Attachments , att )
1079+ }
1080+ }
1081+
1082+ // ExtendedContentMessageWithSear
1083+ if searMsg := content .GetExtendedMessageContentWithSear (); searMsg != nil {
1084+ if nativeURL := searMsg .GetNativeURL (); nativeURL != "" {
1085+ att := & Attachment {
1086+ Type : "link" ,
1087+ URL : nativeURL ,
1088+ }
1089+ msg .Attachments = append (msg .Attachments , att )
1090+ }
1091+ }
1092+ }
1093+ }
1094+
9941095 return msg
9951096}
9961097
1098+ // extractArmadilloLinkAttachment extracts link attachment from Armadillo ExtendedContentMessage
1099+ func (c * Client ) extractArmadilloLinkAttachment (extMsg * waArmadilloXMA.ExtendedContentMessage ) * Attachment {
1100+ if extMsg == nil {
1101+ return nil
1102+ }
1103+
1104+ // Try to get URL from CTAs
1105+ var linkURL string
1106+ if ctas := extMsg .GetCtas (); len (ctas ) > 0 {
1107+ for _ , cta := range ctas {
1108+ if actionURL := cta .GetActionURL (); actionURL != "" {
1109+ // Try to extract actual URL from /l.php redirect
1110+ if parsedURL := extractURLFromLPHP (actionURL ); parsedURL != "" {
1111+ linkURL = parsedURL
1112+ } else {
1113+ linkURL = actionURL
1114+ }
1115+ break
1116+ }
1117+ if nativeURL := cta .GetNativeURL (); nativeURL != "" {
1118+ linkURL = nativeURL
1119+ break
1120+ }
1121+ }
1122+ }
1123+
1124+ // If no URL found, skip creating attachment
1125+ if linkURL == "" {
1126+ return nil
1127+ }
1128+
1129+ att := & Attachment {
1130+ Type : "link" ,
1131+ URL : linkURL ,
1132+ FileName : extMsg .GetTitleText (), // Use as fileName (title)
1133+ Description : extMsg .GetSubtitleText (), // Use as description
1134+ }
1135+
1136+ // Additional metadata
1137+ if header := extMsg .GetHeaderTitle (); header != "" && att .FileName == "" {
1138+ att .FileName = header
1139+ }
1140+
1141+ // Set source text from overlay
1142+ if overlay := extMsg .GetOverlayTitle (); overlay != "" {
1143+ att .SourceText = overlay
1144+ }
1145+
1146+ return att
1147+ }
1148+
9971149// extractE2EEImageAttachment extracts image attachment with full metadata
9981150func (c * Client ) extractE2EEImageAttachment (img * waConsumerApplication.ConsumerApplication_ImageMessage ) * Attachment {
9991151 att := & Attachment {
0 commit comments