twilio-rb 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -10,7 +10,7 @@ It offers an ActiveRecord style API, i.e. one that most Ruby developers are fami
10
10
 
11
11
  The library has been packaged as a gem and is available from rubygems.org. The version that this readme pertains to is 2.0.0.
12
12
 
13
- <pre>gem install twilio-rb --pre</pre>
13
+ <pre>gem install twilio-rb</pre>
14
14
 
15
15
  Please use the Github issue tracker to report any issues or bugs you uncover.
16
16
 
@@ -32,7 +32,7 @@ Configuration for this library is achieved with `Twilio::Config.setup`. One need
32
32
  Twilio::Config.setup \
33
33
  :account_sid => 'AC0000000000000000000000000000',
34
34
  :auth_token => '000000000000000000000000000000'
35
- end</pre>
35
+ </pre>
36
36
 
37
37
  Any method that calls the Twilio API will raise `Twilio::ConfigurationError` if either Account SID or Auth Token are not configured.
38
38
 
@@ -221,6 +221,15 @@ Twilio::CapabilityToken.create \
221
221
  expires: 10.minutes.from_now
222
222
  </pre>
223
223
 
224
+ # Twilio Connect
225
+
226
+ With Twilio Connect you can attribute Twilio usage to accounts of customers that have authorised you to perform API calls on there behalf. twilio-rb supports Twilio Connect. To make an API call using a Twilio Connect account, two extra parameters are required, `account_sid` and `connect`
227
+
228
+ <pre>
229
+ Twilio::SMS.create to: '+12125551234', from: '+6165550000', body: 'this will not be billed to the application developer',
230
+ account_sid: CONNECT_ACCOUNT_SID, connect: true
231
+ </pre>
232
+
224
233
  # Associations
225
234
 
226
235
  Certain resources themselves have subresources, e.g. a call can have many recordings. It would be very convenient to access these via an association proxy, so instead of:
@@ -252,7 +261,7 @@ You can create new subaccounts by using `Twilio::Account.create`
252
261
  There are three ways to perform an operation on an account other than the master account: you can pass in the subaccount sid
253
262
 
254
263
  <pre>Twilio::SMS.create :to => '+19175551234' :from => '+16465550000',
255
- :body => 'This will be billed to a subaccount, sucka!' :account => 'ACXXXXXXXXXXXXXXXXXXXXXXXX'</pre>
264
+ :body => 'This will be billed to a subaccount, sucka!' :account_sid => 'ACXXXXXXXXXXXXXXXXXXXXXXXX'</pre>
256
265
 
257
266
  You can also pass in an object that responds to sid, i.e. an instance of Twilio::Account
258
267
 
@@ -313,7 +322,7 @@ So now your Rails app can respond_to :voice. Insane!
313
322
 
314
323
  <pre>
315
324
  class FooController &lt; ApplicationController
316
- responds_to :html, :voice
325
+ respond_to :html, :voice
317
326
 
318
327
  def index
319
328
  ...
@@ -355,8 +364,6 @@ To access properties of a singleton object the property name should be called as
355
364
 
356
365
  The first time a method is invoked on the object an API call is made to retrieve the data. The methods themselves are not defined until they are called, i.e. lazy evaluation. This strategy means that addtional properties added to subsequent versions of the API should not break the library.
357
366
 
358
- To reload the data when needed `Twilio::Account.reload!` will make another API call and update its own internal state.
359
-
360
367
  Please refer to the Twilio REST API documentation for an up to date list of properties that the sandbox resource implements
361
368
 
362
369
  # Searching for and purchasing available phone numbers
@@ -385,3 +392,4 @@ A recording resource instance has an extra instance method: `#mp3` this returns
385
392
  * TJ Singleton
386
393
  * Christopher Durtschi
387
394
  * Dan Imrie-Situnayake
395
+ * John Trupiano
@@ -2,7 +2,7 @@ require 'active_support/core_ext/string'
2
2
 
3
3
  module Twilio
4
4
  class AssociationProxy
5
- instance_methods.each { |meth| undef_method meth unless meth.to_s =~ /^__/ }
5
+ instance_methods.each { |meth| undef_method meth unless meth.to_s =~ /^__/ || meth.to_s == 'object_id' }
6
6
  def initialize(delegator, target)
7
7
  @delegator, @target = delegator, target
8
8
  @delegator_name = @delegator.class.name.demodulize.downcase
@@ -15,6 +15,9 @@ module Twilio
15
15
  def method_missing(meth, *args, &blk)
16
16
  options = args.empty? ? args.<<({})[-1] : args[-1]
17
17
  options.update :"#{@delegator_name}_sid" => @delegator.sid
