Derferman-twilio 0.1.3
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/Changelog +3 -0
- data/LICENSE +22 -0
- data/README +26 -0
- data/Rakefile +26 -0
- data/example-rest.rb +63 -0
- data/example-twiml.rb +72 -0
- data/lib/twilio.rb +342 -0
- data/tests/response_spec.rb +366 -0
- metadata +68 -0
data/Changelog
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2008 Twilio, Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
Ruby Twilio REST SDK
|
2
|
+
|
3
|
+
|
4
|
+
DESCRIPTION
|
5
|
+
The Twilio REST SDK simplifies the process of makes calls to the Twilio REST.
|
6
|
+
The Twilio REST API lets to you initiate outgoing calls, list previous call,
|
7
|
+
and much more. See http://www.twilio.com/docs for more information.
|
8
|
+
|
9
|
+
|
10
|
+
USAGE
|
11
|
+
To use the twiliorest.rb library with Rails just copy the twiliorest.rb file
|
12
|
+
into the lib directory of your Rails application. Then just require
|
13
|
+
"twiliorest.rb" in the controller or code file you wish to use the Twilio REST
|
14
|
+
API from. As shown in example.rb, you will need to specify the ACCOUNT_ID and
|
15
|
+
ACCOUNT_TOKEN given to you by Twilio before you can make REST requests. In
|
16
|
+
addition, you will need to choose a 'Caller' and 'Called' before making
|
17
|
+
outgoing calls. See http://www.twilio.com/docs for more information.
|
18
|
+
|
19
|
+
|
20
|
+
FILES
|
21
|
+
twiliorest.rb -- include this library in your code
|
22
|
+
example.rb -- example usage of twiliorest library
|
23
|
+
|
24
|
+
|
25
|
+
LICENSE
|
26
|
+
The Twilio SDK is distributed under the MIT License
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
|
4
|
+
spec = Gem::Specification.new do |s|
|
5
|
+
s.name = "twilio"
|
6
|
+
s.version = "0.1.3"
|
7
|
+
s.author = "Kyle Conroy"
|
8
|
+
s.email = "kjconroy@twilio.com"
|
9
|
+
s.homepage = "http://www.twilio.com/docs"
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.summary = "Some description"
|
12
|
+
s.files = FileList["{lib}/*"].to_a
|
13
|
+
s.require_path = "lib"
|
14
|
+
s.test_files = FileList["{test}/response_spec.rb"].to_a
|
15
|
+
s.has_rdoc = true
|
16
|
+
s.extra_rdoc_files = ["README"]
|
17
|
+
s.add_dependency("builder", ">= 2.1.2")
|
18
|
+
end
|
19
|
+
|
20
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
21
|
+
pkg.need_tar = true
|
22
|
+
end
|
23
|
+
|
24
|
+
task :default => "pkg/#{spec.name}-#{spec.version}.gem" do
|
25
|
+
puts "generated latest version"
|
26
|
+
end
|
data/example-rest.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "twiliorest.rb"
|
4
|
+
|
5
|
+
# Twilio REST API version
|
6
|
+
API_VERSION = '2008-08-01'
|
7
|
+
|
8
|
+
# Twilio AccountSid and AuthToken
|
9
|
+
ACCOUNT_SID = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
|
10
|
+
ACCOUNT_TOKEN = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'
|
11
|
+
|
12
|
+
# Outgoing Caller ID previously validated with Twilio
|
13
|
+
CALLER_ID = 'NNNNNNNNNN';
|
14
|
+
|
15
|
+
# Create a Twilio REST account object using your Twilio account ID and token
|
16
|
+
account = TwilioRest::Account.new(ACCOUNT_SID, ACCOUNT_TOKEN)
|
17
|
+
|
18
|
+
# ===========================================================================
|
19
|
+
# 1. Initiate a new outbound call to 415-555-1212
|
20
|
+
# uses a HTTP POST
|
21
|
+
d = {
|
22
|
+
'Caller' => CALLER_ID,
|
23
|
+
'Called' => '415-555-1212',
|
24
|
+
'Url' => 'http://demo.twilio.com/welcome',
|
25
|
+
}
|
26
|
+
resp = account.request("/#{API_VERSION}/Accounts/#{ACCOUNT_SID}/Calls",
|
27
|
+
'POST', d)
|
28
|
+
resp.error! unless resp.kind_of? Net::HTTPSuccess
|
29
|
+
puts "code: %s\nbody: %s" % [resp.code, resp.body]
|
30
|
+
|
31
|
+
# ===========================================================================
|
32
|
+
# 2. Get a list of recent completed calls (i.e. Status = 2)
|
33
|
+
# uses a HTTP GET
|
34
|
+
d = { 'Status' => 2 }
|
35
|
+
resp = account.request("/#{API_VERSION}/Accounts/#{ACCOUNT_SID}/Calls",
|
36
|
+
'GET', d)
|
37
|
+
resp.error! unless resp.kind_of? Net::HTTPSuccess
|
38
|
+
puts "code: %s\nbody: %s" % [resp.code, resp.body]
|
39
|
+
|
40
|
+
# ===========================================================================
|
41
|
+
# 3. Get a list of recent notification log entries
|
42
|
+
# uses a HTTP GET
|
43
|
+
resp = account.request("/#{API_VERSION}/Accounts/#{ACCOUNT_SID}/\
|
44
|
+
Notifications", 'GET')
|
45
|
+
resp.error! unless resp.kind_of? Net::HTTPSuccess
|
46
|
+
puts "code: %s\nbody: %s" % [resp.code, resp.body]
|
47
|
+
|
48
|
+
# ===========================================================================
|
49
|
+
# 4. Get a list of audio recordings for a certain call
|
50
|
+
# uses a HTTP GET
|
51
|
+
d = { 'CallSid' => 'CA5d44cc11756367a4c54e517511484900' }
|
52
|
+
resp = account.request("/#{API_VERSION}/Accounts/#{ACCOUNT_SID}/Recordings",
|
53
|
+
'GET', d)
|
54
|
+
resp.error! unless resp.kind_of? Net::HTTPSuccess
|
55
|
+
puts "code: %s\nbody: %s" % [resp.code, resp.body]
|
56
|
+
|
57
|
+
# ===========================================================================
|
58
|
+
# 5. Delete a specific recording
|
59
|
+
# uses a HTTP DELETE, no response is returned when using DLETE
|
60
|
+
resp = account.request( \
|
61
|
+
"/#{API_VERSION}/Accounts/#{ACCOUNT_SID}/Recordings/\
|
62
|
+
RE7b22d733d3e730d234e94242b9697cae", 'DELETE')
|
63
|
+
puts "code: %s" % [resp.code]
|
data/example-twiml.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require "twilio.rb"
|
2
|
+
|
3
|
+
# Say, Dial, and Play
|
4
|
+
@r = Twilio::Response.new
|
5
|
+
@r.append(Twilio::Say.new "Hello World", :voice => "man", :loop => "10")
|
6
|
+
@r.append(Twilio::Dial.new("5305451766", :timeLimit => "45"))
|
7
|
+
@r.append(Twilio::Play.new("http://www.mp3.com"))
|
8
|
+
puts @r.respond
|
9
|
+
|
10
|
+
# @r.respond; outputs:
|
11
|
+
#<Response>
|
12
|
+
# <Say voice="man" loop="10">Hello World</Say>
|
13
|
+
# <Play>http://www.mp3.com</Play>
|
14
|
+
# <Dial timeLimit="45">5305451766</Dial>
|
15
|
+
#</Response>
|
16
|
+
|
17
|
+
|
18
|
+
# Gather, Redirect
|
19
|
+
@r = Twilio::Response.new;
|
20
|
+
@g = @r.append(Twilio::Gather.new(:numDigits => "10"))
|
21
|
+
@g.append(Twilio::Say.new("Press 1"))
|
22
|
+
@r.append(Twilio::Redirect.new())
|
23
|
+
puts @r.respond
|
24
|
+
|
25
|
+
|
26
|
+
#<Response>
|
27
|
+
# <Gather numDigits="1">
|
28
|
+
# <Say>Press 1</Say>
|
29
|
+
# </Gather>
|
30
|
+
# <Redirect/>
|
31
|
+
#</Response>
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
# Add a Say verb multiple times
|
36
|
+
@r = Twilio::Response.new
|
37
|
+
@say = Twilio::Say.new("Press 1")
|
38
|
+
@r.append(@say);
|
39
|
+
@r.append(@say);
|
40
|
+
puts @r.respond
|
41
|
+
|
42
|
+
#<Response>
|
43
|
+
# <Say>Press 1</Say>
|
44
|
+
# <Say>Press 1</Say>
|
45
|
+
#</Response>
|
46
|
+
|
47
|
+
|
48
|
+
# Set any attribute / value pair
|
49
|
+
|
50
|
+
@r = Twilio::Response.new
|
51
|
+
@r.append(Twilio::Redirect.new(:__crazy => "delicious"))
|
52
|
+
puts @r.respond
|
53
|
+
|
54
|
+
|
55
|
+
#<Response>
|
56
|
+
# <Redirect crazy="delicious"/>
|
57
|
+
#<Response>
|
58
|
+
|
59
|
+
# Convenience methods
|
60
|
+
@r = Twilio::Response.new
|
61
|
+
@r.addSay "Hello World", :voice => "man", :language => "fr", :loop => "10"
|
62
|
+
@r.addDial "5305451766", :timeLimit => "45"
|
63
|
+
@r.addPlay "http://www.mp3.com"
|
64
|
+
puts @r.respond
|
65
|
+
|
66
|
+
# @r.respond; outputs:
|
67
|
+
#<Response>
|
68
|
+
# <Say voice="man" language="fr" loop="10">Hello World</Say>
|
69
|
+
# <Play>http://www.mp3.com</Play>
|
70
|
+
# <Dial timeLimit="45">5305451766</Dial>
|
71
|
+
#</Response>
|
72
|
+
|
data/lib/twilio.rb
ADDED
@@ -0,0 +1,342 @@
|
|
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
|
+
module Twilio
|
27
|
+
require 'net/http'
|
28
|
+
require 'net/https'
|
29
|
+
require 'uri'
|
30
|
+
require 'cgi'
|
31
|
+
require 'rubygems'
|
32
|
+
require 'builder'
|
33
|
+
|
34
|
+
TWILIO_API_URL = 'https://api.twilio.com'
|
35
|
+
|
36
|
+
class RestAccount
|
37
|
+
|
38
|
+
#initialize a twilio account object
|
39
|
+
#
|
40
|
+
#@param [String, String] Your Twilio Acount SID/ID and Auth Token
|
41
|
+
#@return [Object] Twilio account object
|
42
|
+
def initialize(id, token)
|
43
|
+
@id = id
|
44
|
+
@token = token
|
45
|
+
end
|
46
|
+
|
47
|
+
#sends a request and gets a response from the Twilio REST API
|
48
|
+
#
|
49
|
+
#@param [String, String, Hash]
|
50
|
+
#path, the URL (relative to the endpoint URL, after the /v1
|
51
|
+
#method, the HTTP method to use, defaults to POST
|
52
|
+
#vars, for POST or PUT, a dict of data to send
|
53
|
+
#
|
54
|
+
#@return Twilio response XML
|
55
|
+
#@raises [ArgumentError] Invalid path parameter
|
56
|
+
#@raises [NotImplementedError] Method given is not implemented
|
57
|
+
def request(path, method=nil, vars={})
|
58
|
+
if !path || path.length < 1
|
59
|
+
raise ArgumentError, 'Invalid path parameter'
|
60
|
+
end
|
61
|
+
if method && !['GET', 'POST', 'DELETE', 'PUT'].include?(method)
|
62
|
+
raise NotImplementedError, 'HTTP %s not implemented' % method
|
63
|
+
end
|
64
|
+
|
65
|
+
if path[0, 1] == '/'
|
66
|
+
uri = TWILIO_API_URL + path
|
67
|
+
else
|
68
|
+
uri = TWILIO_API_URL + '/' + path
|
69
|
+
end
|
70
|
+
|
71
|
+
return fetch(uri, vars, method)
|
72
|
+
end
|
73
|
+
|
74
|
+
#enocde the parameters into a URL friendly string
|
75
|
+
#
|
76
|
+
#@param [Hash] URL key / values
|
77
|
+
#@return [String] Encoded URL
|
78
|
+
protected
|
79
|
+
def urlencode(params)
|
80
|
+
params.to_a.collect! \
|
81
|
+
{ |k, v| "#{k}=#{CGI.escape(v.to_s)}" }.join("&")
|
82
|
+
end
|
83
|
+
|
84
|
+
# Create the uri for the REST call
|
85
|
+
#
|
86
|
+
#@param [String, Hash] Base URL and URL parameters
|
87
|
+
#@return [String] URI for the REST call
|
88
|
+
def build_get_uri(uri, params)
|
89
|
+
if params && params.length > 0
|
90
|
+
if uri.include?('?')
|
91
|
+
if uri[-1, 1] != '&'
|
92
|
+
uri += '&'
|
93
|
+
end
|
94
|
+
uri += urlencode(params)
|
95
|
+
else
|
96
|
+
uri += '?' + urlencode(params)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
return uri
|
100
|
+
end
|
101
|
+
|
102
|
+
# Returns a http request for the given url and parameters
|
103
|
+
#
|
104
|
+
#@param [String, Hash, String] Base URL, URL parameters, optional METHOD string
|
105
|
+
#@return [String] URI for the REST call
|
106
|
+
def fetch(url, params, method=nil)
|
107
|
+
if method && method == 'GET'
|
108
|
+
url = build_get_uri(url, params)
|
109
|
+
end
|
110
|
+
uri = URI.parse(url)
|
111
|
+
|
112
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
113
|
+
http.use_ssl = true
|
114
|
+
|
115
|
+
if method && method == 'GET'
|
116
|
+
req = Net::HTTP::Get.new(uri.request_uri)
|
117
|
+
elsif method && method == 'DELETE'
|
118
|
+
req = Net::HTTP::Delete.new(uri.request_uri)
|
119
|
+
elsif method && method == 'PUT'
|
120
|
+
req = Net::HTTP::Put.new(uri.request_uri)
|
121
|
+
req.set_form_data(params)
|
122
|
+
else
|
123
|
+
req = Net::HTTP::Post.new(uri.request_uri)
|
124
|
+
req.set_form_data(params)
|
125
|
+
end
|
126
|
+
req.basic_auth(@id, @token)
|
127
|
+
|
128
|
+
return http.request(req)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
module Verb
|
133
|
+
module ClassMethods
|
134
|
+
@attributes = []
|
135
|
+
@allowed_verbs = []
|
136
|
+
attr_accessor :attributes
|
137
|
+
|
138
|
+
def allowed_verbs(*verbs)
|
139
|
+
return @allowed_verbs if verbs == []
|
140
|
+
@allowed_verbs = [] if @allowed_verbs.nil?
|
141
|
+
verbs.each do |verb|
|
142
|
+
@allowed_verbs << verb.to_s.capitalize
|
143
|
+
end
|
144
|
+
@allowed_verbs = @allowed_verbs.uniq
|
145
|
+
end
|
146
|
+
|
147
|
+
def attributes(*attrs)
|
148
|
+
return @attributes if attrs == []
|
149
|
+
@attributes = [] if @attributes.nil?
|
150
|
+
@attributes = (@attributes + attrs).uniq
|
151
|
+
attr_accessor(*@attributes)
|
152
|
+
@attributes
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def attributes
|
157
|
+
self.class.attributes
|
158
|
+
end
|
159
|
+
|
160
|
+
#test if a given verb is allowed to be nested
|
161
|
+
#
|
162
|
+
#@param [Object] Verb to be appended
|
163
|
+
#@return [true, false]
|
164
|
+
def allowed?(verb)
|
165
|
+
self.class.allowed_verbs.nil? ? false : self.class.allowed_verbs.include?(verb.class.name.split('::')[1])
|
166
|
+
end
|
167
|
+
|
168
|
+
#initialize a twilio response object
|
169
|
+
#
|
170
|
+
#@param [String, Hash] Body of the verb, and a hash of the attributes
|
171
|
+
#@return [Object] Twilio Verb object
|
172
|
+
#
|
173
|
+
#@raises [ArgumentError] Invalid Argument
|
174
|
+
def initialize(body = nil, params = {})
|
175
|
+
@children = []
|
176
|
+
if body.class == String
|
177
|
+
@body = body
|
178
|
+
else
|
179
|
+
@body = nil
|
180
|
+
params = body || {}
|
181
|
+
end
|
182
|
+
params.each do |k,v|
|
183
|
+
if !self.class.attributes.nil? && self.class.attributes.include?(k)
|
184
|
+
send(k.to_s+"=",v)
|
185
|
+
else
|
186
|
+
raise ArgumentError, "Attribute Not Supported"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
#set an attribute key / value
|
192
|
+
#no error checking
|
193
|
+
#
|
194
|
+
#@param [Hash] Hash of options
|
195
|
+
#@return void
|
196
|
+
def set(params = {})
|
197
|
+
params.each do |k,v|
|
198
|
+
self.class.attributes k.to_s
|
199
|
+
send(k.to_s+"=",v)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
#output valid Twilio markup
|
204
|
+
#
|
205
|
+
#@param [Hash] Hash of options
|
206
|
+
#@return [String] Twilio Markup (in XML)
|
207
|
+
def respond(opts = {})
|
208
|
+
opts[:builder] ||= Builder::XmlMarkup.new(:indent => opts[:indent])
|
209
|
+
b = opts[:builder]
|
210
|
+
attrs = {}
|
211
|
+
#attributes.each {|a| puts send(a) } unless attributes.nil?
|
212
|
+
attributes.each {|a| attrs[a] = send(a) unless send(a).nil? } unless attributes.nil?
|
213
|
+
|
214
|
+
if @children and @body.nil?
|
215
|
+
b.__send__(self.class.to_s.split(/::/)[-1], attrs) do
|
216
|
+
@children.each {|e|e.respond( opts.merge(:skip_instruct => true) )}
|
217
|
+
end
|
218
|
+
elsif @body and @children == []
|
219
|
+
b.__send__(self.class.to_s.split(/::/)[-1], @body, attrs)
|
220
|
+
else
|
221
|
+
raise ArgumentError, "Cannot have children and a body at the same time"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
#output valid Twilio markup encoded for inclusion in a URL
|
226
|
+
#
|
227
|
+
#@param []
|
228
|
+
#@return [String] URL encoded Twilio Markup (XML)
|
229
|
+
def to_URLstring()
|
230
|
+
CGI::escape(self.respond)
|
231
|
+
end
|
232
|
+
|
233
|
+
def append(verb)
|
234
|
+
if(allowed?(verb))
|
235
|
+
@children << verb
|
236
|
+
@children[-1]
|
237
|
+
else
|
238
|
+
raise ArgumentError, "Verb Not Supported"
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
##### Verb Convenience Methods #####
|
243
|
+
def addSay(string_to_say = nil, opts = {})
|
244
|
+
append(Twilio::Say.new(string_to_say, opts))
|
245
|
+
end
|
246
|
+
|
247
|
+
def addPlay(file_to_play = nil, opts = {})
|
248
|
+
append Twilio::Play.new(file_to_play, opts)
|
249
|
+
end
|
250
|
+
|
251
|
+
def addGather(opts = {})
|
252
|
+
append Twilio::Gather.new(opts)
|
253
|
+
end
|
254
|
+
|
255
|
+
def addRecord(opts = {})
|
256
|
+
append Twilio::Record.new(opts)
|
257
|
+
end
|
258
|
+
|
259
|
+
def addDial(number = nil, opts = {})
|
260
|
+
append Twilio::Dial.new(number, opts)
|
261
|
+
end
|
262
|
+
|
263
|
+
def addRedirect(url = nil, opts = {})
|
264
|
+
append Twilio::Redirect.new(url, opts)
|
265
|
+
end
|
266
|
+
|
267
|
+
def addPause(opts = {})
|
268
|
+
append Twilio::Pause.new(opts)
|
269
|
+
end
|
270
|
+
|
271
|
+
def addHangup
|
272
|
+
append Twilio::Hangup.new
|
273
|
+
end
|
274
|
+
|
275
|
+
def addNumber(number, opts = {})
|
276
|
+
append Twilio::Number.new(number, opts)
|
277
|
+
end
|
278
|
+
|
279
|
+
end
|
280
|
+
|
281
|
+
class Say
|
282
|
+
extend Twilio::Verb::ClassMethods
|
283
|
+
include Twilio::Verb
|
284
|
+
attributes :voice, :language, :loop
|
285
|
+
end
|
286
|
+
|
287
|
+
class Play
|
288
|
+
extend Twilio::Verb::ClassMethods
|
289
|
+
include Twilio::Verb
|
290
|
+
attributes :loop
|
291
|
+
end
|
292
|
+
|
293
|
+
class Gather
|
294
|
+
extend Twilio::Verb::ClassMethods
|
295
|
+
include Twilio::Verb
|
296
|
+
attributes :action, :method, :timeout, :finishOnKey, :numDigits
|
297
|
+
allowed_verbs :play, :say, :pause
|
298
|
+
end
|
299
|
+
|
300
|
+
class Record
|
301
|
+
extend Twilio::Verb::ClassMethods
|
302
|
+
include Twilio::Verb
|
303
|
+
attributes :action, :method, :timeout, :finishOnKey, :maxLength, :transcribe, :transcribeCallback
|
304
|
+
end
|
305
|
+
|
306
|
+
class Dial
|
307
|
+
extend Twilio::Verb::ClassMethods
|
308
|
+
include Twilio::Verb
|
309
|
+
attributes :action, :method, :timeout, :hangupOnStar, :timeLimit, :callerId
|
310
|
+
allowed_verbs :number
|
311
|
+
end
|
312
|
+
|
313
|
+
class Redirect
|
314
|
+
extend Twilio::Verb::ClassMethods
|
315
|
+
include Twilio::Verb
|
316
|
+
attributes :method
|
317
|
+
end
|
318
|
+
|
319
|
+
class Pause
|
320
|
+
extend Twilio::Verb::ClassMethods
|
321
|
+
include Twilio::Verb
|
322
|
+
attributes :length
|
323
|
+
end
|
324
|
+
|
325
|
+
class Hangup
|
326
|
+
extend Twilio::Verb::ClassMethods
|
327
|
+
include Twilio::Verb
|
328
|
+
end
|
329
|
+
|
330
|
+
class Number
|
331
|
+
extend Twilio::Verb::ClassMethods
|
332
|
+
include Twilio::Verb
|
333
|
+
attributes :sendDigits, :url
|
334
|
+
end
|
335
|
+
|
336
|
+
class Response
|
337
|
+
extend Twilio::Verb::ClassMethods
|
338
|
+
include Twilio::Verb
|
339
|
+
allowed_verbs :say, :play, :gather, :record, :dial, :redirect, :pause, :hangup
|
340
|
+
end
|
341
|
+
|
342
|
+
end
|
@@ -0,0 +1,366 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../twilio-rb/twilio.rb'
|
2
|
+
|
3
|
+
module AccountExampleHelperMethods
|
4
|
+
|
5
|
+
def bad_append(verb)
|
6
|
+
|
7
|
+
lambda {verb.append(Twilio::Response)}.should raise_error(ArgumentError)
|
8
|
+
lambda {verb.append(Twilio::Say)}.should raise_error(ArgumentError)
|
9
|
+
lambda {verb.append(Twilio::Play)}.should raise_error(ArgumentError)
|
10
|
+
lambda {verb.append(Twilio::Gather)}.should raise_error(ArgumentError)
|
11
|
+
lambda {verb.append(Twilio::Record)}.should raise_error(ArgumentError)
|
12
|
+
lambda {verb.append(Twilio::Redirect)}.should raise_error(ArgumentError)
|
13
|
+
lambda {verb.append(Twilio::Hangup)}.should raise_error(ArgumentError)
|
14
|
+
lambda {verb.append(Twilio::Pause)}.should raise_error(ArgumentError)
|
15
|
+
lambda {verb.append(Twilio::Number)}.should raise_error(ArgumentError)
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def bad_attr(verb)
|
20
|
+
lambda {verb.new(:crazy => 'delicious')}.should raise_error(ArgumentError)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
describe Twilio::Response do
|
26
|
+
include AccountExampleHelperMethods
|
27
|
+
|
28
|
+
it "should be an empty response" do
|
29
|
+
@r = Twilio::Response.new
|
30
|
+
@r.respond.should == '<Response></Response>'
|
31
|
+
end
|
32
|
+
|
33
|
+
it "add attribute" do
|
34
|
+
@r = Twilio::Response.new
|
35
|
+
@r.set :crazy => 'delicious'
|
36
|
+
@r.respond.should == '<Response crazy="delicious"></Response>'
|
37
|
+
end
|
38
|
+
|
39
|
+
it "bad attribute" do
|
40
|
+
bad_attr(Twilio::Response)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe Twilio::Say do
|
46
|
+
include AccountExampleHelperMethods
|
47
|
+
|
48
|
+
it "should say hello monkey" do
|
49
|
+
@r = Twilio::Response.new
|
50
|
+
@r.append(Twilio::Say.new("Hello Monkey"))
|
51
|
+
@r.respond.should == '<Response><Say>Hello Monkey</Say></Response>'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should say hello monkey and loop 3 times" do
|
55
|
+
@r = Twilio::Response.new
|
56
|
+
@r.append(Twilio::Say.new("Hello Monkey", :loop => 3))
|
57
|
+
@r.respond.should == '<Response><Say loop="3">Hello Monkey</Say></Response>'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should say have a woman say hello monkey and loop 3 times" do
|
61
|
+
@r = Twilio::Response.new
|
62
|
+
@r.append(Twilio::Say.new("Hello Monkey", :voice => 'woman'))
|
63
|
+
@r.respond.should == '<Response><Say voice="woman">Hello Monkey</Say></Response>'
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should say have a woman say hello monkey and loop 3 times and be in french" do
|
67
|
+
@r = Twilio::Response.new
|
68
|
+
@r.append(Twilio::Say.new("Hello Monkey", :language => 'fr'))
|
69
|
+
@r.respond.should == '<Response><Say language="fr">Hello Monkey</Say></Response>'
|
70
|
+
end
|
71
|
+
|
72
|
+
it "convenience method: should say have a woman say hello monkey and loop 3 times and be in french" do
|
73
|
+
@r = Twilio::Response.new
|
74
|
+
@r.addSay "Hello Monkey", :language => 'fr'
|
75
|
+
@r.respond.should == '<Response><Say language="fr">Hello Monkey</Say></Response>'
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should raises exceptions for wrong appending" do
|
79
|
+
@r = Twilio::Response.new
|
80
|
+
@s = @r.append(Twilio::Say.new("Hello Monkey"))
|
81
|
+
bad_append @s
|
82
|
+
end
|
83
|
+
|
84
|
+
it "add attribute" do
|
85
|
+
@r = Twilio::Say.new
|
86
|
+
@r.set :crazy => 'delicious'
|
87
|
+
@r.respond.should == '<Say crazy="delicious"></Say>'
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
describe Twilio::Play do
|
93
|
+
include AccountExampleHelperMethods
|
94
|
+
|
95
|
+
it "should play hello monkey" do
|
96
|
+
@r = Twilio::Response.new
|
97
|
+
@r.append(Twilio::Play.new("Hello Monkey.mp3"))
|
98
|
+
@r.respond.should == '<Response><Play>Hello Monkey.mp3</Play></Response>'
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should play hello monkey" do
|
102
|
+
@r = Twilio::Response.new
|
103
|
+
@r.append(Twilio::Play.new("Hello Monkey.mp3", :loop => '3'))
|
104
|
+
@r.respond.should == '<Response><Play loop="3">Hello Monkey.mp3</Play></Response>'
|
105
|
+
end
|
106
|
+
|
107
|
+
it "convenience method: should play hello monkey" do
|
108
|
+
@r = Twilio::Response.new
|
109
|
+
@r.addPlay "Hello Monkey.mp3", :loop => '3'
|
110
|
+
@r.respond.should == '<Response><Play loop="3">Hello Monkey.mp3</Play></Response>'
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should raises exceptions for wrong appending" do
|
114
|
+
@r = Twilio::Response.new
|
115
|
+
@s = @r.append(Twilio::Play.new("Hello Monkey.mp3", :loop => '3'))
|
116
|
+
bad_append @s
|
117
|
+
end
|
118
|
+
|
119
|
+
it "add attribute" do
|
120
|
+
@r = Twilio::Play.new
|
121
|
+
@r.set :crazy => 'delicious'
|
122
|
+
@r.respond.should == '<Play crazy="delicious"></Play>'
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
describe Twilio::Record do
|
128
|
+
include AccountExampleHelperMethods
|
129
|
+
|
130
|
+
it "should record" do
|
131
|
+
@r = Twilio::Response.new
|
132
|
+
@r.append(Twilio::Record.new())
|
133
|
+
@r.respond.should == '<Response><Record></Record></Response>'
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should record with an action and a get method" do
|
137
|
+
r = Twilio::Response.new
|
138
|
+
r.append(Twilio::Record.new(:action => "example.com", :method => 'GET'))
|
139
|
+
r.respond.should == '<Response><Record action="example.com" method="GET"></Record></Response>'
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should record with an maxlength, finishonkey, and timeout" do
|
143
|
+
r = Twilio::Response.new
|
144
|
+
r.append(Twilio::Record.new(:timeout => "4", :finishOnKey => '#', :maxLength => "30"))
|
145
|
+
r.respond.should == '<Response><Record timeout="4" finishOnKey="#" maxLength="30"></Record></Response>'
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should record with a transcribe and transcribeCallback" do
|
149
|
+
r = Twilio::Response.new
|
150
|
+
r.append(Twilio::Record.new(:transcribeCallback => 'example.com'))
|
151
|
+
r.respond.should == '<Response><Record transcribeCallback="example.com"></Record></Response>'
|
152
|
+
end
|
153
|
+
|
154
|
+
it "convenience methods: should record with a transcribe and transcribeCallback" do
|
155
|
+
r = Twilio::Response.new
|
156
|
+
r.addRecord :transcribeCallback => 'example.com'
|
157
|
+
r.respond.should == '<Response><Record transcribeCallback="example.com"></Record></Response>'
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should raises exceptions for wrong appending" do
|
161
|
+
@r = Twilio::Response.new
|
162
|
+
@s = @r.append(Twilio::Record.new())
|
163
|
+
bad_append @s
|
164
|
+
end
|
165
|
+
|
166
|
+
it "add attribute" do
|
167
|
+
@r = Twilio::Record.new
|
168
|
+
@r.set :crazy => 'delicious'
|
169
|
+
@r.respond.should == '<Record crazy="delicious"></Record>'
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
describe Twilio::Redirect do
|
176
|
+
include AccountExampleHelperMethods
|
177
|
+
|
178
|
+
it "should redirect" do
|
179
|
+
@r = Twilio::Response.new
|
180
|
+
@r.append(Twilio::Redirect.new())
|
181
|
+
@r.respond.should == '<Response><Redirect></Redirect></Response>'
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should redirect to a url via POST" do
|
185
|
+
@r = Twilio::Response.new
|
186
|
+
@r.append(Twilio::Redirect.new("example.com", :method => "POST"))
|
187
|
+
@r.respond.should == '<Response><Redirect method="POST">example.com</Redirect></Response>'
|
188
|
+
end
|
189
|
+
|
190
|
+
it "convenience: should redirect to a url via POST" do
|
191
|
+
@r = Twilio::Response.new
|
192
|
+
@r.addRedirect "example.com", :method => "POST"
|
193
|
+
@r.respond.should == '<Response><Redirect method="POST">example.com</Redirect></Response>'
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should raises exceptions for wrong appending" do
|
197
|
+
@r = Twilio::Response.new
|
198
|
+
@s = @r.append(Twilio::Redirect.new())
|
199
|
+
bad_append @s
|
200
|
+
end
|
201
|
+
|
202
|
+
it "add attribute" do
|
203
|
+
@r = Twilio::Redirect.new
|
204
|
+
@r.set :crazy => 'delicious'
|
205
|
+
@r.respond.should == '<Redirect crazy="delicious"></Redirect>'
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
describe Twilio::Hangup do
|
212
|
+
include AccountExampleHelperMethods
|
213
|
+
|
214
|
+
it "should redirect" do
|
215
|
+
@r = Twilio::Response.new
|
216
|
+
@r.append(Twilio::Hangup.new())
|
217
|
+
@r.respond.should == '<Response><Hangup></Hangup></Response>'
|
218
|
+
end
|
219
|
+
|
220
|
+
it "convenience: should Hangup to a url via POST" do
|
221
|
+
@r = Twilio::Response.new
|
222
|
+
@r.addHangup
|
223
|
+
@r.respond.should == '<Response><Hangup></Hangup></Response>'
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should raises exceptions for wrong appending" do
|
227
|
+
@r = Twilio::Response.new
|
228
|
+
@s = @r.append(Twilio::Hangup.new())
|
229
|
+
bad_append @s
|
230
|
+
end
|
231
|
+
|
232
|
+
it "add attribute" do
|
233
|
+
@r = Twilio::Hangup.new
|
234
|
+
@r.set :crazy => 'delicious'
|
235
|
+
@r.respond.should == '<Hangup crazy="delicious"></Hangup>'
|
236
|
+
end
|
237
|
+
|
238
|
+
end
|
239
|
+
|
240
|
+
describe Twilio::Pause do
|
241
|
+
include AccountExampleHelperMethods
|
242
|
+
|
243
|
+
it "should redirect" do
|
244
|
+
@r = Twilio::Response.new
|
245
|
+
@r.append(Twilio::Pause.new())
|
246
|
+
@r.respond.should == '<Response><Pause></Pause></Response>'
|
247
|
+
end
|
248
|
+
|
249
|
+
it "convenience: should Pause to a url via POST" do
|
250
|
+
@r = Twilio::Response.new
|
251
|
+
@r.addPause :length => '4'
|
252
|
+
@r.respond.should == '<Response><Pause length="4"></Pause></Response>'
|
253
|
+
end
|
254
|
+
|
255
|
+
it "should raises exceptions for wrong appending" do
|
256
|
+
@r = Twilio::Response.new
|
257
|
+
@s = @r.append(Twilio::Pause.new())
|
258
|
+
bad_append @s
|
259
|
+
end
|
260
|
+
|
261
|
+
it "add attribute" do
|
262
|
+
@r = Twilio::Pause.new
|
263
|
+
@r.set :crazy => 'delicious'
|
264
|
+
@r.respond.should == '<Pause crazy="delicious"></Pause>'
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
describe Twilio::Dial do
|
270
|
+
include AccountExampleHelperMethods
|
271
|
+
|
272
|
+
it "should redirect" do
|
273
|
+
@r = Twilio::Response.new
|
274
|
+
@r.append(Twilio::Dial.new("1231231234"))
|
275
|
+
@r.respond.should == '<Response><Dial>1231231234</Dial></Response>'
|
276
|
+
end
|
277
|
+
|
278
|
+
it "convenience: should Hangup to a url via POST" do
|
279
|
+
@r = Twilio::Response.new
|
280
|
+
@r.addDial
|
281
|
+
@r.respond.should == '<Response><Dial></Dial></Response>'
|
282
|
+
end
|
283
|
+
|
284
|
+
it "add a number to a dial" do
|
285
|
+
@r = Twilio::Response.new
|
286
|
+
@d = @r.append(Twilio::Dial.new())
|
287
|
+
@d.append(Twilio::Number.new("1231231234"))
|
288
|
+
@r.respond.should == '<Response><Dial><Number>1231231234</Number></Dial></Response>'
|
289
|
+
end
|
290
|
+
|
291
|
+
it "convenience: add a number to a dial" do
|
292
|
+
@r = Twilio::Response.new
|
293
|
+
@d = @r.addDial
|
294
|
+
@d.addNumber "1231231234"
|
295
|
+
@r.respond.should == '<Response><Dial><Number>1231231234</Number></Dial></Response>'
|
296
|
+
end
|
297
|
+
|
298
|
+
it "add attribute" do
|
299
|
+
@r = Twilio::Dial.new
|
300
|
+
@r.set :crazy => 'delicious'
|
301
|
+
@r.respond.should == '<Dial crazy="delicious"></Dial>'
|
302
|
+
end
|
303
|
+
|
304
|
+
it "bad append" do
|
305
|
+
verb = Twilio::Dial.new
|
306
|
+
lambda {verb.append(Twilio::Response)}.should raise_error(ArgumentError)
|
307
|
+
lambda {verb.append(Twilio::Say)}.should raise_error(ArgumentError)
|
308
|
+
lambda {verb.append(Twilio::Play)}.should raise_error(ArgumentError)
|
309
|
+
lambda {verb.append(Twilio::Gather)}.should raise_error(ArgumentError)
|
310
|
+
lambda {verb.append(Twilio::Record)}.should raise_error(ArgumentError)
|
311
|
+
lambda {verb.append(Twilio::Redirect)}.should raise_error(ArgumentError)
|
312
|
+
lambda {verb.append(Twilio::Hangup)}.should raise_error(ArgumentError)
|
313
|
+
lambda {verb.append(Twilio::Pause)}.should raise_error(ArgumentError)
|
314
|
+
end
|
315
|
+
|
316
|
+
end
|
317
|
+
|
318
|
+
describe Twilio::Gather do
|
319
|
+
include AccountExampleHelperMethods
|
320
|
+
|
321
|
+
it "should redirect" do
|
322
|
+
@r = Twilio::Response.new
|
323
|
+
@r.append(Twilio::Gather.new("1231231234"))
|
324
|
+
@r.respond.should == '<Response><Gather>1231231234</Gather></Response>'
|
325
|
+
end
|
326
|
+
|
327
|
+
it "convenience: should Hangup to a url via POST" do
|
328
|
+
@r = Twilio::Response.new
|
329
|
+
@r.addGather
|
330
|
+
@r.respond.should == '<Response><Gather></Gather></Response>'
|
331
|
+
end
|
332
|
+
|
333
|
+
it "add a number to a Gather" do
|
334
|
+
@r = Twilio::Response.new
|
335
|
+
@g = @r.append(Twilio::Gather.new)
|
336
|
+
@g.append(Twilio::Say.new("Hello World"))
|
337
|
+
@g.append(Twilio::Play.new("Hello World.mp3"))
|
338
|
+
@g.append(Twilio::Pause.new)
|
339
|
+
@r.respond.should == '<Response><Gather><Say>Hello World</Say><Play>Hello World.mp3</Play><Pause></Pause></Gather></Response>'
|
340
|
+
end
|
341
|
+
|
342
|
+
it "convenience: add a number to a Gather" do
|
343
|
+
@r = Twilio::Response.new
|
344
|
+
@g = @r.addGather
|
345
|
+
@g.addSay "Hello World"
|
346
|
+
@g.addPlay "Hello World.mp3"
|
347
|
+
@g.addPause
|
348
|
+
@r.respond.should == '<Response><Gather><Say>Hello World</Say><Play>Hello World.mp3</Play><Pause></Pause></Gather></Response>'
|
349
|
+
end
|
350
|
+
|
351
|
+
it "add attribute" do
|
352
|
+
@r = Twilio::Gather.new
|
353
|
+
@r.set :crazy => 'delicious'
|
354
|
+
@r.respond.should == '<Gather crazy="delicious"></Gather>'
|
355
|
+
end
|
356
|
+
|
357
|
+
it "bad append" do
|
358
|
+
verb = Twilio::Gather.new
|
359
|
+
lambda {verb.append(Twilio::Response)}.should raise_error(ArgumentError)
|
360
|
+
lambda {verb.append(Twilio::Gather)}.should raise_error(ArgumentError)
|
361
|
+
lambda {verb.append(Twilio::Record)}.should raise_error(ArgumentError)
|
362
|
+
lambda {verb.append(Twilio::Redirect)}.should raise_error(ArgumentError)
|
363
|
+
lambda {verb.append(Twilio::Hangup)}.should raise_error(ArgumentError)
|
364
|
+
end
|
365
|
+
|
366
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: Derferman-twilio
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kyle Conroy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-05-16 00:00:00 -07: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:
|
26
|
+
email: kjconroy@twilio.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README
|
33
|
+
files:
|
34
|
+
- LICENSE
|
35
|
+
- README
|
36
|
+
- Changelog
|
37
|
+
- example-rest.rb
|
38
|
+
- example-twiml.rb
|
39
|
+
- lib/twilio.rb
|
40
|
+
- Rakefile
|
41
|
+
has_rdoc: true
|
42
|
+
homepage: http://www.twilio.com/docs
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
version:
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
version:
|
60
|
+
requirements: []
|
61
|
+
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 1.2.0
|
64
|
+
signing_key:
|
65
|
+
specification_version: 2
|
66
|
+
summary: Some description
|
67
|
+
test_files:
|
68
|
+
- tests/response_spec.rb
|