feat: Line Channel (#2904)

- Ability to configure line bots as a channel in chatwoot
- Receive a message sent to the line bot in chatwoot
- Ability to reply to line users from chatwoot

fixes: #2738
This commit is contained in:
Sojan Jose
2021-09-11 01:31:17 +05:30
committed by GitHub
parent 671c5c931f
commit 0a38632f14
37 changed files with 581 additions and 56 deletions
@@ -285,6 +285,28 @@ RSpec.describe 'Inboxes API', type: :request do
expect(response).to have_http_status(:success)
expect(response.body).to include('test@test.com')
end
it 'creates an api inbox when administrator' do
post "/api/v1/accounts/#{account.id}/inboxes",
headers: admin.create_new_auth_token,
params: { name: 'API Inbox', channel: { type: 'api', webhook_url: 'http://test.com' } },
as: :json
expect(response).to have_http_status(:success)
expect(response.body).to include('API Inbox')
end
it 'creates a line inbox when administrator' do
post "/api/v1/accounts/#{account.id}/inboxes",
headers: admin.create_new_auth_token,
params: { name: 'Line Inbox',
channel: { type: 'line', line_channel_id: SecureRandom.uuid, line_channel_secret: SecureRandom.uuid,
line_channel_token: SecureRandom.uuid } },
as: :json
expect(response).to have_http_status(:success)
expect(response.body).to include('Line Inbox')
end
end
end
@@ -0,0 +1,12 @@
require 'rails_helper'
RSpec.describe 'Webhooks::LineController', type: :request do
describe 'POST /webhooks/line/{:line_channel_id}' do
it 'call the line events job with the params' do
allow(Webhooks::LineEventsJob).to receive(:perform_later)
expect(Webhooks::LineEventsJob).to receive(:perform_later)
post '/webhooks/line/line_channel_id', params: { content: 'hello' }
expect(response).to have_http_status(:success)
end
end
end
+11
View File
@@ -0,0 +1,11 @@
# frozen_string_literal: true
FactoryBot.define do
factory :channel_line, class: 'Channel::Line' do
line_channel_id { SecureRandom.uuid }
line_channel_secret { SecureRandom.uuid }
line_channel_token { SecureRandom.uuid }
inbox
account
end
end
+9
View File
@@ -55,5 +55,14 @@ RSpec.describe SendReplyJob, type: :job do
expect(process_service).to receive(:perform)
described_class.perform_now(message.id)
end
it 'calls ::Line:SendOnLineService when its line message' do
line_channel = create(:channel_line)
message = create(:message, conversation: create(:conversation, inbox: line_channel.inbox))
allow(::Line::SendOnLineService).to receive(:new).with(message: message).and_return(process_service)
expect(::Line::SendOnLineService).to receive(:new).with(message: message)
expect(process_service).to receive(:perform)
described_class.perform_now(message.id)
end
end
end
@@ -0,0 +1,38 @@
require 'rails_helper'
RSpec.describe Webhooks::LineEventsJob, type: :job do
subject(:job) { described_class.perform_later(params: params) }
let!(:line_channel) { create(:channel_line) }
let!(:params) { { line_channel_id: line_channel.line_channel_id, 'line' => { test: 'test' } } }
let(:post_body) { params.to_json }
let(:signature) { Base64.strict_encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('SHA256'), line_channel.line_channel_secret, post_body)) }
it 'enqueues the job' do
expect { job }.to have_enqueued_job(described_class)
.with(params: params)
.on_queue('default')
end
context 'when invalid params' do
it 'returns nil when no line_channel_id' do
expect(described_class.perform_now(params: {})).to be_nil
end
it 'returns nil when invalid bot_token' do
expect(described_class.perform_now(params: { 'line_channel_id' => 'invalid_id', 'line' => { test: 'test' } })).to be_nil
end
end
context 'when valid params' do
it 'calls Line::IncomingMessageService' do
process_service = double
allow(Line::IncomingMessageService).to receive(:new).and_return(process_service)
allow(process_service).to receive(:perform)
expect(Line::IncomingMessageService).to receive(:new).with(inbox: line_channel.inbox,
params: params['line'].with_indifferent_access)
expect(process_service).to receive(:perform)
described_class.perform_now(params: params, post_body: post_body, signature: signature)
end
end
end
@@ -0,0 +1,59 @@
require 'rails_helper'
describe Line::IncomingMessageService do
let!(:line_channel) { create(:channel_line) }
let(:params) do
{
'destination': '2342234234',
'events': [
{
'replyToken': '0f3779fba3b349968c5d07db31eab56f',
'type': 'message',
'mode': 'active',
'timestamp': 1_462_629_479_859,
'source': {
'type': 'user',
'userId': 'U4af4980629'
},
'message': {
'id': '325708',
'type': 'text',
'text': 'Hello, world'
}
},
{
'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
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: 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('Hello, world')
end
end
end
end
@@ -0,0 +1,18 @@
require 'rails_helper'
describe Line::SendOnLineService do
describe '#perform' do
context 'when a valid message' do
it 'calls @channel.client.push_message' do
line_client = double
line_channel = create(:channel_line)
message = create(:message, message_type: :outgoing, content: 'test',
conversation: create(:conversation, inbox: line_channel.inbox))
allow(line_client).to receive(:push_message)
allow(Line::Bot::Client).to receive(:new).and_return(line_client)
expect(line_client).to receive(:push_message)
described_class.new(message: message).perform
end
end
end
end