18
+ if @delegator[:connect_app_sid]
19
+ options.update :connect => true, :account_sid => (@delegator[:account_sid] || @delegator[:sid])
20
+ end
18
21
  @target.__send__ meth, *args, &blk
19
22
  end
20
23
  end
@@ -0,0 +1,6 @@
1
+ module Twilio
2
+ class AuthorizedConnectApp
3
+ include Twilio::Resource
4
+ extend Twilio::Finder
5
+ end
6
+ end
data/lib/twilio/call.rb CHANGED
@@ -5,7 +5,7 @@ module Twilio
5
5
  extend Twilio::Finder
6
6
  extend Twilio::Associations
7
7
 
8
- has_many :recordings
8
+ has_many :recordings, :notifications
9
9
 
10
10
  mutable_attributes :url, :method, :status
11
11
 
@@ -4,7 +4,8 @@ module Twilio
4
4
  extend Twilio::Finder
5
5
 
6
6
  def participants
7
- res = self.class.get "/Accounts/#{Twilio::ACCOUNT_SID}/Conferences/#{sid}/Participants.json"
7
+ account_sid = self[:account_sid] if self[:connect_app_sid]
8
+ res = self.class.get "/Accounts/#{self[:account_sid]}/Conferences/#{sid}/Participants.json", :account_sid => account_sid
8
9
  if (400..599).include? res.code
9
10
  raise Twilio::APIError.new "Error ##{res.parsed_response['code']}: #{res.parsed_response['message']}"
10
11
  else
@@ -15,4 +16,4 @@ module Twilio
15
16
  end
16
17
  end
17
18
  end
18
- end
19
+ end
@@ -0,0 +1,8 @@
1
+ module Twilio
2
+ class ConnectApp
3
+ include Twilio::Resource
4
+ extend Twilio::Finder
5
+
6
+ mutable_attributes :friendly_name, :authorize_redirect_url, :deauthorize_callback_url, :deauthorize_callback_method, :permissions, :description, :company_name, :homepage_url
7
+ end
8
+ end
@@ -1,7 +1,8 @@
1
1
  module Twilio
2
2
  module Deletable
3
3
  def destroy
4
- state_guard { freeze && true if self.class.delete path }
4
+ account_sid = self[:account_sid] if self[:connect_app_sid]
5
+ state_guard { freeze && true if self.class.delete path, :account_sid => account_sid }
5
6
  end
6
7
  end
7
8
  end
data/lib/twilio/finder.rb CHANGED
@@ -4,7 +4,9 @@ module Twilio
4
4
  opts = opts.with_indifferent_access
5
5
  # Support subaccounts by optionally passing in an account_sid or account object
6
6
  account_sid = opts.delete('account_sid') || opts.delete('account').try(:sid) || Twilio::ACCOUNT_SID
7
- res = get "#{resource_path(account_sid)}/#{id}.json"
7
+ connect = opts.delete 'connect'
8
+
9
+ res = get "#{resource_path(account_sid)}/#{id}.json", :account_sid => (connect && account_sid)
8
10
  hash = res.parsed_response
9
11
  if (200..299).include? res.code
10
12
  hash['api_version'] = hash['api_version'].to_s # api_version parsed as a date by http_party
@@ -16,16 +18,20 @@ module Twilio
16
18
  opts = opts.with_indifferent_access
17
19
  # Support subaccounts by optionally passing in an account_sid or account object
18
20
  account_sid = opts.delete('account_sid') || opts.delete('account').try(:sid) || Twilio::ACCOUNT_SID
21
+ connect = opts.delete 'connect'
22
+
19
23
  params = prepare_params opts if opts.any?
20
- get("#{resource_path(account_sid)}.json#{params}").parsed_response['total']
24
+ get("#{resource_path(account_sid)}.json#{params}", :account_sid => (connect && account_sid)).parsed_response['total']
21
25
  end
22
26
 
23
27
  def all(opts={})
24
28
  opts = opts.with_indifferent_access
25
29
  # Support subaccounts by optionally passing in an account_sid or account object
26
30
  account_sid = opts.delete('account_sid') || opts.delete('account').try(:sid) || Twilio::ACCOUNT_SID
31
+ connect = opts.delete 'connect'
32
+
27
33
  params = prepare_params opts if opts.any?
28
- handle_response get "#{resource_path(account_sid)}.json#{params}"
34
+ handle_response get "#{resource_path(account_sid)}.json#{params}", :account_sid => (connect && account_sid)
29
35
  end
30
36
 
31
37
  private
@@ -20,7 +20,7 @@ module Twilio
20
20
  private
21
21
 
22
22
  def path
