From 65e91f6a6fddf3fce620351659b822052d1d6fca Mon Sep 17 00:00:00 2001 From: Tejaswini Chile Date: Mon, 15 May 2023 16:25:15 +0530 Subject: [PATCH] fix: Duplicate instagram conversations for echo messages (#7078) --- .../messages/instagram/message_builder.rb | 12 +++---- app/jobs/webhooks/instagram_events_job.rb | 6 +++- .../instagram/message_builder_spec.rb | 33 +++++++++++++++++++ .../instagram_message_create_event.rb | 27 +++++++++++++++ .../webhooks/instagram_events_job_spec.rb | 19 +++++++++++ 5 files changed, 90 insertions(+), 7 deletions(-) diff --git a/app/builders/messages/instagram/message_builder.rb b/app/builders/messages/instagram/message_builder.rb index e917af5db..eb34d4052 100644 --- a/app/builders/messages/instagram/message_builder.rb +++ b/app/builders/messages/instagram/message_builder.rb @@ -63,7 +63,9 @@ class Messages::Instagram::MessageBuilder < Messages::Messenger::MessageBuilder end def conversation - @conversation ||= Conversation.find_by(conversation_params) || build_conversation + @conversation ||= Conversation.where( + "additional_attributes ->> 'type' = 'instagram_direct_message'" + ).find_by(conversation_params) || build_conversation end def message_content @@ -95,7 +97,8 @@ class Messages::Instagram::MessageBuilder < Messages::Messenger::MessageBuilder def build_conversation @contact_inbox ||= contact.contact_inboxes.find_by!(source_id: message_source_id) Conversation.create!(conversation_params.merge( - contact_inbox_id: @contact_inbox.id + contact_inbox_id: @contact_inbox.id, + additional_attributes: { type: 'instagram_direct_message' } )) end @@ -103,10 +106,7 @@ class Messages::Instagram::MessageBuilder < Messages::Messenger::MessageBuilder { account_id: @inbox.account_id, inbox_id: @inbox.id, - contact_id: contact.id, - additional_attributes: { - type: 'instagram_direct_message' - } + contact_id: contact.id } end diff --git a/app/jobs/webhooks/instagram_events_job.rb b/app/jobs/webhooks/instagram_events_job.rb index 0f78c6277..ad02a3c18 100644 --- a/app/jobs/webhooks/instagram_events_job.rb +++ b/app/jobs/webhooks/instagram_events_job.rb @@ -14,7 +14,7 @@ class Webhooks::InstagramEventsJob < ApplicationJob @entries.each do |entry| entry = entry.with_indifferent_access - entry[:messaging].each do |messaging| + messages(entry).each do |messaging| send(@event_name, messaging) if event_name(messaging) end end @@ -29,4 +29,8 @@ class Webhooks::InstagramEventsJob < ApplicationJob def message(messaging) ::Instagram::MessageText.new(messaging).perform end + + def messages(entry) + (entry[:messaging].presence || entry[:standby]) + end end diff --git a/spec/builders/messages/instagram/message_builder_spec.rb b/spec/builders/messages/instagram/message_builder_spec.rb index e33c697eb..3eaa5c25b 100644 --- a/spec/builders/messages/instagram/message_builder_spec.rb +++ b/spec/builders/messages/instagram/message_builder_spec.rb @@ -17,6 +17,14 @@ describe ::Messages::Instagram::MessageBuilder do let(:fb_object) { double } let(:contact) { create(:contact, id: 'Sender-id-1', name: 'Jane Dae') } let(:contact_inbox) { create(:contact_inbox, contact_id: contact.id, inbox_id: instagram_inbox.id, source_id: 'Sender-id-1') } + let(:conversation) do + create(:conversation, account_id: account.id, inbox_id: instagram_inbox.id, contact_id: contact.id, + additional_attributes: { type: 'instagram_direct_message', conversation_language: 'en' }) + end + let(:message) do + create(:message, account_id: account.id, inbox_id: instagram_inbox.id, conversation_id: conversation.id, message_type: 'outgoing', + source_id: 'message-id-1') + end describe '#perform' do it 'creates contact and message for the facebook inbox' do @@ -45,6 +53,31 @@ describe ::Messages::Instagram::MessageBuilder do expect(message.content).to eq('This is the first message from the customer') end + it 'discard echo message already sent by chatwoot' do + message + + expect(instagram_inbox.conversations.count).to be 1 + expect(instagram_inbox.messages.count).to be 1 + + allow(Koala::Facebook::API).to receive(:new).and_return(fb_object) + allow(fb_object).to receive(:get_object).and_return( + { + name: 'Jane', + id: 'Sender-id-1', + account_id: instagram_inbox.account_id, + profile_pic: 'https://chatwoot-assets.local/sample.png' + }.with_indifferent_access + ) + messaging = dm_params[:entry][0]['messaging'][0] + contact_inbox + described_class.new(messaging, instagram_inbox, outgoing_echo: true).perform + + instagram_inbox.reload + + expect(instagram_inbox.conversations.count).to be 1 + expect(instagram_inbox.messages.count).to be 1 + end + it 'creates message with for reply with story id' do allow(Koala::Facebook::API).to receive(:new).and_return(fb_object) allow(fb_object).to receive(:get_object).and_return( diff --git a/spec/factories/instagram/instagram_message_create_event.rb b/spec/factories/instagram/instagram_message_create_event.rb index 0220feab5..6b66c29a7 100644 --- a/spec/factories/instagram/instagram_message_create_event.rb +++ b/spec/factories/instagram/instagram_message_create_event.rb @@ -26,6 +26,33 @@ FactoryBot.define do initialize_with { attributes } end + factory :instagram_message_standby_event, class: Hash do + entry do + [ + { + 'time': '2021-09-08T06:34:04+0000', + 'id': 'instagram-message-id-123', + 'standby': [ + { + 'sender': { + 'id': 'Sender-id-1' + }, + 'recipient': { + 'id': 'chatwoot-app-user-id-1' + }, + 'timestamp': '2021-09-08T06:34:04+0000', + 'message': { + 'mid': 'message-id-1', + 'text': 'This is the first standby message from the customer, after 24 hours.' + } + } + ] + } + ] + end + initialize_with { attributes } + end + factory :instagram_story_reply_event, class: Hash do entry do [ diff --git a/spec/jobs/webhooks/instagram_events_job_spec.rb b/spec/jobs/webhooks/instagram_events_job_spec.rb index 91085f967..b5e73e2f5 100644 --- a/spec/jobs/webhooks/instagram_events_job_spec.rb +++ b/spec/jobs/webhooks/instagram_events_job_spec.rb @@ -21,6 +21,7 @@ describe Webhooks::InstagramEventsJob do let!(:instagram_channel) { create(:channel_instagram_fb_page, account: account, instagram_id: 'chatwoot-app-user-id-1') } let!(:instagram_inbox) { create(:inbox, channel: instagram_channel, account: account, greeting_enabled: false) } let!(:dm_params) { build(:instagram_message_create_event).with_indifferent_access } + let!(:standby_params) { build(:instagram_message_standby_event).with_indifferent_access } let!(:test_params) { build(:instagram_test_text_event).with_indifferent_access } let!(:unsend_event) { build(:instagram_message_unsend_event).with_indifferent_access } let!(:attachment_params) { build(:instagram_message_attachment_event).with_indifferent_access } @@ -45,6 +46,24 @@ describe Webhooks::InstagramEventsJob do expect(instagram_inbox.messages.count).to be 1 end + it 'creates standby message in the instagram inbox' do + allow(Koala::Facebook::API).to receive(:new).and_return(fb_object) + allow(fb_object).to receive(:get_object).and_return( + return_object.with_indifferent_access + ) + instagram_webhook.perform_now(standby_params[:entry]) + + instagram_inbox.reload + + expect(instagram_inbox.contacts.count).to be 1 + expect(instagram_inbox.contacts.last.additional_attributes['social_profiles']['instagram']).to eq 'some_user_name' + expect(instagram_inbox.conversations.count).to be 1 + expect(instagram_inbox.messages.count).to be 1 + + message = instagram_inbox.messages.last + expect(message.content).to eq('This is the first standby message from the customer, after 24 hours.') + end + it 'creates test text message in the instagram inbox' do allow(Koala::Facebook::API).to receive(:new).and_return(fb_object) allow(fb_object).to receive(:get_object).and_return(