diff --git a/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue b/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue index eb9b26f30..b5022c9a2 100644 --- a/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue +++ b/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue @@ -144,6 +144,7 @@ import { FEATURE_FLAGS } from 'dashboard/featureFlags'; import { ALLOWED_FILE_TYPES, ALLOWED_FILE_TYPES_FOR_TWILIO_WHATSAPP, + ALLOWED_FILE_TYPES_FOR_LINE, } from 'shared/constants/messages'; import VideoCallButton from '../VideoCallButton.vue'; import AIAssistanceButton from '../AIAssistanceButton.vue'; @@ -270,6 +271,9 @@ export default { return this.showFileUpload || this.isNote; }, showAudioRecorderButton() { + if (this.isALineChannel) { + return false; + } // Disable audio recorder for safari browser as recording is not supported const isSafari = /^((?!chrome|android|crios|fxios).)*safari/i.test( navigator.userAgent @@ -291,6 +295,9 @@ export default { if (this.isATwilioWhatsAppChannel) { return ALLOWED_FILE_TYPES_FOR_TWILIO_WHATSAPP; } + if (this.isALineChannel) { + return ALLOWED_FILE_TYPES_FOR_LINE; + } return ALLOWED_FILE_TYPES; }, enableDragAndDrop() { diff --git a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue index 3712a08e6..e18e1c0e2 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue @@ -392,7 +392,8 @@ export default { this.isAPIInbox || this.isAnEmailChannel || this.isASmsInbox || - this.isATelegramChannel + this.isATelegramChannel || + this.isALineChannel ); }, replyButtonLabel() { diff --git a/app/javascript/shared/constants/messages.js b/app/javascript/shared/constants/messages.js index 1cf24f6a4..b53ca6826 100644 --- a/app/javascript/shared/constants/messages.js +++ b/app/javascript/shared/constants/messages.js @@ -55,6 +55,8 @@ export const ALLOWED_FILE_TYPES_FOR_TWILIO_WHATSAPP = 'audio/mpeg, audio/opus, audio/ogg, audio/amr,' + 'video/mp4,' + 'application/pdf,'; +// https://developers.line.biz/en/reference/messaging-api/#image-message, https://developers.line.biz/en/reference/messaging-api/#video-message +export const ALLOWED_FILE_TYPES_FOR_LINE = 'image/png, image/jpeg,video/mp4'; export const CSAT_RATINGS = [ { diff --git a/app/services/line/send_on_line_service.rb b/app/services/line/send_on_line_service.rb index a30de4ab4..f8d704128 100644 --- a/app/services/line/send_on_line_service.rb +++ b/app/services/line/send_on_line_service.rb @@ -6,7 +6,8 @@ class Line::SendOnLineService < Base::SendOnChannelService end def perform_reply - response = channel.client.push_message(message.conversation.contact_inbox.source_id, [{ type: 'text', text: message.content }]) + response = channel.client.push_message(message.conversation.contact_inbox.source_id, build_payload) + return if response.blank? parsed_json = JSON.parse(response.body) @@ -20,6 +21,37 @@ class Line::SendOnLineService < Base::SendOnChannelService end end + def build_payload + if message.content && message.attachments.any? + [text_message, *attachments] + elsif message.content.nil? && message.attachments.any? + attachments + else + text_message + end + end + + def attachments + message.attachments.map do |attachment| + # Support only image and video for now, https://developers.line.biz/en/reference/messaging-api/#image-message + next unless attachment.file_type == 'image' || attachment.file_type == 'video' + + { + type: attachment.file_type, + originalContentUrl: attachment.download_url, + previewImageUrl: attachment.download_url + } + end + end + + # https://developers.line.biz/en/reference/messaging-api/#text-message + def text_message + { + type: 'text', + text: message.content + } + end + # https://developers.line.biz/en/reference/messaging-api/#error-responses def external_error(error) # Message containing information about the error. See https://developers.line.biz/en/reference/messaging-api/#error-messages diff --git a/spec/services/line/send_on_line_service_spec.rb b/spec/services/line/send_on_line_service_spec.rb index 2320f8679..bed8917b8 100644 --- a/spec/services/line/send_on_line_service_spec.rb +++ b/spec/services/line/send_on_line_service_spec.rb @@ -92,5 +92,57 @@ describe Line::SendOnLineService do expect(message.status).to eq('delivered') end end + + context 'with message attachments' do + it 'sends the message with text and attachments' do + attachment = message.attachments.new(account_id: message.account_id, file_type: :image) + attachment.file.attach(io: Rails.root.join('spec/assets/avatar.png').open, filename: 'avatar.png', content_type: 'image/png') + expected_url_regex = %r{rails/active_storage/disk/[a-zA-Z0-9=_\-+]+/avatar\.png} + + expect(line_client).to receive(:push_message).with( + message.conversation.contact_inbox.source_id, + [ + { type: 'text', text: message.content }, + { + type: 'image', + originalContentUrl: match(expected_url_regex), + previewImageUrl: match(expected_url_regex) + } + ] + ) + + described_class.new(message: message).perform + end + + it 'sends the message with attachments only' do + attachment = message.attachments.new(account_id: message.account_id, file_type: :image) + attachment.file.attach(io: Rails.root.join('spec/assets/avatar.png').open, filename: 'avatar.png', content_type: 'image/png') + message.update!(content: nil) + expected_url_regex = %r{rails/active_storage/disk/[a-zA-Z0-9=_\-+]+/avatar\.png} + + expect(line_client).to receive(:push_message).with( + message.conversation.contact_inbox.source_id, + [ + { + type: 'image', + originalContentUrl: match(expected_url_regex), + previewImageUrl: match(expected_url_regex) + } + ] + ) + + described_class.new(message: message).perform + end + + it 'sends the message with text only' do + message.attachments.destroy_all + expect(line_client).to receive(:push_message).with( + message.conversation.contact_inbox.source_id, + { type: 'text', text: message.content } + ) + + described_class.new(message: message).perform + end + end end end