How to say "unless variable.HTTP Error 400 " in rails - ruby-on-rails

I'm trying to build a call tracking app to learn twilio and rails. Right now, I'm adding the functioanlity to buy phone numbers.
I want to do an if/else statement in my create action, where if the phone number was saved to the database, and the twilio number was actually purchased, than do this, else do that.
But, the twilio number doesn't return true or false. Here's what they say in their docs :
HTTP POST
Purchases a new phone number for your account. If a phone number is
found for your request, Twilio will add it to your account and bill
you for the first month's cost of the phone number. If Twilio cannot
find a phone number to match your request, you will receive an HTTP
400 with Twilio error code 21452.
So, what I'd like to do is to build an if statement where, if the return is HTTP 400, then do x.
Here's the code I have at present
#This saves the Twilio number to the database, and buys it.
def create
#user = current_user
#phone = #user.phones.build(params[:phone])
client = Twilio::REST::Client.new(#user.twilio_account_sid, #user.twilio_auth_token)
number = client.account.incoming_phone_numbers.create({:phone_number => #phone.twilio_number, :voice_url => VOICE_URL, :voice_method => "POST"})
if #phone.save && number.true
flash[:success] = "Phone Number Created!"
redirect_to user_path
else
render new_phone_path
flash[:error] = "It looks like there were errors with the submission"
end
end
What would I need to change && number.true with, to reference the HTTP 400 Error?
I'm not sure if this is even possible -- so if you have ideas, I'm all ears :).

Three years later and I just wanted to share that we have a fully featured Call Tracking tutorial in Rails to help you get up and running more quickly:
https://www.twilio.com/docs/tutorials/walkthrough/call-tracking/ruby/rails
The application has three main features:
It purchases phone numbers from Twilio to use in different marketing campaigns (like a billboard or a bus advertisement)
It forwards incoming calls for those phone numbers to a salesperson
It displays charts showing data about the phone numbers and the calls they receive
And you'll want to make sure to grab the Ruby helper library before you get started.

Related

Twilio security PIN for conference call

I am using twilio gem for making calls in my rails app. Everything is working fine, now I want to add a conference functionality(adding conference functionality is easy) which should ask for pin before joining call, I don't want to add PIN logic manually. If suppose I will add code for entering PIN, how twilio will work to add all those clients to conference who entered PIN correctly. Does twilio support any thing like this? Any body have any idea about this kind of functionality?
Twilio developer evangelist here.
The URL that usha shared is a good start for adding PIN functionality for conferences. There's no automatic way to do it, you need to use a combination of <Gather> and your own logic for the correct PIN to make this work.
In Rails that might look a bit like this:
Initial webhook for incoming calls to the conference number:
def start_conference
response = Twilio::TwiML::VoiceResponse.new
response.gather(:action => conference_gather_url, :num_digits => 4) do |gather|
gather.say("Please enter the code for the conference", :voice => 'alice')
end
return :xml => response.to_xml
end
In this example, when the user enters 4 digits the call will automatically cause a request to the conference_gather_url with the digits that were entered sent as the Digits parameter in the body of the request.
Then the action needs to check that the PIN is correct and allow access to the conference if it is. I have included a pin_is_correct? method below, it is up to you to implement this.
def conference_gather
pin = params["Digits"]
response = Twilio::TwiML::VoiceResponse.new
if pin_is_correct?(pin)
response.dial do |dial|
dial.conference("CONFERENCE_NAME")
end
else
response.say("Your pin was incorrect. Goodbye.")
response.hangup
end
return :xml => response.to_xml
end
Let me know if that helps at all.

What can be the reason of "Unable to find subscription with identifier" in Rails ActionCable?

I'm building a messenger application using Rails 5.0.0.rc1 + ActionCable + Redis.
I've single channel ApiChannel and a number of actions in it. There are some "unicast" actions -> ask for something, get something back, and "broadcast" actions -> do something, broadcast the payload to some connected clients.
From time to time I'm getting RuntimeError exception from here: https://github.com/rails/rails/blob/master/actioncable/lib/action_cable/connection/subscriptions.rb#L70 Unable to find subscription with identifier (...).
What can be a reason of this? In what situation can I get such exception? I spent quite a lot of time on investigating the issue (and will continue to do so) and any hints would be greatly appreciated!
It looks like it's related to this issue: https://github.com/rails/rails/issues/25381
Some kind of race conditions when Rails reply the subscription has been created but in fact it hasn't been done yet.
As a temporary solution adding a small timeout after establishing the subscription has solved the issue.
More investigation needs to be done, though.
The reason for this error might be the difference of the identifiers you subscribe to and messaging to. I use ActionCable in Rails 5 API mode (with gem 'devise_token_auth') and I faced the same error too:
SUBSCRIBE (ERROR):
{"command":"subscribe","identifier":"{\"channel\":\"UnreadChannel\"}"}
SEND MESSAGE (ERROR):
{"command":"message","identifier":"{\"channel\":\"UnreadChannel\",\"correspondent\":\"client2#example.com\"}","data":"{\"action\":\"process_unread_on_server\"}"}
For some reason ActionCable requires your client instance to apply the same identifier twice - while subscribing and while messaging:
/var/lib/gems/2.3.0/gems/actioncable-5.0.1/lib/action_cable/connection/subscriptions.rb:74
def find(data)
if subscription = subscriptions[data['identifier']]
subscription
else
raise "Unable to find subscription with identifier: #{data['identifier']}"
end
end
This is a live example: I implement a messaging subsystem where users get the unread messages notifications in the real-time mode. At the time of the subscription, I don't really need a correspondent, but at the messaging time - I do.
So the solution is to move the correspondent from identifier hash to the data hash:
SEND MESSAGE (CORRECT):
{"command":"message","identifier":"{\"channel\":\"UnreadChannel\"}","data":"{\"correspondent\":\"client2#example.com\",\"action\":\"process_unread_on_server\"}"}
This way the error is gone.
Here's my UnreadChannel code:
class UnreadChannel < ApplicationCable::Channel
def subscribed
if current_user
unread_chanel_token = signed_token current_user.email
stream_from "unread_#{unread_chanel_token}_channel"
else
# http://api.rubyonrails.org/classes/ActionCable/Channel/Base.html#class-ActionCable::Channel::Base-label-Rejecting+subscription+requests
reject
end
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
def process_unread_on_server param_message
correspondent = param_message["correspondent"]
correspondent_user = User.find_by email: correspondent
if correspondent_user
unread_chanel_token = signed_token correspondent
ActionCable.server.broadcast "unread_#{unread_chanel_token}_channel",
sender_id: current_user.id
end
end
end
helper: (you shouldn't expose plain identifiers - encode them the same way Rails encodes plain cookies to signed ones)
def signed_token string1
token = string1
# http://vesavanska.com/2013/signing-and-encrypting-data-with-tools-built-in-to-rails
secret_key_base = Rails.application.secrets.secret_key_base
verifier = ActiveSupport::MessageVerifier.new secret_key_base
signed_token1 = verifier.generate token
pos = signed_token1.index('--') + 2
signed_token1.slice pos..-1
end
To summarize it all you must first call SUBSCRIBE command if you want later call MESSAGE command. Both commands must have the same identifier hash (here "channel"). What is interesting here, the subscribed hook is not required (!) - even without it you can still send messages (after SUBSCRIBE) (but nobody would receive them - without the subscribed hook).
Another interesting point here is that inside the subscribed hook I use this code:
stream_from "unread_#{unread_chanel_token}_channel"
and obviously the unread_chanel_token could be whatever - it applies only to the "receiving" direction.
So the subscription identifier (like \"channel\":\"UnreadChannel\") has to be considered as a "password" for the future message-sending operations (e.g. it applies only to the "sending" direction) - if you want to send a message, (first send subscribe, and then) provide the same "pass" again, or you'll get the described error.
And more of it - it's really just a "password" - as you can see, you can actually send a message to whereever you want:
ActionCable.server.broadcast "unread_#{unread_chanel_token}_channel", sender_id: current_user.id
Weird, right?
This all is pretty complicated. Why is it not described in the official documentation?

Twilio: Multiple outbound conferences at once using one Twilio phone number.

Just wondering if any Twilio experts can shed some light onto how I might handle having multiple conferences attached to the same Twilio number happening at once.
In the simplest case I would be looking to handle 2 person conferences (so basically just a regular call).
E.g. lets say I have two 2-person conferences scheduled for 1:00 and those two calls are waiting in a queue to be set up. At 1:00 Twilio would pull the first call from the queue and send out outbound calls to connect User A and User B in the first conference, then it would pull the second call from the queue and send out outbound calls to User C and User D to connect them in a second separate conference. Apart from Twilio’s 1-second per call limit is there anything stopping me from using the same Twilio number to connect both separate conferences?
Is it simply the fact that when my app pulls the second call from the queue it is making separate HTTP requests that keeps the two conferences separate even though they're attached to the same number? I’m working in Rails but I’d appreciate input from anyone as to how I might need to handle that in my code.
Twilio developer evangelist here.
As Akhil says, there's no limit on making multiple conferences from the same caller id.
What you might do to accomplish this is set a URL parameter in the URL you pass to the create call method that indicates which conference your users will join. For example:
client = Twilio::REST::Client.new(ACCOUNT_SID, AUTH_TOKEN)
client.calls.create(
:from => YOUR_TWILIO_NUMBER,
:to => user.phone_number,
:url => "/conference?conference_room=#{user.current_conference}"
)
Then, in your route you can look up the conference name and add the user to it.
def conference
conf_room = params[:conference_room]
twiml = Twilio::TwiML::Response.new do |r|
r.Dial do
r.Conference conf_room
end
end
render :xml => twiml.to_xml
end
Let me know if that helps at all!
There is no limitation in making multiple conferences at once from the same caller ID. You can have any number of simultaneous calls from the same number at a time (Respecting twilio's 1 call per second limit).
The key here is to have a unique name for a conference and join users to the correct conference.

Twilio post to url with params[:text_response] and params[:phone_number]

I am using ruby 2.0.0 and Rails 4.0.
I am sending a text message out via my rails app to my end user.
When they respond, I want to redirect them to an api call:
www.myapp.com/api/verify_text_response
Within that API call, I want to see what the text message sent from the end user to my url is. Ideally, I would receive a param of "text_response" that I could then do what I wanted to with.
How can I redirect a reply from my end_user to the above url, and capture the phone number it came from as well as the message sent to me in my params? If this isn't possible, how can I use TwiML to do something similar?
End Goal
For what it's worth, this is what I'm trying to accomplish:
I send a text message out - "Would you like to subscribe?"
The end user responds "Yes" or "No".
I change the subscribed attribute on my subscription model to true or false.
I send another text message saying either "You are subscribed." or "You are not subscribed.".
Item's #3 and #4 are based on the user responding "Yes" or "No" in item #2.
The twilio guide here for Ruby is the most useful documentation out there. They recommend using the Twilio gem in your Rails application by adding the twilio-ruby gem to your Gemfile.
All you need to do to is add the following code to one of your controller's actions (the one that is routed to by www.myapp.com/api/verify_text_response:
def receive_text
# Not exactly sure this is the right parameter, but it's easy to test
sender_message = params[:Body]
response = if (sender_message == "Yes")
"You are subscribed."
else
"You are not subscribed."
end
twiml = Twilio::TwiML::Response.new do |r|
r.Message(response)
end
twiml.text
end
To make your Rails application accessible to Twilio, follow the directions found on this page:
Copy and paste the URL of your server into the "SMS" URL of a number
on the Numbers page of your Twilio Account. On the page for that
number, change the Method from "POST" to "GET".
I wasn't exactly sure from looking at the documentation which parameter holds the user's response (I thought it was probably params[:Body]), but the best way to figure out is simply by printing out the parameters that the controller receives when you send a text message to your Twilio number.

Rails 3 and Twilio to do phone verification

I am building an app in Rails 3, using twilio to verify a businesses existance. Basically, when you create a new buisiness I randomly generate a 6 digit number and then call the business phone number with this verification code and the user needs to enter it back in the system to finish the signup process. I am having trouble finding any relevant examples as to how to get this set up. I've found this, but it seems horribly outdated and doesn't work with Rails 3 seemingly. The documentation for the twilio-rb gem is confusing as well.
Does anyone know of any examples or have any code samples that could point me in the right direction?
As I said in the comment on your question itself, I am the author of the twilio-rb gem you mention. Off the top of my head, I would implement a verifications resource that you post a telephone number to.
POST /verifications.voice { telephone_number: '+12125551234' }
In the create action use Twilio::Call.create to create a new call with Twilio
def create
#verification = Verification.new params[:verification]
if #verification.save
Twilio::Call.create to: #verification.telephone_number,
from: YOUR_CALLER_ID, url: verification_url(#verification, format: :voice)
# 201 created and return verification code etc
else
# Handle errors
end
end
You will also want to rescue any API errors that twilio-rb might raise. The url refers to the show action of the verification resource instance. Twilio will then dial the supplied telephone number, and when the call is connected will request the url, e.g. GET /verifications/1.voice so you'll need a show view that asks for the verification code and collects the digits with the <Gather> verb:
res.gather num_digits: 4, action: twilio_hack_verification_url(#verification, :format => :voice), method: 'POST' do |form|
form.say 'Please enter the your 4 digit verification code'
end
Since Twilio currently does not implement the PUT verb, you'll to add a member to your resource
resources :verifications do
member { post 'twilio_hack' }
end
Then in your controller update the object with the user input:
def twilio_hack
#verification = Verification.find(params[:id]).tap do |v|
v.user_input params['Digits']
v.save
end
if #verification.confirmed?
# handle success
else
# handle failure
end
end
Finally in your model you'll need code that generates the verification code, and verifies if it is confirmed
class Verification < ActiveRecord::Base
before_save -> { self[:confirmed] = true if user_input == verification_code }, if: user_input
before_create -> { self[:verification_code] = rand.to_s[2..5] }
end
This is all untested and off the top of my head with about 2 minutes thought, but it should get you started.
When you wish to verify a Business:
Generate a verification code.
Use the Twilio REST API to initiate an outbound call, passing a URL for a callback to a controller which will handle the verification logic. Docs at Twilio are here and an example is here.
This means that you need to pass the verification code into your controller via the callback URL. Use a non-resourceful route with a bound parameter. See here.
Write a controller that handles the call and processes the verification:
Emit TwiML that challenges the user to enter the verification code. I have found using Nokogiri to build the TwiML myself to be the most straightforward approach. (See the method phone_greeting in this simple app I wrote: here.)
If it's correct, flag the Business as verified, congratulate the user, and hang up.
If not, loop.
Hopefully that's enough information to point you in the right direction.
Have you considered using Twilio's Outgoing Caller IDs to help solve this problem?
When calling Twilio over REST to add a new caller id to your account, Twilio will return a 6 digit verification code (property ValidationCode) for you to display in your UI, and then Twilio will automatically call the number and prompt for the code. When the user verifies the number over the phone, their number will be added to your account's caller ids. You can then query Twilio for their phone number over REST (parameter PhoneNumber) to ensure the verification was successful.
See here for documentation:
Add a caller id: http://www.twilio.com/docs/api/rest/outgoing-caller-ids#list-post
Find a caller id: http://www.twilio.com/docs/api/rest/outgoing-caller-ids#list

Resources