dancroak-twilio 2.3.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 (45) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +39 -0
  3. data/Rakefile +49 -0
  4. data/VERSION.yml +4 -0
  5. data/lib/twilio.rb +42 -0
  6. data/lib/twilio/account.rb +12 -0
  7. data/lib/twilio/call.rb +33 -0
  8. data/lib/twilio/connection.rb +24 -0
  9. data/lib/twilio/incoming_phone_number.rb +16 -0
  10. data/lib/twilio/local_phone_number.rb +21 -0
  11. data/lib/twilio/notification.rb +20 -0
  12. data/lib/twilio/outgoing_caller_id.rb +32 -0
  13. data/lib/twilio/recording.rb +24 -0
  14. data/lib/twilio/toll_free_phone_number.rb +21 -0
  15. data/lib/twilio/twilio_object.rb +16 -0
  16. data/lib/twilio/verb.rb +315 -0
  17. data/test/fixtures/xml/account.xml +11 -0
  18. data/test/fixtures/xml/account_renamed.xml +11 -0
  19. data/test/fixtures/xml/call.xml +18 -0
  20. data/test/fixtures/xml/call_new.xml +14 -0
  21. data/test/fixtures/xml/calls.xml +36 -0
  22. data/test/fixtures/xml/incoming_phone_number.xml +12 -0
  23. data/test/fixtures/xml/incoming_phone_numbers.xml +24 -0
  24. data/test/fixtures/xml/notification.xml +19 -0
  25. data/test/fixtures/xml/notifications.xml +32 -0
  26. data/test/fixtures/xml/outgoing_caller_id.xml +10 -0
  27. data/test/fixtures/xml/outgoing_caller_id_new.xml +7 -0
  28. data/test/fixtures/xml/outgoing_caller_ids.xml +20 -0
  29. data/test/fixtures/xml/recording.xml +10 -0
  30. data/test/fixtures/xml/recordings.xml +20 -0
  31. data/test/fixtures/xml/transcription.xml +13 -0
  32. data/test/fixtures/xml/transcriptions.xml +26 -0
  33. data/test/fixtures/yml/verb_responses.yml +119 -0
  34. data/test/test_helper.rb +29 -0
  35. data/test/twilio/account_test.rb +35 -0
  36. data/test/twilio/call_test.rb +72 -0
  37. data/test/twilio/connection_test.rb +26 -0
  38. data/test/twilio/incoming_phone_number_test.rb +35 -0
  39. data/test/twilio/local_phone_number_test.rb +35 -0
  40. data/test/twilio/notification_test.rb +40 -0
  41. data/test/twilio/outgoing_caller_id_test.rb +51 -0
  42. data/test/twilio/recording_test.rb +53 -0
  43. data/test/twilio/toll_free_phone_number_test.rb +35 -0
  44. data/test/twilio/verb_test.rb +204 -0
  45. metadata +127 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Phil Misiowiec, Webficient LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,39 @@
