feat: Ability to receive attachments from LINE messenger (#3094)

Add support to add videos, audio, and images from line to chatwoot.

Fixes #3039
This commit is contained in:
Murtaza Bagwala 2021-10-11 19:06:41 +05:30 committed by GitHub
parent 2c3e37b157
commit 3d3f0ff6ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 180 additions and 5 deletions

View file

@ -14,20 +14,63 @@ class Line::IncomingMessageService
set_contact
set_conversation
# TODO: iterate over the events and handle the attachments in future
# https://github.com/line/line-bot-sdk-ruby#synopsis
parse_events
end
private
def parse_events
params[:events].each do |event|
next unless message_created? event
attach_files event['message']
end
end
def message_created?(event)
return unless event_type_message?(event)
@message = @conversation.messages.create(
content: params[:events].first['message']['text'],
content: event['message']['text'],
account_id: @inbox.account_id,
inbox_id: @inbox.id,
message_type: :incoming,
sender: @contact,
source_id: (params[:events].first['message']['id']).to_s
source_id: event['message']['id'].to_s
)
@message
end
def attach_files(message)
return unless message_type_non_text?(message['type'])
response = inbox.channel.client.get_message_content(message['id'])
file_name = "media-#{message['id']}.#{response.content_type.split('/')[1]}"
temp_file = Tempfile.new(file_name)
temp_file.binmode
temp_file << response.body
temp_file.rewind
@message.attachments.new(
account_id: @message.account_id,
file_type: file_content_type(response),
file: {
io: temp_file,
filename: file_name,
content_type: response.content_type
}
)
@message.save!
end
private
def event_type_message?(event)
event['type'] == 'message'
end
def message_type_non_text?(type)
[Line::Bot::Event::MessageType::Video, Line::Bot::Event::MessageType::Audio, Line::Bot::Event::MessageType::Image].include?(type)
end
def account
@account ||= inbox.account
@ -70,4 +113,8 @@ class Line::IncomingMessageService
avatar_url: line_contact_info['pictureUrl']
}
end
def file_content_type(file_content)
file_type(file_content.content_type)
end
end

BIN
spec/assets/sample.mp4 Normal file

Binary file not shown.

View file

@ -35,6 +35,76 @@ describe Line::IncomingMessageService do
}.with_indifferent_access
end
let(:image_params) do
{
'destination': '2342234234',
'events': [
{
'replyToken': '0f3779fba3b349968c5d07db31eab56f',
'type': 'message',
'mode': 'active',
'timestamp': 1_462_629_479_859,
'source': {
'type': 'user',
'userId': 'U4af4980629'
},
'message': {
'type': 'image',
'id': '354718',
'contentProvider': {
'type': 'line'
}
}
},
{
'replyToken': '8cf9239d56244f4197887e939187e19e',
'type': 'follow',
'mode': 'active',
'timestamp': 1_462_629_479_859,
'source': {
'type': 'user',
'userId': 'U4af4980629'
}
}
]
}.with_indifferent_access
end
let(:video_params) do
{
'destination': '2342234234',
'events': [
{
'replyToken': '0f3779fba3b349968c5d07db31eab56f',
'type': 'message',
'mode': 'active',
'timestamp': 1_462_629_479_859,
'source': {
'type': 'user',
'userId': 'U4af4980629'
},
'message': {
'type': 'video',
'id': '354718',
'contentProvider': {
'type': 'line'
}
}
},
{
'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
@ -55,5 +125,63 @@ describe Line::IncomingMessageService do
expect(line_channel.inbox.messages.first.content).to eq('Hello, world')
end
end
context 'when valid image 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)
file = fixture_file_upload(Rails.root.join('spec/assets/avatar.png'), 'image/png')
allow(line_bot).to receive(:get_message_content).and_return(
OpenStruct.new({
body: Base64.encode64(file.read),
content_type: 'image/png'
})
)
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: image_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(nil)
expect(line_channel.inbox.messages.first.attachments.first.file_type).to eq('image')
expect(line_channel.inbox.messages.first.attachments.first.file.blob.filename.to_s).to eq('media-354718.png')
end
end
context 'when valid video 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)
file = fixture_file_upload(Rails.root.join('spec/assets/sample.mp4'), 'video/mp4')
allow(line_bot).to receive(:get_message_content).and_return(
OpenStruct.new({
body: Base64.encode64(file.read),
content_type: 'video/mp4'
})
)
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: video_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(nil)
expect(line_channel.inbox.messages.first.attachments.first.file_type).to eq('video')
expect(line_channel.inbox.messages.first.attachments.first.file.blob.filename.to_s).to eq('media-354718.mp4')
end
end
end
end