diff --git a/app/javascript/dashboard/components/widgets/conversation/MessagePreview.vue b/app/javascript/dashboard/components/widgets/conversation/MessagePreview.vue index d2f6b44c5..22d69439e 100644 --- a/app/javascript/dashboard/components/widgets/conversation/MessagePreview.vue +++ b/app/javascript/dashboard/components/widgets/conversation/MessagePreview.vue @@ -20,7 +20,15 @@ icon="info" /> - + + + {{ $t('CHAT_LIST.ATTACHMENTS.image.CONTENT') }} + + {{ parsedLastMessage }} @@ -88,6 +96,9 @@ export default { attachmentMessageContent() { return `CHAT_LIST.ATTACHMENTS.${this.lastMessageFileType}.CONTENT`; }, + isMessageSticker() { + return this.message && this.message.content_type === 'sticker'; + }, }, }; diff --git a/app/models/message.rb b/app/models/message.rb index 93258da5a..27d5b6046 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -89,7 +89,8 @@ class Message < ApplicationRecord article: 7, incoming_email: 8, input_csat: 9, - integrations: 10 + integrations: 10, + sticker: 11 } enum status: { sent: 0, delivered: 1, read: 2, failed: 3 } # [:submitted_email, :items, :submitted_values] : Used for bot message types diff --git a/app/services/line/incoming_message_service.rb b/app/services/line/incoming_message_service.rb index 48a52eb8f..121ba1ce2 100644 --- a/app/services/line/incoming_message_service.rb +++ b/app/services/line/incoming_message_service.rb @@ -4,6 +4,7 @@ class Line::IncomingMessageService include ::FileTypeHelper pattr_initialize [:inbox!, :params!] + LINE_STICKER_IMAGE_URL = 'https://stickershop.line-scdn.net/stickershop/v1/sticker/%s/iphone/sticker.png'.freeze def perform # probably test events @@ -31,8 +32,9 @@ class Line::IncomingMessageService return unless event_type_message?(event) @message = @conversation.messages.create!( - content: event['message']['text'], + content: message_content(event), account_id: @inbox.account_id, + content_type: message_content_type(event), inbox_id: @inbox.id, message_type: :incoming, sender: @contact, @@ -41,6 +43,33 @@ class Line::IncomingMessageService @message end + def message_content(event) + message_type = event.dig('message', 'type') + case message_type + when 'text' + event.dig('message', 'text') + when 'sticker' + sticker_id = event.dig('message', 'stickerId') + sticker_image_url(sticker_id) + end + end + + # Currently, Chatwoot doesn't support stickers. As a temporary solution, + # we're displaying stickers as images using the sticker ID in markdown format. + # This is subject to change in the future. We've chosen not to download and display the sticker as an image because the sticker's information + # and images are the property of the creator or legal owner. We aim to avoid storing it on our server without their consent. + # If there are any permission or rendering issues, the URL may break, and we'll display the sticker ID as text instead. + # Ref: https://developers.line.biz/en/reference/messaging-api/#wh-sticker + def sticker_image_url(sticker_id) + "![sticker-#{sticker_id}](#{LINE_STICKER_IMAGE_URL % sticker_id})" + end + + def message_content_type(event) + return 'sticker' if event['message']['type'] == 'sticker' + + 'text' + end + def attach_files(message) return unless message_type_non_text?(message['type']) @@ -65,7 +94,7 @@ class Line::IncomingMessageService end def event_type_message?(event) - event['type'] == 'message' + event['type'] == 'message' || event['type'] == 'sticker' end def message_type_non_text?(type) diff --git a/spec/services/line/incoming_message_service_spec.rb b/spec/services/line/incoming_message_service_spec.rb index ee53421b5..0547cfbd0 100644 --- a/spec/services/line/incoming_message_service_spec.rb +++ b/spec/services/line/incoming_message_service_spec.rb @@ -105,6 +105,41 @@ describe Line::IncomingMessageService do }.with_indifferent_access end + let(:sticker_params) do + { + 'destination': '2342234234', + 'events': [ + { + 'replyToken': '0f3779fba3b349968c5d07db31eab56f', + 'type': 'message', + 'mode': 'active', + 'timestamp': 1_462_629_479_859, + 'source': { + 'type': 'user', + 'userId': 'U4af4980629' + }, + 'message': { + 'type': 'sticker', + 'id': '1501597916', + 'quoteToken': 'q3Plxr4AgKd...', + 'stickerId': '52002738', + 'packageId': '11537' + } + }, + { + 'replyToken': '8cf9239d56244f4197887e939187e19e', + 'type': 'follow', + 'mode': 'active', + 'timestamp': 1_462_629_479_859, + 'source': { + 'type': 'user', + 'userId': 'U4af4980629' + } + } + ] + }.with_indifferent_access + end + describe '#perform' do context 'when valid text message params' do it 'creates appropriate conversations, message and contacts' do @@ -126,6 +161,26 @@ describe Line::IncomingMessageService do end end + context 'when valid sticker message params' do + it 'creates appropriate conversations, message and contacts' do + line_bot = double + line_user_profile = double + allow(Line::Bot::Client).to receive(:new).and_return(line_bot) + allow(line_bot).to receive(:get_profile).and_return(line_user_profile) + allow(line_user_profile).to receive(:body).and_return( + { + 'displayName': 'LINE Test', + 'userId': 'U4af4980629', + 'pictureUrl': 'https://test.com' + }.to_json + ) + described_class.new(inbox: line_channel.inbox, params: sticker_params).perform + expect(line_channel.inbox.conversations).not_to eq(0) + expect(Contact.all.first.name).to eq('LINE Test') + expect(line_channel.inbox.messages.first.content).to eq('![sticker-52002738](https://stickershop.line-scdn.net/stickershop/v1/sticker/52002738/iphone/sticker.png)') + end + end + context 'when valid image message params' do it 'creates appropriate conversations, message and contacts' do line_bot = double