I don't understand the Twilio URL Parameter on Voice - ruby

I understand the purpose of this for more complex functionality, but I'm trying to make a simple app that does nothing more than forwards to a phone number. I don't want to hard code the forward via a Twimlet because I want to build a web app that dynamically allows me to assign the numbers. Can someone tell me what I'd put for URL parameter in this situation?
get '/forward-call' do
#client = Twilio::REST::Client.new
#call = #client.account.calls.create(
{:to => "+15127778888",
:from => "+15122222222",
:url => "What in the foo should I put here?"})
end

Twilio developer evangelist here.
Does your /forward-call endpoint get called when someone makes a call to your Twilio number?
If so, you don't want to be calling the REST API right now, you want to respond to the webhook with some TwiML. In your case, you'd want something like this:
get '/forward-call' do
content_type 'text/xml'
"<Response>
<Dial><Number>#{NUMBER_TO_FORWARD_TO}</Number></Dial>
</Response>"
end
Does that help at all? Let me know if I can help out any more at all.

Related

How to reference "from" field in TWIML to make a simple call b/w two phones

Trying to follow this tutorial:
https://www.twilio.com/docs/quickstart/ruby/rest/call-request
This code only dials the to number for me:
#call = #client.calls.create(
:from => '+14159341234', # From your Twilio number
:to => '+18004567890', # To any number
# Fetch instructions from this URL when the call connects
:url => 'http://twimlets.com/holdmusic?Bucket=com.twilio.music.ambient'
)
For me, this code never dials the from phone. Just the "to:" number gets called, when answered, it plays music. The "from" number doesn't never rings. I'm guessing I have to write TWIML to dial the first number (to), but I don't see any reference to the variable "to" in TWIML, is there a sample twiml that will simply connect two phones?
You're dealing with three numbers in this picture. One is your Twilio number from where the call is made '+14159341234', then, you have the two numbers you'd like to call and connect.
Let's be clear, you won't hear your Twilio number ring, it's at Twilio and it's kind of virtual.
The code you have so far, when you run it, uses your Twilio number :from => '+14159341234' to make a call :to => '+18004567890'.
So, what happens when people at :to => '+18004567890' answer? Twilio's system (the platform) makes a request to :url => 'http://twimlets.com/holdmusic?Bucket=com.twilio.music.ambient' from where is served some XML, some TWIML. You can actually see what is served if you go with your browser to http://twimlets.com/holdmusic?Bucket=com.twilio.music.ambient
To do what you want to do, to dial another number instead of playing music, you need to change that url to some place from where you serve this kind of TWIML:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>Hello. Please wait.</Say>
<Dial>+12223334444</Dial>
</Response>
If you don't have your public server from where you can serve XML, you can use a native TwiML bin, that you create in your Twilio account console here: https://www.twilio.com/console/runtime/twiml-bins .
Once you create your TwiML bin, under properties for the bin, you'll have a URL to put in place of http://twimlets.com/holdmusic?Bucket=com.twilio.music.ambient, something like https://handler.twilio.com/twiml/EH7e58b64f8488ff8c022bf83c910fb49b.
P.S. You might want to also google twilio click to call and/or twilio conference as other way to connect two phones.

Ruby on Sinatra: Imitate a request based on a parameter

