twiliolib 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+