ctm 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.
- data/.gitignore +1 -0
- data/Gemfile +2 -0
- data/README.md +125 -0
- data/Rakefile +10 -0
- data/TODO +38 -0
- data/ctm.gemspec +20 -0
- data/examples/buy_numbers.rb +14 -0
- data/examples/example.rb +38 -0
- data/examples/manage_numbers.rb +45 -0
- data/examples/manage_receivng_numbers.rb +25 -0
- data/examples/manage_sources.rb +25 -0
- data/examples/manage_users.rb +31 -0
- data/examples/manage_webhooks.rb +16 -0
- data/lib/ctm.rb +20 -0
- data/lib/ctm/account.rb +38 -0
- data/lib/ctm/auth.rb +24 -0
- data/lib/ctm/available_number.rb +18 -0
- data/lib/ctm/base.rb +49 -0
- data/lib/ctm/call.rb +11 -0
- data/lib/ctm/error.rb +16 -0
- data/lib/ctm/list.rb +80 -0
- data/lib/ctm/number.rb +25 -0
- data/lib/ctm/number_list.rb +63 -0
- data/lib/ctm/receiving_number.rb +25 -0
- data/lib/ctm/receiving_number_list.rb +39 -0
- data/lib/ctm/sale.rb +8 -0
- data/lib/ctm/source.rb +33 -0
- data/lib/ctm/token.rb +15 -0
- data/lib/ctm/user.rb +30 -0
- data/lib/ctm/webhook.rb +15 -0
- metadata +189 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Gemfile.lock
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
CallTrackingMetrics Ruby API
|
2
|
+
============================
|
3
|
+
|
4
|
+
Installation
|
5
|
+
------------
|
6
|
+
|
7
|
+
gem install ctm
|
8
|
+
|
9
|
+
|
10
|
+
Usage
|
11
|
+
-----
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
|
15
|
+
require 'ctm'
|
16
|
+
|
17
|
+
# get an access token
|
18
|
+
access_token = CTM::Auth.authenticate(ENV['CTM_TOKEN'], ENV['CTM_SECRET'])
|
19
|
+
|
20
|
+
# see the list of accounts
|
21
|
+
puts CTM::Account.list(access_token).inspect
|
22
|
+
|
23
|
+
# use this access token globally, instead of passing it to each method
|
24
|
+
CTM::Auth.token = access_token
|
25
|
+
|
26
|
+
# get my first account
|
27
|
+
account = CTM::Account.first
|
28
|
+
|
29
|
+
# get an account by name
|
30
|
+
account = CTM::Account.find("name" => "My Account Name")
|
31
|
+
|
32
|
+
# get a list of numbers within this account, returns 10 at a time by default
|
33
|
+
numbers = account.numbers
|
34
|
+
puts numbers.first.inspect
|
35
|
+
puts numbers.total_entries.inspect
|
36
|
+
puts numbers.page.inspect
|
37
|
+
puts numbers.per_page.inspect
|
38
|
+
numbers.each {|number|
|
39
|
+
puts number.id
|
40
|
+
puts "#{number.name} #{number.number} -> #{number.formatted}"
|
41
|
+
}
|
42
|
+
|
43
|
+
# get the next 20 numbers on page 2
|
44
|
+
numbers = account.numbers(:page => 2, :per_page => 20)
|
45
|
+
|
46
|
+
# search for new numbers to purchase
|
47
|
+
numbers = account.numbers.search("+1", :areacode => "410")
|
48
|
+
numbers = account.numbers.search("+1", :tollfree => true, :areacode => "888")
|
49
|
+
numbers = account.number.search("+44", :contains => "55")
|
50
|
+
|
51
|
+
# purchase a new number
|
52
|
+
number = account.numbers.buy(numbers.first.digits)
|
53
|
+
if number.purchased?
|
54
|
+
puts "successfully purchased the number: #{number.digits_formated}"
|
55
|
+
else
|
56
|
+
puts "failed to purchase that number"
|
57
|
+
end
|
58
|
+
|
59
|
+
# release the number, removing it from the account
|
60
|
+
number.release!
|
61
|
+
|
62
|
+
# create a source from a predefined source
|
63
|
+
source = account.sources.create(predefined: 'google_adwords')
|
64
|
+
|
65
|
+
# list predefined sources
|
66
|
+
predefined = account.predefined
|
67
|
+
|
68
|
+
# customize a source
|
69
|
+
source = account.sources.find(:name => "Google Adwords")
|
70
|
+
source.landing_url = "utm_campaign=MyCampaign"
|
71
|
+
source.save
|
72
|
+
|
73
|
+
# assign a source to a number
|
74
|
+
source.numbers.add(number)
|
75
|
+
|
76
|
+
# get a list of receiving numbers
|
77
|
+
receiving_numbers = account.receiving_numbers
|
78
|
+
|
79
|
+
# add a receiving number, note +1 country code is required
|
80
|
+
receiving_number = account.receiving_numbers.create(name: "my number", number:"+15555555555")
|
81
|
+
|
82
|
+
# assign a receiving number to the tracking number
|
83
|
+
number.receiving_numbers.add(receiving_number)
|
84
|
+
# get the list of receiving numbers for this number
|
85
|
+
puts number.receiving_numbers.inspect
|
86
|
+
number.save
|
87
|
+
|
88
|
+
# modify the routing preference for the number
|
89
|
+
number.routing = :simultaneous # :round_robin, :least_connected
|
90
|
+
number.save
|
91
|
+
|
92
|
+
# add a new user to the account
|
93
|
+
account.users.create(first_name: 'First', last_name: 'Last', email: 'email@example.com', notify: true)
|
94
|
+
|
95
|
+
# list the users
|
96
|
+
users = account.users
|
97
|
+
|
98
|
+
# create a webhook to send call data at the start of the call
|
99
|
+
account.webhooks.create(weburl: "http://myhost.com/new_calls", position: 'start')
|
100
|
+
|
101
|
+
# create a webhook to send call data at the end of the call
|
102
|
+
account.webhooks.create(weburl: "http://myhost.com/new_calls", position: 'end')
|
103
|
+
|
104
|
+
# list webhooks
|
105
|
+
account.webhooks
|
106
|
+
|
107
|
+
# calls - list the calls
|
108
|
+
account.calls
|
109
|
+
|
110
|
+
call = account.calls.first
|
111
|
+
|
112
|
+
call.notes = "some notes to attach to the call"
|
113
|
+
call.save
|
114
|
+
|
115
|
+
# get sale record
|
116
|
+
call.sale
|
117
|
+
|
118
|
+
# create sale record, marking the call as a conversion
|
119
|
+
call.sale.create(name: "Who", score: 5, conversion: true, value: 34, date: '2013-04-24T00:00:00Z')
|
120
|
+
# or update the sale record
|
121
|
+
sale = call.sale
|
122
|
+
sale.name = "Todd"
|
123
|
+
sale.save
|
124
|
+
|
125
|
+
```
|
data/Rakefile
ADDED
data/TODO
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
* Accounts
|
2
|
+
x list accounts
|
3
|
+
- create account with shared billing
|
4
|
+
- create account without shared billing
|
5
|
+
* Numbers
|
6
|
+
x list numbers
|
7
|
+
x buy number
|
8
|
+
x search available numbers
|
9
|
+
x list receiving numbers
|
10
|
+
x add receiving number
|
11
|
+
x rem receiving number
|
12
|
+
x get assigned source
|
13
|
+
x add source
|
14
|
+
- rem source
|
15
|
+
|
16
|
+
* Receiving Numbers
|
17
|
+
x list receiving numbers
|
18
|
+
x add receiving number
|
19
|
+
x rem receiving number
|
20
|
+
* Sources
|
21
|
+
x list sources
|
22
|
+
x add source
|
23
|
+
x rem source
|
24
|
+
x list numbers for the source
|
25
|
+
* Users
|
26
|
+
x list users
|
27
|
+
x add user
|
28
|
+
x update user
|
29
|
+
x rem user
|
30
|
+
* Webhooks
|
31
|
+
x list webhooks for account
|
32
|
+
x add webhook
|
33
|
+
x rem webhook
|
34
|
+
* Calls
|
35
|
+
- list calls
|
36
|
+
- show call
|
37
|
+
- add sale to call
|
38
|
+
- rem sale from call
|
data/ctm.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "ctm"
|
3
|
+
s.version = "0.0.1"
|
4
|
+
s.authors = ["CallTrackingMetrics", "Todd Fisher"]
|
5
|
+
s.email = "info@calltrackingmetrics.com"
|
6
|
+
s.files = `git ls-files`.split("\n")
|
7
|
+
s.test_files = `git ls-files -- {test}/*`.split("\n")
|
8
|
+
s.homepage = "http://github.com/calltracking/ctm-ruby"
|
9
|
+
s.require_path = "lib"
|
10
|
+
s.rubygems_version = "1.3.5"
|
11
|
+
s.summary = "API Library for CallTrackingMetrics"
|
12
|
+
s.add_runtime_dependency "phony"
|
13
|
+
s.add_runtime_dependency "httparty"
|
14
|
+
s.add_runtime_dependency "activesupport"
|
15
|
+
s.add_development_dependency "rack", '~> 1.3.0'
|
16
|
+
s.add_development_dependency "mocha"
|
17
|
+
s.add_development_dependency 'fakeweb', '~> 1.3.0'
|
18
|
+
s.add_development_dependency "rake"
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__),"..", "lib")))
|
2
|
+
require 'ctm'
|
3
|
+
|
4
|
+
access_token = CTM::Auth.authenticate(ENV['CTM_TOKEN'], ENV['CTM_SECRET'])
|
5
|
+
account = access_token.accounts.first
|
6
|
+
|
7
|
+
availble_numbers = account.numbers.search("US", :area_code => "410")
|
8
|
+
availble_numbers.each do|num|
|
9
|
+
puts "#{num.friendly_name} -> #{num.phone_number}"
|
10
|
+
end
|
11
|
+
number_to_buy = availble_numbers.first
|
12
|
+
|
13
|
+
number = account.numbers.buy("+15005550006")
|
14
|
+
puts "purchased: #{number.formatted} #{number.number}"
|
data/examples/example.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__),"..", "lib")))
|
2
|
+
require 'ctm'
|
3
|
+
|
4
|
+
access_token = CTM::Auth.authenticate(ENV['CTM_TOKEN'], ENV['CTM_SECRET'])
|
5
|
+
puts "Accounts you have access to:"
|
6
|
+
access_token.accounts.each do|account|
|
7
|
+
puts "#{account.name} -> #{account.status}, #{account.balance}, #{account.stats.inspect}"
|
8
|
+
end
|
9
|
+
account = access_token.accounts.first
|
10
|
+
|
11
|
+
numbers = account.numbers
|
12
|
+
puts "Tracking Numbers #{numbers.total_entries} within the Account"
|
13
|
+
numbers.each do|number|
|
14
|
+
puts "#{number.id}: #{number.name} #{number.number} -> #{number.formatted}"
|
15
|
+
end
|
16
|
+
receiving_numbers = account.receiving_numbers
|
17
|
+
puts "Receiving Numbers #{receiving_numbers.total_entries} within the Account"
|
18
|
+
receiving_numbers.each do|number|
|
19
|
+
puts "#{number.id}: #{number.name} #{number.number} -> #{number.formatted}"
|
20
|
+
end
|
21
|
+
|
22
|
+
sources = account.sources
|
23
|
+
puts "Tracking Sources #{sources.total_entries} within the Account"
|
24
|
+
sources.each do|source|
|
25
|
+
puts "#{source.id}: #{source.name} #{source.referring_url} -> #{source.landing_url}"
|
26
|
+
end
|
27
|
+
|
28
|
+
users = account.users
|
29
|
+
puts "Users #{users.total_entries} within the Account"
|
30
|
+
users.each do|user|
|
31
|
+
puts "#{user.id}: #{user.name} #{user.email} -> #{user.role}"
|
32
|
+
end
|
33
|
+
|
34
|
+
webhooks = account.webhooks
|
35
|
+
puts "Webhooks #{webhooks.total_entries} within the Account"
|
36
|
+
webhooks.each do|wh|
|
37
|
+
puts "#{wh.id}: #{wh.weburl} #{wh.with_resource_url} -> #{wh.position}"
|
38
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__),"..", "lib")))
|
2
|
+
require 'ctm'
|
3
|
+
|
4
|
+
access_token = CTM::Auth.authenticate(ENV['CTM_TOKEN'], ENV['CTM_SECRET'])
|
5
|
+
account = access_token.accounts.first
|
6
|
+
|
7
|
+
numbers = account.numbers
|
8
|
+
puts "Tracking Numbers #{numbers.total_entries} within the Account"
|
9
|
+
numbers.each do|number|
|
10
|
+
puts "#{number.id}: #{number.name} #{number.number} -> #{number.formatted}"
|
11
|
+
end
|
12
|
+
|
13
|
+
number = numbers.first
|
14
|
+
# add receiving number
|
15
|
+
receiving_numbers = number.receiving_numbers
|
16
|
+
puts "Receiving Numbers #{receiving_numbers.total_entries} assigned to the tracking number"
|
17
|
+
receiving_numbers.each do|number|
|
18
|
+
puts "#{number.id}: #{number.name} #{number.number} -> #{number.formatted}"
|
19
|
+
end
|
20
|
+
receiving_number = account.receiving_numbers.find(:name => "laures phone").first
|
21
|
+
puts "Adding and removing: #{receiving_number.number}"
|
22
|
+
number.receiving_numbers.add(receiving_number)
|
23
|
+
number.receiving_numbers.rem(receiving_number)
|
24
|
+
|
25
|
+
# add tracking source
|
26
|
+
source = account.sources.find(:name => "Google Organic").first
|
27
|
+
puts source.name
|
28
|
+
source.numbers.each do|number|
|
29
|
+
puts "#{number.id}: #{number.name} #{number.number} -> #{number.formatted}"
|
30
|
+
end
|
31
|
+
|
32
|
+
source = account.sources.find(:name => "test source1").first
|
33
|
+
if !source
|
34
|
+
source = account.sources.create(:name => "test source1")
|
35
|
+
end
|
36
|
+
|
37
|
+
number = account.numbers.find(:name => "test number1").first
|
38
|
+
puts number.formatted
|
39
|
+
|
40
|
+
number.receiving_numbers.add(receiving_number)
|
41
|
+
|
42
|
+
source.numbers.add(number)
|
43
|
+
source.numbers.each do|number|
|
44
|
+
puts "#{number.id}: #{number.name} #{number.number} -> #{number.formatted}"
|
45
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__),"..", "lib")))
|
2
|
+
require 'ctm'
|
3
|
+
|
4
|
+
access_token = CTM::Auth.authenticate(ENV['CTM_TOKEN'], ENV['CTM_SECRET'])
|
5
|
+
account = access_token.accounts.first
|
6
|
+
|
7
|
+
receiving_numbers = account.receiving_numbers
|
8
|
+
puts "Receiving Numbers #{receiving_numbers.total_entries} within the Account"
|
9
|
+
receiving_numbers.each do|number|
|
10
|
+
puts "#{number.id}: #{number.name} #{number.number} -> #{number.formatted}"
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
rn = account.receiving_numbers.create(:number => "+14109999999", :name => "test number")
|
15
|
+
rescue CTM::Error::Create => e
|
16
|
+
if e.message.match(/already exists/)
|
17
|
+
rn = account.receiving_numbers.find(:number => "+14109999999").first
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
puts rn.inspect
|
22
|
+
rn.name = "another test"
|
23
|
+
rn.save
|
24
|
+
|
25
|
+
rn.release!
|
@@ -0,0 +1,25 @@
|
|
1
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__),"..", "lib")))
|
2
|
+
require 'ctm'
|
3
|
+
|
4
|
+
access_token = CTM::Auth.authenticate(ENV['CTM_TOKEN'], ENV['CTM_SECRET'])
|
5
|
+
account = access_token.accounts.first
|
6
|
+
|
7
|
+
sources = account.sources
|
8
|
+
puts "Tracking Sources #{sources.total_entries} within the Account"
|
9
|
+
sources.each do|source|
|
10
|
+
puts "#{source.id}: #{source.name} #{source.referring_url} -> #{source.landing_url}"
|
11
|
+
end
|
12
|
+
|
13
|
+
source = account.sources.create(:name => "My Source",
|
14
|
+
:referring_url => "google",
|
15
|
+
:landing_url => "utm_campaign=paid",
|
16
|
+
:online => true)
|
17
|
+
puts source.name
|
18
|
+
puts source.referring_url
|
19
|
+
puts source.landing_url
|
20
|
+
|
21
|
+
source.name = "Foo bar"
|
22
|
+
|
23
|
+
source.save
|
24
|
+
|
25
|
+
source.release!
|
@@ -0,0 +1,31 @@
|
|
1
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__),"..", "lib")))
|
2
|
+
require 'ctm'
|
3
|
+
access_token = CTM::Auth.authenticate(ENV['CTM_TOKEN'], ENV['CTM_SECRET'])
|
4
|
+
account = access_token.accounts.first
|
5
|
+
|
6
|
+
# find user by email
|
7
|
+
users = account.users.find(:email => "todd@calltrackingmetrics.com")
|
8
|
+
users.each do|user|
|
9
|
+
puts "#{user.id}: #{user.name} #{user.email} -> #{user.role}"
|
10
|
+
end
|
11
|
+
|
12
|
+
# find by last name
|
13
|
+
users = account.users.find(:last_name => "fisher")
|
14
|
+
users.each do|user|
|
15
|
+
puts "#{user.id}: #{user.name} #{user.email} -> #{user.role}"
|
16
|
+
end
|
17
|
+
|
18
|
+
# add a new user
|
19
|
+
user = account.users.create(:email => "foo@bar11#{Time.now.to_i}.com",
|
20
|
+
:first_name => "Me",
|
21
|
+
:last_name => "You",
|
22
|
+
:password => "foobar1234",
|
23
|
+
:role => "call_manager")
|
24
|
+
# update user
|
25
|
+
user.first_name = "No"
|
26
|
+
user.last_name = "Yes"
|
27
|
+
user.role = "admin"
|
28
|
+
user.save
|
29
|
+
|
30
|
+
# remove user from account
|
31
|
+
user.release!
|
@@ -0,0 +1,16 @@
|
|
1
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__),"..", "lib")))
|
2
|
+
require 'ctm'
|
3
|
+
|
4
|
+
access_token = CTM::Auth.authenticate(ENV['CTM_TOKEN'], ENV['CTM_SECRET'])
|
5
|
+
account = access_token.accounts.first
|
6
|
+
|
7
|
+
webhooks = account.webhooks
|
8
|
+
puts "Webhooks #{webhooks.total_entries} within the Account"
|
9
|
+
webhooks.each do|wh|
|
10
|
+
puts "#{wh.id}: #{wh.weburl} #{wh.with_resource_url} -> #{wh.position}"
|
11
|
+
end
|
12
|
+
|
13
|
+
# get requests when the call starts
|
14
|
+
webhook = webhooks.create(:weburl => "http://example.com/myhook", :position => "start")
|
15
|
+
|
16
|
+
webhook.release!
|
data/lib/ctm.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module CTM ; end
|
2
|
+
require 'httparty'
|
3
|
+
require 'active_support/inflector'
|
4
|
+
|
5
|
+
require 'ctm/error'
|
6
|
+
require 'ctm/base'
|
7
|
+
require 'ctm/list'
|
8
|
+
require 'ctm/account'
|
9
|
+
require 'ctm/auth'
|
10
|
+
require 'ctm/available_number'
|
11
|
+
require 'ctm/call'
|
12
|
+
require 'ctm/number'
|
13
|
+
require 'ctm/number_list'
|
14
|
+
require 'ctm/receiving_number'
|
15
|
+
require 'ctm/receiving_number_list'
|
16
|
+
require 'ctm/sale'
|
17
|
+
require 'ctm/source'
|
18
|
+
require 'ctm/token'
|
19
|
+
require 'ctm/user'
|
20
|
+
require 'ctm/webhook'
|
data/lib/ctm/account.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module CTM
|
2
|
+
class Account < Base
|
3
|
+
attr_reader :id
|
4
|
+
attr_accessor :name, :status, :stats, :balance
|
5
|
+
|
6
|
+
# {"id"=>25, "name"=>"CallTrackingMetrics", "user_role"=>"admin", "status"=>"active",
|
7
|
+
# "stats"=>{"calls"=>{"2013-04-18"=>3, "2013-04-25"=>1}, "tracking_numbers"=>48},
|
8
|
+
# "url"=>"http://ctmdev.co/api/v1/accounts/25.json", "balance"=>{"cents"=>23739, "currency"=>"USD", "precision"=>2}}
|
9
|
+
def initialize(data, token=nil)
|
10
|
+
super(data, token)
|
11
|
+
@id = data['id']
|
12
|
+
@name = data['name']
|
13
|
+
@status = data['status']
|
14
|
+
@stats = data['stats']['calls']
|
15
|
+
@balance = "$" + (data['balance']['cents'].to_i / 100).to_s + "." + (data['balance']['cents'].to_i % 100).to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
def numbers(options={})
|
19
|
+
CTM::NumberList.new(options.merge(:account_id => @id), @token)
|
20
|
+
end
|
21
|
+
|
22
|
+
def receiving_numbers(options={})
|
23
|
+
CTM::List.new('ReceivingNumber', options.merge(:account_id => @id), @token)
|
24
|
+
end
|
25
|
+
|
26
|
+
def sources(options={})
|
27
|
+
CTM::List.new('Source', options.merge(:account_id => @id), @token)
|
28
|
+
end
|
29
|
+
|
30
|
+
def users(options={})
|
31
|
+
CTM::List.new('User', options.merge(:account_id => @id), @token)
|
32
|
+
end
|
33
|
+
|
34
|
+
def webhooks(options={})
|
35
|
+
CTM::List.new('Webhook', options.merge(:account_id => @id), @token)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/ctm/auth.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module CTM
|
2
|
+
class Auth
|
3
|
+
include HTTParty
|
4
|
+
base_uri ENV["CTM_URL"] || "api.calltrackingmetrics.com"
|
5
|
+
|
6
|
+
def self.token=(token)
|
7
|
+
@token = token
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.token
|
11
|
+
@token
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.authenticate(token, secret)
|
15
|
+
res = self.post("/api/v1/authentication", :body => {:token => token, :secret => secret})
|
16
|
+
if res.parsed_response && res.parsed_response['success']
|
17
|
+
CTM::Token.new(res.parsed_response)
|
18
|
+
else
|
19
|
+
raise CTM::Error::Auth.new("Failed to authenticate")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module CTM
|
2
|
+
class AvailableNumber < Base
|
3
|
+
attr_reader :friendly_name, :latitude, :longitude, :rate_center, :lata, :region, :postal_code, :iso_country, :phone_number
|
4
|
+
|
5
|
+
def initialize(data, token=nil)
|
6
|
+
super(data, token)
|
7
|
+
@friendly_name = data['friendly_name']
|
8
|
+
@latitude = data['latitude']
|
9
|
+
@longitude = data['longitude']
|
10
|
+
@lata = data['lata']
|
11
|
+
@region = data['region']
|
12
|
+
@postal_code = data['postal_code']
|
13
|
+
@iso_country = data['iso_country']
|
14
|
+
@phone_number = data['phone_number']
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
data/lib/ctm/base.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
module CTM
|
2
|
+
class Base
|
3
|
+
include HTTParty
|
4
|
+
base_uri ENV["CTM_URL"] || "api.calltrackingmetrics.com"
|
5
|
+
|
6
|
+
attr_reader :token, :account_id
|
7
|
+
|
8
|
+
|
9
|
+
def initialize(data, token=nil)
|
10
|
+
@token = token || CTM::Auth.token
|
11
|
+
@account_id = data['account_id']
|
12
|
+
@list_token_type = self.class.to_s.sub(/CTM::/,'').underscore.pluralize
|
13
|
+
if @account_id
|
14
|
+
@list_type_path = "accounts/#{@account_id}/#{@list_token_type}"
|
15
|
+
else
|
16
|
+
@list_type_path = @list_token_type
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def save(options={})
|
21
|
+
puts "save: #{options.inspect}"
|
22
|
+
path_str = "/api/v1/#{@list_type_path}/#{@id}.json"
|
23
|
+
res = self.class.put(path_str, :body => options.merge(:auth_token => @token))
|
24
|
+
end
|
25
|
+
|
26
|
+
def release!
|
27
|
+
path_str = "/api/v1/#{@list_type_path}/#{@id}.json"
|
28
|
+
res = self.class.delete(path_str, :body => {:auth_token => @token})
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.create(options)
|
32
|
+
list_type_path = options.delete(:list_type_path)
|
33
|
+
list_token_type = options.delete(:list_token_type)
|
34
|
+
account_id = options.delete(:account_id)
|
35
|
+
token = options.delete(:token)
|
36
|
+
path_str = "/api/v1/#{list_type_path}.json"
|
37
|
+
puts "create: #{self} -> #{options.inspect}"
|
38
|
+
res = self.post(path_str, :body => options.merge(:auth_token => token))
|
39
|
+
puts "result: #{res.parsed_response.inspect}"
|
40
|
+
puts "properties: #{list_type_path.inspect} -> #{list_token_type.inspect} -> #{account_id}"
|
41
|
+
if res.parsed_response['status'] == 'error'
|
42
|
+
raise CTM::Error::Create.new(res.parsed_response['reason'])
|
43
|
+
else
|
44
|
+
self.new(res.parsed_response[list_token_type.singularize], token)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
data/lib/ctm/call.rb
ADDED
data/lib/ctm/error.rb
ADDED
data/lib/ctm/list.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# Generic List Object to handle paginated lists of objects
|
2
|
+
module CTM
|
3
|
+
class List
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
include HTTParty
|
7
|
+
base_uri ENV["CTM_URL"] || "api.calltrackingmetrics.com"
|
8
|
+
|
9
|
+
attr_reader :list_type, :token, :per_page, :page, :total_entries, :objects
|
10
|
+
|
11
|
+
# e.g. Account, token
|
12
|
+
def initialize(list_type, options={}, token=nil, fetched_objects=nil)
|
13
|
+
@list_type = list_type
|
14
|
+
@list_token_type = list_type.underscore.pluralize
|
15
|
+
@object_klass = CTM.module_eval(list_type)
|
16
|
+
@token = token || CTM::Auth.token
|
17
|
+
@account_id = options[:account_id]
|
18
|
+
if @account_id
|
19
|
+
@list_type_path = "accounts/#{@account_id}/#{@list_token_type}"
|
20
|
+
else
|
21
|
+
@list_type_path = @list_token_type
|
22
|
+
end
|
23
|
+
if fetched_objects
|
24
|
+
map_data(fetched_objects)
|
25
|
+
else
|
26
|
+
fetch_page(options)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def each &block
|
31
|
+
@objects.each do |obj|
|
32
|
+
if block_given?
|
33
|
+
block.call obj
|
34
|
+
else
|
35
|
+
yield obj
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def create(options)
|
41
|
+
@object_klass.create(options.merge(:list_type_path => @list_type_path,
|
42
|
+
:list_token_type => @list_token_type,
|
43
|
+
:account_id => @account_id,
|
44
|
+
:token => @token))
|
45
|
+
end
|
46
|
+
|
47
|
+
def find(options)
|
48
|
+
first_name = options.delete(:first_name)
|
49
|
+
last_name = options.delete(:last_name)
|
50
|
+
options[:filter] = options.delete(:filter) || "#{first_name} #{last_name}".strip if first_name || last_name
|
51
|
+
|
52
|
+
fetch_page(options)
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def fetch_page(options={})
|
59
|
+
options = {:per_page => 10, :page => 1}.merge(options)
|
60
|
+
path_str = "/api/v1/#{@list_type_path}.json"
|
61
|
+
res = self.class.get(path_str, :query => options.merge(:auth_token => @token))
|
62
|
+
data = res.parsed_response
|
63
|
+
if data["status"] && data["status"] == "error"
|
64
|
+
puts data.inspect
|
65
|
+
raise CTM::Error::List.new(data["message"] || data["reason"])
|
66
|
+
end
|
67
|
+
map_data(data)
|
68
|
+
end
|
69
|
+
|
70
|
+
def map_data(data)
|
71
|
+
@page = data['page']
|
72
|
+
@per_page = data['per_page']
|
73
|
+
@total_entries = data['total_entries']
|
74
|
+
@objects = data[@list_token_type].map {|obj|
|
75
|
+
@object_klass.new(obj, @token)
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
data/lib/ctm/number.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module CTM
|
2
|
+
class Number < Base
|
3
|
+
attr_reader :id, :account_id
|
4
|
+
attr_accessor :name, :number, :formatted, :split, :routing
|
5
|
+
|
6
|
+
def initialize(data, token=nil)
|
7
|
+
super(data, token)
|
8
|
+
@id = data['id']
|
9
|
+
@account_id = data['account_id']
|
10
|
+
@name = data['name']
|
11
|
+
@number = data['number']
|
12
|
+
@formatted = data['formatted']
|
13
|
+
@split = data['split']
|
14
|
+
@routing = data['routing']
|
15
|
+
end
|
16
|
+
|
17
|
+
def receiving_numbers(options={})
|
18
|
+
CTM::ReceivingNumberList.new(options.merge(:account_id => @account_id, :number_id => @id), @token)
|
19
|
+
end
|
20
|
+
|
21
|
+
def source
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module CTM
|
2
|
+
class NumberList < List
|
3
|
+
def initialize(options={}, token=nil)
|
4
|
+
super('Number', options, token)
|
5
|
+
@source_id = options[:source_id]
|
6
|
+
if @source_id && @account_id
|
7
|
+
@list_type_path = "accounts/#{@account_id}/sources/#{@source_id}/#{@list_token_type}"
|
8
|
+
elsif @account_id
|
9
|
+
@list_type_path = "accounts/#{@account_id}/#{@list_token_type}"
|
10
|
+
else
|
11
|
+
@list_type_path = @list_token_type
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# find a number within the given country/region and options like area_code or containing with contains
|
16
|
+
def search(country_code, options={})
|
17
|
+
options = {:country_code => country_code}.merge(options)
|
18
|
+
path_str = "/api/v1/#{@list_type_path}/search.json"
|
19
|
+
res = self.class.get(path_str, :query => options.merge(:auth_token => @token))
|
20
|
+
data = res.parsed_response
|
21
|
+
if data["status"] == "success"
|
22
|
+
list_data = {'available_numbers' => data['results'].map {|res| res.merge('account_id' => @account_id) },
|
23
|
+
'page' => 1,
|
24
|
+
'per_page' => data['results'].size,
|
25
|
+
'total_entries' => data['results'].size}
|
26
|
+
CTM::List.new('AvailableNumber', {:account_id => @account_id}, @token, list_data)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# buy number with the digits
|
31
|
+
def buy(digits)
|
32
|
+
path_str = "/api/v1/#{@list_type_path}.json"
|
33
|
+
res = self.class.post(path_str, :body => {:phone_number => digits}.merge(:auth_token => @token))
|
34
|
+
if res && res['status'] == 'success'
|
35
|
+
CTM::Number.new(res['number'], @token)
|
36
|
+
else
|
37
|
+
puts res.inspect
|
38
|
+
raise CTM::Error::Buy.new(res["reason"])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# add trackng number to tracking source
|
43
|
+
def add(number)
|
44
|
+
path_str = "/api/v1/#{@list_type_path}/#{number.id}/add.json"
|
45
|
+
puts "Add to #{@account_id}:#{@source_id} -> #{number.id} -> #{path_str}"
|
46
|
+
# accounts/25 /sources/5012 /numbers
|
47
|
+
# /api/v1/accounts/:account_id/sources/:source_id/numbers/:id/add
|
48
|
+
res = self.class.post(path_str, :body => {}.merge(:auth_token => @token))
|
49
|
+
if res && res['status'] == 'success'
|
50
|
+
CTM::Source.new(res['source'], @token)
|
51
|
+
else
|
52
|
+
puts res.inspect
|
53
|
+
raise CTM::Error::Add.new(res["reason"])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def rem
|
58
|
+
puts "Rem to #{@account_id}:#{@source_id} -> #{number.id} -> #{@list_type_path}"
|
59
|
+
# /api/v1/accounts/:account_id/sources/:source_id/numbers/:id/rem
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module CTM
|
2
|
+
class ReceivingNumber < Base
|
3
|
+
attr_reader :id, :account_id
|
4
|
+
attr_accessor :name, :number, :formatted, :split
|
5
|
+
|
6
|
+
def initialize(data, token=nil)
|
7
|
+
super(data, token)
|
8
|
+
@id = data['id']
|
9
|
+
@account_id = data['account_id']
|
10
|
+
@name = data['name']
|
11
|
+
@number = data['number']
|
12
|
+
@formatted = data['formatted']
|
13
|
+
@split = data['split']
|
14
|
+
end
|
15
|
+
|
16
|
+
def save
|
17
|
+
options = {
|
18
|
+
:name => @name,
|
19
|
+
:number => @number
|
20
|
+
}
|
21
|
+
super(options)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module CTM
|
2
|
+
class ReceivingNumberList < List
|
3
|
+
def initialize(options={}, token=nil)
|
4
|
+
super('ReceivingNumber', options, token)
|
5
|
+
@account_id = options[:account_id]
|
6
|
+
@number_id = options[:number_id]
|
7
|
+
if @number_id && @account_id
|
8
|
+
@list_type_path = "accounts/#{@account_id}/numbers/#{@number_id}/#{@list_token_type}"
|
9
|
+
elsif @account_id
|
10
|
+
@list_type_path = "accounts/#{@account_id}/#{@list_token_type}"
|
11
|
+
else
|
12
|
+
@list_type_path = @list_token_type
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def add(receiving_number)
|
17
|
+
path_str = "/api/v1/#{@list_type_path}/#{receiving_number.id}/add.json"
|
18
|
+
res = self.class.post(path_str, :body => {}.merge(:auth_token => @token))
|
19
|
+
if res && res['status'] == 'success'
|
20
|
+
CTM::Number.new(res['receiving_number'], @token)
|
21
|
+
else
|
22
|
+
puts res.inspect
|
23
|
+
raise CTM::Error::Add.new(res["reason"])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def rem(receiving_number)
|
28
|
+
path_str = "/api/v1/#{@list_type_path}/#{receiving_number.id}/rem.json"
|
29
|
+
res = self.class.delete(path_str, :body => {}.merge(:auth_token => @token))
|
30
|
+
if res && res['status'] == 'success'
|
31
|
+
CTM::Number.new(res['receiving_number'], @token)
|
32
|
+
else
|
33
|
+
puts res.inspect
|
34
|
+
raise CTM::Error::Add.new(res["reason"])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/lib/ctm/sale.rb
ADDED
data/lib/ctm/source.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module CTM
|
2
|
+
class Source < Base
|
3
|
+
attr_reader :id, :account_id
|
4
|
+
attr_accessor :name, :referring_url, :landing_url, :position, :online
|
5
|
+
|
6
|
+
def initialize(data, token=nil)
|
7
|
+
super(data, token)
|
8
|
+
@id = data['id']
|
9
|
+
@account_id = data['account_id']
|
10
|
+
@name = data['name']
|
11
|
+
@referring_url = data['referring_url']
|
12
|
+
@landing_url = data['landing_url']
|
13
|
+
@position = data['position']
|
14
|
+
@online = data['online']
|
15
|
+
end
|
16
|
+
|
17
|
+
def save
|
18
|
+
options = {
|
19
|
+
:name => @name,
|
20
|
+
:position => @position,
|
21
|
+
:online => @online,
|
22
|
+
:referring_url => @referring_url,
|
23
|
+
:landing_url => @landing_url
|
24
|
+
}
|
25
|
+
super(options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def numbers(options={})
|
29
|
+
CTM::NumberList.new(options.merge(:account_id => @account_id, :source_id => @id), @token)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
data/lib/ctm/token.rb
ADDED
data/lib/ctm/user.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module CTM
|
2
|
+
class User < Base
|
3
|
+
attr_reader :id
|
4
|
+
attr_accessor :first_name, :last_name, :email, :role
|
5
|
+
|
6
|
+
def name
|
7
|
+
"#{first_name} #{last_name}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(data, token=nil)
|
11
|
+
super(data, token)
|
12
|
+
@id = data['id']
|
13
|
+
@first_name = data['first_name']
|
14
|
+
@last_name = data['last_name']
|
15
|
+
@email = data['email']
|
16
|
+
@role = data['role']
|
17
|
+
end
|
18
|
+
|
19
|
+
def save
|
20
|
+
options = {
|
21
|
+
:first_name => @first_name,
|
22
|
+
:last_name => @last_name,
|
23
|
+
:email => @email,
|
24
|
+
:role => @role
|
25
|
+
}
|
26
|
+
super(options)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/lib/ctm/webhook.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module CTM
|
2
|
+
class Webhook < Base
|
3
|
+
attr_reader :id
|
4
|
+
attr_accessor :weburl, :with_resource_url, :position
|
5
|
+
|
6
|
+
def initialize(data, token=nil)
|
7
|
+
super(data, token)
|
8
|
+
@id = data['id']
|
9
|
+
@weburl = data['weburl']
|
10
|
+
@with_resource_url = data['with_resource_url']
|
11
|
+
@position = data['position']
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ctm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- CallTrackingMetrics
|
9
|
+
- Todd Fisher
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2013-04-30 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: phony
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0'
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: httparty
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: activesupport
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: rack
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ~>
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 1.3.0
|
71
|
+
type: :development
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ~>
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 1.3.0
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: mocha
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
type: :development
|
88
|
+
prerelease: false
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: fakeweb
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ~>
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 1.3.0
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ~>
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.3.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
description:
|
128
|
+
email: info@calltrackingmetrics.com
|
129
|
+
executables: []
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- .gitignore
|
134
|
+
- Gemfile
|
135
|
+
- Gemfile.lock
|
136
|
+
- README.md
|
137
|
+
- Rakefile
|
138
|
+
- TODO
|
139
|
+
- ctm.gemspec
|
140
|
+
- examples/buy_numbers.rb
|
141
|
+
- examples/example.rb
|
142
|
+
- examples/manage_numbers.rb
|
143
|
+
- examples/manage_receivng_numbers.rb
|
144
|
+
- examples/manage_sources.rb
|
145
|
+
- examples/manage_users.rb
|
146
|
+
- examples/manage_webhooks.rb
|
147
|
+
- lib/ctm.rb
|
148
|
+
- lib/ctm/account.rb
|
149
|
+
- lib/ctm/auth.rb
|
150
|
+
- lib/ctm/available_number.rb
|
151
|
+
- lib/ctm/base.rb
|
152
|
+
- lib/ctm/call.rb
|
153
|
+
- lib/ctm/error.rb
|
154
|
+
- lib/ctm/list.rb
|
155
|
+
- lib/ctm/number.rb
|
156
|
+
- lib/ctm/number_list.rb
|
157
|
+
- lib/ctm/receiving_number.rb
|
158
|
+
- lib/ctm/receiving_number_list.rb
|
159
|
+
- lib/ctm/sale.rb
|
160
|
+
- lib/ctm/source.rb
|
161
|
+
- lib/ctm/token.rb
|
162
|
+
- lib/ctm/user.rb
|
163
|
+
- lib/ctm/webhook.rb
|
164
|
+
homepage: http://github.com/calltracking/ctm-ruby
|
165
|
+
licenses: []
|
166
|
+
post_install_message:
|
167
|
+
rdoc_options: []
|
168
|
+
require_paths:
|
169
|
+
- lib
|
170
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
171
|
+
none: false
|
172
|
+
requirements:
|
173
|
+
- - ! '>='
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
176
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
179
|
+
- - ! '>='
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
requirements: []
|
183
|
+
rubyforge_project:
|
184
|
+
rubygems_version: 1.8.24
|
185
|
+
signing_key:
|
186
|
+
specification_version: 3
|
187
|
+
summary: API Library for CallTrackingMetrics
|
188
|
+
test_files: []
|
189
|
+
has_rdoc:
|