diff --git a/app/services/facebook/send_reply_service.rb b/app/services/facebook/send_reply_service.rb index 37630f12e..99a67e46b 100644 --- a/app/services/facebook/send_reply_service.rb +++ b/app/services/facebook/send_reply_service.rb @@ -1,68 +1,66 @@ -module Facebook - class SendReplyService - pattr_initialize [:message!] +class Facebook::SendReplyService + pattr_initialize [:message!] - def perform - return if message.private - return if inbox.channel.class.to_s != 'Channel::FacebookPage' - return unless outgoing_message_from_chatwoot? + def perform + return if message.private + return if inbox.channel.class.to_s != 'Channel::FacebookPage' + return unless outgoing_message_from_chatwoot? - Bot.deliver(delivery_params, access_token: message.channel_token) - end + Bot.deliver(delivery_params, access_token: message.channel_token) + end - private + private - delegate :contact, to: :conversation + delegate :contact, to: :conversation - def inbox - @inbox ||= message.inbox - end + def inbox + @inbox ||= message.inbox + end - def conversation - @conversation ||= message.conversation - end + def conversation + @conversation ||= message.conversation + end - def outgoing_message_from_chatwoot? - # messages sent directly from chatwoot won't have fb_id. - message.outgoing? && !message.fb_id - end + def outgoing_message_from_chatwoot? + # messages sent directly from chatwoot won't have fb_id. + message.outgoing? && !message.fb_id + end - # def reopen_lock - # if message.incoming? && conversation.locked? - # conversation.unlock! - # end - # end + # def reopen_lock + # if message.incoming? && conversation.locked? + # conversation.unlock! + # end + # end - def fb_message_params - { - recipient: { id: contact.get_source_id(inbox.id) }, - message: { text: message.content } - } - end + def fb_message_params + { + recipient: { id: contact.get_source_id(inbox.id) }, + message: { text: message.content } + } + end - def delivery_params - if twenty_four_hour_window_over? - fb_message_params.merge(tag: 'ISSUE_RESOLUTION') - else - fb_message_params - end - end - - def twenty_four_hour_window_over? - last_incoming_message = conversation.messages.incoming.last - - is_after_24_hours = (Time.current - last_incoming_message.created_at) / 3600 >= 24 - - return false unless is_after_24_hours - - return false if last_incoming_message && sent_first_outgoing_message_after_24_hours?(last_incoming_message.id) - - true - end - - def sent_first_outgoing_message_after_24_hours?(last_incoming_message_id) - # we can send max 1 message after 24 hour window - conversation.messages.outgoing.where('id > ?', last_incoming_message_id).count == 1 + def delivery_params + if twenty_four_hour_window_over? + fb_message_params.merge(tag: 'ISSUE_RESOLUTION') + else + fb_message_params end end + + def twenty_four_hour_window_over? + last_incoming_message = conversation.messages.incoming.last + + is_after_24_hours = (Time.current - last_incoming_message.created_at) / 3600 >= 24 + + return false unless is_after_24_hours + + return false if last_incoming_message && sent_first_outgoing_message_after_24_hours?(last_incoming_message.id) + + true + end + + def sent_first_outgoing_message_after_24_hours?(last_incoming_message_id) + # we can send max 1 message after 24 hour window + conversation.messages.outgoing.where('id > ?', last_incoming_message_id).count == 1 + end end diff --git a/spec/factories/facebook_page.rb b/spec/factories/facebook_page.rb new file mode 100644 index 000000000..3323b64f7 --- /dev/null +++ b/spec/factories/facebook_page.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :facebook_page, class: 'Channel::FacebookPage' do + sequence(:page_id) { |n| n } + sequence(:user_access_token) { |n| "random-token-#{n}" } + sequence(:name) { |n| "Facebook Page #{n}" } + sequence(:page_access_token) { |n| "page-access-token-#{n}" } + account + end +end diff --git a/spec/factories/messages.rb b/spec/factories/messages.rb index 4d6e6dfea..4c60c1d04 100644 --- a/spec/factories/messages.rb +++ b/spec/factories/messages.rb @@ -5,7 +5,6 @@ FactoryBot.define do content { 'Message' } status { 'sent' } message_type { 'incoming' } - fb_id { SecureRandom.uuid } account inbox conversation diff --git a/spec/services/facebook/send_reply_service_spec.rb b/spec/services/facebook/send_reply_service_spec.rb new file mode 100644 index 000000000..f926fa833 --- /dev/null +++ b/spec/services/facebook/send_reply_service_spec.rb @@ -0,0 +1,51 @@ +require 'rails_helper' + +describe Facebook::SendReplyService do + subject(:send_reply_service) { described_class.new(message: message) } + + before do + allow(Facebook::Messenger::Subscriptions).to receive(:subscribe).and_return(true) + allow(bot).to receive(:deliver) + end + + let!(:account) { create(:account) } + let(:bot) { class_double('Bot').as_stubbed_const } + let!(:widget_inbox) { create(:inbox, account: account) } + let!(:facebook_channel) { create(:facebook_page, account: account) } + let!(:facebook_inbox) { create(:inbox, channel: facebook_channel, account: account) } + let!(:contact) { create(:contact, account: account) } + let(:conversation) { create(:conversation, contact: contact, inbox: facebook_inbox) } + + describe '#perform' do + context 'without reply' do + it 'if message is private' do + create(:message, message_type: 'outgoing', private: true, inbox: facebook_inbox, account: account) + expect(bot).not_to have_received(:deliver) + end + + it 'if inbox channel is not facebook page' do + create(:message, message_type: 'outgoing', inbox: widget_inbox, account: account) + expect(bot).not_to have_received(:deliver) + end + + it 'if message is not outgoing' do + create(:message, message_type: 'incoming', inbox: facebook_inbox, account: account) + expect(bot).not_to have_received(:deliver) + end + + it 'if message has an FB ID' do + create(:message, message_type: 'outgoing', inbox: facebook_inbox, account: account, fb_id: SecureRandom.uuid) + expect(bot).not_to have_received(:deliver) + end + end + + context 'with reply' do + it 'if message is sent from chatwoot and is outgoing' do + create(:contact_inbox, contact: contact, inbox: facebook_inbox) + create(:message, message_type: :incoming, inbox: facebook_inbox, account: account, conversation: conversation) + create(:message, message_type: 'outgoing', inbox: facebook_inbox, account: account, conversation: conversation) + expect(bot).to have_received(:deliver) + end + end + end +end