incontact 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.env +9 -0
- data/.gitignore +21 -0
- data/.travis.yml +7 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +20 -0
- data/README.md +41 -0
- data/Rakefile +12 -0
- data/docs/agent_sessions.md +33 -0
- data/docs/agents.md +54 -0
- data/docs/api.md +12 -0
- data/docs/contacts.md +62 -0
- data/incontact.gemspec +31 -0
- data/lib/incontact.rb +38 -0
- data/lib/incontact/agent_sessions.rb +16 -0
- data/lib/incontact/agents.rb +11 -0
- data/lib/incontact/api.rb +43 -0
- data/lib/incontact/api_test.rb +31 -0
- data/lib/incontact/call_lists.rb +19 -0
- data/lib/incontact/connection.rb +124 -0
- data/lib/incontact/contacts.rb +7 -0
- data/lib/incontact/dispositions.rb +7 -0
- data/lib/incontact/error.rb +20 -0
- data/lib/incontact/models/agent.rb +6 -0
- data/lib/incontact/models/call_list.rb +6 -0
- data/lib/incontact/models/contact.rb +6 -0
- data/lib/incontact/models/disposition.rb +7 -0
- data/lib/incontact/models/token.rb +9 -0
- data/lib/incontact/resources.rb +9 -0
- data/lib/incontact/responses/agent_response.rb +11 -0
- data/lib/incontact/responses/agent_session_response.rb +6 -0
- data/lib/incontact/responses/call_list_response.rb +11 -0
- data/lib/incontact/responses/contact_response.rb +11 -0
- data/lib/incontact/responses/disposition_response.rb +12 -0
- data/lib/incontact/token_authenticated_resource.rb +10 -0
- data/lib/incontact/tokens.rb +49 -0
- data/lib/incontact/version.rb +3 -0
- metadata +206 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 513309e9128c0cb13d3c3b43746668d09e83e9235f341bede89dd3c581b473a3
|
4
|
+
data.tar.gz: 3795681ee7683934a9ceaca74f7120bbe8e79a388dbc5b1c1fe6c6b29a3f9018
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d7058cf29bee8230c705e9f1d398eb76945c50aa0f5ae339b10b75c9a9b04fd8e5a6e07980756ab94f8f13be4b7d7523a8eebccfd919c314e7e5f91ee2d08b33
|
7
|
+
data.tar.gz: 5e816f845862eeb2210ba6d9ea4d88a612ee7126bc18d32ff6142b6abd8cd29c0b34d1ac0b68430c020b42bfb3da12af8e031ff74bdbcec64577d09db4564b0c
|
data/.env
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Used in tests
|
2
|
+
|
3
|
+
export INCONTACT_TOKEN_URL=https://api.incontact.com/InContactAuthorizationServer/token
|
4
|
+
export INCONTACT_APP_NAME=dashboard
|
5
|
+
export INCONTACT_VENDOR_NAME=VeryGoodBusinessCo
|
6
|
+
export INCONTACT_BUSINESS_UNIT_NUMBER=123456
|
7
|
+
export INCONTACT_SCOPE="AdminApi RealTimeApi"
|
8
|
+
export INCONTACT_PASSWORD=Apple123!
|
9
|
+
export INCONTACT_USERNAME=dashboard@verygoodbusiness.com
|
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
*.DS_Store
|
4
|
+
.bundle
|
5
|
+
.config
|
6
|
+
.yardoc
|
7
|
+
.ruby-version
|
8
|
+
Gemfile.lock
|
9
|
+
InstalledFiles
|
10
|
+
_yardoc
|
11
|
+
coverage
|
12
|
+
doc/
|
13
|
+
lib/bundler/man
|
14
|
+
pkg
|
15
|
+
rdoc
|
16
|
+
spec/reports
|
17
|
+
test/tmp
|
18
|
+
test/version_tmp
|
19
|
+
tmp
|
20
|
+
bin/
|
21
|
+
.env.*
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2017 CustomInk.com
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# InContact [](https://travis-ci.org/customink/incontact_client)
|
2
|
+
|
3
|
+
This gem is a library for accessing [InContact's API](https://developer.incontact.com/API)
|
4
|
+
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'incontact'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
## Configuration
|
17
|
+
|
18
|
+
The following environmental variables need to be defined. They will be used to set all configurations for the client
|
19
|
+
without the need to customize a YAML config file. An example configuration:
|
20
|
+
|
21
|
+
export INCONTACT_TOKEN_URL=https://api.incontact.com/InContactAuthorizationServer/token
|
22
|
+
export INCONTACT_APP_NAME=dashboard
|
23
|
+
export INCONTACT_VENDOR_NAME=VeryGoodBusinessCo
|
24
|
+
export INCONTACT_BUSINESS_UNIT_NUMBER=123456
|
25
|
+
export INCONTACT_SCOPE="AdminApi RealTimeApi" # Scope used for tokens. Leaving this blank will set scope to all APIs
|
26
|
+
export INCONTACT_USERNAME=dashboard@verygoodbusiness.com # Admin user who can access all data
|
27
|
+
export INCONTACT_PASSWORD=Apple123!
|
28
|
+
|
29
|
+
It is recommended to use [dotenv](https://github.com/bkeepers/dotenv) to set
|
30
|
+
your ENV variables.
|
31
|
+
|
32
|
+
## Documentation
|
33
|
+
|
34
|
+
[Api](docs/api.md)
|
35
|
+
|
36
|
+
[Agents](docs/agents.md)
|
37
|
+
|
38
|
+
[Agent Sessions](docs/agent_sessions.md)
|
39
|
+
|
40
|
+
[Contacts](docs/contacts.md)
|
41
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
### Agent Sessions
|
2
|
+
|
3
|
+
You can access agent session data using the `InContact::Api#agent_session` method.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
api = InContact::Api.new
|
7
|
+
agent_sessions = api.agent_sessions # => #<InContact::AgentSessions> instance
|
8
|
+
```
|
9
|
+
|
10
|
+
To join a session:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
# Pass in the Agent ID
|
14
|
+
# Returns an InContact::Responses::AgentSessionRespose
|
15
|
+
|
16
|
+
agent_session_response = agent_sessions.join_agent_session(1234567) # => {
|
17
|
+
# "session_id" => 12346
|
18
|
+
# }
|
19
|
+
agent_session_response.session_id # => 123456
|
20
|
+
```
|
21
|
+
|
22
|
+
To mask and unmask a call:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
# Pass in session ID and contact ID
|
26
|
+
|
27
|
+
session_id = 1234567
|
28
|
+
contact_id = 7564313
|
29
|
+
|
30
|
+
agent_sessions.mask_call(session_id, contact_id) # => nil
|
31
|
+
|
32
|
+
agent_session.unmask_call(session_id, contact_id) # => nil
|
33
|
+
```
|
data/docs/agents.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
### Agents
|
2
|
+
|
3
|
+
You can access agent data using the `InContact::Api#agents` method.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
api = InContact::Api.new
|
7
|
+
agents = api.agents # => #<InContact::Agents> instance
|
8
|
+
```
|
9
|
+
|
10
|
+
To get all agents:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
# Returns an InContact::Responses::AgentResponse
|
14
|
+
|
15
|
+
agent_response = agents.all # => {
|
16
|
+
# "business_unit_id" => 123467,
|
17
|
+
# "last_poll_time" => "2017-04-25T19:12:22.117Z",
|
18
|
+
# "total_records" => 1000,
|
19
|
+
# "agents" => [...]
|
20
|
+
# }
|
21
|
+
|
22
|
+
agent_response.total_records # => 1000
|
23
|
+
agent_response.agents # Returns Array of agent data
|
24
|
+
```
|
25
|
+
|
26
|
+
To find one agent:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
# Returns an InContact::Responses::AgentResponse
|
30
|
+
|
31
|
+
agent_response = agents.find(1234567) # => {
|
32
|
+
# "business_unit_id" => 4592889,
|
33
|
+
# "last_poll_time" => "2017-04-21T18:12:32.120Z",
|
34
|
+
# "agents" => [...]
|
35
|
+
# }
|
36
|
+
|
37
|
+
# Returns the agents data
|
38
|
+
# See InContact API for available data
|
39
|
+
# The InContact APT returns data with keys in CamelCase
|
40
|
+
agent = agent_response.agents.first # => {
|
41
|
+
# "agent_id" => 1234567
|
42
|
+
# "user_name" => "billsmith@business.com"
|
43
|
+
# "first_name" => "Bill"
|
44
|
+
# "last_name" => "Smith"
|
45
|
+
# "email_adress" => "billsmith@business.com"
|
46
|
+
# "is_active" => true
|
47
|
+
# ...
|
48
|
+
# }
|
49
|
+
|
50
|
+
agent["first_name"] # => "Bill"
|
51
|
+
|
52
|
+
# The model is an OpenStruct, so this will also work
|
53
|
+
agent.first_name # => "Bill"
|
54
|
+
```
|
data/docs/api.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
### Api
|
2
|
+
|
3
|
+
The `InContact::Api` class will be the main source to use the API.
|
4
|
+
|
5
|
+
To set up:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
InContact::Api.new
|
9
|
+
```
|
10
|
+
|
11
|
+
That's it! This will automatically get a token for use in the API. Check the
|
12
|
+
other docs for how to get specific data.
|
data/docs/contacts.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
### Contacts
|
2
|
+
|
3
|
+
You can access contact data using the `InContact::Api#contacts method`
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
api = InContact::Api.new
|
7
|
+
contacts = api.contacts # => #<InContact::Contacts> instance
|
8
|
+
```
|
9
|
+
|
10
|
+
To get active Contacts:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
# Returns an InContact::Responses::ContactResponse
|
14
|
+
|
15
|
+
contact_response = contacts.active # => {
|
16
|
+
# "result_set" => {
|
17
|
+
# "business_unit_id" => "4592889",
|
18
|
+
# "last_poll_time" => "2017-04-21T18:13:13.600Z",
|
19
|
+
# "active_contacts" => [...]
|
20
|
+
# }
|
21
|
+
# }
|
22
|
+
|
23
|
+
# The active_contacts method contains array of contact data
|
24
|
+
# See InContact API for all available data
|
25
|
+
|
26
|
+
contact_response.active_contacts # => [
|
27
|
+
# {
|
28
|
+
# "agent_id" => "1234568",
|
29
|
+
# "campaign_id" => "111111",
|
30
|
+
# "campaign_name" => "Test",
|
31
|
+
# "contact_dd" => "111111111",
|
32
|
+
# "contact_start" => "2017-04-21T18:12:53.123Z",
|
33
|
+
# "first_name" => "Bill",
|
34
|
+
# "last_name" => "Smith",
|
35
|
+
# "media_type_name" => "Call",
|
36
|
+
# ...
|
37
|
+
# },
|
38
|
+
# {
|
39
|
+
# "agent_id" => "1234569",
|
40
|
+
# "campaign_id" => "111112",
|
41
|
+
# "campaign_name" => "Test",
|
42
|
+
# "contact_id" => "111111112",
|
43
|
+
# "contact_start" => "2017-04-21T18:12:53.123Z",
|
44
|
+
# "first_name" => "Joe",
|
45
|
+
# "last_name" => "Johnson",
|
46
|
+
# "media_type_name" => "Call",
|
47
|
+
# ...
|
48
|
+
# },
|
49
|
+
# ...
|
50
|
+
# ]
|
51
|
+
|
52
|
+
# Getting some data
|
53
|
+
|
54
|
+
|
55
|
+
contact = contact_response.active_contacts.first
|
56
|
+
contact["first_name"] # => "Bill"
|
57
|
+
|
58
|
+
# The model is an OpenStruct, so this will also work
|
59
|
+
contact.first_name # => "Bill"
|
60
|
+
```
|
61
|
+
|
62
|
+
|
data/incontact.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "incontact/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "incontact"
|
8
|
+
spec.version = InContact::VERSION
|
9
|
+
spec.authors = ["Spreemo"]
|
10
|
+
spec.email = ["engineering@spreemo.com"]
|
11
|
+
spec.description = "A Ruby gem to access the InContact API"
|
12
|
+
spec.summary = spec.description
|
13
|
+
spec.homepage = "https://github.com/spreemo/incontact_client"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency "faraday"
|
23
|
+
spec.add_dependency "faraday_middleware"
|
24
|
+
spec.add_dependency "retryable"
|
25
|
+
spec.add_dependency "activesupport"
|
26
|
+
spec.add_development_dependency "dotenv"
|
27
|
+
spec.add_development_dependency "pry"
|
28
|
+
spec.add_development_dependency "minitest"
|
29
|
+
spec.add_development_dependency "webmock"
|
30
|
+
spec.add_development_dependency "rake"
|
31
|
+
end
|
data/lib/incontact.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require "active_support/all"
|
2
|
+
require "retryable"
|
3
|
+
require "faraday"
|
4
|
+
require "faraday_middleware"
|
5
|
+
require "incontact/error"
|
6
|
+
require "incontact/version"
|
7
|
+
require "ostruct"
|
8
|
+
|
9
|
+
module InContact
|
10
|
+
autoload :Api, "incontact/api"
|
11
|
+
autoload :Tokens, "incontact/tokens"
|
12
|
+
autoload :Connection, "incontact/connection"
|
13
|
+
autoload :TokenAuthenticatedResource, "incontact/token_authenticated_resource"
|
14
|
+
autoload :Agents, "incontact/agents"
|
15
|
+
autoload :Contacts, "incontact/contacts"
|
16
|
+
autoload :AgentSessions, "incontact/agent_sessions"
|
17
|
+
autoload :CallLists, "incontact/call_lists"
|
18
|
+
autoload :Dispositions, "incontact/dispositions"
|
19
|
+
autoload :Resources, "incontact/resources"
|
20
|
+
|
21
|
+
module Models
|
22
|
+
autoload :Token, "incontact/models/token"
|
23
|
+
autoload :Agent, "incontact/models/agent"
|
24
|
+
autoload :Contact, "incontact/models/contact"
|
25
|
+
autoload :AgentSession, "incontact/models/agent_session"
|
26
|
+
autoload :CallList, "incontact/models/call_list"
|
27
|
+
autoload :Disposition, "incontact/models/disposition"
|
28
|
+
end
|
29
|
+
|
30
|
+
module Responses
|
31
|
+
autoload :ContactResponse, "incontact/responses/contact_response"
|
32
|
+
autoload :AgentResponse, "incontact/responses/agent_response"
|
33
|
+
autoload :AgentSessionResponse, "incontact/responses/agent_session_response"
|
34
|
+
autoload :CallListResponse, "incontact/responses/call_list_response"
|
35
|
+
autoload :CallListResponse, "incontact/responses/call_list_response"
|
36
|
+
autoload :DispositionResponse, "incontact/responses/disposition_response"
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module InContact
|
2
|
+
class AgentSessions < TokenAuthenticatedResource
|
3
|
+
def join_agent_session(agent_id)
|
4
|
+
agent_request_data = { "asAgentId" => agent_id }
|
5
|
+
connection.post("agent-sessions/join", agent_request_data)
|
6
|
+
end
|
7
|
+
|
8
|
+
def mask_call(session_id, contact_id)
|
9
|
+
connection.post("agent-sessions/#{session_id}/interactions/#{contact_id}/mask")
|
10
|
+
end
|
11
|
+
|
12
|
+
def unmask_call(session_id, contact_id)
|
13
|
+
connection.post("agent-sessions/#{session_id}/interactions/#{contact_id}/unmask")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module InContact
|
2
|
+
class Api
|
3
|
+
attr_reader :token
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@token = InContact::Tokens.get
|
7
|
+
end
|
8
|
+
|
9
|
+
def agents
|
10
|
+
@agents ||= create_resource(InContact::Resources::AGENTS)
|
11
|
+
end
|
12
|
+
|
13
|
+
def contacts
|
14
|
+
@contacts ||= create_resource(InContact::Resources::CONTACTS)
|
15
|
+
end
|
16
|
+
|
17
|
+
def agent_sessions
|
18
|
+
@agent_sessions ||= create_resource(InContact::Resources::AGENT_SESSIONS)
|
19
|
+
end
|
20
|
+
|
21
|
+
def call_lists
|
22
|
+
@call_lists ||= create_resource(InContact::Resources::CALL_LISTS)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def create_resource(resource)
|
28
|
+
resource_model = "InContact::#{resource}".constantize
|
29
|
+
data_model = "InContact::Responses::#{resource.singularize}Response".constantize
|
30
|
+
connection = create_connection(data_model)
|
31
|
+
|
32
|
+
resource_model.new(connection)
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_connection(data_model)
|
36
|
+
url = token.resource_server_base_uri
|
37
|
+
authorization = token.authorization
|
38
|
+
options = { default_data_model: data_model }
|
39
|
+
|
40
|
+
InContact::Connection.new(url, authorization, options)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module InContact
|
2
|
+
class ApiTest < TestCase
|
3
|
+
before do
|
4
|
+
mock_request(:post, "", 200, "token", body, ENV["INCONTACT_TOKEN_URL"])
|
5
|
+
end
|
6
|
+
|
7
|
+
let(:api) { InContact::Api.new }
|
8
|
+
|
9
|
+
it "will get a token on initialization" do
|
10
|
+
api.token.wont_be_nil
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#agents" do
|
14
|
+
it "will return an agent resource class" do
|
15
|
+
api.agents.must_be_kind_of InContact::Agents
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#agent_sessions" do
|
20
|
+
it "will return an agent session resource class" do
|
21
|
+
api.agents.must_be_kind_of InContact::AgentSessions
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#agents" do
|
26
|
+
it "will return a contact resource class" do
|
27
|
+
api.agents.must_be_kind_of InContact::Contacts
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module InContact
|
2
|
+
class CallLists < TokenAuthenticatedResource
|
3
|
+
def all
|
4
|
+
connection.get("lists/call-lists")
|
5
|
+
end
|
6
|
+
|
7
|
+
def find(call_list_id)
|
8
|
+
connection.get("lists/call-lists/#{call_list_id}")
|
9
|
+
end
|
10
|
+
|
11
|
+
def upload_file(call_list_id, body)
|
12
|
+
connection.post("lists/call-lists/#{call_list_id}/upload", body)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create(body)
|
16
|
+
connection.post("lists/call-lists", body)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module InContact
|
2
|
+
class Connection
|
3
|
+
TIMEOUT = 60
|
4
|
+
OPEN_TIMEOUT = 10
|
5
|
+
MAX_TRIES = 2
|
6
|
+
RETRY_SLEEP = 1
|
7
|
+
API_PATH_PREFIX = "services/v8.0/"
|
8
|
+
|
9
|
+
attr_reader :url
|
10
|
+
attr_reader :authorization
|
11
|
+
attr_reader :default_data_model
|
12
|
+
|
13
|
+
def initialize(url, authorization, options = {})
|
14
|
+
@url = url
|
15
|
+
@authorization = authorization
|
16
|
+
@default_data_model = options[:default_data_model] || OpenStruct
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(path, params = {})
|
20
|
+
request :get, path, params
|
21
|
+
end
|
22
|
+
|
23
|
+
def post(path, payload = "", params = {})
|
24
|
+
request :post, path, params, payload
|
25
|
+
end
|
26
|
+
|
27
|
+
def request(type, path, params = {}, body=nil)
|
28
|
+
timeout_override = params.delete :timeout
|
29
|
+
open_timeout_override = params.delete :open_timeout
|
30
|
+
data_model_override = params.delete :data_model_override
|
31
|
+
response = Retryable.retryable(retryable_options(params)) do
|
32
|
+
request_with_exception_handling do
|
33
|
+
connection.send(type) do |req|
|
34
|
+
req.path = API_PATH_PREFIX + path unless path.blank?
|
35
|
+
req.options[:timeout] = timeout_override || TIMEOUT
|
36
|
+
req.options[:open_timeout] = open_timeout_override || OPEN_TIMEOUT
|
37
|
+
req.params = params
|
38
|
+
req.body = body.to_json unless body.blank?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
raise_response_errors(response)
|
43
|
+
parse_response(response, data_model_override)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def retryable_options(options)
|
49
|
+
{}.tap do |retry_options|
|
50
|
+
retry_options[:tries] = options.delete(:max_tries) || MAX_TRIES
|
51
|
+
retry_options[:sleep] = options.delete(:retry_sleep) || RETRY_SLEEP
|
52
|
+
retry_options[:on] = [ConnectionError]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def request_with_exception_handling
|
57
|
+
yield
|
58
|
+
rescue => exception
|
59
|
+
raise ConnectionError, exception
|
60
|
+
end
|
61
|
+
|
62
|
+
def raise_response_errors(response)
|
63
|
+
return if response.success?
|
64
|
+
error_messages = response.body.respond_to?(:exception_message) &&
|
65
|
+
response.body.errors.present? ? response.body.errors.join("\n") : ""
|
66
|
+
case response.status
|
67
|
+
when 404
|
68
|
+
raise ResourceNotFound.new(error_messages, response)
|
69
|
+
when 400...600
|
70
|
+
raise Error.new(error_messages, response)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def connection
|
75
|
+
@connection ||= create_connection
|
76
|
+
end
|
77
|
+
|
78
|
+
def create_connection
|
79
|
+
Faraday.new(url: url) do |faraday|
|
80
|
+
faraday.headers["Accept-Encoding"] = "none"
|
81
|
+
faraday.headers["Content-Type"] = "application/json; charset=utf-8"
|
82
|
+
faraday.headers["Authorization"] = authorization
|
83
|
+
faraday.use FaradayMiddleware::ParseJson
|
84
|
+
faraday.adapter Faraday.default_adapter
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def parse_response(response, data_model_override)
|
89
|
+
data = response.body
|
90
|
+
map_response_item_to_model(data, data_model_override)
|
91
|
+
end
|
92
|
+
|
93
|
+
def data_model(item)
|
94
|
+
klass = name.demodulize.underscore.singularize.classify
|
95
|
+
"InContact::Responses::#{klass}Response".constantize rescue nil
|
96
|
+
end
|
97
|
+
|
98
|
+
def map_response_item_to_model(item, data_model_override)
|
99
|
+
return item if item.blank? || data_model_override.is_a?(FalseClass)
|
100
|
+
|
101
|
+
# Change keys to snake case
|
102
|
+
item = underscore_hash_keys(item)
|
103
|
+
data_model_klass = data_model_override || default_data_model
|
104
|
+
return item if data_model_klass.nil?
|
105
|
+
data_model_klass.new(item)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Based on ActiveSupport's Hash#deep_transform_keys, which is only available in
|
109
|
+
# versions >= 4.0.2. We'll port it here to work with versions < 4.0.2
|
110
|
+
# Source: https://github.com/rails/rails/blob/55f9b8129a50206513264824abb44088230793c2/activesupport/lib/active_support/core_ext/hash/keys.rb#L143-L154
|
111
|
+
def underscore_hash_keys(item)
|
112
|
+
case item
|
113
|
+
when Hash
|
114
|
+
item.each_with_object({}) do |(key, value), result|
|
115
|
+
result[key.underscore] = underscore_hash_keys(value)
|
116
|
+
end
|
117
|
+
when Array
|
118
|
+
item.map { |value| underscore_hash_keys(value) }
|
119
|
+
else
|
120
|
+
item
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module InContact
|
2
|
+
class Error < StandardError
|
3
|
+
attr_reader :response
|
4
|
+
|
5
|
+
def initialize(exception, response = nil)
|
6
|
+
@response = response
|
7
|
+
if exception.instance_of? Faraday::Error::ClientError
|
8
|
+
super exception.message
|
9
|
+
elsif exception.is_a? String
|
10
|
+
super exception
|
11
|
+
else
|
12
|
+
super "Unknown exception: #{exception.message}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class ConnectionError < Error ; end
|
18
|
+
class ResourceError < Error ; end
|
19
|
+
class ResourceNotFound < ResourceError ; end
|
20
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "base64"
|
2
|
+
|
3
|
+
module InContact
|
4
|
+
class Tokens
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def get
|
8
|
+
Connection.new(url, authorization, token_options).post(path, token_request_data)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def url
|
14
|
+
ENV["INCONTACT_TOKEN_URL"]
|
15
|
+
end
|
16
|
+
|
17
|
+
def path
|
18
|
+
""
|
19
|
+
end
|
20
|
+
|
21
|
+
def token_request_data
|
22
|
+
{
|
23
|
+
grant_type: "password",
|
24
|
+
username: ENV["INCONTACT_USERNAME"],
|
25
|
+
password: ENV["INCONTACT_PASSWORD"],
|
26
|
+
scope: ENV["INCONTACT_SCOPE"]
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def token_options
|
31
|
+
{
|
32
|
+
default_data_model: InContact::Models::Token
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def authorization
|
37
|
+
"basic #{encoded_auth_string}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def auth_string
|
41
|
+
"#{ENV["INCONTACT_APP_NAME"]}@#{ENV["INCONTACT_VENDOR_NAME"]}:#{ENV["INCONTACT_BUSINESS_UNIT_NUMBER"]}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def encoded_auth_string
|
45
|
+
Base64.encode64(auth_string).chomp
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
metadata
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: incontact
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Spreemo
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-02-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday_middleware
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: retryable
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activesupport
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: dotenv
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: minitest
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: webmock
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rake
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: A Ruby gem to access the InContact API
|
140
|
+
email:
|
141
|
+
- engineering@spreemo.com
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- ".env"
|
147
|
+
- ".gitignore"
|
148
|
+
- ".travis.yml"
|
149
|
+
- Gemfile
|
150
|
+
- LICENSE.txt
|
151
|
+
- README.md
|
152
|
+
- Rakefile
|
153
|
+
- docs/agent_sessions.md
|
154
|
+
- docs/agents.md
|
155
|
+
- docs/api.md
|
156
|
+
- docs/contacts.md
|
157
|
+
- incontact.gemspec
|
158
|
+
- lib/incontact.rb
|
159
|
+
- lib/incontact/agent_sessions.rb
|
160
|
+
- lib/incontact/agents.rb
|
161
|
+
- lib/incontact/api.rb
|
162
|
+
- lib/incontact/api_test.rb
|
163
|
+
- lib/incontact/call_lists.rb
|
164
|
+
- lib/incontact/connection.rb
|
165
|
+
- lib/incontact/contacts.rb
|
166
|
+
- lib/incontact/dispositions.rb
|
167
|
+
- lib/incontact/error.rb
|
168
|
+
- lib/incontact/models/agent.rb
|
169
|
+
- lib/incontact/models/call_list.rb
|
170
|
+
- lib/incontact/models/contact.rb
|
171
|
+
- lib/incontact/models/disposition.rb
|
172
|
+
- lib/incontact/models/token.rb
|
173
|
+
- lib/incontact/resources.rb
|
174
|
+
- lib/incontact/responses/agent_response.rb
|
175
|
+
- lib/incontact/responses/agent_session_response.rb
|
176
|
+
- lib/incontact/responses/call_list_response.rb
|
177
|
+
- lib/incontact/responses/contact_response.rb
|
178
|
+
- lib/incontact/responses/disposition_response.rb
|
179
|
+
- lib/incontact/token_authenticated_resource.rb
|
180
|
+
- lib/incontact/tokens.rb
|
181
|
+
- lib/incontact/version.rb
|
182
|
+
homepage: https://github.com/spreemo/incontact_client
|
183
|
+
licenses:
|
184
|
+
- MIT
|
185
|
+
metadata: {}
|
186
|
+
post_install_message:
|
187
|
+
rdoc_options: []
|
188
|
+
require_paths:
|
189
|
+
- lib
|
190
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
196
|
+
requirements:
|
197
|
+
- - ">="
|
198
|
+
- !ruby/object:Gem::Version
|
199
|
+
version: '0'
|
200
|
+
requirements: []
|
201
|
+
rubyforge_project:
|
202
|
+
rubygems_version: 2.7.5
|
203
|
+
signing_key:
|
204
|
+
specification_version: 4
|
205
|
+
summary: A Ruby gem to access the InContact API
|
206
|
+
test_files: []
|