23
- "/Accounts/#{Twilio::ACCOUNT_SID}/Conferences/#{conference_sid}/Participants/#{call_sid}.json"
23
+ "/Accounts/#{account_sid}/Conferences/#{conference_sid}/Participants/#{call_sid}.json"
24
24
  end
25
25
  end
26
26
  end
@@ -4,11 +4,15 @@ module Twilio
4
4
  def self.included(base)
5
5
  base.instance_eval do
6
6
  def create(attrs={})
7
- attrs = attrs.with_indifferent_access
7
+ attrs = attrs.with_indifferent_access
8
8
  # Support subaccounts by optionally passing in an account_sid or account object
9
- account_sid = attrs.delete('account_sid') || attrs.delete('account').try(:sid) || Twilio::ACCOUNT_SID
9
+ account_sid = attrs.delete('account_sid') || attrs.delete('account').try(:sid) || Twilio::ACCOUNT_SID
10
+ connect = attrs.delete 'connect'
11
+ request_opts = { :body => Hash[attrs.map { |k,v| [k.to_s.camelize, v]}] }
10
12
 
11
- res = post "#{resource_path(account_sid)}.json", :body => Hash[attrs.map { |k,v| [k.to_s.camelize, v]}]
13
+ request_opts.update(:account_sid => account_sid) if connect
14
+
15
+ res = post "#{resource_path(account_sid)}.json", request_opts
12
16
 
13
17
  if (400..599).include? res.code
14
18
  raise Twilio::APIError.new "Error ##{res.parsed_response['code']}: #{res.parsed_response['message']}"
@@ -1,10 +1,12 @@
1
1
  require 'active_support/core_ext/string' # Chill! we only use the bits of AS we need!
2
2
  require 'active_support/core_ext/hash'
3
+ require 'active_support/core_ext/array/extract_options'
4
+
3
5
 
4
6
  module Twilio
5
7
  module Resource
6
- def initialize(attrs ={}) #:nodoc:
7
- @attributes = attrs.with_indifferent_access
8
+ def initialize(attrs={}) #:nodoc:
9
+ @attributes = attrs.with_indifferent_access
8
10
  end
9
11
 
10
12
  def inspect
@@ -21,20 +23,22 @@ module Twilio
21
23
 
22
24
  def update_attributes(attrs={})
23
25
  state_guard do
24
- handle_response klass.post path, :body => Hash[attrs.map { |k,v| [k.to_s.camelize, v]}]
26
+ # state account sid if this is a resource created with a connect subaccount
27
+ account_sid = self[:account_sid] if self[:connect_app_sid]
28
+ handle_response klass.post path, :body => Hash[attrs.map { |k,v| [k.to_s.camelize, v]}], :account_sid => account_sid
25
29
  end
26
30
  end
27
31
 
28
32
  private
29
- def resource_name
33
+ def resource_name #:nodoc:
30
34
  klass.name.demodulize.pluralize
31
35
  end
32
36
 
33
- def klass
37
+ def klass #:nodoc:
34
38
  self.class == Module ? self : self.class
35
39
  end
36
40
 
37
- def state_guard
41
+ def state_guard #:nodoc:
38
42
  if frozen?
39
43
  raise RuntimeError, "#{self.class.name.demodulize} has already been destroyed"
40
44
  else
@@ -42,7 +46,7 @@ module Twilio
42
46
  end
43
47
  end
44
48
 
45
- def path
49
+ def path #:nodoc:
46
50
  uri[11,uri.length]
47
51
  end
48
52
 
@@ -55,7 +59,7 @@ module Twilio
55
59
  end
56
60
  end
57
61
 
58
- def method_missing(id, *args, &blk) #:nodoc
62
+ def method_missing(id, *args, &blk) #:nodoc:
59
63
  meth = id.to_s
60
64
  if meth =~ /\=$/
61
65
  add_attr_writer meth
@@ -71,25 +75,25 @@ module Twilio
71
75
  end
72
76
  end
73
77
 
74
- def add_predicate(attribute)
78
+ def add_predicate(attribute) # :nodoc:
75
79
  metaclass.class_eval do
