Compare commits

...
Author SHA1 Message Date
Muhsin 33bafb0f63 fix(whatsapp): resolve replies across scoped message ids 2026-07-21 12:31:40 +04:00
3 changed files with 44 additions and 0 deletions
@@ -0,0 +1,37 @@
class Whatsapp::InReplyToMessageFinder
MESSAGE_TOKEN_PATTERN = /(?<![0-9a-f])(?:[0-9a-f]{32}|[0-9a-f]{20})(?![0-9a-f])/i
pattr_initialize [:conversation!, :source_id!]
def perform
exact_match || matching_scoped_message
end
private
def exact_match
conversation.messages.find_by(source_id: source_id)
end
def matching_scoped_message
token = message_token(source_id)
return if token.blank?
# Phone-scoped and BSUID-scoped WAMIDs can carry the same message token
# even when their complete source IDs differ.
matches = conversation.messages.where('source_id LIKE ?', 'wamid.%').select(:id, :source_id).select do |message|
message_token(message.source_id) == token
end
matches.one? ? matches.first : nil
end
def message_token(message_id)
return unless message_id.start_with?('wamid.')
tokens = Base64.strict_decode64(message_id.delete_prefix('wamid.')).scan(MESSAGE_TOKEN_PATTERN)
tokens.one? ? tokens.first.downcase : nil
rescue ArgumentError
nil
end
end
@@ -174,6 +174,7 @@ class Whatsapp::IncomingMessageBaseService
def message_content_attributes(message)
content_attrs = outgoing_echo ? { external_echo: true } : {}
content_attrs[:in_reply_to] = @in_reply_to_message_id if @in_reply_to_message_id.present?
content_attrs[:in_reply_to_external_id] = @in_reply_to_external_id if @in_reply_to_external_id.present?
referral_content_attrs = referral_attributes(message)
content_attrs[:referral] = referral_content_attrs if referral_content_attrs.present?
@@ -69,6 +69,12 @@ module Whatsapp::IncomingMessageServiceHelpers
def process_in_reply_to(message)
@in_reply_to_external_id = message['context']&.[]('id')
return if @in_reply_to_external_id.blank?
@in_reply_to_message_id = Whatsapp::InReplyToMessageFinder.new(
conversation: @conversation,
source_id: @in_reply_to_external_id
).perform&.id
end
def referral_attributes(message)