twilio_resource 0.1.0

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/README.md ADDED
@@ -0,0 +1,78 @@
1
+ Description
2
+ -----------
3
+
4
+ TwilioResource is a wrapper around the [Twilio API](http://www.twilio.com/docs/api/2008-08-01/rest/)
5
+ using Rails' ActiveResource. This allows you to treat Twilio objects
6
+ as if they're local ActiveRecord models:
7
+
8
+ phone = TwilioResource::LocalIncomingPhoneNumber.new(:url => 'http://www.example.com',
9
+ :area_code => '206',
10
+ :method => 'GET',
11
+ :friendly_name =g> "My First Phone Number",
12
+ :account_id => Twilio::Base.user)
13
+ phone.save
14
+
15
+
16
+ The wrapper doesn't support the entire Twilio API, but it should be
17
+ simple enough to add new functionality as needed by following the
18
+ models that are already built.
19
+
20
+ Supported Functionality
21
+ =======================
22
+ - Requesting, listing, and deleting new local and toll-free numbers
23
+ - Placing and listing calls made to a phone number
24
+
25
+ Todo
26
+ ----
27
+ - Conference resource
28
+ - Redirecting calls
29
+ - Support data returned in xml attributes
30
+ - SMS resource
31
+ - Recordings, Transcriptions, and Notifications
32
+ - Wrap more exceptions
33
+ - Add documentation on supported attributes to the ActiveResource models
34
+
35
+ Setup
36
+ =====
37
+
38
+ Before you start using TwilioResource, you have to give it your Twilio
39
+ login credentials. You can do this in your Rails initializer:
40
+
41
+ require 'twilio_resource'
42
+ TwilioResource.setup('token', 'sid')
43
+
44
+ Examples
45
+ ========
46
+
47
+ Requesting a new phone number:
48
+
49
+ phone = TwilioResource::LocalIncomingPhoneNumber.new(:url => 'http://www.example.com',
50
+ :area_code => '206',
51
+ :method => 'GET',
52
+ :friendly_name => "My First Phone Number",
53
+ :account_id => Twilio::Base.user)
54
+ phone.save
55
+
56
+ Requesting a new toll-free phone number:
57
+
58
+ phone = TwilioResource::TollFreeIncomingPhoneNumber.new(:url => 'http://www.example.com',
59
+ :area_code => '206',
60
+ :method => 'GET',
61
+ :friendly_name => "My First Phone Number",
62
+ :account_id => Twilio::Base.user)
63
+ phone.save
64
+
65
+ Retrieving a list of completed calls to a given phone number:
66
+
67
+ TwilioResource::Call.find(:all, :params => {
68
+ :account_id => Twilio::Base.user,
69
+ :status => Twilio::Call::COMPLETE,
70
+ :called => '2065551212'})
71
+
72
+ Placing a call:
73
+
74
+ TwilioResource::Call.new({
75
+ :account_id => Twilio::Base.user,
76
+ :caller => '2065551111',
77
+ :called => '2065551212',
78
+ :url => 'http://example.com/call.xml'})
@@ -0,0 +1,27 @@
1
+ require 'logger'
2
+ require 'activeresource'
3
+
4
+ require 'twilio_resource/twilio_format'
5
+ require 'twilio_resource/exceptions'
6
+
7
+ module TwilioResource
8
+
9
+ class << self
10
+ attr_accessor :logger
11
+ end
12
+
13
+ # Sets up the credentials the ActiveResources will use to access the
14
+ # twilio API. Optionally takes a +logger+, which defaults to +STDOUT+.
15
+ def self.setup(sid, token, logger = nil)
16
+ @logger = logger || Logger.new(STDOUT)
17
+ TwilioResource::Base.sid = sid
18
+ TwilioResource::Base.token = token
19
+ end
20
+ end
21
+
22
+ require 'twilio_resource/base'
23
+ require 'twilio_resource/account'
24
+ require 'twilio_resource/call'
25
+ require 'twilio_resource/incoming_phone_number'
26
+ require 'twilio_resource/local_incoming_phone_number'
27
+ require 'twilio_resource/toll_free_incoming_phone_number'
@@ -0,0 +1,6 @@
1
+
2
+ # Encapsulates a Twilio account. Not much to do here. Documentation
3
+ # can be found at
4
+ # http://www.twilio.com/docs/api/2008-08-01/rest/account
5
+ class TwilioResource::Account < TwilioResource::Base
6
+ end
@@ -0,0 +1,83 @@
1
+ # Encapsulates the changes that need to be made to active_resource's
2
+ # defaults in order to communicate with Twilio. There are a few main
3
+ # issues with ActiveResource's defaults:
4
+ #
5
+ # 1. Twilio's urls don't take an extension. ActiveResource requires
6
+ # endpoints to have an extension corresponding to the type of data,
7
+ # for example: +resource.xml+ or +resource.json+. Twilio's are
8
+ # always xml, but have no extension.
9
+ #
10
+ # 2. Twilio uses capitalized names in their URLs. For instance,
11
+ # instead of '/account/1/calls/1', they use '/Account/1/Calls/1'.
12
+ #
13
+ # 3. Twilio takes form encoded params, like token=blah&sid=foo, but
14
+ # returns data in XML. These changes are encapsulated in
15
+ # ActiveResource::Formats::TwilioFormat.
16
+ #
17
+ # All of the Twilio ActiveResource classes inherit from this class.
18
+ class TwilioResource::Base < ActiveResource::Base
19
+
20
+ class << self
21
+ attr_accessor :sid
22
+ attr_accessor :token
23
+
24
+ alias_method :user, :sid
25
+ alias_method :user=, :sid=
26
+ alias_method :password, :token
27
+ alias_method :password=, :token=
28
+ end
29
+
30
+ # Have to override this to make empty extensions work (without the dot)
31
+ def self.element_path(id, prefix_options = {}, query_options = nil)
32
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
33
+ extension = format.extension.blank? ? "" : ".#{format.extension}"
34
+ path = "#{prefix(prefix_options)}#{collection_name}/#{id}#{extension}#{query_string(query_options)}"
35
+ TwilioResource.logger.info("Request: #{path}")
36
+ path
37
+ end
38
+
39
+ # Have to override this to make empty extensions work (without the dot)
40
+ def self.collection_path(prefix_options = {}, query_options = nil)
41
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
42
+ extension = format.extension.blank? ? "" : ".#{format.extension}"
43
+ path = "#{prefix(prefix_options)}#{collection_name}#{extension}#{query_string(query_options)}"
44
+ TwilioResource.logger.info("Request: #{path}")
45
+ path
46
+ end
47
+
48
+ # Have to override this to make empty extensions work (without the dot)
49
+ def self.custom_method_collection_url(method_name, options = {})
50
+ prefix_options, query_options = split_options(options)
51
+ extension = format.extension.blank? ? "" : ".#{format.extension}"
52
+ path = "#{prefix(prefix_options)}#{collection_name}/#{method_name}#{extension}#{query_string(query_options)}"
53
+ TwilioResource.logger.info("Request: #{path}")
54
+ path
55
+ end
56
+
57
+ # Twilio uses capitalized path names
58
+ def self.element_name
59
+ super.camelize
60
+ end
61
+
62
+ def self.query_string(params)
63
+ # camelize all the param keys, because that's what Twilio expects
64
+ fixed_params_list = params.map {|k, v| [k.to_s.camelize, v]}.flatten
65
+ fixed_params_hash = Hash[*fixed_params_list] # Hash really needs a decent #map
66
+ super(fixed_params_hash)
67
+ end
68
+
69
+ # we should wrap the exceptions we can
70
+ def save(*params)
71
+ begin
72
+ super(*params)
73
+ rescue => e
74
+ raise TwilioResource::Exception.find_exception(e)
75
+ end
76
+
77
+ end
78
+
79
+
80
+ self.site = "https://api.twilio.com"
81
+ self.prefix = '/2008-08-01/'
82
+ self.format = :twilio
83
+ end
@@ -0,0 +1,20 @@
1
+
2
+ # Encapsulates a Twilio call resource. Documentation:
3
+ # - http://www.twilio.com/docs/api/2008-08-01/rest/call
4
+ # - http://www.twilio.com/docs/api/2008-08-01/rest/making_calls
5
+ class TwilioResource::Call < TwilioResource::Base
6
+ self.prefix = superclass.prefix_source + 'Accounts/:account_id/'
7
+
8
+ NOT_DIALED = 0
9
+ IN_PROGRESS = 1
10
+ COMPLETE = 2
11
+
12
+ # Returns the status of the call. Can be
13
+ # TwilioResource::Call::NOT_DIALED,
14
+ # TwilioResource::Call::IN_PROGRESS, or
15
+ # TwilioResource::Call::COMPLETE
16
+ def status
17
+ attributes["status"].to_i if attributes["status"]
18
+ end
19
+
20
+ end
@@ -0,0 +1,39 @@
1
+ module TwilioResource
2
+ end
3
+
4
+ # Wraps Twilio exceptions with a ruby exception class. Currently supports:
5
+ #
6
+ # - Error 21452 - No Phone Numbers Found
7
+ class TwilioResource::Exception < StandardError
8
+
9
+ # Given a twilio error xml response, returns the corresponding
10
+ # exception if it is mapped, or the xml response otherwise.
11
+ def self.find_exception(e)
12
+ new_exception = if e.respond_to?(:response)
13
+ exception_data = Hash.from_xml(e.response.body)
14
+
15
+
16
+ code = exception_data['twilio_response'] &&
17
+ exception_data['twilio_response']['rest_exception'] &&
18
+ exception_data['twilio_response']['rest_exception']['code']
19
+ exception_klass = twilio_exceptions[code.to_i] if code
20
+ exception_klass.nil? ? e : exception_klass.new
21
+ else
22
+ e
23
+ end
24
+ end
25
+
26
+ # Hash mapping error codes to exception classes.
27
+ def self.twilio_exceptions
28
+ {
29
+ 21452 => TwilioResource::NoPhoneNumbersFoundException,
30
+ }
31
+ end
32
+
33
+ end
34
+
35
+ class TwilioResource::NoPhoneNumbersFoundException < TwilioResource::Exception
36
+ def message
37
+ "No phone numbers found"
38
+ end
39
+ end
@@ -0,0 +1,6 @@
1
+ # Represents a Twilio-controlled phone number that can receive
2
+ # incoming phone calls. Documentation is at
3
+ # http://www.twilio.com/docs/api/2008-08-01/rest/incoming-phone-numbers
4
+ class TwilioResource::IncomingPhoneNumber < TwilioResource::Base
5
+ self.prefix = superclass.prefix_source + 'Accounts/:account_id/'
6
+ end
@@ -0,0 +1,14 @@
1
+ # Represents a Twilio-controlled "local" phone number that can receive
2
+ # incoming phone calls. If there are no numbers available in the
3
+ # specified area code, #save will throw a
4
+ # TwilioResource::NoPhoneNumbersFoundException. Documentation is at
5
+ # http://www.twilio.com/docs/api/2008-08-01/rest/incoming-phone-numbers
6
+ class TwilioResource::LocalIncomingPhoneNumber < TwilioResource::IncomingPhoneNumber
7
+
8
+ self.prefix = superclass.prefix_source + 'IncomingPhoneNumbers/'
9
+
10
+ def self.collection_name
11
+ 'Local'
12
+ end
13
+
14
+ end
@@ -0,0 +1,14 @@
1
+ # Represents a Twilio-controlled toll-free phone number that can receive
2
+ # incoming phone calls. If there are no numbers available in the
3
+ # specified area code, #save will throw a
4
+ # TwilioResource::NoPhoneNumbersFoundException. Documentation is at
5
+ # http://www.twilio.com/docs/api/2008-08-01/rest/incoming-phone-numbers
6
+ class TwilioResource::TollFreeIncomingPhoneNumber < TwilioResource::IncomingPhoneNumber
7
+
8
+ self.prefix = superclass.prefix_source + 'IncomingPhoneNumbers/'
9
+
10
+ def self.collection_name
11
+ 'TollFree'
12
+ end
13
+
14
+ end
@@ -0,0 +1,56 @@
1
+ module ActiveResource
2
+ module Formats
3
+ module TwilioFormat
4
+ extend self
5
+
6
+ def extension
7
+ ""
8
+ end
9
+
10
+ def mime_type
11
+ 'application/x-www-form-urlencoded'
12
+ end
13
+
14
+ # twilio uses camelcase for all of its params, and uses a query string for posts.
15
+ def encode(hash, options = {})
16
+ camelized_hash = ActiveSupport::OrderedHash.new
17
+ hash.each do |k, v|
18
+ camelized_hash[k.camelize] = v
19
+ end
20
+
21
+ TwilioResource.logger.info("Request: #{camelized_hash.to_query}")
22
+ camelized_hash.to_query
23
+ end
24
+
25
+ def decode(xml)
26
+ TwilioResource.logger.debug("Response: #{xml}")
27
+ from_xml_data(Hash.from_xml(xml))
28
+ end
29
+
30
+ private
31
+ # Manipulate from_xml Hash, because twilio doesn't format their
32
+ # xml in the way active_resource expects it.
33
+ def from_xml_data(data)
34
+ if data.is_a?(Hash) && data['twilio_response']
35
+ from_xml_data(data['twilio_response'])
36
+ else
37
+ data.each do |k, v|
38
+ # convert array-like things to actual arrays. twilio
39
+ # paginates their arrays, so it's easy to detect here. If
40
+ # it's the empty set, initialize it to an array so
41
+ # active_resource doesn't throw a fit.
42
+ if v["page"]
43
+ array_data = v[k.singularize]
44
+ data[k] = [array_data].flatten.compact
45
+ elsif v.blank?
46
+ data[k] = []
47
+ end
48
+ end
49
+ # now we have "calls" => [c1, c2, ...], but active_resource
50
+ # expects [c1, c2, c3]
51
+ data.values.first
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,17 @@
1
+ require 'test_helper'
2
+ require 'twilio_mock'
3
+
4
+ class TwilioResource::AccountTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ super
8
+ TwilioMock.setup_remote_fixtures
9
+ end
10
+
11
+ def test_find_account
12
+ TwilioResource::Base.user = 1
13
+ account = TwilioResource::Account.find(1)
14
+ assert_equal "2", account.status
15
+ end
16
+
17
+ end
data/test/call_test.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'test_helper'
2
+ require 'twilio_mock'
3
+
4
+ class TwilioResource::CallTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ super
8
+ TwilioMock.setup_remote_fixtures
9
+ end
10
+
11
+ def test_find_all
12
+ calls = TwilioResource::Call.find(:all, :params => {:account_id => 1})
13
+ assert_equal 2, calls.length
14
+ end
15
+
16
+ # what the hell, twilio? who uses capitalization to distinguish
17
+ # between param types? you, that's who.
18
+ def test_find_by_status
19
+ calls = TwilioResource::Call.find(:all, :params => {:account_id => 1, :status => TwilioResource::Call::COMPLETE})
20
+ assert_equal TwilioResource::Call::COMPLETE, calls.first.status
21
+ end
22
+
23
+ def test_find_by_start_time
24
+ calls = TwilioResource::Call.find(:all, :params => {:account_id => 1, :start_time => '2009-09-01'})
25
+ assert_equal 1, calls.length
26
+ end
27
+
28
+ def test_no_results
29
+ calls = TwilioResource::Call.find(:all, :params => {:account_id => 1, :status => TwilioResource::Call::COMPLETE, :start_time => '2009-09-01'})
30
+ assert_equal 0, calls.length
31
+ end
32
+
33
+ end
@@ -0,0 +1,20 @@
1
+ require 'test_helper'
2
+ require 'twilio_mock'
3
+
4
+ class TwilioResource::IncomingPhoneNumberTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ super
8
+ TwilioMock.setup_remote_fixtures
9
+ end
10
+
11
+ def test_find
12
+ local_number = TwilioResource::IncomingPhoneNumber.find(1, :params => {:account_id => 1})
13
+ assert_equal '4158675309', local_number.phone_number
14
+ end
15
+
16
+ def test_delete_from_class
17
+ assert TwilioResource::IncomingPhoneNumber.delete(1, :account_id => 1)
18
+ end
19
+
20
+ end
@@ -0,0 +1,39 @@
1
+ require 'test_helper'
2
+ require 'twilio_mock'
3
+
4
+ class TwilioResource::LocalIncomingPhoneNumberTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ super
8
+ TwilioMock.setup_remote_fixtures
9
+ end
10
+
11
+ def test_provision_local_number
12
+ phone = TwilioResource::LocalIncomingPhoneNumber.new(:url => "http://example.com/calls",
13
+ :area_code => "206",
14
+ :method => 'POST',
15
+ :friendly_name => "My Local Number",
16
+ :account_id => 1)
17
+ assert_equal "AreaCode=206&FriendlyName=My+Local+Number&Method=POST&Url=http%3A%2F%2Fexample.com%2Fcalls", phone.encode
18
+ phone.save
19
+
20
+ assert_equal '2064567890', phone.phone_number
21
+ end
22
+
23
+ def test_save_with_unavailable_number_throws_exception
24
+ TwilioResource::Base.user = 2
25
+ phone = TwilioResource::LocalIncomingPhoneNumber.new(:url => "http://example.com/calls",
26
+ :area_code => "815",
27
+ :method => 'POST',
28
+ :friendly_name => "My Local Number",
29
+ :account_id => TwilioResource::Base.user)
30
+ assert_equal "AreaCode=815&FriendlyName=My+Local+Number&Method=POST&Url=http%3A%2F%2Fexample.com%2Fcalls", phone.encode
31
+ assert_raises TwilioResource::NoPhoneNumbersFoundException do
32
+ phone.save
33
+ end
34
+
35
+ end
36
+
37
+ # test find, update
38
+
39
+ end
@@ -0,0 +1,7 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'activeresource'
4
+ require 'twilio_resource'
5
+
6
+ TwilioResource.setup('1', '1')
7
+ TwilioResource.logger.level = Logger::WARN
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+ require 'twilio_mock'
3
+
4
+ class TwilioResource::TollFreeIncomingPhoneNumberTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ super
8
+ TwilioMock.setup_remote_fixtures
9
+ end
10
+
11
+ def test_provision_toll_free_number
12
+ TwilioResource::Base.user = 1
13
+ phone = TwilioResource::TollFreeIncomingPhoneNumber.new(:url => "http://example.com/calls",
14
+ :method => 'POST',
15
+ :friendly_name => "My Local Number",
16
+ :account_id => TwilioResource::Base.user)
17
+ assert_equal "FriendlyName=My+Local+Number&Method=POST&Url=http%3A%2F%2Fexample.com%2Fcalls", phone.encode
18
+ phone.save
19
+
20
+ assert_equal '8774567890', phone.phone_number
21
+ end
22
+
23
+ # test find, update
24
+
25
+ end
@@ -0,0 +1,334 @@
1
+ require 'active_resource/http_mock'
2
+
3
+ class TwilioMock
4
+
5
+ def self.setup_remote_fixtures
6
+ ActiveResource::HttpMock.respond_to do |mock|
7
+ mock.get '/2008-08-01/Accounts/1', auth_get(1), main_account
8
+ mock.post '/2008-08-01/Accounts/1/IncomingPhoneNumbers/Local', auth_post(1), local_number_provision_success
9
+ mock.post '/2008-08-01/Accounts/2/IncomingPhoneNumbers/Local', auth_post(2), no_local_number, 400
10
+ mock.post '/2008-08-01/Accounts/1/IncomingPhoneNumbers/TollFree', auth_post(1), toll_free_number_provision_success
11
+
12
+ mock.get '/2008-08-01/Accounts/1/Calls', auth_get(1), all_calls
13
+ mock.get '/2008-08-01/Accounts/1/Calls?StartTime=2009-09-01', auth_get(1), recent_calls
14
+ mock.get '/2008-08-01/Accounts/1/Calls?Status=2', auth_get(1), succeeded_recent_calls
15
+ mock.get '/2008-08-01/Accounts/1/Calls?StartTime=2009-09-01&Status=2', auth_get(1), no_calls
16
+
17
+ mock.get '/2008-08-01/Accounts/1/IncomingPhoneNumbers/1', auth_get(1), phone_number_data
18
+ mock.delete '/2008-08-01/Accounts/1/IncomingPhoneNumbers/1', auth_delete(1), phone_number_delete_success
19
+ mock.delete '/2008-08-01/Accounts/2/IncomingPhoneNumbers/2', auth_delete(2), "", 404
20
+
21
+ end
22
+
23
+ end
24
+
25
+ def self.auth_delete(account_id)
26
+ old_account_id = TwilioResource::Base.user
27
+ TwilioResource::Base.user = account_id
28
+ auth = TwilioResource::Account.connection.send(:build_request_headers, {}, :delete)
29
+ TwilioResource::Base.user = old_account_id
30
+ auth
31
+ end
32
+
33
+ def self.auth_post(account_id)
34
+ old_account_id = TwilioResource::Base.user
35
+ TwilioResource::Base.user = account_id
36
+ auth = TwilioResource::Account.connection.send(:build_request_headers, {}, :post)
37
+ TwilioResource::Base.user = old_account_id
38
+ auth
39
+ end
40
+
41
+ def self.auth_get(account_id)
42
+ old_account_id = TwilioResource::Base.user
43
+ TwilioResource::Base.user = account_id
44
+ auth = TwilioResource::Account.connection.send(:build_request_headers, {}, :get)
45
+ TwilioResource::Base.user = old_account_id
46
+ auth
47
+ end
48
+
49
+ def self.phone_number_data
50
+ <<END
51
+ <TwilioResponse>
52
+ <IncomingPhoneNumber>
53
+ <Sid>PNe536dfda7c6184afab78d980cb8cdf43</Sid>
54
+ <AccountSid>AC35542fc30a091bed0c1ed511e1d9935d</AccountSid>
55
+ <FriendlyName>My Home Phone Number</FriendlyName>
56
+ <PhoneNumber>4158675309</PhoneNumber>
57
+ <Url>http://mycompany.com/handleMainLineCall.asp</Url>
58
+ <Method>GET</Method>
59
+ <DateCreated>Tue, 01 Apr 2008 11:26:32 -0700</DateCreated>
60
+ <DateUpdated>Tue, 01 Apr 2008 11:26:32 -0700</DateUpdated>
61
+ </IncomingPhoneNumber>
62
+ </TwilioResponse>
63
+ END
64
+ end
65
+
66
+ def self.main_account
67
+ <<END
68
+ <TwilioResponse>
69
+ <Account>
70
+ <Sid>AC309475e5fede1b49e100272a8640f438</Sid>
71
+ <FriendlyName>My Twilio Account</FriendlyName>
72
+ <Status>2</Status>
73
+ <StatusText>Active</StatusText>
74
+ <DateCreated>Wed, 02 Apr 2008 17:33:38 -0700</DateCreated>
75
+ <DateUpdated>Wed, 02 Apr 2008 17:34:18 -0700</DateUpdated>
76
+ <AuthToken>3a2630a909aadbf60266234756fb15a0</AuthToken>
77
+ </Account>
78
+ </TwilioResponse>
79
+ END
80
+ end
81
+
82
+ def self.phone_number_delete_success
83
+ <<END
84
+ <TwilioResponse />
85
+ END
86
+ end
87
+
88
+ def self.all_calls
89
+ <<END
90
+ <TwilioResponse>
91
+ <Calls page="0" numpages="1" pagesize="50" total="38" start="0" end="37">
92
+ <Call>
93
+ <Sid>CA42ed11f93dc08b952027ffbc406d0868</Sid>
94
+ <DateCreated>Sat, 07 Feb 2009 13:15:19 -0800</DateCreated>
95
+ <DateUpdated>Sat, 07 Feb 2009 13:15:19 -0800</DateUpdated>
96
+ <CallSegmentSid/>
97
+ <AccountSid>AC309475e5fede1b49e100272a8640f438</AccountSid>
98
+ <Called>4159633717</Called>
99
+ <Caller>4156767925</Caller>
100
+ <PhoneNumberSid>PN01234567890123456789012345678900</PhoneNumberSid>
101
+ <Status>2</Status>
102
+ <StartTime>Thu, 03 Apr 2008 04:36:33 -0400</StartTime>
103
+ <EndTime>Thu, 03 Apr 2008 04:36:47 -0400</EndTime>
104
+ <Duration>14</Duration>
105
+ <Price/>
106
+ <Flags>1</Flags>
107
+ </Call>
108
+ <Call>
109
+ <Sid>CA751e8fa0a0105cf26a0d7a9775fb4bfb</Sid>
110
+ <DateCreated>Sat, 07 Feb 2009 13:15:19 -0800</DateCreated>
111
+ <DateUpdated>Sat, 07 Feb 2009 13:15:19 -0800</DateUpdated>
112
+ <CallSegmentSid/>
113
+ <AccountSid>AC309475e5fede1b49e100272a8640f438</AccountSid>
114
+ <Called>2064287985</Called>
115
+ <Caller>4156767925</Caller>
116
+ <PhoneNumberSid>PNd59c2ba27ef48264773edb90476d1674</PhoneNumberSid>
117
+ <Status>2</Status>
118
+ <StartTime>Thu, 03 Apr 2008 01:37:05 -0400</StartTime>
119
+ <EndTime>Thu, 03 Apr 2008 01:37:40 -0400</EndTime>
120
+ <Duration>35</Duration>
121
+ <Price/>
122
+ <Flags>1</Flags>
123
+ </Call>
124
+ </Calls>
125
+ </TwilioResponse>
126
+ END
127
+ end
128
+
129
+ def self.succeeded_calls
130
+ <<END
131
+ <TwilioResponse>
132
+ <Calls page="0" numpages="1" pagesize="50" total="38" start="0" end="37">
133
+ <Call>
134
+ <Sid>CA42ed11f93dc08b952027ffbc406d0868</Sid>
135
+ <DateCreated>Sat, 07 Feb 2009 13:15:19 -0800</DateCreated>
136
+ <DateUpdated>Sat, 07 Feb 2009 13:15:19 -0800</DateUpdated>
137
+ <CallSegmentSid/>
138
+ <AccountSid>AC309475e5fede1b49e100272a8640f438</AccountSid>
139
+ <Called>4159633717</Called>
140
+ <Caller>4156767925</Caller>
141
+ <PhoneNumberSid>PN01234567890123456789012345678900</PhoneNumberSid>
142
+ <Status>2</Status>
143
+ <StartTime>Thu, 03 Apr 2008 04:36:33 -0400</StartTime>
144
+ <EndTime>Thu, 03 Apr 2008 04:36:47 -0400</EndTime>
145
+ <Duration>14</Duration>
146
+ <Price/>
147
+ <Flags>1</Flags>
148
+ </Call>
149
+ <Call>
150
+ <Sid>1000</Sid>
151
+ <DateCreated>Sat, 07 Feb 2009 13:15:19 -0800</DateCreated>
152
+ <DateUpdated>Sat, 07 Feb 2009 13:15:19 -0800</DateUpdated>
153
+ <CallSegmentSid>10001</CallSegmentSid>
154
+ <AccountSid>AC309475e5fede1b49e100272a8640f438</AccountSid>
155
+ <Called>4159633717</Called>
156
+ <Caller>4156767925</Caller>
157
+ <PhoneNumberSid>ABC123</PhoneNumberSid>
158
+ <Status>2</Status>
159
+ <StartTime>Thu, 03 Apr 2008 04:36:33 -0400</StartTime>
160
+ <EndTime>Thu, 03 Apr 2008 04:36:47 -0400</EndTime>
161
+ <Duration>14</Duration>
162
+ <Price/>
163
+ <Flags>1</Flags>
164
+ </Call>
165
+ <Call>
166
+ <Sid>1001</Sid>
167
+ <DateCreated>Sat, 07 Feb 2009 13:15:19 -0800</DateCreated>
168
+ <DateUpdated>Sat, 07 Feb 2009 13:15:19 -0800</DateUpdated>
169
+ <CallSegmentSid>10002</CallSegmentSid>
170
+ <AccountSid>AC309475e5fede1b49e100272a8640f438</AccountSid>
171
+ <Called>4159633717</Called>
172
+ <Caller>4156767925</Caller>
173
+ <PhoneNumberSid>ABC123</PhoneNumberSid>
174
+ <Status>2</Status>
175
+ <StartTime>Thu, 03 Apr 2008 04:36:33 -0400</StartTime>
176
+ <EndTime>Thu, 03 Apr 2008 04:36:47 -0400</EndTime>
177
+ <Duration>14</Duration>
178
+ <Price/>
179
+ <Flags>1</Flags>
180
+ </Call>
181
+ <Call>
182
+ <Sid>1002</Sid>
183
+ <DateCreated>Sat, 07 Feb 2009 13:15:19 -0800</DateCreated>
184
+ <DateUpdated>Sat, 07 Feb 2009 13:15:19 -0800</DateUpdated>
185
+ <CallSegmentSid>10003</CallSegmentSid>
186
+ <AccountSid>AC309475e5fede1b49e100272a8640f438</AccountSid>
187
+ <Called>4159633717</Called>
188
+ <Caller>4156767925</Caller>
189
+ <PhoneNumberSid>ABC123</PhoneNumberSid>
190
+ <Status>2</Status>
191
+ <StartTime>Thu, 03 Apr 2008 04:36:33 -0400</StartTime>
192
+ <EndTime>Thu, 03 Apr 2008 04:36:47 -0400</EndTime>
193
+ <Duration>14</Duration>
194
+ <Price/>
195
+ <Flags>1</Flags>
196
+ </Call>
197
+ <Call>
198
+ <Sid>1003</Sid>
199
+ <DateCreated>Sat, 07 Feb 2009 13:15:19 -0800</DateCreated>
200
+ <DateUpdated>Sat, 07 Feb 2009 13:15:19 -0800</DateUpdated>
201
+ <CallSegmentSid>10004</CallSegmentSid>
202
+ <AccountSid>AC309475e5fede1b49e100272a8640f438</AccountSid>
203
+ <Called>4159633717</Called>
204
+ <Caller>4156767925</Caller>
205
+ <PhoneNumberSid>UNKNOWN</PhoneNumberSid>
206
+ <Status>2</Status>
207
+ <StartTime>Thu, 03 Apr 2008 04:36:33 -0400</StartTime>
208
+ <EndTime>Thu, 03 Apr 2008 04:36:47 -0400</EndTime>
209
+ <Duration>14</Duration>
210
+ <Price/>
211
+ <Flags>1</Flags>
212
+ </Call>
213
+ <Call>
214
+ <Sid>AVENDORIDAVENDORIDAVENDORID</Sid>
215
+ <DateCreated>Sat, 07 Feb 2009 13:15:19 -0800</DateCreated>
216
+ <DateUpdated>Sat, 07 Feb 2009 13:15:19 -0800</DateUpdated>
217
+ <CallSegmentSid>10004</CallSegmentSid>
218
+ <AccountSid>AC309475e5fede1b49e100272a8640f438</AccountSid>
219
+ <Called>4159633717</Called>
220
+ <Caller>4156767925</Caller>
221
+ <PhoneNumberSid>ABC123</PhoneNumberSid>
222
+ <Status>2</Status>
223
+ <StartTime>Thu, 03 Apr 2008 04:36:33 -0400</StartTime>
224
+ <EndTime>Thu, 03 Apr 2008 04:36:47 -0400</EndTime>
225
+ <Duration>14</Duration>
226
+ <Price/>
227
+ <Flags>1</Flags>
228
+ </Call>
229
+ </Calls>
230
+ </TwilioResponse>
231
+ END
232
+ end
233
+
234
+ def self.recent_calls
235
+ <<END
236
+ <TwilioResponse>
237
+ <Calls page="0" numpages="1" pagesize="50" total="38" start="0" end="37">
238
+ <Call>
239
+ <Sid>CA42ed11f93dc08b952027ffbc406d0868</Sid>
240
+ <DateCreated>Sat, 07 Feb 2009 13:15:19 -0800</DateCreated>
241
+ <DateUpdated>Sat, 07 Feb 2009 13:15:19 -0800</DateUpdated>
242
+ <CallSegmentSid/>
243
+ <AccountSid>AC309475e5fede1b49e100272a8640f438</AccountSid>
244
+ <Called>4159633717</Called>
245
+ <Caller>4156767925</Caller>
246
+ <PhoneNumberSid>PN01234567890123456789012345678900</PhoneNumberSid>
247
+ <Status>1</Status>
248
+ <StartTime>Thu, 03 Apr 2008 04:36:33 -0400</StartTime>
249
+ <EndTime>Thu, 03 Apr 2008 04:36:47 -0400</EndTime>
250
+ <Duration>14</Duration>
251
+ <Price/>
252
+ <Flags>1</Flags>
253
+ </Call>
254
+ </Calls>
255
+ </TwilioResponse>
256
+ END
257
+ end
258
+
259
+
260
+ def self.succeeded_recent_calls
261
+ <<END
262
+ <TwilioResponse>
263
+ <Calls page="0" numpages="1" pagesize="50" total="38" start="0" end="37">
264
+ <Call>
265
+ <Sid>CA42ed11f93dc08b952027ffbc406d0868</Sid>
266
+ <DateCreated>Sat, 07 Feb 2009 13:15:19 -0800</DateCreated>
267
+ <DateUpdated>Sat, 07 Feb 2009 13:15:19 -0800</DateUpdated>
268
+ <CallSegmentSid>8142ed11f93dc08b952027ffbc406d0868</CallSegmentSid>
269
+ <AccountSid>AC309475e5fede1b49e100272a8640f438</AccountSid>
270
+ <Called>4159633717</Called>
271
+ <Caller>4156767925</Caller>
272
+ <PhoneNumberSid>PN01234567890123456789012345678900</PhoneNumberSid>
273
+ <Status>2</Status>
274
+ <StartTime>Thu, 03 Apr 2008 04:36:33 -0400</StartTime>
275
+ <EndTime>Thu, 03 Apr 2008 04:36:47 -0400</EndTime>
276
+ <Duration>14</Duration>
277
+ <Price/>
278
+ <Flags>1</Flags>
279
+ </Call>
280
+ </Calls>
281
+ </TwilioResponse>
282
+ END
283
+ end
284
+
285
+ def self.no_calls
286
+ <<END
287
+ <TwilioResponse>
288
+ <Calls page="0" numpages="1" pagesize="50" total="38" start="0" end="37">
289
+ </Calls>
290
+ </TwilioResponse>
291
+ END
292
+ end
293
+
294
+ def self.local_number_provision_success
295
+ <<END
296
+ <TwilioResponse>
297
+ <IncomingPhoneNumber>
298
+ <Sid>PNe536dfda7c6184afab78d980cb8cdf43</Sid>
299
+ <AccountSid>AC35542fc30a091bed0c1ed511e1d9935d</AccountSid>
300
+ <FriendlyName>My Local Number</FriendlyName>
301
+ <PhoneNumber>2064567890</PhoneNumber>
302
+ <Url>http://example.com/calls</Url>
303
+ <Method>GET</Method>
304
+ <DateCreated>Tue, 01 Apr 2008 11:26:32 -0700</DateCreated>
305
+ <DateUpdated>Tue, 01 Apr 2008 11:26:32 -0700</DateUpdated>
306
+ </IncomingPhoneNumber>
307
+ </TwilioResponse>
308
+ END
309
+ end
310
+
311
+ def self.toll_free_number_provision_success
312
+ <<END
313
+ <TwilioResponse>
314
+ <IncomingPhoneNumber>
315
+ <Sid>PNe536dfda7c6184afab78d980cb8cdf43</Sid>
316
+ <AccountSid>AC35542fc30a091bed0c1ed511e1d9935d</AccountSid>
317
+ <FriendlyName>My Toll Free Number</FriendlyName>
318
+ <PhoneNumber>8774567890</PhoneNumber>
319
+ <Url>http://example.com/calls</Url>
320
+ <Method>GET</Method>
321
+ <DateCreated>Tue, 01 Apr 2008 11:26:32 -0700</DateCreated>
322
+ <DateUpdated>Tue, 01 Apr 2008 11:26:32 -0700</DateUpdated>
323
+ </IncomingPhoneNumber>
324
+ </TwilioResponse>
325
+ END
326
+ end
327
+
328
+ def self.no_local_number
329
+ <<END
330
+ <TwilioResponse><RestException><Status>400</Status><Message>No phone numbers found</Message><Code>21452</Code><MoreInfo>http://www.twilio.com/docs/errors/21452</MoreInfo></RestException></TwilioResponse>
331
+ END
332
+ end
333
+
334
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: twilio_resource
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Justin Weiss
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-06-16 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activeresource
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 3
30
+ - 2
31
+ version: 2.3.2
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description:
35
+ email: justin@uberweiss.org
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files:
41
+ - README.md
42
+ files:
43
+ - lib/twilio_resource/account.rb
44
+ - lib/twilio_resource/base.rb
45
+ - lib/twilio_resource/call.rb
46
+ - lib/twilio_resource/exceptions.rb
47
+ - lib/twilio_resource/incoming_phone_number.rb
48
+ - lib/twilio_resource/local_incoming_phone_number.rb
49
+ - lib/twilio_resource/toll_free_incoming_phone_number.rb
50
+ - lib/twilio_resource/twilio_format.rb
51
+ - lib/twilio_resource.rb
52
+ - test/account_test.rb
53
+ - test/call_test.rb
54
+ - test/incoming_phone_number_test.rb
55
+ - test/local_incoming_phone_number_test.rb
56
+ - test/test_helper.rb
57
+ - test/toll_free_incoming_phone_number_test.rb
58
+ - test/twilio_mock.rb
59
+ - README.md
60
+ has_rdoc: true
61
+ homepage: http://github.com/justinweiss/twilio_resource
62
+ licenses: []
63
+
64
+ post_install_message:
65
+ rdoc_options: []
66
+
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.6
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: An ActiveResource API wrapper for Twilio
90
+ test_files:
91
+ - test/account_test.rb
92
+ - test/call_test.rb
93
+ - test/incoming_phone_number_test.rb
94
+ - test/local_incoming_phone_number_test.rb
95
+ - test/toll_free_incoming_phone_number_test.rb