Twilio URL not routing correctly in Worker - ruby-on-rails

I have a twilio app that is making phone calls. I put the guts of it in a Worker, and now cannot get the API to recognize the url I am passing as a valid url for my TwiML response. Code is below. Any ideas? Also note that I have tried both #{root_path}connect and #{root_url}connect
Worker
#numbers.each do |dial|
if (dial.phone_number =~ /[\(\)0-9\- \+\.]{10,11}/).nil?
raise Exception, "bad phone number"
end
call = client.account.calls.create(
:from => my_number,
:to => dial.phone_number,
:url => "#{root_path}connect"
)
controller
def connect
response = Twilio::TwiML::Response.new do |r|
r.Say 'The Time Has come to take over the world Pinky', :voice => 'alice'
end
render text: response.text
end
routes
root :to => 'call_logs#index'
resources :call_logs, only: [:create, :index] do
collection { post :call_score_range,:call_warrants_with_date_range,:connect }
end

Twilio developer evangelist here.
I think your problem is that the worker has no concept of Rails' routes. Routes are only available by default in controllers and views, so you are probably not passing a URL to Twilio.
I can't see where you call your worker from in the first place, but one idea would be to pass the URL you want to send to the API into the worker from where it is created in a controller.
I hope this helps. Please let me know if there's anything else I can do for you.

Related

Twilio can't find xml on rails

I am integrating twilio click to call into my rails project.
Everything works fine however the url: in my twilio controller cannot be found on heroku. However, it can be found if you navigate to it in a browser. The phone dials but the voice says "Sorry a problem has occurred, good bye." If I change the url to an external xml file it works fine, just doesn't recognize this particular one. So I'm lead to believe that the controller etc works fine.
twillio_controller.rb
def call
#full_phone = current_user.phone
#partial_phone = #full_phone.last(-1)
#connected_number = "+61" + #partial_phone
#client = Twilio::REST::Client.new ##twilio_sid, ##twilio_token
# Connect an outbound call to the number submitted
#call = #client.calls.create(
:from => ##twilio_number,
:to => #connected_number,
:url => 'http://besttradies.herokuapp.com/mytradies/connect.xml', # Fetch instructions from this URL when the call connects
)
#msg = { :message => 'Phone call incoming!', :status => 'ok' }
end
def connect
# Our response to this request will be an XML document in the "TwiML"
# format. Our Ruby library provides a helper for generating one
# of these documents
response = Twilio::TwiML::Response.new do |r|
r.Say 'If this were a real click to call implementation, you would be connected to an agent at this point.', :voice => 'alice'
end
render text: response.text
end
The OP solved in the comments above:
Figured it out. Routes for connect needed to be POST and I also had to
add skip_before_action :verify_authenticity_token to the twilio
controller as it was behind membership doors.

WEBrick::HTTPStatus::LengthRequired with Twilio

Following the tutorial for Twilio Client. Got stuck here where you do the testing
https://www.twilio.com/docs/quickstart/ruby/client/incoming-calls
curl -X POST http://localhost:3000/voice
I keep getting the WEBrick::HTTPStatus::LengthRequired response.
When I put it as
curl -X POST http://localhost:3000/voice -d ''
It works. But how do I fix for this in my routes or controller?
routes.rb
post 'voice', to: 'calls#voice', as: :voice
controller
def voice
response = Twilio::TwiML::Response.new do |r|
# Should be your Twilio Number or a verified Caller ID
r.Dial :callerId => '+16479316790' do |d|
d.Client 'jenny'
end
end
render :text => response.text
end
Thanks!
Also, if you have done this previously... having trouble adding localhost:3000 as the callback url in the dashboard. Any suggestions?
The voice URL does not need to be a POST request, it can be a GET request. In the App dashboard, you can change the type of the voice request URL to GET and then modify your routes.rb to use get.
Using 'localhost' as the domain will not work as want a URL to point to your webserver. What you instead want is the full URL to your web server which you can accomplish with something like ngrok.

What is the idiomatic means of organizing this code the "rails way"

