ctm 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
@@ -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
+ ```
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rake/testtask'
4
+
5
+ task :default => :test
6
+
7
+ Rake::TestTask.new(:test) do |t|
8
+ t.test_files = FileList['test/*_test.rb']
9
+ t.verbose = false
10
+ end
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
@@ -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}"
@@ -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!
@@ -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'
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,11 @@
1
+ module CTM
2
+ class Call < Base
3
+ attr_reader :id
4
+
5
+ def initialize(data, token=nil)
6
+ super(data, token)
7
+ @id = data['id']
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ module CTM
2
+ class Error < Exception
3
+ class Auth < Exception
4
+ end
5
+ class List < Exception
6
+ end
7
+ class Buy < Exception
8
+ end
9
+ class Create < Exception
10
+ end
11
+ class Add < Exception
12
+ end
13
+ class Rem < Exception
14
+ end
15
+ end
16
+ end
@@ -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
@@ -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
@@ -0,0 +1,8 @@
1
+ module CTM
2
+ class Sale
3
+
4
+ def initialize
5
+ end
6
+
7
+ end
8
+ end
@@ -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
@@ -0,0 +1,15 @@
1
+ module CTM
2
+ class Token
3
+ attr_reader :token, :expires
4
+
5
+ def initialize(data)
6
+ @token = data['token']
7
+ @expires = data['expires']
8
+ end
9
+
10
+ def accounts(options={})
11
+ CTM::List.new('Account', options, @token)
12
+ end
13
+
14
+ end
15
+ end
@@ -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
@@ -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: