fix: scope external_url override to Instagram DM conversations only (#13982)

Previously, all incoming messages from Facebook channel with
instagram_id had their attachment data_url and thumb_url overridden with
external_url. This caused issues for non-Instagram conversations
originating from Facebook Message where the file URL should be used
instead.

Narrows the override to only apply when the conversation type is
instagram_direct_message, which is the only case where Instagram's CDN
URLs need to be used directly.

Fixes
https://linear.app/chatwoot/issue/CW-6722/videos-are-missing-in-facebook-conversation

---------

Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Pranav
2026-04-02 07:26:23 -07:00
committed by GitHub
parent b9b5a18767
commit 441fe4db11
2 changed files with 86 additions and 6 deletions

View File

@@ -120,7 +120,7 @@ class Attachment < ApplicationRecord
height: file.metadata[:height] height: file.metadata[:height]
} }
metadata[:data_url] = metadata[:thumb_url] = external_url if message.inbox.instagram? && message.incoming? metadata[:data_url] = metadata[:thumb_url] = external_url if instagram_incoming_message?
metadata metadata
end end
@@ -156,6 +156,14 @@ class Attachment < ApplicationRecord
} }
end end
def instagram_incoming_message?
return false unless message.incoming?
return true if message.inbox.instagram_direct?
message.inbox.instagram? && message.conversation&.additional_attributes&.dig('type') == 'instagram_direct_message'
end
def set_extension def set_extension
return unless file.attached? return unless file.attached?
return if extension.present? return if extension.present?

View File

@@ -57,11 +57,6 @@ RSpec.describe Attachment do
}.to_json, headers: {}) }.to_json, headers: {})
end end
it 'returns external url as data and thumb urls when message is incoming' do
external_url = instagram_message.attachments.first.external_url
expect(instagram_message.attachments.first.push_event_data[:data_url]).to eq external_url
end
it 'returns original attachment url as data url if the message is outgoing' do it 'returns original attachment url as data url if the message is outgoing' do
message = create(:message, :instagram_story_mention, message_type: :outgoing) message = create(:message, :instagram_story_mention, message_type: :outgoing)
expect(message.attachments.first.push_event_data[:data_url]).not_to eq message.attachments.first.external_url expect(message.attachments.first.push_event_data[:data_url]).not_to eq message.attachments.first.external_url
@@ -155,6 +150,83 @@ RSpec.describe Attachment do
end end
end end
describe 'push_event_data for instagram direct message attachments' do
let(:account) { create(:account) }
let(:instagram_inbox) do
create(:inbox, account: account,
channel: create(:channel_instagram_fb_page, account: account, instagram_id: 'instagram-dm-test'))
end
context 'when conversation type is instagram_direct_message' do
let(:conversation) do
create(:conversation, account: account, inbox: instagram_inbox,
additional_attributes: { 'type' => 'instagram_direct_message' })
end
let(:instagram_message) { create(:message, account: account, inbox: instagram_inbox, conversation: conversation, message_type: :incoming) }
it 'uses external_url for data_url and thumb_url' do
attachment = instagram_message.attachments.new(account_id: account.id, file_type: :image, external_url: 'https://instagram.com/image.jpg')
attachment.file.attach(io: Rails.root.join('spec/assets/avatar.png').open, filename: 'avatar.png', content_type: 'image/png')
attachment.save!
event_data = attachment.push_event_data
expect(event_data[:data_url]).to eq('https://instagram.com/image.jpg')
expect(event_data[:thumb_url]).to eq('https://instagram.com/image.jpg')
end
end
context 'when conversation type is not instagram_direct_message' do
let(:conversation) do
create(:conversation, account: account, inbox: instagram_inbox,
additional_attributes: { 'type' => 'other_type' })
end
let(:instagram_message) { create(:message, account: account, inbox: instagram_inbox, conversation: conversation, message_type: :incoming) }
it 'uses file_url for data_url instead of external_url' do
attachment = instagram_message.attachments.new(account_id: account.id, file_type: :image, external_url: 'https://instagram.com/image.jpg')
attachment.file.attach(io: Rails.root.join('spec/assets/avatar.png').open, filename: 'avatar.png', content_type: 'image/png')
attachment.save!
event_data = attachment.push_event_data
expect(event_data[:data_url]).not_to eq('https://instagram.com/image.jpg')
end
end
context 'when message is outgoing on instagram DM conversation' do
let(:conversation) do
create(:conversation, account: account, inbox: instagram_inbox,
additional_attributes: { 'type' => 'instagram_direct_message' })
end
let(:outgoing_message) { create(:message, account: account, inbox: instagram_inbox, conversation: conversation, message_type: :outgoing) }
it 'does not override data_url with external_url' do
attachment = outgoing_message.attachments.new(account_id: account.id, file_type: :image, external_url: 'https://instagram.com/image.jpg')
attachment.file.attach(io: Rails.root.join('spec/assets/avatar.png').open, filename: 'avatar.png', content_type: 'image/png')
attachment.save!
event_data = attachment.push_event_data
expect(event_data[:data_url]).not_to eq('https://instagram.com/image.jpg')
end
end
context 'when inbox is Channel::Instagram (direct login)' do
let(:instagram_channel) { create(:channel_instagram, account: account) }
let(:direct_inbox) { instagram_channel.inbox }
let(:conversation) { create(:conversation, account: account, inbox: direct_inbox) }
let(:incoming_message) { create(:message, account: account, inbox: direct_inbox, conversation: conversation, message_type: :incoming) }
it 'uses external_url for data_url and thumb_url' do
attachment = incoming_message.attachments.new(account_id: account.id, file_type: :image, external_url: 'https://instagram.com/image.jpg')
attachment.file.attach(io: Rails.root.join('spec/assets/avatar.png').open, filename: 'avatar.png', content_type: 'image/png')
attachment.save!
event_data = attachment.push_event_data
expect(event_data[:data_url]).to eq('https://instagram.com/image.jpg')
expect(event_data[:thumb_url]).to eq('https://instagram.com/image.jpg')
end
end
end
describe 'push_event_data for ig_reel attachments' do describe 'push_event_data for ig_reel attachments' do
it 'returns external_url as data_url when no file is attached' do it 'returns external_url as data_url when no file is attached' do
attachment = message.attachments.create!( attachment = message.attachments.create!(