Add helpscout API adapter

This commit is contained in:
Paul Chavard 2018-08-29 10:43:00 +01:00
parent c1bdb8a4be
commit 6453b53a41
3 changed files with 259 additions and 0 deletions

133
app/lib/helpscout/api.rb Normal file
View file

@ -0,0 +1,133 @@
class Helpscout::API
MAILBOXES = 'mailboxes'
CONVERSATIONS = 'conversations'
TAGS = 'tags'
FIELDS = 'fields'
OAUTH2_TOKEN = 'oauth2/token'
def add_tags(conversation_id, tags)
call_api(:put, "#{CONVERSATIONS}/#{conversation_id}/#{TAGS}", {
tags: tags
})
end
def add_custom_fields(conversation_id, dossier_id, browser)
body = {
'Dossier ID': dossier_id,
'Browser': browser
}.compact.map do |key, value|
{ id: custom_fields[key], value: value }
end
call_api(:put, "#{CONVERSATIONS}/#{conversation_id}/#{FIELDS}", { fields: body })
end
def create_conversation(email, subject, text, file)
body = {
subject: subject,
customer: customer(email),
mailboxId: mailbox_id,
type: 'email',
status: 'active',
threads: [
{
type: 'customer',
customer: customer(email),
text: text,
attachments: attachments(file)
}
]
}.compact
call_api(:post, CONVERSATIONS, body)
end
private
def attachments(file)
if file.present?
[
{
fileName: file.original_filename,
mimeType: file.content_type,
data: Base64.strict_encode64(file.read)
}
]
else
[]
end
end
def customer(email)
{
email: email
}
end
def custom_fields
@custom_fields ||= get_custom_fields.reduce({}) do |fields, field|
fields[field[:name].to_sym] = field[:id]
fields
end
end
def get_custom_fields
parse_response_body(fetch_custom_fields)[:_embedded][:fields]
end
def fetch_custom_fields
call_api(:get, "#{MAILBOXES}/#{mailbox_id}/#{FIELDS}")
end
def call_api(method, path, body = nil)
url = "#{HELPSCOUT_API_URL}/#{path}"
case method
when :get
Typhoeus.get(url, {
headers: headers
})
when :post
Typhoeus.post(url, {
body: body.to_json,
headers: headers
})
when :put
Typhoeus.put(url, {
body: body.to_json,
headers: headers
})
end
end
def parse_response_body(response)
JSON.parse(response.body, symbolize_names: true)
end
def mailbox_id
Rails.application.secrets.helpscout[:mailbox_id]
end
def headers
{
'Authorization': "Bearer #{access_token}",
'Content-Type': 'application/json; charset=UTF-8'
}
end
def access_token
@access_token ||= get_access_token
end
def get_access_token
parse_response_body(fetch_access_token)[:access_token]
end
def fetch_access_token
Typhoeus.post("#{HELPSCOUT_API_URL}/#{OAUTH2_TOKEN}", body: {
grant_type: 'client_credentials',
client_id: Rails.application.secrets.helpscout[:client_id],
client_secret: Rails.application.secrets.helpscout[:client_secret]
})
end
end

View file

@ -0,0 +1,56 @@
class Helpscout::FormAdapter
attr_reader :params
def initialize(params = {}, api = nil)
@params = params
@api = api || Helpscout::API.new
end
TYPE_INFO = 'info demarche'
TYPE_PERDU = 'usager perdu'
TYPE_INSTRUCTION = 'info instruction'
TYPE_AMELIORATION = 'produit'
TYPE_AUTRE = 'autre'
OPTIONS = [
[I18n.t(TYPE_INFO, scope: [:support]), TYPE_INFO],
[I18n.t(TYPE_PERDU, scope: [:support]), TYPE_PERDU],
[I18n.t(TYPE_INSTRUCTION, scope: [:support]), TYPE_INSTRUCTION],
[I18n.t(TYPE_AMELIORATION, scope: [:support]), TYPE_AMELIORATION],
[I18n.t(TYPE_AUTRE, scope: [:support]), TYPE_AUTRE]
]
def send_form
conversation_id = create_conversation
if conversation_id.present?
add_tags(conversation_id)
add_custom_fields(conversation_id)
true
else
false
end
end
private
def add_tags(conversation_id)
@api.add_tags(conversation_id, params[:tags])
end
def add_custom_fields(conversation_id)
@api.add_custom_fields(conversation_id, params[:dossier_id], params[:browser])
end
def create_conversation
response = @api.create_conversation(
params[:email],
params[:subject],
params[:text],
params[:file]
)
response.success? ? response.headers['Resource-ID'] : nil
end
end

View file

@ -0,0 +1,70 @@
require 'spec_helper'
describe Helpscout::FormAdapter do
describe '#send_form' do
let(:api) { spy(double(:api)) }
context 'create_conversation' do
before do
allow(api).to receive(:create_conversation)
.and_return(double(success?: false))
described_class.new(params, api).send_form
end
let(:params) {
{
email: email,
subject: subject,
text: text
}
}
let(:email) { 'paul.chavard@beta.gouv.fr' }
let(:subject) { 'Bonjour' }
let(:text) { "J'ai un problem" }
it 'should call method' do
expect(api).to have_received(:create_conversation)
.with(email, subject, text, nil)
end
end
context 'add_tags' do
before do
allow(api).to receive(:create_conversation)
.and_return(
double(
success?: true,
headers: {
'Resource-ID' => conversation_id
}
)
)
described_class.new(params, api).send_form
end
let(:params) {
{
email: email,
subject: subject,
text: text,
tags: tags
}
}
let(:email) { 'paul.chavard@beta.gouv.fr' }
let(:subject) { 'Bonjour' }
let(:text) { "J'ai un problem" }
let(:tags) { ['info demarche'] }
let(:conversation_id) { '123' }
it 'should call method' do
expect(api).to have_received(:create_conversation)
.with(email, subject, text, nil)
expect(api).to have_received(:add_tags)
.with(conversation_id, tags)
expect(api).to have_received(:add_custom_fields)
.with(conversation_id, nil, nil)
end
end
end
end