mirror of
https://github.com/chatwoot/chatwoot.git
synced 2026-06-04 21:02:35 +08:00
Adds storage support for WhatsApp business-scoped user identifiers received from Meta Cloud API and Twilio WhatsApp webhooks. The change keeps existing phone-based behavior intact, stores BSUID and parent BSUID values as additional `contact_inboxes.source_id` rows for the same contact, and allows BSUID-only inbound messages to create contacts, conversations, and messages without requiring a phone number. Related: https://github.com/chatwoot/chatwoot/issues/13837 **What changed** - Extended WhatsApp source ID validation to accept regular BSUID and parent BSUID formats. - For Meta Cloud API, stores phone, `user_id`, and `parent_user_id` identifiers as contact inbox source IDs when they are present. - For Twilio WhatsApp, stores phone, `ExternalUserId`, and `ParentExternalUserId` identifiers as contact inbox source IDs while preserving the existing `whatsapp:` Twilio source ID shape. - Supports BSUID-only inbound messages by creating a contact, contact inbox, conversation, and message even when the phone number is missing. - Links phone-first and later BSUID-only messages to the same contact when the first payload contains both phone and BSUID. - Stores WhatsApp usernames in contact `additional_attributes`, matching existing social channel patterns. - Keeps existing phone-based outbound and new-conversation behavior unchanged for this milestone. **How to test** 1. Send a Meta Cloud webhook payload with both `wa_id` and `user_id`. 2. Verify Chatwoot creates or finds the phone `contact_inbox` and also creates a BSUID `contact_inbox` for the same contact. 3. Send a later Meta Cloud payload for the same user with only `user_id` / `from_user_id`. 4. Verify Chatwoot finds the BSUID `contact_inbox` and creates the inbound message without requiring a phone number. 5. Send a Twilio WhatsApp webhook with `From: whatsapp:+E164`, `ExternalUserId`, and optionally `ParentExternalUserId`. 6. Verify Chatwoot stores the Twilio phone and BSUID identifiers as `whatsapp:`-prefixed source IDs for the same contact. 7. Send a Twilio WhatsApp webhook where `From` is `whatsapp:<BSUID>` and there is no phone number. 8. Verify Chatwoot creates the contact, contact inbox, conversation, and message without a phone number. --------- Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com>
22 lines
1.3 KiB
Ruby
22 lines
1.3 KiB
Ruby
module RegexHelper
|
|
# user https://rubular.com/ to quickly validate your regex
|
|
|
|
# the following regext needs atleast one character which should be
|
|
# valid unicode letter, unicode number, underscore, hyphen
|
|
# shouldn't start with a underscore or hyphen
|
|
UNICODE_CHARACTER_NUMBER_HYPHEN_UNDERSCORE = Regexp.new('\A[\p{L}\p{N}]+[\p{L}\p{N}_-]+\Z')
|
|
# Regex to match mention markdown links and extract display names
|
|
# Matches: [@display name](mention://user|team/id/url_encoded_name)
|
|
# Captures: 1) @display name (including emojis), 2) url_encoded_name
|
|
# Uses [^]]+ to match any characters except ] in display name to support emojis
|
|
# NOTE: Still used by Slack integration (lib/integrations/slack/send_on_slack_service.rb)
|
|
# while notifications use CommonMarker for better markdown processing
|
|
MENTION_REGEX = Regexp.new('\[(@[^\\]]+)\]\(mention://(?:user|team)/\d+/([^)]+)\)')
|
|
|
|
TWILIO_CHANNEL_SMS_REGEX = Regexp.new('\A\+\d{1,15}\z')
|
|
WHATSAPP_BSUID_PATTERN = '[A-Z]{2}\.(?:ENT\.)?[A-Za-z0-9]{1,128}'.freeze
|
|
WHATSAPP_BSUID_REGEX = Regexp.new("\\A#{WHATSAPP_BSUID_PATTERN}\\z")
|
|
TWILIO_CHANNEL_WHATSAPP_REGEX = Regexp.new("\\A(?:whatsapp:\\+\\d{1,15}|whatsapp:#{WHATSAPP_BSUID_PATTERN})\\z")
|
|
WHATSAPP_CHANNEL_REGEX = Regexp.new("\\A(?:\\d{1,15}|#{WHATSAPP_BSUID_PATTERN})\\z")
|
|
end
|