forked from marks/Tropo-Twitter-by-Phone
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Mark S
committed
Jan 27, 2010
1 parent
a415612
commit bf9d141
Showing
3 changed files
with
121 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
require 'time' | ||
|
||
# Helper to take out http[s]:// so Tropo TTS doesn't try to stream the URL as if it were an audio file. | ||
# => Method by @Skram | ||
def reformat_uris(text) | ||
text.gsub(/https?:\/\//, "link to ") | ||
end | ||
|
||
# Helper to convert number to ordinal. | ||
# Such as: 1 = "first", 2 = "second", 3 = "third", ... 99 = "ninety-ninth", and so on. | ||
# => Method by @Skram | ||
def say_as_ordinal(number) | ||
"<?xml version='1.0' encoding='UTF-8'?><speak><say-as interpret-as='ordinal'>#{number}</say-as></speak>" | ||
end | ||
|
||
|
||
### Borrowed from 2nd answer on http://stackoverflow.com/questions/195740/how-do-you-do-relative-time-in-rails | ||
### => Thanks MattW! - http://stackoverflow.com/users/4494/mattw | ||
module PrettyDate | ||
def to_pretty | ||
a = (Time.now-self).to_i | ||
case a | ||
when 0 then return 'just now' | ||
when 1 then return 'a second ago' | ||
when 2..59 then return a.to_s+' seconds ago' | ||
when 60..119 then return 'a minute ago' #120 = 2 minutes | ||
when 120..3540 then return (a/60).to_i.to_s+' minutes ago' | ||
when 3541..7100 then return 'an hour ago' # 3600 = 1 hour | ||
when 7101..82800 then return ((a+99)/3600).to_i.to_s+' hours ago' | ||
when 82801..172000 then return 'a day ago' # 86400 = 1 day | ||
when 172001..518400 then return ((a+800)/(60*60*24)).to_i.to_s+' days ago' | ||
when 518400..1036800 then return 'a week ago' | ||
end | ||
return ((a+180000)/(60*60*24*7)).to_i.to_s+' weeks ago' | ||
end | ||
end | ||
Time.send :include, PrettyDate |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
%w(rubygems sinatra tropo-webapi-ruby/lib/tropo-webapi-ruby.rb pp open-uri rexml/document goodies.rb).each{|lib| require lib} | ||
enable :sessions | ||
|
||
post '/start.json' do | ||
v = Tropo::Generator.parse request.env["rack.input"].read | ||
session[:id] = v[:session][:id] | ||
session[:caller] = v[:session][:from] | ||
session[:user] = "voxeo" | ||
session[:page] = 1 # This shouldn't be tinkered with unless you don't want the most recent tweets to be heard. | ||
t = Tropo::Generator.new | ||
t.on :event => 'continue', :next => '/process.json' | ||
t.on :event => 'error', :next => '/error.json' # For fatal programming errors. Log some details so we can fix it | ||
t.on :event => 'hangup', :next => '/hangup.json' # When a user hangs or call is done. We will want to log some details. | ||
t.on :event => 'incomplete', :next => '/incomplete.json' | ||
t.say "You have reached @#{session[:user]}'s tweets-by-phone." | ||
|
||
t.ask :name => 'count', :bargein => true, :timeout => 7, :required => true, :attempts => 4, | ||
:say => [{:event => "timeout", :value => "Sorry, I did not hear anything."}, | ||
{:event => "nomatch:1 nomatch:2 nomatch:3", :value => "That wasn't a one digit number."}, | ||
{:value => "How many tweets do you want to listen to at once? Enter or say a one digit number."}, | ||
{:event => "nomatch:3", :value => "This is your last attempt. Watch it."}], | ||
:choices => { :value => "[1 DIGITS]"} | ||
t.response | ||
end | ||
|
||
# NOTE, This incomplete event is not necessary. | ||
# To be more user friendly, you can simply not define an incomplete action and | ||
# validate input with Ruby logic inside the 'continue' event's document. | ||
post '/incomplete.json' do | ||
v = Tropo::Generator.parse request.env["rack.input"].read | ||
t = Tropo::Generator.new | ||
t.on :event => 'error', :next => '/error.json' # For fatal programming errors. Log some details so we can fix it | ||
t.on :event => 'hangup', :next => '/hangup.json' # When a user hangs or call is done. We will want to log some details. | ||
t.say "You failed to enter a valid number #{v[:result][:actions][:attempts]} times." | ||
t.say "Please call back and try again or contact us for help." | ||
t.hangup | ||
t.response | ||
end | ||
|
||
post '/process.json' do | ||
v = Tropo::Generator.parse request.env["rack.input"].read | ||
t = Tropo::Generator.new | ||
t.on :event => 'error', :next => '/error.json' # For fatal programming errors. Log some details so we can fix it | ||
t.on :event => 'hangup', :next => '/hangup.json' # When a user hangs or call is done. We will want to log some details. | ||
t.on :event => 'continue', :next => '/say_page_of_tweets.json' | ||
session[:count] = v[:result][:actions][:count][:value] | ||
# t.say "@#{session[:user]} tweets coming right up!" | ||
t.response | ||
end | ||
|
||
post '/say_page_of_tweets.json' do | ||
t = Tropo::Generator.new | ||
t.on :event => 'error', :next => '/error.json' # For fatal programming errors. Log some details so we can fix it | ||
t.on :event => 'hangup', :next => '/hangup.json' # When a user hangs or call is done. We will want to log some details. | ||
t.on :event => 'continue', :next => '/say_page_of_tweets.json' | ||
t.say "I'm about to read you the" | ||
t.say say_as_ordinal(session[:page]) | ||
t.say " #{session[:count]} tweets by #{session[:user]}." | ||
source = "http://twitter.com/statuses/user_timeline/#{session[:user]}.rss?count=#{session[:count]}&page=#{session[:page]}" | ||
rss = REXML::Document.new(open(source).read).root | ||
rss.root.elements.each("channel/item") { |element| | ||
t.say "Tweet from about #{Time.parse(element.get_text('pubDate').to_s).to_pretty}" | ||
t.say reformat_uris(element.get_text('title').to_s) + "," # comma for extra pause between tweets. | ||
} | ||
session[:page] += 1 | ||
t.response | ||
end | ||
|
||
post '/hangup.json' do | ||
v = Tropo::Generator.parse request.env["rack.input"].read | ||
if v[:result][:complete] | ||
puts "Call complete. Call duration: #{v[:result][:call_duration]} second(s)" | ||
else | ||
puts "/!\\ Caller hung up. Call duration: #{v[:result][:call_duration]} second(s)." | ||
end | ||
puts " Caller info: ID=#{session[:caller][:id]}, Name=#{session[:caller][:name]}" | ||
puts " Call logged in CDR. Tropo session ID: #{session[:id]}" | ||
end | ||
|
||
post '/error.json' do | ||
v = Tropo::Generator.parse request.env["rack.input"].read | ||
puts "!"*10 + "ERROR (see rack.input below); call ended" | ||
pp v # Print the JSON to our Sinatra console/log so we can find the error | ||
end |