76
80
  define_method(attribute) { self['status'] =~ /^#{attribute.gsub '?', ''}/i ? true : false }
77
81
  end
78
82
  end
79
83
 
80
- def add_attr_writer(attribute) #:nodoc
84
+ def add_attr_writer(attribute) # :nodoc:
81
85
  metaclass.class_eval do
82
- define_method(attribute) { |value| self[attribute.to_s.gsub(/\=$/, '').to_sym] = value } unless respond_to? attribute
86
+ define_method(attribute) { |value| self[attribute.to_s.gsub(/\=$/, '').to_sym] = value }
83
87
  end
84
88
  end
85
89
 
86
- def add_attr_reader(attribute) #:nodoc
90
+ def add_attr_reader(attribute) #:nodoc:
87
91
  metaclass.class_eval do
88
- define_method(attribute) { self[attribute] } unless respond_to? attribute
92
+ define_method(attribute) { self[attribute] }
89
93
  end
90
94
  end
91
95
 
92
- def metaclass #:nodoc
96
+ def metaclass #:nodoc:
93
97
  class << self; self; end
94
98
  end
95
99
 
@@ -105,8 +109,10 @@ module Twilio
105
109
  # decorate http methods with authentication
106
110
  %w<post get put delete>.each do |meth|
107
111
  define_method(meth) do |*args| # splatted args necessary hack since <= 1.8.7 does not support optional block args
108
- opts = args[1] || {}
109
- super args.first, opts.merge(:basic_auth => { :username => Twilio::ACCOUNT_SID, :password => Twilio::AUTH_TOKEN })
112
+ opts = args.extract_options!
113
+ account_sid = opts.delete :account_sid
114
+ # if account sid is passed in as an option use it for basic auth (twilio connect)
115
+ super args.first, opts.merge(:basic_auth => { :username => account_sid || Twilio::ACCOUNT_SID, :password => Twilio::AUTH_TOKEN })
110
116
  end
111
117
  end
112
118
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twilio-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-22 00:00:00.000000000Z
12
+ date: 2011-11-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &70316353672100 !ruby/object:Gem::Requirement
16
+ requirement: &70313885127680 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.0.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70316353672100
24
+ version_requirements: *70313885127680
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: i18n
27
- requirement: &70316353671640 !ruby/object:Gem::Requirement
27
+ requirement: &70313885159460 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,21 +32,21 @@ dependencies:
32
32
  version: '0.5'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70316353671640
35
+ version_requirements: *70313885159460
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: yajl-ruby
38
- requirement: &70316353671180 !ruby/object:Gem::Requirement
38
+ requirement: &70313885159000 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
- - - ! '>='
41
+ - - ~>
42
42
  - !ruby/object:Gem::Version
43
- version: 0.7.7
43
+ version: 0.8.3
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70316353671180
46
+ version_requirements: *70313885159000
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: httparty
49
- requirement: &70316353670720 !ruby/object:Gem::Requirement
49
+ requirement: &70313885158540 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 0.6.1
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70316353670720
57
+ version_requirements: *70313885158540
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: builder
60
- requirement: &70316353670260 !ruby/object:Gem::Requirement
60
+ requirement: &70313885158080 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 3.0.0
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70316353670260
68
+ version_requirements: *70313885158080
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: jwt
71
- requirement: &70316353669780 !ruby/object:Gem::Requirement
71
+ requirement: &70313885157620 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: 0.1.3
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *70316353669780
79
+ version_requirements: *70313885157620
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: webmock
82
- requirement: &70316353669320 !ruby/object:Gem::Requirement
82
+ requirement: &70313885157160 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: 1.6.1
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70316353669320
90
+ version_requirements: *70313885157160
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: rspec
93
- requirement: &70316353668860 !ruby/object:Gem::Requirement
93
+ requirement: &70313885156700 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: 2.2.0
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70316353668860
101
+ version_requirements: *70313885156700
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: mocha
104
- requirement: &70316353668400 !ruby/object:Gem::Requirement
104
+ requirement: &70313885156240 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: 0.9.10
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70316353668400
112
+ version_requirements: *70313885156240
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: timecop
115
- requirement: &70316353667940 !ruby/object:Gem::Requirement
115
+ requirement: &70313885155780 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: 0.3.5
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *70316353667940
123
+ version_requirements: *70313885155780
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: rake
126
- requirement: &70316353667480 !ruby/object:Gem::Requirement
126
+ requirement: &70313885155320 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ~>
@@ -131,7 +131,7 @@ dependencies:
131
131
  version: 0.8.7
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *70316353667480
134
+ version_requirements: *70313885155320
135
135
  description: A nice Ruby wrapper for the Twilio REST API
136
136
  email: sjtgraham@mac.com
137
137
  executables: []
@@ -144,11 +144,13 @@ files:
144
144
  - lib/twilio/application.rb
145
145
  - lib/twilio/association_proxy.rb
146
146
  - lib/twilio/associations.rb
147
+ - lib/twilio/authorized_connect_app.rb
147
148
  - lib/twilio/available_phone_number.rb
148
149
  - lib/twilio/call.rb
149
150
  - lib/twilio/capability.rb
150
151
  - lib/twilio/conference.rb
151
152
  - lib/twilio/config.rb
153
+ - lib/twilio/connect_app.rb
152
154
  - lib/twilio/deletable.rb
153
155
  - lib/twilio/finder.rb
154
156
  - lib/twilio/incoming_phone_number.rb