Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial support for new SMS features

  • Loading branch information...
commit a7fd6aa45d3b8008112a5a4cb25dd63c4b635b4d 1 parent 25fe003
@kdaigle kdaigle authored
View
1  lib/twilio.rb
@@ -26,6 +26,7 @@
require 'twilio/twilio_object'
require 'twilio/account'
require 'twilio/call'
+require 'twilio/sms'
require 'twilio/connection'
require 'twilio/incoming_phone_number'
require 'twilio/local_phone_number'
View
21 lib/twilio/sms.rb
@@ -0,0 +1,21 @@
+module Twilio
+ # An SMS message resource represents an Inbound or Outbound SMS message. When someone sends a text message from
+ # or to your application, either via the REST API, or during a call via the verb, an SMS message resource is created.
+ class Sms < TwilioObject
+ # Example:
+ # Twilio.connect('my_twilio_sid', 'my_auth_token')
+ # Twilio::Sms.message(CALLER_ID, user_number, 'This is my simple SMS message')
+ def message(from, to, body)
+ Twilio.post("/SMS/Messages", :body => {:From => from, :To => to, :Body => body})
+ end
+
+ def list(optional = {})
+ Twilio.get("/SMS/Messages", :query => optional)
+ end
+
+ def get(sms_message_sid)
+ Twilio.get("/SMS/Messages/#{sms_message_sid}")
+ end
+
+ end
+end
View
118 lib/twilio/verb.rb
@@ -15,28 +15,28 @@ module Twilio
# }
# verb.response
class Verb
-
+
attr_reader :response
-
+
class << self
def method_missing(method_id, *args) #:nodoc:
v = Verb.new
v.send(method_id, *args)
end
end
-
+
def initialize(&block)
@xml = Builder::XmlMarkup.new
@xml.instruct!
-
+
if block_given?
@chain = true
@response = @xml.Response { block.call(self) }
end
end
-
- # The Say verb converts text to speech that is read back to the caller.
- # Say is useful for dynamic text that is difficult to prerecord.
+
+ # The Say verb converts text to speech that is read back to the caller.
+ # Say is useful for dynamic text that is difficult to prerecord.
#
# Examples:
# Twilio::Verb.say 'The time is 9:35 PM.'
@@ -47,7 +47,7 @@ def initialize(&block)
#
# Twilio::Verb.say 'Your PIN is 1234', :loop => 4
# Twilio::Verb.say 'Your PIN is 1 2 3 4', :loop => 4
- #
+ #
# If you need a longer pause between each loop, instead of explicitly calling the Pause
# verb within a block, you can set the convenient pause option:
#
@@ -69,7 +69,7 @@ def say(*args)
raise ArgumentError, 'say expects String or Hash argument'
end
end
-
+
output {
if options[:pause]
loop_with_pause(options[:loop], @xml) do
@@ -80,8 +80,8 @@ def say(*args)
end
}
end
-
- # The Play verb plays an audio URL back to the caller.
+
+ # The Play verb plays an audio URL back to the caller.
# Examples:
# Twilio::Verb.play 'http://foo.com/cowbell.mp3'
# Twilio::Verb.play 'http://foo.com/cowbell.mp3', :loop => 3
@@ -113,13 +113,13 @@ def play(*args)
end
else
@xml.Play(options[:audio_url], :loop => options[:loop])
- end
+ end
}
end
-
- # The Gather verb collects digits entered by a caller into their telephone keypad.
- # When the caller is done entering data, Twilio submits that data to a provided URL,
- # as either a HTTP GET or POST request, just like a web browser submits data from an HTML form.
+
+ # The Gather verb collects digits entered by a caller into their telephone keypad.
+ # When the caller is done entering data, Twilio submits that data to a provided URL,
+ # as either a HTTP GET or POST request, just like a web browser submits data from an HTML form.
#
# Options (see http://www.twilio.com/docs/api_reference/TwiML/gather) are passed in as a hash
#
@@ -140,18 +140,18 @@ def play(*args)
# verb.response # represents the final xml output
def gather(*args, &block)
options = args.shift || {}
- output {
+ output {
if block_given?
@xml.Gather(options) { block.call}
else
- @xml.Gather(options)
+ @xml.Gather(options)
end
}
end
-
+
#play, say, pause
-
- # The Record verb records the caller's voice and returns a URL that links to a file
+
+ # The Record verb records the caller's voice and returns a URL that links to a file
# containing the audio recording.
#
# Options (see http://www.twilio.com/docs/api_reference/TwiML/record) are passed in as a hash
@@ -165,15 +165,15 @@ def record(*args)
options = args.shift
output { @xml.Record(options) }
end
-
- # The Dial verb connects the current caller to an another phone. If the called party picks up,
- # the two parties are connected and can communicate until one hangs up. If the called party does
+
+ # The Dial verb connects the current caller to an another phone. If the called party picks up,
+ # the two parties are connected and can communicate until one hangs up. If the called party does
# not pick up, if a busy signal is received, or the number doesn't exist, the dial verb will finish.
#
- # If an action verb is provided, Twilio will submit the outcome of the call attempt to the action URL.
+ # If an action verb is provided, Twilio will submit the outcome of the call attempt to the action URL.
# If no action is provided, Dial will fall through to the next verb in the document.
#
- # Note: this is different than the behavior of Record and Gather. Dial does not submit back to the
+ # Note: this is different than the behavior of Record and Gather. Dial does not submit back to the
# current document URL if no action is provided.
#
# Options (see http://www.twilio.com/docs/api_reference/TwiML/dial) are passed in as a hash
@@ -206,16 +206,16 @@ def dial(*args, &block)
raise ArgumentError, 'dial expects String or Hash argument'
end
end
-
- output {
+
+ output {
if block_given?
@xml.Dial(options) { block.call }
else
- @xml.Dial(number_to_dial, options)
+ @xml.Dial(number_to_dial, options)
end
}
end
-
+
# The <Dial> verb's <Conference> noun allows you to connect to a conference room.
# Much like how the <Number> noun allows you to connect to another phone number,
# the <Conference> noun allows you to connect to a named conference room and talk
@@ -243,12 +243,12 @@ def conference(*args)
raise ArgumentError, 'conference expects String or Hash argument'
end
end
-
+
output { @xml.Conference(conference_name, options)}
end
-
- # The Pause (secondary) verb waits silently for a number of seconds.
- # It is normally chained with other verbs.
+
+ # The Pause (secondary) verb waits silently for a number of seconds.
+ # It is normally chained with other verbs.
#
# Options (see http://www.twilio.com/docs/api_reference/TwiML/pause) are passed in as a hash
#
@@ -263,7 +263,7 @@ def pause(*args)
options = args.shift
output { @xml.Pause(options) }
end
-
+
# The Redirect (secondary) verb transfers control to a different URL.
# It is normally chained with other verbs.
#
@@ -288,12 +288,38 @@ def redirect(*args)
raise ArgumentError, 'dial expects String or Hash argument'
end
end
-
+
output { @xml.Redirect(redirect_to_url, options) }
end
-
- # The Hangup (secondary) verb ends the call.
- #
+
+ # The <Sms> verb sends a SMS message to a phone number.
+ #
+ # Options (see http://www.twilio.com/docs/api/2008-08-01/twiml/sms/sms) ars passed in as a hash
+ #
+ # Examples:
+ # verb = Twilio::Verb.new { |v|
+ # v.sms 'Meet at South Street'
+ # }
+ #
+ def sms(*args)
+ message = ''
+ options = {}
+ args.each do |arg|
+ case arg
+ when String
+ message = arg
+ when Hash
+ options.merge!(arg)
+ else
+ raise ArgumentError, 'sms expects STring or Hash argument'
+ end
+ end
+
+ output { @xml.Sms(message, options) }
+ end
+
+ # The Hangup (secondary) verb ends the call.
+ #
# Examples:
# If your response is only a hangup:
#
@@ -309,7 +335,7 @@ def redirect(*args)
def hangup
output { @xml.Hangup }
end
-
+
# The Number element specifies a phone number. The number element has two optional attributes: sendDigits and url.
# Number elements can only be nested in Dial verbs
def number(*args)
@@ -325,18 +351,18 @@ def number(*args)
raise ArgumentError, 'dial expects String or Hash argument'
end
end
-
+
output { @xml.Number(number_to_dial, options) }
end
-
+
private
-
+
def output
@chain ? yield : @xml.Response { yield }
- end
-
+ end
+
def loop_with_pause(loop_count, xml, &verb_action)
- last_iteration = loop_count-1
+ last_iteration = loop_count-1
loop_count.times do |i|
yield verb_action
xml.Pause unless i == last_iteration
View
14 test/fixtures/xml/sms.xml
@@ -0,0 +1,14 @@
+<TwilioResponse>
+ <SMSMessage>
+ <Sid>SM872fb94e3b358913777cdb313f25b46f</Sid>
+ <DateCreated>Sun, 04 Oct 2009 03:48:08 -0700</DateCreated>
+ <DateUpdated>Sun, 04 Oct 2009 03:48:10 -0700</DateUpdated>
+ <DateSent>Sun, 04 Oct 2009 03:48:10 -0700</DateSent>
+ <AccountSid>AC5ea872f6da5a21de157d80997a64bd33</AccountSid>
+ <To>4158675309</To>
+ <From>6505551212</From>
+ <Body>Hi there Jenny! Why didn't you call me back?</Body>
+ <Status>sent</Status>
+ <Flags>2</Flags>
+ </SMSMessage>
+</TwilioResponse>
View
29 test/fixtures/xml/sms_messages.xml
@@ -0,0 +1,29 @@
+<TwilioResponse>
+ <SMSMessages page="0" numpages="2" pagesize="50" total="69" start="0"
+end="49">
+ <SMSMessage>
+ <Sid>SM872fb94e3b358913777cdb313f25b46f</Sid>
+ <DateCreated>Sun, 04 Oct 2009 03:48:08 -0700</DateCreated>
+ <DateUpdated>Sun, 04 Oct 2009 03:48:10 -0700</DateUpdated>
+ <DateSent>Sun, 04 Oct 2009 03:48:10 -0700</DateSent>
+ <AccountSid>AC5ea872f6da5a21de157d80997a64bd33</AccountSid>
+ <To>4158675309</To>
+ <From>6505551212</From>
+ <Body>Hi there Jenny! Want to grab dinner?</Body>
+ <Status>sent</Status>
+ <Flags>2</Flags>
+ </SMSMessage>
+ <SMSMessage>
+ <Sid>SM47dfd824add482e1fee25ee3ce216113</Sid>
+ <DateCreated>Sun, 04 Oct 2009 03:48:07 -0700</DateCreated>
+ <DateUpdated>Sun, 04 Oct 2009 03:48:07 -0700</DateUpdated>
+ <DateSent>Sun, 04 Oct 2009 03:48:07 -0700</DateSent>
+ <AccountSid>AC5ea872f6da5a21de157d80997a64bd33</AccountSid>
+ <To>6505551212</To>
+ <From>4158675309</From>
+ <Body>The judge said you can't text me anymore.</Body>
+ <Status>sent</Status>
+ <Flags>1</Flags>
+ </SMSMessage>
+ </SMSMessages>
+</TwilioResponse>
View
14 test/fixtures/xml/sms_new.xml
@@ -0,0 +1,14 @@
+<TwilioResponse>
+ <SMSMessage>
+ <Sid>SM872fb94e3b358913777cdb313f25b46f</Sid>
+ <DateCreated>Sun, 04 Oct 2009 03:48:08 -0700</DateCreated>
+ <DateUpdated>Sun, 04 Oct 2009 03:48:10 -0700</DateUpdated>
+ <DateSent>Sun, 04 Oct 2009 03:48:10 -0700</DateSent>
+ <AccountSid>AC5ea872f6da5a21de157d80997a64bd33</AccountSid>
+ <To>5558675309</To>
+ <From>4155551212</From>
+ <Body>Hi Jenny! Want to grab dinner?</Body>
+ <Status>sent</Status>
+ <Flags>2</Flags>
+ </SMSMessage>
+</TwilioResponse>
View
23 test/twilio/sms_test.rb
@@ -0,0 +1,23 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class SmsTest < Test::Unit::TestCase #:nodoc: all
+ context "A call" do
+ setup do
+ Twilio.connect('mysid', 'mytoken')
+ end
+
+ should "be messaged" do
+ assert_equal stub_response(:post, :sms_new, :resource => 'SMS/Messages'),
+ Twilio::Sms.message('4155551212', '5558675309', 'Hi Jenny! Want to grab dinner?')
+ end
+
+ should "be retrievable as a list" do
+ assert_equal stub_response(:get, :sms_messages, :resource => 'SMS/Messages'), Twilio::Sms.list
+ end
+
+ should "retrieve an individual sms" do
+ assert_equal stub_response(:get, :sms, :resource => 'SMS/Messages/SM872fb94e3b358913777cdb313f25b46f'),
+ Twilio::Sms.get('SM872fb94e3b358913777cdb313f25b46f')
+ end
+ end
+end
View
105 test/twilio/verb_test.rb
@@ -3,30 +3,30 @@
class VerbTest < Test::Unit::TestCase #:nodoc: all
context "A Twilio Verb" do
should "say 'hi'" do
- assert_match %r{<Say( loop="1"| language="en"| voice="man"){3}>hi</Say>},
+ assert_match %r{<Say( loop="1"| language="en"| voice="man"){3}>hi</Say>},
Twilio::Verb.say('hi')
end
should "say 'hi' with female voice" do
- assert_match %r{<Say( loop="1"| language="en"| voice="woman"){3}>hi</Say>},
+ assert_match %r{<Say( loop="1"| language="en"| voice="woman"){3}>hi</Say>},
Twilio::Verb.say('hi', :voice => 'woman')
end
-
+
should "say 'hola' in Spanish with female voice" do
assert_match %r{<Say( loop="1"| language="es"| voice="woman"){3}>hola</Say>},
Twilio::Verb.say('hola', :voice => 'woman', :language => 'es')
end
-
+
should "say 'hi' three times" do
- assert_match %r{<Say( loop="3"| language="en"| voice="man"){3}>hi</Say>},
+ assert_match %r{<Say( loop="3"| language="en"| voice="man"){3}>hi</Say>},
Twilio::Verb.say('hi', :loop => 3)
end
-
+
should "say 'hi' three times with pause" do
assert_match %r{<Say( language="en"| voice="man"){2}>hi</Say><Pause/><Say( language="en"| voice="man"){2}>hi</Say><Pause/><Say( language="en"| voice="man"){2}>hi</Say>},
Twilio::Verb.say('hi', :loop => 3, :pause => true)
end
-
+
should "say 'hi' with pause and say 'bye'" do
verb = Twilio::Verb.new { |v|
v.say 'hi', :loop => 1
@@ -35,7 +35,7 @@ class VerbTest < Test::Unit::TestCase #:nodoc: all
}
assert_match %r{<Say( loop="1"| language="en"| voice="man"){3}>hi</Say><Pause></Pause><Say( loop="1"| language="en"| voice="man"){3}>bye</Say>}, verb.response
end
-
+
should "say 'hi' with 2 second pause and say 'bye'" do
verb = Twilio::Verb.new { |v|
v.say 'hi'
@@ -44,53 +44,53 @@ class VerbTest < Test::Unit::TestCase #:nodoc: all
}
assert_match %r{<Say( loop="1"| language="en"| voice="man"){3}>hi</Say><Pause length="2"/><Say( loop="1"| language="en"| voice="man"){3}>bye</Say>}, verb.response
end
-
+
should "play mp3 response" do
assert_equal verb_response(:play_mp3), Twilio::Verb.play('http://foo.com/cowbell.mp3')
end
-
+
should "play mp3 response two times" do
assert_equal verb_response(:play_mp3_two_times), Twilio::Verb.play('http://foo.com/cowbell.mp3', :loop => 2)
end
-
+
should "play mp3 response two times with pause" do
- assert_equal verb_response(:play_mp3_two_times_with_pause),
+ assert_equal verb_response(:play_mp3_two_times_with_pause),
Twilio::Verb.play('http://foo.com/cowbell.mp3', :loop => 2, :pause => true)
end
-
+
should "gather" do
assert_equal verb_response(:gather), Twilio::Verb.gather
end
-
+
should "gather with action" do
assert_equal verb_response(:gather_with_action), Twilio::Verb.gather(:action => 'http://foobar.com')
end
-
+
should "gather with GET method" do
assert_equal verb_response(:gather_with_get_method), Twilio::Verb.gather(:method => 'GET')
end
-
+
should "gather with timeout" do
assert_equal verb_response(:gather_with_timeout), Twilio::Verb.gather(:timeout => 10)
end
-
+
should "gather with finish key" do
assert_equal verb_response(:gather_with_finish_key), Twilio::Verb.gather(:finishOnKey => '*')
end
-
+
should "gather with num digits" do
assert_equal verb_response(:gather_with_num_digits), Twilio::Verb.gather(:numDigits => 5)
end
-
+
should "gather with all options set" do
- verb_response = Twilio::Verb.gather :action => 'http://foobar.com',
- :finishOnKey => '*',
- :method => 'GET',
+ verb_response = Twilio::Verb.gather :action => 'http://foobar.com',
+ :finishOnKey => '*',
+ :method => 'GET',
:numDigits => 5,
- :timeout => 10
+ :timeout => 10
assert_match %r{<Gather( finishOnKey="\*"| action="http://foobar.com"| method="GET"| numDigits="5"| timeout="10"){5}/>}, verb_response
end
-
+
should "gather and say instructions" do
verb = Twilio::Verb.new { |v|
v.gather {
@@ -100,7 +100,7 @@ class VerbTest < Test::Unit::TestCase #:nodoc: all
}
assert_match %r{<Gather><Say( loop="1"| language="en"| voice="man"){3}>Please enter your account number followed by the pound sign</Say></Gather><Say( loop="1"| language="en"| voice="man"){3}>We didn't receive any input. Goodbye!</Say>}, verb.response
end
-
+
should "gather with timeout and say instructions" do
verb = Twilio::Verb.new { |v|
v.gather(:timeout => 10) {
@@ -110,69 +110,69 @@ class VerbTest < Test::Unit::TestCase #:nodoc: all
}
assert_match %r{<Gather timeout="10"><Say( loop="1"| language="en"| voice="man"){3}>Please enter your account number followed by the pound sign</Say></Gather><Say( loop="1"| language="en"| voice="man"){3}>We didn't receive any input. Goodbye!</Say>}, verb.response
end
-
+
should "record" do
assert_equal verb_response(:record), Twilio::Verb.record
end
-
+
should "record with action" do
assert_equal verb_response(:record_with_action), Twilio::Verb.record(:action => 'http://foobar.com')
end
-
+
should "record with GET method" do
assert_equal verb_response(:record_with_get_method), Twilio::Verb.record(:method => 'GET')
end
-
+
should "record with timeout" do
assert_equal verb_response(:record_with_timeout), Twilio::Verb.record(:timeout => 10)
end
-
+
should "record with finish key" do
assert_equal verb_response(:record_with_finish_key), Twilio::Verb.record(:finishOnKey => '*')
end
-
+
should "record with max length" do
- assert_equal verb_response(:record_with_max_length), Twilio::Verb.record(:maxLength => 1800)
+ assert_equal verb_response(:record_with_max_length), Twilio::Verb.record(:maxLength => 1800)
end
-
+
should "record with transcribe" do
assert_match %r{<Record( transcribe="true"| transcribeCallback="/handle_transcribe"){2}/>},
Twilio::Verb.record(:transcribe => true, :transcribeCallback => '/handle_transcribe')
end
-
+
should "dial" do
assert_equal verb_response(:dial), Twilio::Verb.dial('415-123-4567')
end
-
+
should "dial with action" do
assert_equal verb_response(:dial_with_action), Twilio::Verb.dial('415-123-4567', :action => 'http://foobar.com')
end
-
+
should "dial with GET method" do
assert_equal verb_response(:dial_with_get_method), Twilio::Verb.dial('415-123-4567', :method => 'GET')
end
-
+
should "dial with timeout" do
assert_equal verb_response(:dial_with_timeout), Twilio::Verb.dial('415-123-4567', :timeout => 10)
end
-
+
should "dial with hangup on star" do
assert_equal verb_response(:dial_with_hangup_on_star), Twilio::Verb.dial('415-123-4567', :hangupOnStar => true)
end
-
+
should "dial with time limit" do
assert_equal verb_response(:dial_with_time_limit), Twilio::Verb.dial('415-123-4567', :timeLimit => 3600)
end
-
+
should "dial with caller id" do
assert_equal verb_response(:dial_with_caller_id), Twilio::Verb.dial('415-123-4567', :callerId => '858-987-6543')
end
-
+
should "dial with timeout and caller id" do
assert_match %r{<Dial( timeout="10"| callerId="858-987-6543"){2}>415-123-4567</Dial>},
Twilio::Verb.dial('415-123-4567', :timeout => 10, :callerId => '858-987-6543')
end
-
+
should "dial with redirect" do
verb = Twilio::Verb.new { |v|
v.dial '415-123-4567'
@@ -180,7 +180,7 @@ class VerbTest < Test::Unit::TestCase #:nodoc: all
}
assert_equal verb_response(:dial_with_redirect), verb.response
end
-
+
should "dial with number and send digits" do
verb = Twilio::Verb.new { |v|
v.dial {
@@ -189,7 +189,7 @@ class VerbTest < Test::Unit::TestCase #:nodoc: all
}
assert_equal verb_response(:dial_with_number_and_send_digits), verb.response
end
-
+
should "dial multiple numbers" do
verb = Twilio::Verb.new { |v|
v.dial {
@@ -200,7 +200,7 @@ class VerbTest < Test::Unit::TestCase #:nodoc: all
}
assert_equal verb_response(:dial_multiple_numbers), verb.response
end
-
+
should "dial a conference" do
verb = Twilio::Verb.new { |v|
v.dial {
@@ -209,7 +209,7 @@ class VerbTest < Test::Unit::TestCase #:nodoc: all
}
assert_equal verb_response(:dial_conference), verb.response
end
-
+
should "dial a muted conference" do
verb = Twilio::Verb.new { |v|
v.dial {
@@ -218,11 +218,11 @@ class VerbTest < Test::Unit::TestCase #:nodoc: all
}
assert_equal verb_response(:dial_muted_conference), verb.response
end
-
+
should "hangup" do
assert_equal verb_response(:hangup), Twilio::Verb.hangup
end
-
+
should "say hi and hangup" do
verb = Twilio::Verb.new { |v|
v.say 'hi'
@@ -231,5 +231,14 @@ class VerbTest < Test::Unit::TestCase #:nodoc: all
assert_match %r{<Say( loop="1"| language="en"| voice="man"){3}>hi</Say><Hangup/>},
verb.response
end
+
+ should "send a simple SMS message" do
+ verb = Twilio::Verb.new { |v|
+ v.sms 'Join us at the bar', :to => "8005554321", :from => "9006661111", :action => "/smsService", :method => "GET"
+ }
+
+ assert_match %r{<Sms( to="8005554321"| from="9006661111"| action="/smsService"| method="GET"){4}>Join us at the bar</Sms>},
+ verb.response
+ end
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.