ApiWrapperFor8x8 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -19,3 +19,4 @@ ctags
19
19
  __Tagbar__
20
20
  tags
21
21
  Makefile
22
+ spec/fixture/*
data/README.md CHANGED
@@ -19,7 +19,36 @@ Or install it yourself as:
19
19
 
20
20
  ## Usage
21
21
 
22
- TODO: Write usage instructions here
22
+ ###Setup
23
+ ```ruby
24
+ @api_connection = ApiWrapperFor8x8::Connection.new({
25
+ :username => 'foo', # your username for 8x8
26
+ :password => 'bar' # your password for 8x8
27
+ })
28
+ ```
29
+
30
+ ###Params for each call
31
+ Date range: it has to be a iso8601 format and a string with comma separated, Ex "#{(Time.now-3600*24).iso8601,Time.now.iso8601}"
32
+ Timezone: it need to be following: list_of_timezone[http://en.wikipedia.org/wiki/List_of_zoneinfo_time_zones], Ex. America/Los_Angeles
33
+ It has more params, which can be seen on 8x8 site[http://www.8x8.com/Support/BusinessSupport/Documentation/VirtualContactCenterDocumentation/VirtualContactCenterStats.aspx]
34
+
35
+ ###Channel
36
+
37
+ Get a list of channels
38
+ ```ruby
39
+ @api_coonection.channel_list
40
+ ```
41
+
42
+ Get a list of agnets
43
+ ```ruby
44
+ @api_coonection.agent_list
45
+ ```
46
+
47
+ Get a list of agnet details
48
+ ```ruby
49
+ @api_coonection.agents_details({:d => 'YOUR DATE RANGE', :tz => 'YOUR TIMEZONE'}, {FILTER OPTIONS})
50
+ ```
51
+
23
52
 
24
53
  ## Contributing
25
54
 
@@ -5,4 +5,5 @@ require 'ApiWrapperFor8x8/error'
5
5
  require 'ApiWrapperFor8x8/agent'
6
6
  require 'ApiWrapperFor8x8/agents'
7
7
  require 'ApiWrapperFor8x8/channel'
8
+ require 'ApiWrapperFor8x8/stats'
8
9
  require 'ApiWrapperFor8x8/connection'
@@ -1,8 +1,8 @@
1
1
  module ApiWrapperFor8x8
2
2
  module Agent
3
3
 
4
- def agent_detail(id, params)
5
- get("/stats/agents/#{id}/statistics.json", params)
4
+ def agent_detail(id, params, filtered_options)
5
+ get("/stats/agents/#{id}/statistics.json", params, filtered_options)
6
6
  end
7
7
 
8
8
  end
@@ -2,30 +2,24 @@ module ApiWrapperFor8x8
2
2
  module Agents
3
3
  include ApiWrapperFor8x8::Agent
4
4
 
5
- def agent_list(params={})
6
- get('/stats/agents.json', params)
5
+ # Get a list of all the agents
6
+ #
7
+ def agent_list(filtered_options={})
8
+ get('/stats/agents.json', {}, filtered_options)
7
9
  end
8
10
 
11
+ # Get all the details of agents
12
+ #
13
+ # Ex. Get details for date range of '2013-09-04T00:00:00-07:00,2013-09-04T23:59:59-07:00'
14
+ # and filtered with queue-name and agent-id
15
+ # @api_connection.agents_detail({:d => '2013-09-04T00:00:00-07:00,2013-09-04T23:59:59-07:00'},
16
+ # {"agent-id"=>"foo", "queue-name"=>"bar"})
9
17
  def agents_detail(params={}, filtered_options={})
10
18
  details = []
11
- filtered_agents(agent_list(params), filtered_options).each do |agent|
12
- details << agent_detail(agent['agent-id'], params)
19
+ agent_list.each do |agent|
20
+ details.concat(agent_detail(agent['agent-id'], params, filtered_options))
13
21
  end
14
- details.flatten
22
+ details
15
23
  end
16
-
17
- def filtered_agents(agent_list, filtered_options)
18
- if filtered_options.size == 0
19
- return list
20
- end
21
- agent_list.select do |agent|
22
- flag = true
23
- filtered_options.each do |key, value|
24
- flag = false unless (agent[key] && agent[key] == value)
25
- end
26
- flag
27
- end
28
- end
29
-
30
24
  end
31
25
  end
@@ -1,8 +1,10 @@
1
1
  module ApiWrapperFor8x8
2
2
  module Channel
3
3
 
4
- def channel_list(options={})
5
- get "/stats/channels.json", options
4
+ # Get a list of channels
5
+ #
6
+ def channel_list(filtered_options={})
7
+ get "/stats/channels.json", {}, filtered_options
6
8
  end
7
9
 
8
10
  # Get one details on the channel
@@ -21,6 +23,13 @@ module ApiWrapperFor8x8
21
23
 
22
24
  # It is easier for geting the sum of a value from the
23
25
  # an array of records with the restriction you can set
26
+ #
27
+ # Ex. Get a sum of 'accepted-count' from channel_id: 1, date range
28
+ # , filtered_options, and queue-name
29
+ # @api_connection.channel_sum_x('accepted-count',
30
+ # 1,
31
+ # {:d => '2013-09-04T00:00:00-07:00,2013-09-04T23:59:59-07:00'},
32
+ # {"agent-id"=>"foo", "queue-name"=>"bar"}}
24
33
  def channel_sum_x(x, guid=0, params_options={}, filtered_options={})
25
34
  details = channel_details(guid, params_options, filtered_options)
26
35
  sum = details.map {|detail| detail[x]}.inject(:+) if details
@@ -4,12 +4,13 @@ module ApiWrapperFor8x8
4
4
 
5
5
  include ApiWrapperFor8x8::Channel
6
6
  include ApiWrapperFor8x8::Agents
7
+ include ApiWrapperFor8x8::Stats
7
8
 
8
9
  RECORDS_LIMIT = 50
9
10
  MAX_TRY = 3
10
11
  VALID_SEGMENT = ['channels', 'agents', 'statistics']
11
12
 
12
- base_uri "#{ENV['PHONE_SYSTEM_URL']}"
13
+ base_uri "https://na3.mycontactual.com/api"
13
14
  format :json
14
15
 
15
16
  def initialize(creds={})
@@ -20,9 +21,11 @@ module ApiWrapperFor8x8
20
21
  end
21
22
 
22
23
  def request(method, url, options={})
23
- raise "Please set usranme and password" unless api_token_keys_valid?
24
+ unless api_token_keys_valid?
25
+ raise ApiWrapperFor8x8::ResponseError.new(nil, "Please set username and password correctly")
26
+ end
24
27
  options[:basic_auth] = @configuration
25
- self.class.__send__(method, url, options).parsed_response
28
+ parsed_response(self.class.__send__(method, url, options))
26
29
  end
27
30
 
28
31
  def api_token_keys_valid?
@@ -93,5 +96,19 @@ module ApiWrapperFor8x8
93
96
  flag
94
97
  end
95
98
  end
99
+
100
+ def parsed_response(response)
101
+ if response.is_a? Net::HTTPResponse
102
+ unless response.is_a? Net::HTTPSuccess
103
+ raise ApiWrapperFor8x8::ResponseError.new(response)
104
+ end
105
+ JSON.parse(response.body)
106
+ else
107
+ unless response.success?
108
+ raise ApiWrapperFor8x8::ResponseError.new(response)
109
+ end
110
+ response.parsed_response
111
+ end
112
+ end
96
113
  end
97
114
  end
@@ -15,6 +15,8 @@ module ApiWrapperFor8x8
15
15
  def common_solutions
16
16
  if @response.code.to_i == 401
17
17
  "Check your credentials and make sure they are correct and not expired"
18
+ elsif @response.code.to_i >= 500 && @response.code.to_i < 600
19
+ "Check the format of your json"
18
20
  end
19
21
  end
20
22
 
@@ -0,0 +1,50 @@
1
+ module ApiWrapperFor8x8
2
+ module Stats
3
+
4
+ DEFAULT_STAT_ATTR = ["entered-count", "accepted-count", "abandoned-count", "time-waiting"]
5
+ # Since the api only aggregate the records by half an
6
+ # hour, so why not they have aggregate by hour
7
+ def stats_per_hour(url, params={}, filtered_opts={}, stats_attr=[])
8
+ raise ApiWrapperFor8x8::ResponseError.new({}, "Required date range!") unless params[:d]
9
+ if stats_attr.include?('queue-name') || stats_attr.include?('time-stamp')
10
+ raise ApiWrapperFor8x8::ResponseError.new({}, "Does not support queue-name or time-stamp as stat attribute")
11
+ end
12
+
13
+ stats = get(url, params, filtered_opts)
14
+ stats_attr = DEFAULT_STAT_ATTR if stats_attr.size == 0
15
+ times = params[:d].split(',')
16
+ start = Time.parse(times.first)
17
+ stop = Time.parse(times.last)
18
+ hash = {}
19
+
20
+ # init the hash object
21
+ (beginning_of_hour(start).to_i..end_of_hour(stop).to_i).step(3600) do |h|
22
+ hour = Time.at(h)
23
+ hour_key = hour.iso8601
24
+ hash[hour_key] = {}
25
+ hash[hour_key]['timestamp'] = hour
26
+ stats_attr.each { |key| hash[hour_key][key] = 0 }
27
+ end
28
+
29
+ # insert stats data to hash with timestamp as key
30
+ stats.each do |stat|
31
+ timestamp = stat["time-stamp"]
32
+ timekey = hash[timestamp] ? timestamp : (Time.parse(timestamp) - 1800).iso8601
33
+ stats_attr.each do |stat_attr|
34
+ stats_by_time = hash[timekey] || {}
35
+ stats_by_time[stat_attr] += stat[stat_attr] if stats_by_time[stat_attr] && stat[stat_attr]
36
+ end
37
+ end if stats
38
+ return hash.collect{ |key, value| value }
39
+ end
40
+
41
+ def beginning_of_hour(time)
42
+ Time.mktime(time.year, time.month, time.day, time.hour).send(Time.now.gmt? ? :gmt : :localtime)
43
+ end
44
+
45
+ def end_of_hour(time)
46
+ beginning_of_hour(time)+3600
47
+ end
48
+
49
+ end
50
+ end
@@ -1,3 +1,3 @@
1
1
  module ApiWrapperFor8x8
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Agent' do
4
+ describe "get_detail" do
5
+ it "should have call get with correct params" do
6
+ id = 0
7
+ expect(@api).to receive(:get).with("/stats/agents/#{id}/statistics.json", {}, {})
8
+ @api.agent_detail(id, {}, {})
9
+ end
10
+ end
11
+ end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe ApiWrapperFor8x8::Agents do
4
4
  describe "agent_list" do
5
5
  it "should GET /stats/agents.json" do
6
- @api.should_receive(:get).with('/stats/agents.json', {})
6
+ @api.should_receive(:get).with('/stats/agents.json', {}, {})
7
7
  @api.agent_list
8
8
  end
9
9
  end
@@ -15,22 +15,9 @@ describe ApiWrapperFor8x8::Agents do
15
15
  resp = {'statistics' => {'statistic' => agents}}
16
16
  agent_details = [{'agent-id' => agent_id, 'accepted-count' => 23}]
17
17
  @api.stub(:agent_list)
18
- expect(@api).to receive(:filtered_agents).with(agents, {}).and_return(agents)
19
- expect(@api).to receive(:agent_list).with({}).and_return(agents)
20
- expect(@api).to receive(:agent_detail).with(agent_id, {}).and_return(agent_details)
18
+ expect(@api).to receive(:agent_list).and_return(agents)
19
+ expect(@api).to receive(:agent_detail).with(agent_id, {}, {}).and_return(agent_details)
21
20
  @api.agents_detail.should == agent_details
22
21
  end
23
22
  end
24
-
25
- describe "filtered_agents" do
26
- before :each do
27
- @agent1 = {"agent-id" => "a", "enabled" => 'Y'}
28
- @agent2 = {"agent-id" => 'b', "enabled" => 'D'}
29
- @agent_lists = [@agent1, @agent2]
30
- end
31
- it "should filter agents with enabled" do
32
- @api.filtered_agents(@agent_lists, {"enabled" => "Y"}).should == [@agent1]
33
- @api.filtered_agents(@agent_lists, {"enabled" => "D"}).should == [@agent2]
34
- end
35
- end
36
23
  end
@@ -8,7 +8,7 @@ describe ApiWrapperFor8x8::Channel do
8
8
 
9
9
  describe "channel_list" do
10
10
  it "should GET /stats/channels.json" do
11
- @api.should_receive(:get).with('/stats/channels.json', {})
11
+ @api.should_receive(:get).with('/stats/channels.json', {}, {})
12
12
  @api.channel_list
13
13
  end
14
14
 
@@ -81,12 +81,11 @@ describe ApiWrapperFor8x8::Connection do
81
81
  end
82
82
  end
83
83
 
84
-
85
- it "should get /stats/agents.json" do
86
- url = "/stats/agents.json"
87
- @api.should_receive(:get_stat).with(@httparty_response, url).and_return([{}])
88
- @api.should_receive(:request).with(:get, url, {}).and_return(@httparty_response)
89
- @api.get(url)
84
+ describe "base_uri" do
85
+ it "should not be empty or nil" do
86
+ ApiWrapperFor8x8::Connection::base_uri.should_not be_nil
87
+ ApiWrapperFor8x8::Connection::base_uri.size.should_not be_zero
88
+ end
90
89
  end
91
90
 
92
91
  end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe ApiWrapperFor8x8::ResponseError do
4
+ describe "For OAth response" do
5
+ before do
6
+ @net_http_response = Net::HTTPSuccess.new('1.1', '200', 'OK')
7
+ @error = ApiWrapperFor8x8::ResponseError.new(@net_http_response)
8
+ end
9
+
10
+ it "response should return Net::HTTP response" do
11
+ @error.response.should == @net_http_response
12
+ end
13
+
14
+ it "code should return response code" do
15
+ @error.code.should == '200'
16
+ end
17
+
18
+ describe "message" do
19
+ it "should return response message" do
20
+ @error.message.should == 'OK'
21
+ end
22
+
23
+ it "should return specified message" do
24
+ error = ApiWrapperFor8x8::ResponseError.new(@net_http_response, "No way")
25
+ error.message.should == 'No way'
26
+ end
27
+ end
28
+
29
+
30
+ describe "common_solutions" do
31
+ describe "on 401" do
32
+ it "should suggest to check credentials" do
33
+ net_http_response = Net::HTTPUnauthorized.new('1.1', '401', 'Unauthorized Access')
34
+ error = ApiWrapperFor8x8::ResponseError.new(net_http_response)
35
+ error.common_solutions.should match /Check your credentials/i
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -5,6 +5,7 @@ require 'rspec/expectations'
5
5
  require 'httparty'
6
6
  require 'json'
7
7
 
8
+ require_relative '../lib/ApiWrapperFor8x8/stats.rb'
8
9
  Dir[File.dirname(__FILE__)+'/../lib/ApiWrapperFor8x8/*.rb'].each{|file| require file}
9
10
 
10
11
  RSpec.configure do |config|
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe "ApiWrapperFor8x8::Stats" do
4
+ describe "stats_per_hour" do
5
+
6
+ context "should return correct data with valid params" do
7
+ before :each do
8
+ @url = "/stats/channels/1/statistics.json"
9
+ @params = {:d => '2013-05-28T12:54:55-07:00,2013-05-28T19:54:55-07:00', :tz => 'America/Los_Angeles'}
10
+ @resp = [{"time-stamp" => "2013-05-28T13:30:00-07:00",
11
+ "entered-count" => 3,
12
+ "accepted-count" => 2,
13
+ "abandoned-count" => 1,
14
+ "time-waiting" => 24
15
+ },{"time-stamp" => "2013-05-28T14:00:00-07:00",
16
+ "entered-count" => 10,
17
+ "accepted-count" => 8,
18
+ "abandoned-count" => 2,
19
+ "time-waiting" => 124},
20
+ {"time-stamp" => "2013-05-28T19:00:00-07:00",
21
+ "entered-count" => 20,
22
+ "accepted-count" => 19,
23
+ "abandoned-count" => 1,
24
+ "time-waiting" => 144}]
25
+ end
26
+
27
+ it "should return an array of hash that includes all the stat attr and the timestamp" do
28
+ expect(@api).to receive(:get).with(@url, @params, {}).and_return(@resp)
29
+ ret = @api.stats_per_hour(@url, @params, {})
30
+
31
+ ret.size.should == 9
32
+ ret.map {|r| r['entered-count']}.inject {|sum,num| sum+num}.should == 33
33
+ ret.map {|r| r['accepted-count']}.inject {|sum,num| sum+num}.should == 29
34
+ ret.map {|r| r['abandoned-count']}.inject {|sum,num| sum+num}.should == 4
35
+ end
36
+ end
37
+
38
+ end
39
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ApiWrapperFor8x8
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-25 00:00:00.000000000 Z
12
+ date: 2013-09-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -143,13 +143,16 @@ files:
143
143
  - lib/ApiWrapperFor8x8/channel.rb
144
144
  - lib/ApiWrapperFor8x8/connection.rb
145
145
  - lib/ApiWrapperFor8x8/error.rb
146
+ - lib/ApiWrapperFor8x8/stats.rb
146
147
  - lib/ApiWrapperFor8x8/version.rb
147
148
  - spec/.rspec
148
149
  - spec/agent_spec.rb
149
150
  - spec/agents_spec.rb
150
151
  - spec/channel_spec.rb
151
152
  - spec/connection_spec.rb
153
+ - spec/error_spec.rb
152
154
  - spec/spec_helper.rb
155
+ - spec/stats_spec.rb
153
156
  - spec/version_spec.rb
154
157
  homepage: https://github.com/daifu/api-wrapper-for-8x8
155
158
  licenses:
@@ -182,5 +185,7 @@ test_files:
182
185
  - spec/agents_spec.rb
183
186
  - spec/channel_spec.rb
184
187
  - spec/connection_spec.rb
188
+ - spec/error_spec.rb
185
189
  - spec/spec_helper.rb
190
+ - spec/stats_spec.rb
186
191
  - spec/version_spec.rb