twiliolib 2.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.
Files changed (3) hide show
  1. data/README.markdown +34 -0
  2. data/lib/twiliolib.rb +380 -0
  3. metadata +65 -0
data/README.markdown ADDED
@@ -0,0 +1,34 @@
1
+ ## Ruby Twilio Helper Library
2
+
3
+ ### Description
4
+ The Twilio REST SDK simplifies the process of makes calls to the Twilio REST.
5
+ The Twilio REST API lets to you initiate outgoing calls, list previous call,
6
+ and much more. See http://www.twilio.com/docs for more information.
7
+
8
+ ### Installation
9
+
10
+ sudo gem install twiliolib -s http://gemcutter.org
11
+
12
+ If you need to create a custom build, clone the repository and do a rake build to create the gem
13
+
14
+ ### USAGE
15
+ As shown in example.rb, you will need to specify the ACCOUNT_ID and
16
+ ACCOUNT_TOKEN given to you by Twilio before you can make REST requests. In
17
+ addition, you will need to choose a 'Caller' and 'Called' before making
18
+ outgoing calls. See http://www.twilio.com/docs for more information.
19
+
20
+ ### FILES
21
+ * **lib/twilio.rb**: include this library in your code
22
+ * **example-rest.rb**: example usage of REST
23
+ * **example-twiml.rb**: example usage of the TwiML generator
24
+ * **example-utils.rb**: example usage of utilities
25
+
26
+ ### LICENSE
27
+ The Twilio Ruby Helper Library is distributed under the MIT License
28
+
29
+ ### THANKS
30
+ * Jay Philips (@adhearsion) for some great advice
31
+ * Michael Ansel (@michaelansel) for a great starting point <http://github.com/michaelansel/twilio-rails/tree/master>
32
+
33
+ ### OTHER GEMS
34
+ Also check out webficient's [twilio gem](http://github.com/webficient/twilio)
data/lib/twiliolib.rb ADDED
@@ -0,0 +1,380 @@
1
+ =begin
2
+ Copyright (c) 2009 Twilio, Inc.
3
+
4
+ Permission is hereby granted, free of charge, to any person
5
+ obtaining a copy of this software and associated documentation
6
+ files (the "Software"), to deal in the Software without
7
+ restriction, including without limitation the rights to use,
8
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the
10
+ Software is furnished to do so, subject to the following
11
+ conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
+ OTHER DEALINGS IN THE SOFTWARE.
24
+ =end
25
+
26
+ # @author Twilio
27
+ module Twilio
28
+ require 'net/http'
29
+ require 'net/https'
30
+ require 'uri'
31
+ require 'cgi'
32
+ require 'rubygems'
33
+ require 'builder'
34
+ require 'openssl'
35
+ require 'base64'
36
+
37
+ TWILIO_API_URL = 'https://api.twilio.com'
38
+
39
+ # Twilio REST Helpers
40
+ class RestAccount
41
+
42
+ #initialize a twilio account object
43
+ #
44
+ #@param [String, String] Your Twilio Acount SID/ID and Auth Token
45
+ #@return [Object] Twilio account object
46
+ def initialize(id, token)
47
+ @id = id
48
+ @token = token
49
+ end
50
+
51
+ #sends a request and gets a response from the Twilio REST API
52
+ #
53
+ #@param [String, String, Hash]
54
+ #path, the URL (relative to the endpoint URL, after the /v1
55
+ #method, the HTTP method to use, defaults to POST
56
+ #vars, for POST or PUT, a dict of data to send
57
+ #
58
+ #@return Twilio response XML
59
+ #@raises [ArgumentError] Invalid path parameter
60
+ #@raises [NotImplementedError] Method given is not implemented
61
+ def request(path, method=nil, vars={})
62
+ if !path || path.length < 1
63
+ raise ArgumentError, 'Invalid path parameter'
64
+ end
65
+ if method && !['GET', 'POST', 'DELETE', 'PUT'].include?(method)
66
+ raise NotImplementedError, 'HTTP %s not implemented' % method
67
+ end
68
+
69
+ if path[0, 1] == '/'
70
+ uri = TWILIO_API_URL + path
71
+ else
72
+ uri = TWILIO_API_URL + '/' + path
73
+ end
74
+
75
+ return fetch(uri, vars, method)
76
+ end
77
+
78
+ #enocde the parameters into a URL friendly string
79
+ #
80
+ #@param [Hash] URL key / values
81
+ #@return [String] Encoded URL
82
+ protected
83
+ def urlencode(params)
84
+ params.to_a.collect! \
85
+ { |k, v| "#{k}=#{CGI.escape(v.to_s)}" }.join("&")
86
+ end
87
+
88
+ # Create the uri for the REST call
89
+ #
90
+ #@param [String, Hash] Base URL and URL parameters
91
+ #@return [String] URI for the REST call
92
+ def build_get_uri(uri, params)
93
+ if params && params.length > 0
94
+ if uri.include?('?')
95
+ if uri[-1, 1] != '&'
96
+ uri += '&'
97
+ end
98
+ uri += urlencode(params)
99
+ else
100
+ uri += '?' + urlencode(params)
101
+ end
102
+ end
103
+ return uri
104
+ end
105
+
106
+ # Returns a http request for the given url and parameters
107
+ #
108
+ #@param [String, Hash, String] Base URL, URL parameters, optional METHOD
109
+ #@return [String] URI for the REST call
110
+ def fetch(url, params, method=nil)
111
+ if method && method == 'GET'
112
+ url = build_get_uri(url, params)
113
+ end
114
+ uri = URI.parse(url)
115
+
116
+ http = Net::HTTP.new(uri.host, uri.port)
117
+ http.use_ssl = true
118
+
119
+ if method && method == 'GET'
120
+ req = Net::HTTP::Get.new(uri.request_uri)
121
+ elsif method && method == 'DELETE'
122
+ req = Net::HTTP::Delete.new(uri.request_uri)
123
+ elsif method && method == 'PUT'
124
+ req = Net::HTTP::Put.new(uri.request_uri)
125
+ req.set_form_data(params)
126
+ else
127
+ req = Net::HTTP::Post.new(uri.request_uri)
128
+ req.set_form_data(params)
129
+ end
130
+ req.basic_auth(@id, @token)
131
+
132
+ return http.request(req)
133
+ end
134
+ end
135
+
136
+ # Twiml Response Helpers
137
+ module Verb
138
+ module ClassMethods
139
+ @attributes = []
140
+ @allowed_verbs = []
141
+ attr_accessor :attributes
142
+
143
+ def allowed_verbs(*verbs)
144
+ return @allowed_verbs if verbs == []
145
+ @allowed_verbs = [] if @allowed_verbs.nil?
146
+ verbs.each do |verb|
147
+ @allowed_verbs << verb.to_s.capitalize
148
+ end
149
+ @allowed_verbs = @allowed_verbs.uniq
150
+ end
151
+
152
+ def attributes(*attrs)
153
+ return @attributes if attrs == []
154
+ @attributes = [] if @attributes.nil?
155
+ @attributes = (@attributes + attrs).uniq
156
+ attr_accessor(*@attributes)
157
+ @attributes
158
+ end
159
+ end
160
+
161
+ def attributes
162
+ self.class.attributes
163
+ end
164
+
165
+ #test if a given verb is allowed to be nested
166
+ #
167
+ #@param [Object] Verb to be appended
168
+ #@return [true, false]
169
+ def allowed?(verb)
170
+ self.class.allowed_verbs.nil? ? false : self.class.allowed_verbs.include?(verb.class.name.split('::')[1])
171
+ end
172
+
173
+ #initialize a twilio response object
174
+ #
175
+ #@param [String, Hash] Body of the verb, and a hash of the attributes
176
+ #@return [Object] Twilio Verb object
177
+ #
178
+ #@raises [ArgumentError] Invalid Argument
179
+ def initialize(body = nil, params = {})
180
+ @children = []
181
+ if body.class == String
182
+ @body = body
183
+ else
184
+ @body = nil
185
+ params = body || {}
186
+ end
187
+ params.each do |k,v|
188
+ if !self.class.attributes.nil? && self.class.attributes.include?(k)
189
+ send(k.to_s+"=",v)
190
+ else
191
+ raise ArgumentError, "Attribute Not Supported"
192
+ end
193
+ end
194
+ end
195
+
196
+ #set an attribute key / value
197
+ #no error checking
198
+ #
199
+ #@param [Hash] Hash of options
200
+ #@return void
201
+ def set(params = {})
202
+ params.each do |k,v|
203
+ self.class.attributes k.to_s
204
+ send(k.to_s+"=",v)
205
+ end
206
+ end
207
+
208
+ #output valid Twilio markup
209
+ #
210
+ #@param [Hash] Hash of options
211
+ #@return [String] Twilio Markup (in XML)
212
+ def respond(opts = {})
213
+ opts[:builder] ||= Builder::XmlMarkup.new(:indent => opts[:indent])
214
+ b = opts[:builder]
215
+ attrs = {}
216
+ attributes.each {|a| attrs[a] = send(a) unless send(a).nil? } unless attributes.nil?
217
+
218
+ if @children and @body.nil?
219
+ b.__send__(self.class.to_s.split(/::/)[-1], attrs) do
220
+ @children.each {|e|e.respond( opts.merge(:skip_instruct => true) )}
221
+ end
222
+ elsif @body and @children == []
223
+ b.__send__(self.class.to_s.split(/::/)[-1], @body, attrs)
224
+ else
225
+ raise ArgumentError, "Cannot have children and a body at the same time"
226
+ end
227
+ end
228
+
229
+ #output valid Twilio markup encoded for inclusion in a URL
230
+ #
231
+ #@param []
232
+ #@return [String] URL encoded Twilio Markup (XML)
233
+ def asURL()
234
+ CGI::escape(self.respond)
235
+ end
236
+
237
+ def append(verb)
238
+ if(allowed?(verb))
239
+ @children << verb
240
+ @children[-1]
241
+ else
242
+ raise ArgumentError, "Verb Not Supported"
243
+ end
244
+ end
245
+
246
+ # Verb Convenience Methods
247
+ def addSay(string_to_say = nil, opts = {})
248
+ append Twilio::Say.new(string_to_say, opts)
249
+ end
250
+
251
+ def addPlay(file_to_play = nil, opts = {})
252
+ append Twilio::Play.new(file_to_play, opts)
253
+ end
254
+
255
+ def addGather(opts = {})
256
+ append Twilio::Gather.new(opts)
257
+ end
258
+
259
+ def addRecord(opts = {})
260
+ append Twilio::Record.new(opts)
261
+ end
262
+
263
+ def addDial(number = nil, opts = {})
264
+ append Twilio::Dial.new(number, opts)
265
+ end
266
+
267
+ def addRedirect(url = nil, opts = {})
268
+ append Twilio::Redirect.new(url, opts)
269
+ end
270
+
271
+ def addPause(opts = {})
272
+ append Twilio::Pause.new(opts)
273
+ end
274
+
275
+ def addHangup
276
+ append Twilio::Hangup.new
277
+ end
278
+
279
+ def addNumber(number, opts = {})
280
+ append Twilio::Number.new(number, opts)
281
+ end
282
+
283
+ def addConference(room, opts = {})
284
+ append Twilio::Conference.new(room, opts)
285
+ end
286
+
287
+ end
288
+
289
+ class Say
290
+ extend Twilio::Verb::ClassMethods
291
+ include Twilio::Verb
292
+ attributes :voice, :language, :loop
293
+ end
294
+
295
+ class Play
296
+ extend Twilio::Verb::ClassMethods
297
+ include Twilio::Verb
298
+ attributes :loop
299
+ end
300
+
301
+ class Gather
302
+ extend Twilio::Verb::ClassMethods
303
+ include Twilio::Verb
304
+ attributes :action, :method, :timeout, :finishOnKey, :numDigits
305
+ allowed_verbs :play, :say, :pause
306
+ end
307
+
308
+ class Record
309
+ extend Twilio::Verb::ClassMethods
310
+ include Twilio::Verb
311
+ attributes :action, :method, :timeout, :finishOnKey, :maxLength, :transcribe, :transcribeCallback
312
+ end
313
+
314
+ class Dial
315
+ extend Twilio::Verb::ClassMethods
316
+ include Twilio::Verb
317
+ attributes :action, :method, :timeout, :hangupOnStar, :timeLimit, :callerId
318
+ allowed_verbs :number, :conference
319
+ end
320
+
321
+ class Redirect
322
+ extend Twilio::Verb::ClassMethods
323
+ include Twilio::Verb
324
+ attributes :method
325
+ end
326
+
327
+ class Pause
328
+ extend Twilio::Verb::ClassMethods
329
+ include Twilio::Verb
330
+ attributes :length
331
+ end
332
+
333
+ class Hangup
334
+ extend Twilio::Verb::ClassMethods
335
+ include Twilio::Verb
336
+ end
337
+
338
+ class Number
339
+ extend Twilio::Verb::ClassMethods
340
+ include Twilio::Verb
341
+ attributes :sendDigits, :url
342
+ end
343
+
344
+ class Conference
345
+ extend Twilio::Verb::ClassMethods
346
+ include Twilio::Verb
347
+ attributes :muted, :beep, :startConferenceOnEnter, :endConferenceOnExit, :waitUrl, :waitMethod
348
+ end
349
+
350
+ class Response
351
+ extend Twilio::Verb::ClassMethods
352
+ include Twilio::Verb
353
+ allowed_verbs :say, :play, :gather, :record, :dial, :redirect, :pause, :hangup
354
+ end
355
+
356
+ # Twilio Utility function and Request Validation class
357
+ class Utils
358
+
359
+ #initialize a twilio utils abject
360
+ #
361
+ #@param [String, String] Your Twilio Acount SID/ID and Auth Token
362
+ #@return [Object] Twilio account object
363
+ def initialize(id, token)
364
+ @id = id
365
+ @token = token
366
+ end
367
+
368
+ def validateRequest(signature, url, params = {})
369
+ sorted_post_params = params.sort
370
+ data = url
371
+ sorted_post_params.each do |pkey|
372
+ data = data + pkey[0]+pkey[1]
373
+ end
374
+ digest = OpenSSL::Digest::Digest.new('sha1')
375
+ expected = Base64.encode64(OpenSSL::HMAC.digest(digest, @id, data)).strip
376
+ return expected == signature
377
+ end
378
+ end
379
+
380
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: twiliolib
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Twilio
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-03 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: builder
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.1.2
24
+ version:
25
+ description: A Ruby gem for communicating with the Twilio API and generating TwiML
26
+ email: help@twilio.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.markdown
33
+ files:
34
+ - lib/twiliolib.rb
35
+ - README.markdown
36
+ has_rdoc: true
37
+ homepage: http://www.twilio.com/docs
38
+ licenses: []
39
+
40
+ post_install_message:
41
+ rdoc_options: []
42
+
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ requirements: []
58
+
59
+ rubyforge_project:
60
+ rubygems_version: 1.3.5
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: Some description
64
+ test_files: []
65
+