fix: Do not allow sending messages if merged contact has a duplicate session (#11152)
In this PR https://github.com/chatwoot/chatwoot/pull/11139, if there is an attempt to create a duplication session for the contact in the same inbox, we will anonymize the old session. This PR would prevent sending messages to the older sessions. The support agents will have to create a new conversation to continue messages with customer.
This commit is contained in:
@@ -12,8 +12,10 @@ class Base::SendOnChannelService
|
||||
|
||||
def perform
|
||||
validate_target_channel
|
||||
|
||||
return unless outgoing_message?
|
||||
return if invalid_message?
|
||||
return if invalid_source_id?
|
||||
|
||||
perform_reply
|
||||
end
|
||||
@@ -49,6 +51,29 @@ class Base::SendOnChannelService
|
||||
message.private? || outgoing_message_originated_from_channel?
|
||||
end
|
||||
|
||||
def invalid_source_id?
|
||||
return false unless channels_to_validate?
|
||||
|
||||
return false if contact_inbox.source_id == expected_source_id
|
||||
|
||||
message.update!(status: :failed, external_error: I18n.t('errors.channel_service.invalid_source_id'))
|
||||
true
|
||||
end
|
||||
|
||||
def expected_source_id
|
||||
ContactInbox::SourceIdService.new(
|
||||
contact: contact,
|
||||
channel_type: inbox.channel_type,
|
||||
medium: inbox.channel.try(:medium)
|
||||
).generate
|
||||
rescue ArgumentError
|
||||
nil
|
||||
end
|
||||
|
||||
def channels_to_validate?
|
||||
inbox.sms? || inbox.whatsapp? || inbox.email? || inbox.twilio?
|
||||
end
|
||||
|
||||
def validate_target_channel
|
||||
raise 'Invalid channel service was called' if inbox.channel.class != channel_class
|
||||
end
|
||||
|
||||
55
app/services/contact_inbox/source_id_service.rb
Normal file
55
app/services/contact_inbox/source_id_service.rb
Normal file
@@ -0,0 +1,55 @@
|
||||
class ContactInbox::SourceIdService
|
||||
pattr_initialize [:contact!, :channel_type!, { medium: nil }]
|
||||
|
||||
def generate
|
||||
case channel_type
|
||||
when 'Channel::TwilioSms'
|
||||
twilio_source_id
|
||||
when 'Channel::Whatsapp'
|
||||
wa_source_id
|
||||
when 'Channel::Email'
|
||||
email_source_id
|
||||
when 'Channel::Sms'
|
||||
phone_source_id
|
||||
when 'Channel::Api', 'Channel::WebWidget'
|
||||
SecureRandom.uuid
|
||||
else
|
||||
raise ArgumentError, "Unsupported operation for this channel: #{channel_type}"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def email_source_id
|
||||
raise ArgumentError, 'contact email required' unless contact.email
|
||||
|
||||
contact.email
|
||||
end
|
||||
|
||||
def phone_source_id
|
||||
raise ArgumentError, 'contact phone number required' unless contact.phone_number
|
||||
|
||||
contact.phone_number
|
||||
end
|
||||
|
||||
def wa_source_id
|
||||
raise ArgumentError, 'contact phone number required' unless contact.phone_number
|
||||
|
||||
# whatsapp doesn't want the + in e164 format
|
||||
contact.phone_number.delete('+').to_s
|
||||
end
|
||||
|
||||
def twilio_source_id
|
||||
raise ArgumentError, 'contact phone number required' unless contact.phone_number
|
||||
raise ArgumentError, 'medium required for Twilio channel' if medium.blank?
|
||||
|
||||
case medium
|
||||
when 'sms'
|
||||
contact.phone_number
|
||||
when 'whatsapp'
|
||||
"whatsapp:#{contact.phone_number}"
|
||||
else
|
||||
raise ArgumentError, "Unsupported Twilio medium: #{medium}"
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user