I am currently developing a Ruby API based on Sinatra. This API mostly receives GET requests from an existing social platform which supports external API integration.
The social platform fires off GET requests in the following format (only relevant parameters shown):
GET /{command}
Parameters: command and text
Where text is a string that the user has entered.
In my case, params[:text] is in fact a series of commands, delimited by a space. What I want to achieve is, for example: If params[:text]="corporate finance"
Then I want my API to interpret the request as a GET request to
/{command}/corporate/finance
instead of requesting /{command} with a string as a parameter containing the rest of the request.
Can this be achieved on my side? Nothing can be changed in terms of the initial request from the social platform.
EDIT: I think a better way of explaining what I am trying to achieve is the following:
GET /list?text=corporate finance
Should hit the same endpoint/route as
GET /list/corporate/finance
This must not affect the initial GET request from the social platform as it expects a response containing text to display to the user. Is there a neat, best practice way of doing this?
get "/" do {
text = params[:text].split.join "/"
redirect "#{params[:command]}/#{text}"
end
might do the trick. Didn't check though.
EDIT: ok, the before filter was stupid. Basically you could also route to "/" and then redirect. Or, even better:
get "/:command" do {
text = params[:text].split.join "/"
redirect "#{params[:command]}/#{text}"
}
There a many possible ways of achieving this. You should check the routes section of the sinatra docs (https://github.com/sinatra/sinatra)
The answer by three should do the trick, and to get around the fact that the filter will be invoked with every request, a conditional like this should do:
before do
if params[:text]
sub_commands = params[:text].split.join "/"
redirect "#{params[:command]}/#{sub_commands}"
end
end
I have tested it in a demo application and it seems to work fine.
The solution was to use the call! method.
I used a regular expression to intercept calls which match /something with no further parameters (i.e. /something/something else). I think this step can be done more elegantly.
From there, I split up my commands:
get %r{^\/\w+$} do
params[:text] ? sub_commands="/"+params[:text].split.join("/") : sub_commands=""
status, headers, body = call! env.merge("PATH_INFO" => "/#{params[:command]}#{sub_commands}")
[status, headers, body]
end
This achieves exactly what I needed, as it activates the correct endpoint, as if the URL was typed it the usual format i.e. /command/subcommand1/subcommand2 etc.
Sorry, I completely misunderstood your question, so I replace my answer with this:
require 'sinatra'
get '/list/?*' do
"yep"
end
like this, the following routes all lead to the same
You need to add a routine for each command or replace the command with a * and depend your output based on a case when.
The params entered by the user can be referred by the params hash.
http://localhost:4567/list
http://localhost:4567/list/corporate/finance
http://localhost:4567/list?text=corporate/finance

twilio, sinatra ruby force hangup and then callback

I want to call my Twilio number which hangs up immediately and then calls me back. This is similar (but not identical) to a previous question of mine.
The problem lies with forcing Twilio to hang up.
The ruby code is:
get '/callback' do
to = params['From']
from = 'my Twilio number'
"<Response><Hangup/></Response>"
sleep 5
# set up a client to talk to the Twilio REST API
#client = Twilio::REST::Client.new account_sid, auth_token
#call = #client.account.calls.create(
:from => from, # From your Twilio number
:to => to, # To any number
# Fetch instructions from this URL when the call connects
:url => 'https://dl.dropboxusercontent.com/u/85088004/twilio/twilio.xml'
)
end
This produces a message: "We are sorry but a system error has occurred". The problem lies with the hangup instruction. I have tried as above and also
<Response><Hangup/></Response> #without enclosing double or single quotes
and
Twilio::TwiML::Response.new do |r|
r.Hangup
end.text
Neither produces the desired result of hangup.
What's wrong?
Many thanks in advance!
Definitely go with #Kevin's advice and get in touch with Twilio support. But one comment I would like to add. At the end of your /callback action, the last value is the #call variable you are assigning when you create a call, Ruby will be trying to return this value as the result of the HTTP request.
Ruby returns the last value evaluated at the end of a method. In this case, that value is what Sinatra responds to the HTTP Get request with by default.
Judging by the literal string you have <Response><Hangup/></Response>, I'm guessing you are not using a view, and expect that to be the result of the get request. You should place that at the very end of your method as below. I've also added a content_type which just sets the response header to say the response is XML.
get '/callback' do
to = params['From']
from = 'my Twilio number'
# set up a client to talk to the Twilio REST API
#client = Twilio::REST::Client.new account_sid, auth_token
#call = #client.account.calls.create(
:from => from, # From your Twilio number
:to => to, # To any number
# Fetch instructions from this URL when the call connects
:url => 'https://dl.dropboxusercontent.com/u/85088004/twilio/twilio.xml')
#ruby returns the last value in a method:
content_type 'text/xml'
"<Response><Hangup/></Response>"
end
Make sure that you have your Twilio Voice Callback set to a Get request as well (the default is post).
I've also removed the sleep 5 that you had in there. I can see where you are going with it. Respond with the hangup TwiML, wait a few seconds, then make a new call. Sadly, Sinatra doesn't quite work that way. It will not respond to the HTTP request until the end of the method. So you're just going to have it sit and wait for 5 seconds with no reason.
This does pose a bit of an issue, as you tell Twilio to make an outbound call to the number that you are about to hangup on, so you basically have a race condition. Does the call disconnect first, or does the outbound start ringing to a busy number.
There are a number of ways of doing this, but I'd suggest a thread. It's a little tricky, but this SO answer goes into some detail.
You should check your Twilio Debugger at twilio.com/user/account/debugger. This will give more information about the failure.