Within our Rails app, I have several webhooks, called by external services (namely PayPal IPN, Mailgun and Pusher). Currently, each type has it's own controller + necessary routes, for example:
post 'jobs/:job_id/comments/reply' => 'mailgun#incoming_email_comment'
post '/webhook' => 'pusher#webhook'
post '/paypal/ipn', :to => 'paypal#ipn', :as => :paypal_ipn
Is there a cleaner, more "rails way" to achieve this?
For example post '/webhook' => 'pusher#webhook'
pushers_controller.rb
class Pushers <ApplicationController
def webhook
....
end
end
routes.rb
resources :pushers do
collection do
post 'webhook'
end
end
now you can get url for that route like this
webhook_pushers_path
or
link_to 'some text', webhook_pushers_path
As you can see, now you don't need write url by hands. Rails automatically creates it using name of your controller and your action.
You can read more there http://guides.rubyonrails.org/routing.html#adding-more-restful-actions

Does the twilio-ruby gem handle SMS responses?

The only reference to SMS on the readme file is regarding sending SMS messages.
# send an sms
#client.account.sms.messages.create(
:from => '+14159341234',
:to => '+16105557069',
:body => 'Hey there!'
)
I'm wondering if the twilio-ruby gem provides visibility to SMS responses? I want to do some keyword response logic like the example they give here in PHP.
For others who may have this issue, I found this example application from this question to be very useful. What you need to do is:
Setup your Twilio Number SMS URL to Post to a certain controller in your application (e.g., myapp.com/twilio/process-sms)
Add a route to match that URL to the correct action in your Twilio controller
Write some simple logic like below to process responses/messages to your number according to your custom business logic
Respond, if necessary, using a .xml.erb file like the one below
class TwilioController < ApplicationController
def process_sms
#city = params[:FromCity].capitalize
#state = params[:FromState]
#from = params[:From]
u = User.find_by_phone_number(#from)
#user = u.name
b = params[:Body]
if b.downcase.include?("question")
#type = "Question"
#question = u.questions.build(:description => b)
#question.save!
render 'new_question.xml.erb', :content_type => 'text/xml'
elsif b.downcase.include?("contact")
#type = "Contact"
#contact = u.contacts.build(:name => b)
#contact.save!
render 'new_contact.xml.erb', :content_type => 'text/xml'
else
#type = "Not sure"
render 'not_sure.xml.erb', :content_type => 'text/xml'
end
The .build will create the object and the .save will save the object. Then you just return to Twilio the TWIML that you want to respond to the user. such as:
app/views/twilio/new_contact.xml.erb
<Response>
<Sms>We added a new contact for you.</Sms>
</Response>
When you get an SMS on your Twilio number, Twilio will make an HTTP request to your server. You can respond to the incoming SMS by responding to the request with XML, like this:
<Response>
<Sms>This is my response</Sms>
</Response>
You can either generate the XML response yourself, or the helper libraries contain methods that help you return XML to the client. I would suggest taking a look at the Twilio Ruby SMS quickstart for a simple example, and then going from there.

Rails 3.1 Routes with fixed structured params

I have an sms gateway which pushes me get-requests if a user replys an received sms.
# gateway pushes following fixed style get-params
# to my server/reply_from_gateway-action: ?id=123456&answer=Test
# => http://myserver.aaa/reply_from_gateway?id=123456&answer=Test
And now I want to add following route, since the sms gateway has a defined get parameter structure:
get "deactivate_via_sms?id=:id&answer=:answer" => "reminders#deactivate_via_sms"
:as => "deactivate_via_sms"
But that doesn't work, can you help me?
You can pull CGI-style parameters out of params by hand in your controller, you don't need (or want) them in the route:
get "deactivate_via_sms" => "reminders#deactivate_via_sms", :as => "deactivate_via_sms"
and then in RemindersController#deactivate_via_sms:
def deactivate_via_sms
id = params[:id]
answer = params[:answer]
#...
end
You can pull CGI-style parameters out of params by hand in your controller, you don't need (or want) them in the route
but in this case you can't use helpers such as
deactivate_via_sms_path(id,answer)
or you can use this code for creating helper
get "deactivate_via_sms?id=:id&answer=:answer" => "reminders#deactivate_via_sms"
:as => "deactivate_via_sms"
but your routing will fail
I resolved this issue by changing "?" to "/" in route
get "deactivate_via_sms/id=:id&answer=:answer" => "reminders#deactivate_via_sms"
:as => "deactivate_via_sms"
routing works and helper method also works fine

Resources