ApiWrapperFor8x8 0.0.1 → 0.0.3

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.
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