1
+ = Twilio Gem
2
+
3
+ The Twilio gem provides two major pieces of functionality: (1) a Ruby wrapper for the Twilio REST API and (2) response handlers based on the Twilio Markup XML (TwiML).
4
+
5
+ See http://www.twilio.com/docs/index for Twilio's API documentation.
6
+
7
+ For an overview of the Twilio Gem and a sample use case, check out http://www.webficient.com/2009/06/22/hello-this-is-your-rails-app-calling-you.
8
+
9
+ == Calling the Twilio REST API
10
+
11
+ First set your credentials by calling the connect method:
12
+
13
+ Twilio.connect('my_twilio_sid', 'my_auth_token')
14
+
15
+ Now call any of the Twilio classes:
16
+
17
+ Twilio::Call.make('1234567890', '9876543210', 'http://mysite.com/connected_call')
18
+ Twilio::Recording.list
19
+
20
+ == Responding to Twilio
21
+
22
+ When Twilio calls your application URL, your response must use the Twilio Markup XML (http://www.twilio.com/docs/api_reference/TwiML/). The Twilio gem makes this very easy
23
+ by providing a Twilio Verb class.
24
+
25
+ For example, in a Ruby on Rails application, you could do the following inside a controller class:
26
+
27
+ Twilio::Verb.dial('415-123-4567')
28
+
29
+ and you can nest multiple verbs inside a block:
30
+
31
+ verb = Twilio::Verb.new { |v|
32
+ v.say("The time is #{Time.now}")
33
+ v.hangup
34
+ }
35
+ verb.response
36
+
37
+ == Copyright
38
+
39
+ Copyright (c) 2009 Phil Misiowiec, Webficient LLC. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "twilio"
8
+ gem.summary = %Q{Twilio API Client}
9
+ gem.email = "github@webficient.com"
10
+ gem.homepage = "http://github.com/webficient/twilio"
11
+ gem.authors = ["Phil Misiowiec"]
12
+ gem.add_dependency 'builder'
13
+ gem.add_dependency 'httparty'
14
+ end
15
+ rescue LoadError
16
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
17
+ end
18
+
19
+ require 'rake/rdoctask'
20
+ Rake::RDocTask.new do |rdoc|
21
+ rdoc.rdoc_dir = 'rdoc'
22
+ rdoc.title = 'twilio'
23
+ rdoc.options << '--line-numbers' << '--inline-source'
24
+ rdoc.rdoc_files.include('README*')
25
+ rdoc.rdoc_files.include('lib/**/*.rb')
26
+ end
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/*_test.rb'
32
+ test.verbose = false
33
+ end
34
+
35
+ begin
36
+ require 'rcov/rcovtask'
37
+ Rcov::RcovTask.new do |test|
38
+ test.libs << 'test'
39
+ test.pattern = 'test/**/*_test.rb'
40
+ test.verbose = true
41
+ end
42
+ rescue LoadError
43
+ task :rcov do
44
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
45
+ end
46
+ end
47
+
48
+
49
+ task :default => :test
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 0
3
+ :major: 2
4
+ :minor: 3
data/lib/twilio.rb ADDED
@@ -0,0 +1,42 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+
3
+ #--
4
+ # Copyright (c) 2009 Phil Misiowiec, phil@webficient.com
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #++
25
+
26
+ require 'rubygems'
27
+ gem 'httparty', '>= 0.4.3'
28
+ require 'httparty'
29
+ gem 'builder', '>= 2.1.2'
30
+ require 'builder'
31
+
32
+ require 'twilio/twilio_object'
33
+ require 'twilio/account'
34
+ require 'twilio/call'
35
+ require 'twilio/connection'
36
+ require 'twilio/incoming_phone_number'
37
+ require 'twilio/local_phone_number'
38
+ require 'twilio/notification'
39
+ require 'twilio/outgoing_caller_id'
40
+ require 'twilio/recording'
41
+ require 'twilio/toll_free_phone_number'
42
+ require 'twilio/verb'
@@ -0,0 +1,12 @@
1
+ module Twilio
2
+ # The Account resource represents your Twilio Account.
3
+ class Account < TwilioObject
4
+ def get
5
+ Twilio.get('')
6
+ end
7
+
8
+ def update_name(name)
9
+ Twilio.put('', :body => {:FriendlyName => name})
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,33 @@
1
+ module Twilio
2
+ # A Call represenents a connection between a telephone and Twilio. This may be
3
+ # inbound, when a person calls your application, or outbound when your application
4
+ # initiates the call, either via the REST API, or during a call via the Dial Verb.
5
+ class Call < TwilioObject
6
+ # Example:
7
+ # Twilio.connect('my_twilio_sid', 'my_auth_token')
8
+ # Twilio::Call.make(CALLER_ID, user_number, 'http://myapp.com/twilio_response_handler')
9
+ def make(caller, called, url, optional = {})
10
+ Twilio.post("/Calls", :body => {:Caller => caller, :Called => called, :Url => url}.merge(optional))
11
+ end
12
+
13
+ def list(optional = {})
14
+ Twilio.get("/Calls", :query => optional)
15
+ end
16
+
17
+ def get(call_sid)
18
+ Twilio.get("/Calls/#{call_sid}")
19
+ end
20
+
21
+ def segments(call_sid, call_segment_sid = nil)
22
+ Twilio.get("/Calls/#{call_sid}/Segments#{ '/' + call_segment_sid if call_segment_sid }")
23
+ end
24
+
25
+ def recordings(call_sid)
26
+ Twilio.get("/Calls/#{call_sid}/Recordings")
27
+ end
28
+
29
+ def notifications(call_sid)
30
+ Twilio.get("/Calls/#{call_sid}/Notifications")
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,24 @@
1
+ module Twilio
2
+ include HTTParty
3
+ TWILIO_URL = "https://api.twilio.com/2008-08-01/Accounts"
4
+
5
+ # The connect method caches your Twilio account id and authentication token
6
+ # Example:
7
+ # Twilio.connect('AC309475e5fede1b49e100272a8640f438', '3a2630a909aadbf60266234756fb15a0')
8
+ def self.connect(account_sid, auth_token)
9
+ self.base_uri "#{TWILIO_URL}/#{account_sid}"
10
+ self.basic_auth account_sid, auth_token
11
+ end
12
+
13
+ # DEPRECATED - use Twilio.connect
14
+ class Connection
15
+ include HTTParty
16
+ TWILIO_URL = "https://api.twilio.com/2008-08-01/Accounts"
17
+
18
+ def initialize(account_sid, auth_token)
19
+ self.class.base_uri "#{TWILIO_URL}/#{account_sid}"
20
+ self.class.basic_auth account_sid, auth_token
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,16 @@
1
+ module Twilio
2
+ # An IncomingPhoneNumber resource represents a phone number given to you by
3
+ # Twilio to receive incoming phone calls.
4
+ # Example:
5
+ # Twilio.connect('my_twilio_sid', 'my_auth_token')
6
+ # Twilio::IncomingPhoneNumber.list
7
+ class IncomingPhoneNumber < TwilioObject
8
+ def list(optional = {})
9
+ Twilio.get("/IncomingPhoneNumbers", :query => optional)
10
+ end
11
+
12
+ def get(incoming_sid)
13
+ Twilio.get("/IncomingPhoneNumbers/#{incoming_sid}")
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ module Twilio
2
+ # This sub-resource represents only Local phone numbers, or in other words, not toll-free numbers.
3
+ # Also allows you to request a new local phone number be added to your account.
4
+ # Example:
5
+ # Twilio.connect('my_twilio_sid', 'my_auth_token')
6
+ # Twilio::LocalPhoneNumber.list
7
+ class LocalPhoneNumber < TwilioObject
8
+ def create(url, area_code = nil, method = 'POST', friendly_name = nil)
9
+ Twilio.post("/IncomingPhoneNumbers/Local", :body => {
10
+ :Url => url,
11
+ :AreaCode => area_code,
12
+ :Method => method,
13
+ :FriendlyName => friendly_name
14
+ })
15
+ end
16
+
17
+ def list
18
+ Twilio.get("/IncomingPhoneNumbers/Local")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ module Twilio
2
+ # A Notification represenents a log entry made by Twilio in the course of handling
3
+ # your calls or using the REST API.
4
+ # Example:
5
+ # Twilio.connect('my_twilio_sid', 'my_auth_token')
6
+ # Twilio::Notification.list
7
+ class Notification < TwilioObject
8
+ def list(optional = {})
9
+ Twilio.get('/Notifications', :query => optional)
10
+ end
11
+
12
+ def get(notification_sid)
13
+ Twilio.get("/Notifications/#{notification_sid}")
14
+ end
15
+
16
+ def delete(notification_sid)
17
+ Twilio.delete("/Notifications/#{notification_sid}")
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,32 @@
1
+ module Twilio
2
+ # An OutgoingCallerId resource represents an outgoing Caller ID that you have
3
+ # registered with Twilio for use when making an outgoing call or using the Dial Verb.
4
+ # Example:
5
+ # Twilio.connect('my_twilio_sid', 'my_auth_token')
6
+ # Twilio::OutgoingCallerId.list
7
+ class OutgoingCallerId < TwilioObject
8
+ def create(phone_number, friendly_name = phone_number, call_delay = 0)
9
+ Twilio.post("/OutgoingCallerIds", :body => {
10
+ :PhoneNumber => phone_number,
11
+ :FriendlyName => friendly_name,
12
+ :CallDelay => call_delay
13
+ })
14
+ end
15
+
16
+ def list(optional = {})
17
+ Twilio.get("/OutgoingCallerIds", :query => optional)
18
+ end
19
+
20
+ def get(callerid_sid)
21
+ Twilio.get("/OutgoingCallerIds/#{callerid_sid}")
22
+ end
23
+
24
+ def update_name(callerid_sid, name)
25
+ Twilio.put("/OutgoingCallerIds/#{callerid_sid}", :body => {:FriendlyName => name})
26
+ end
27
+
28
+ def delete(callerid_sid)
29
+ Twilio.delete("/OutgoingCallerIds/#{callerid_sid}")
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,24 @@
1
+ module Twilio
2
+ # Recordings are generated when you use the Record Verb. Those recordings are
3
+ # hosted on Twilio's REST API for you to access.
4
+ # Example:
5
+ # Twilio.connect('my_twilio_sid', 'my_auth_token')
6
+ # Twilio::Recording.list
7
+ class Recording < TwilioObject
8
+ def list(optional = {})
9
+ Twilio.get("/Recordings", :query => optional)
10
+ end
11
+
12
+ def get(recording_sid)
13
+ Twilio.get("/Recordings/#{recording_sid}")
14
+ end
15
+
16
+ def delete(recording_sid)
17
+ Twilio.delete("/Recordings/#{recording_sid}")
18
+ end
19
+
20
+ def transcriptions(recording_sid, transcription_sid = nil)
21
+ Twilio.get("/Recordings/#{recording_sid}/Transcriptions#{ '/' + transcription_sid if transcription_sid }")
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ module Twilio
2
+ # This sub-resource represents only Toll Free phone numbers, or in other words, not local numbers.
3
+ # Also allows you to request a new toll free phone number be added to your account.
4
+ # Example:
5
+ # Twilio.connect('my_twilio_sid', 'my_auth_token')
6
+ # Twilio::TollFreePhoneNumber.list
7
+ class TollFreePhoneNumber < TwilioObject
8
+ def create(url, area_code = nil, method = 'POST', friendly_name = nil)
9
+ Twilio.post("/IncomingPhoneNumbers/TollFree", :body => {
10
+ :Url => url,
11
+ :AreaCode => area_code,
12
+ :Method => method,
13
+ :FriendlyName => friendly_name
14
+ })
15
+ end
16
+
17
+ def list
18
+ Twilio.get("/IncomingPhoneNumbers/TollFree")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ module Twilio
2
+ class TwilioObject #:nodoc: all
3
+ attr_reader :connection
4
+
5
+ def initialize(connection = nil)
6
+ @connection = connection
7
+ end
8
+
9
+ class << self
10
+ def method_missing(method_id, *args) #:nodoc:
11
+ o = self.new
12
+ o.send(method_id, *args)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,315 @@
1
+ module Twilio
2
+ # Twilio Verbs enable your application to respond to Twilio requests (to your app) with XML responses.
3
+ # There are 5 primary verbs (say, play, gather, record, dial) and 3 secondary (hangup, pause, redirect).
4
+ # Verbs can be chained and, in some cases, nested.
5
+ #
6
+ # If your response consists of a single verb, you can call a Verb class method:
7
+ #
8
+ # Twilio::Verb.say('The time is 9:35 PM.')
9
+ #
10
+ # But if you need to chain several verbs together, just wrap them in an instance block and call the 'response' attribute:
11
+ #
12
+ # verb = Twilio::Verb.new { |v|
13
+ # v.dial('415-123-4567')
14
+ # v.redirect('http://www.foo.com/nextInstructions')
15
+ # }
16
+ # verb.response
17
+ class Verb
18
+
19
+ attr_reader :response
20
+
21
+ class << self
22
+ def method_missing(method_id, *args) #:nodoc:
23
+ v = Verb.new
24
+ v.send(method_id, *args)
25
+ end
26
+ end
27
+
28
+ def initialize(&block)
29
+ @xml = Builder::XmlMarkup.new
30
+ @xml.instruct!
31
+
32
+ if block_given?
33
+ @chain = true
34
+ @response = @xml.Response { block.call(self) }
35
+ end
36
+ end
37
+
38
+ # The Say verb converts text to speech that is read back to the caller.
39
+ # Say is useful for dynamic text that is difficult to prerecord.
40
+ #
41
+ # Examples:
42
+ # Twilio::Verb.say('The time is 9:35 PM.')
43
+ # Twilio::Verb.say('The time is 9:35 PM.', :loop => 3)
44
+ #
45
+ # With numbers, 12345 will be spoken as "twelve thousand three hundred forty five" while
46
+ # 1 2 3 4 5 will be spoken as "one two three four five."
47
+ #
48
+ # Twilio::Verb.say('Your PIN is 1234', :loop => 4)
49
+ # Twilio::Verb.say('Your PIN is 1 2 3 4', :loop => 4)
50
+ #
51
+ # If you need a longer pause between each loop, instead of explicitly calling the Pause
52
+ # verb within a block, you can set the convenient pause option:
53
+ #
54
+ # Twilio::Verb.say('Your PIN is 1 2 3 4', :loop => 4, :pause => true)
55
+ #
56
+ # Options (see http://www.twilio.com/docs/api_reference/TwiML/say) are passed in as a hash:
57
+ #
58
+ # Twilio::Verb.say('The time is 9:35 PM.', :voice => 'woman')
59
+ # Twilio::Verb.say('The time is 9:35 PM.', {:voice => 'woman', :language => 'es'})
60
+ def say(*args)
61
+ options = {:voice => 'man', :language => 'en', :loop => 1}
62
+ args.each do |arg|
63
+ case arg
64
+ when String
65
+ options[:text_to_speak] = arg
66
+ when Hash
67
+ options.merge!(arg)
68
+ else
69
+ raise ArgumentError, 'say expects String or Hash argument'
70
+ end
71
+ end
72
+
73
+ output {
74
+ if options[:pause]
75
+ loop_with_pause(options[:loop], @xml) do
76
+ @xml.Say(options[:text_to_speak], :voice => options[:voice], :language => options[:language])
77
+ end
78
+ else
79
+ @xml.Say(options[:text_to_speak], :voice => options[:voice], :language => options[:language], :loop => options[:loop])
80
+ end
81
+ }
82
+ end
83
+
84
+ # The Play verb plays an audio URL back to the caller.
85
+ # Examples:
86
+ # Twilio::Verb.play('http://foo.com/cowbell.mp3')
87
+ # Twilio::Verb.play('http://foo.com/cowbell.mp3', :loop => 3)
88
+ #
89
+ # If you need a longer pause between each loop, instead of explicitly calling the Pause
90
+ # verb within a block, you can set the convenient pause option:
91
+ #
92
+ # Twilio::Verb.play('http://foo.com/cowbell.mp3', :loop => 3, :pause => true)
93
+ #
94
+ # Options (see http://www.twilio.com/docs/api_reference/TwiML/play) are passed in as a hash,
95
+ # but only 'loop' is currently supported.
96
+ def play(*args)
97
+ options = {:loop => 1}
98
+ args.each do |arg|
99
+ case arg
100
+ when String
101
+ options[:audio_url] = arg
102
+ when Hash
103
+ options.merge!(arg)
104
+ else
105
+ raise ArgumentError, 'play expects String or Hash argument'
106
+ end
107
+ end
108
+
109
+ output {
110
+ if options[:pause]
111
+ loop_with_pause(options[:loop], @xml) do
112
+ @xml.Play(options[:audio_url])
113
+ end
114
+ else
115
+ @xml.Play(options[:audio_url], :loop => options[:loop])
116
+ end
117
+ }
118
+ end
119
+
120
+ # The Gather verb collects digits entered by a caller into their telephone keypad.
121
+ # When the caller is done entering data, Twilio submits that data to a provided URL,
122
+ # as either a HTTP GET or POST request, just like a web browser submits data from an HTML form.
123
+ #
124
+ # Options (see http://www.twilio.com/docs/api_reference/TwiML/gather) are passed in as a hash
125
+ #
126
+ # Examples:
127
+ # Twilio::Verb.gather
128
+ # Twilio::Verb.gather(:action => 'http://foobar.com')
129
+ # Twilio::Verb.gather(:finishOnKey => '*')
130
+ # Twilio::Verb.gather(:action => 'http://foobar.com', :finishOnKey => '*')
131
+ #
132
+ # Gather also lets you nest the Play, Say, and Pause verbs:
133
+ #
134
+ # verb = Twilio::Verb.new { |v|
135
+ # v.gather(:action => '/process_gather', :method => 'GET) {
136
+ # v.say('Please enter your account number followed by the pound sign')
137
+ # }
138
+ # v.say("We didn't receive any input. Goodbye!")
139
+ # }
140
+ # verb.response # represents the final xml output
141
+ def gather(*args, &block)
142
+ options = args.shift || {}
143
+ output {
144
+ if block_given?
145
+ @xml.Gather(options) { block.call }
146
+ else
147
+ @xml.Gather(options)
148
+ end
149
+ }
150
+ end
151
+
152
+ #play, say, pause
153
+
154
+ # The Record verb records the caller's voice and returns a URL that links to a file
155
+ # containing the audio recording.
156
+ #
157
+ # Options (see http://www.twilio.com/docs/api_reference/TwiML/record) are passed in as a hash
158
+ #
159
+ # Examples:
160
+ # Twilio::Verb.record
161
+ # Twilio::Verb.record(:action => 'http://foobar.com')
162
+ # Twilio::Verb.record(:finishOnKey => '*')
163
+ # Twilio::Verb.record(:transcribe => true, :transcribeCallback => '/handle_transcribe')
164
+ def record(*args)
165
+ options = args.shift
166
+ output { @xml.Record(options) }
167
+ end
168
+
169
+ # The Dial verb connects the current caller to an another phone. If the called party picks up,
170
+ # the two parties are connected and can communicate until one hangs up. If the called party does
171
+ # not pick up, if a busy signal is received, or the number doesn't exist, the dial verb will finish.
172
+ #
173
+ # If an action verb is provided, Twilio will submit the outcome of the call attempt to the action URL.
174
+ # If no action is provided, Dial will fall through to the next verb in the document.
175
+ #
176
+ # Note: this is different than the behavior of Record and Gather. Dial does not submit back to the
177
+ # current document URL if no action is provided.
178
+ #
179
+ # Options (see http://www.twilio.com/docs/api_reference/TwiML/dial) are passed in as a hash
180
+ #
181
+ # Examples:
182
+ # Twilio::Verb.dial('415-123-4567')
183
+ # Twilio::Verb.dial('415-123-4567', :action => 'http://foobar.com')
184
+ # Twilio::Verb.dial('415-123-4567', {:timeout => 10, :callerId => '858-987-6543'})
185
+ #
186
+ # Twilio also supports an alternate form in which a Number object is nested inside Dial:
187
+ #
188
+ # verb = Twilio::Verb.new { |v|
189
+ # v.dial {
190
+ # v.number('415-123-4567')
191
+ # v.number('415-123-4568')
192
+ # v.number('415-123-4569')
193
+ # }
194
+ # }
195
+ # verb.response # represents the final xml output
196
+ def dial(*args, &block)
197
+ number_to_dial = ''
198
+ options = {}
199
+ args.each do |arg|
200
+ case arg
201
+ when String
202
+ number_to_dial = arg
203
+ when Hash
204
+ options.merge!(arg)
205
+ else
206
+ raise ArgumentError, 'dial expects String or Hash argument'
207
+ end
208
+ end
209
+
210
+ output {
211
+ if block_given?
212
+ @xml.Dial(options) { block.call }
213
+ else
214
+ @xml.Dial(number_to_dial, options)
215
+ end
216
+ }
217
+ end
218
+
219
+ # The Pause (secondary) verb waits silently for a number of seconds.
220
+ # It is normally chained with other verbs.
221
+ #
222
+ # Options (see http://www.twilio.com/docs/api_reference/TwiML/pause) are passed in as a hash
223
+ #
224
+ # Examples:
225
+ # verb = Twilio::Verb.new { |v|
226
+ # v.say('greetings')
227
+ # v.pause(:length => 2)
228
+ # v.say('have a nice day')
229
+ # }
230
+ # verb.response
231
+ def pause(*args)
232
+ options = args.shift
233
+ output { @xml.Pause(options) }
234
+ end
235
+
236
+ # The Redirect (secondary) verb transfers control to a different URL.
237
+ # It is normally chained with other verbs.
238
+ #
239
+ # Options (see http://www.twilio.com/docs/api_reference/TwiML/redirect) are passed in as a hash
240
+ #
241
+ # Examples:
242
+ # verb = Twilio::Verb.new { |v|
243
+ # v.dial('415-123-4567')
244
+ # v.redirect('http://www.foo.com/nextInstructions')
245
+ # }
246
+ # verb.response
247
+ def redirect(*args)
248
+ redirect_to_url = ''
249
+ options = {}
250
+ args.each do |arg|
251
+ case arg
252
+ when String
253
+ redirect_to_url = arg
254
+ when Hash
255
+ options.merge!(arg)
256
+ else
257
+ raise ArgumentError, 'dial expects String or Hash argument'
258
+ end
259
+ end
260
+
261
+ output { @xml.Redirect(redirect_to_url, options) }
262
+ end
263
+
264
+ # The Hangup (secondary) verb ends the call.
265
+ #
266
+ # Examples:
267
+ # If your response is only a hangup:
268
+ #
269
+ # Twilio::Verb.hangup
270
+ #
271
+ # If your response is chained:
272
+ #
273
+ # verb = Twilio::Verb.new { |v|
274
+ # v.say("The time is #{Time.now}")
275
+ # v.hangup
276
+ # }
277
+ # verb.response
278
+ def hangup
279
+ output { @xml.Hangup }
280
+ end
281
+
282
+ # The Number element specifies a phone number. The number element has two optional attributes: sendDigits and url.
283
+ # Number elements can only be nested in Dial verbs
284
+ def number(*args)
285
+ number_to_dial = ''
286
+ options = {}
287
+ args.each do |arg|
288
+ case arg
289
+ when String
290
+ number_to_dial = arg
291
+ when Hash
292
+ options.merge!(arg)
293
+ else
294
+ raise ArgumentError, 'dial expects String or Hash argument'
295
+ end
296
+ end
297
+
298
+ output { @xml.Number(number_to_dial, options) }
299
+ end
300
+
301
+ private
302
+
303
+ def output
304
+ @chain ? yield : @xml.Response { yield }
305
+ end
306
+
307
+ def loop_with_pause(loop_count, xml, &verb_action)
308
+ last_iteration = loop_count-1
309
+ loop_count.times do |i|
310
+ yield verb_action
311
+ xml.Pause unless i == last_iteration
312
+ end
313
+ end
314
+ end
315
+ end