Twilio Send Message Method for Windows Phone 7.5

How do I fill in the send message method for Twilio, I know how to fill in the from, to and body. the only part that befuddles me is the System.Action. Please help.
System.Action is basicly a method.
You can call SendSmsMessage this way:
Twilio.TwilioRestClient.SendSmsMessage("from", "to", "message", (smsmessage) => { });
I'm not familiar with Twilio or the SendSmsMessage method, but I suspect, that this method gets called when SendSmsMessage finishes or something like that. In this case, smsmessage is a parameter that is usable in the Action.
You can read more about System.Action here and about c# lamdas in general here

Grab Facebook signed_request with Sinatra

I'm trying to figure out whether or not a user likes our brand page. Based off of that, we want to show either a like button or some 'thank you' text.
I'm working with a sinatra application hosted on heroku.
I tried the code from this thread: Decoding Facebook's signed request in Ruby/Sinatra
However, it doesn't seem to grab the signed_request and I can't figure out why.
I have the following methods:
get "/tab" do
#encoded_request = params[:signed_request]
#json_request = decode_data(#encoded_request)
#signed_request = Crack::JSON.parse(#json_request)
erb :index
end
# used by Canvas apps - redirect the POST to be a regular GET
post "/tab" do
#encoded_request = params[:signed_request]
#json_request = decode_data(#encoded_request)
#signed_request = Crack::JSON.parse(#json_request)
redirect '/tab'
end
I also have the helper messages from that thread, as they seem to make sense to me:
helpers do
def base64_url_decode(payload)
encoded_str = payload.gsub('-','+').gsub('_','/')
encoded_str += '=' while !(encoded_str.size % 4).zero?
Base64.decode64(encoded_str)
end
def decode_data(signed_request)
payload = signed_request.split('.')
data = base64_url_decode(payload)
end
end
However, when I just do
#encoded_request = params[:signed_request]
and read that out in my view with:
<%= #encoded_request %>
I get nothing at all.
Shouldn't this return at least something? My app seems to be crashing because well, there's nothing to be decoded.
I can't seem to find a lot of information about this around the internet so I'd be glad if someone could help me out.
Are there better ways to know whether or not a user likes our page? Or, is this the way to go and am I just overlooking something obvious?
Thanks!
The hint should be in your app crashing because there's nothing to decode.
I suspect the parameters get lost when redirecting. Think about it at the HTTP level:
The client posts to /tab with the signed_request in the params.
The app parses the signed_request and stores the result in instance variables.
The app redirects to /tab, i.e. sends a response with code 302 (or similar) and a Location header pointing to /tab. This completes the request/response cycle and the instance variables get discarded.
The client makes a new request: a GET to /tab. Because of the way redirects work, this will no longer have the params that were sent with the original POST.
The app tries to parse the signed_request param but crashes because no such param was sent.
The simplest solution would be to just render the template in response to the POST instead of redirecting.
If you really need to redirect, you need to carefully pass along the signed_request as query parameters in the redirect path. At least that's a solution I've used in the past. There may be simpler ways to solve this, or libraries that handle some of this for you.

Resources