Twilio - Save SMS body, sid and sender in Ruby - ruby

I have followed the guide here to set up a sinatra app that successfully receives and responds to a text sent to my Twilio account.
require 'sinatra'
require 'twilio-ruby'
post '/receive_sms' do
content_type 'text/xml'
response = Twilio::TwiML::Response.new do |r|
r.Message 'Message recieved'
end
response.to_xml
end
How can I retrieve the SMS body, sender, and SID of the message and store them as a variable? Ex: body = "Test message"
I have tried adding response.text to return the xml response and possibly parse the output but did not have any luck with this.

Twilio developer evangelist here.
The message parameters are sent as form encoded parameters, which luckily Sinatra already reads for you. You can get the body, sender and SID like so:
require 'sinatra'
require 'twilio-ruby'
post '/receive_sms' do
body = params["Body"]
sid = params["MessageSid"]
sender = params["From"]
content_type 'text/xml'
response = Twilio::TwiML::Response.new do |r|
r.Message 'Message recieved'
end
response.to_xml
end
You can see all the parameters available in Twilio's request in the documentation.

Related

OAuth error in using twitter API v2 for posting a tweet

Now I took a sample code of Twitter v2 API from this link. This sample code shows how OAuth and twitter v2 API work for positng a tweet. It works fine with my consumer key and consumer secret.
And I want to simplify the code like below. It assumes that the access token and access token secret are already known and it skips the process of user's approval, like providing the URL that provides PIN.
require 'typhoeus'
require 'json'
consumer_key = CONSUMER_KEY
consumer_secret = CONSUMER_SECRET
token = ACCESS_TOKEN
token_secret = ACCESS_TOKEN_SECRET
consumer = OAuth::Consumer.new(consumer_key, consumer_secret, :site => 'https://api.twitter.com')
options = {
:method => :post,
headers: {
"User-Agent": "v2CreateTweetRuby",
"content-type": "application/json"
},
body: JSON.dump("Hello, world!")
}
create_tweet_url = "https://api.twitter.com/2/tweets"
request = Typhoeus::Request.new(create_tweet_url, options)
access_token = OAuth::Token.new(token, token_secret)
oauth_params = {:consumer => consumer, :token => access_token}
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => create_tweet_url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
puts response
Then, I see the below error message.
ruby test_tweet.rb
/usr/local/lib/ruby/gems/3.1.0/gems/oauth-0.5.10/lib/oauth/request_proxy.rb:18:in `proxy': Typhoeus::Request (OAuth::RequestProxy::UnknownRequestType)
from /usr/local/lib/ruby/gems/3.1.0/gems/oauth-0.5.10/lib/oauth/signature.rb:12:in `build'
from /usr/local/lib/ruby/gems/3.1.0/gems/oauth-0.5.10/lib/oauth/signature.rb:23:in `sign'
from /usr/local/lib/ruby/gems/3.1.0/gems/oauth-0.5.10/lib/oauth/client/helper.rb:49:in `signature'
from /usr/local/lib/ruby/gems/3.1.0/gems/oauth-0.5.10/lib/oauth/client/helper.rb:82:in `header'
from test_tweet.rb:28:in `<main>'
When I used irb and tried step by step, this error happens at oauth_helper.header. As this is the first time to use OAuth API, I may be making some easy mistakes. Does anybody find anything wrong in my code?
I confirmed that my access token and access token secret work at https://web.postman.co/.
Thanks.
You need to insert
require 'oauth/request_proxy/typhoeus_request'
and your code may complete task you desire.
Other lines looks good to me!
In oauth/request_proxy.rb, oauth library check class of request object.
https://github.com/oauth-xx/oauth-ruby/blob/master/lib/oauth/request_proxy.rb
return request if request.is_a?(OAuth::RequestProxy::Base)
klass = available_proxies[request.class]
# Search for possible superclass matches.
if klass.nil?
request_parent = available_proxies.keys.find { |rc| request.is_a?(rc) }
klass = available_proxies[request_parent]
end
raise UnknownRequestType, request.class.to_s unless klass
By requiring 'oauth/request_proxy/typhoeus_request', Typhoeus::Request inherits OAuth::RequestProxy::Base and raising UnknownRequestType error can be avoided.
https://github.com/oauth-xx/oauth-ruby/blob/master/lib/oauth/request_proxy/typhoeus_request.rb

After create user by firebase authentication, is there a way to generate email verification link and send it to the user?

Below is code to create user by firebase authentication.
require 'google/apis/identitytoolkit_v3'
service_account = "./firebase-auth.json"
service = Google::Apis::IdentitytoolkitV3::IdentityToolkitService.new
service.authorization = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io: File.open(service_account),
scope: 'https://www.googleapis.com/auth/identitytoolkit'
)
request = Google::Apis::IdentitytoolkitV3::SignupNewUserRequest.new(
email: 'sample#example.com',
email_verified: false
)
service.signup_new_user(request)
After create user, I want to send email link for sign-in automatically.Maybe it's possible by Node.js, Java, Python, and Go because they're supported officially. https://firebase.google.com/docs/auth/admin/email-action-links#node.js_3
Is there a way to do that by ruby-client? (I just want to send email below)
Email template at firebase console
Even if ruby-client doesn't provide the option, you should be able to implement the API client from scratch like below. (Look up official document more carefully.)
require 'net/http'
require 'uri'
require 'json'
uri = URI.parse("https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=[YOUR_API_KEY]")
request = Net::HTTP::Post.new(uri)
request.content_type = "application/json"
request.body = JSON.dump({requestType: "PASSWORD_RESET",email: "[EMAIL_OF_THE_USER]"})
response = Net::HTTP.start(uri.host, uri.port, { use_ssl: true }) do |http|
http.request(request)
end

Mocking a post request with binary data in Sinatra

I have an endpoint in my Sinatra application that will be receiving binary data as part of the body. The other application sending it data will have a Faraday request that looks like this:
connection = Faraday.new(url: "https://example.com/post_data") do |conn|
conn.request :multipart
conn.adapter :net_http
conn.headers['Content-Type'] = 'octet/stream'
end
#response ||= connection.post do |req|
req.params = { :host => host,
:verification => "false"}
req.body = my_base64_encoded_binary
end
Then, in Sinatra, I will have an endpoint that receives those request parameters and binary data and passes it along to a model, like so:
post '/post_data' do
request.body.rewind
payload = request.body.read
raise Sinatra::NotFound unless payload and params[:host]
output = MyOutput.new(params, payload)
content_type 'application/json'
body output.data
end
When I try to test this endpoint using Rack::Test helpers, I end up in a weird situation. I can't seem to create the proper mock in order to test this endpoint properly. Based on some manual testing with PostMan, I'm pretty certain my endpoint works properly. It's just the test that's holding me up. Here is the spec:
it "should return a json response" do
post(url, :host => host, :verification => "false") do |req|
req.body = [my_binary]
req.content_type = "application/octet-stream"
end
expect(last_response.status).to eq(200)
expect(last_response.content_type).to eq("application/json")
end
And when I inspect what the incoming request looks like in the test, it does not contain a proper body. params is properly set to the host and verification settings I set, but the body is also being set to the params (inspected through payload = request.body.read) instead of the binary.
Is there a different way to set up the mock so that the binary properly is set to the body of the request, and the parameters are still set to the request parameters properly?
The answer is that the only way to post the body is where I was adding the params in the rack test helper. I needed to take the params and move them into the query string of the URL in the request, and then only add the binary as the body of the post request in the test helper.
let(:url) { "http://example.com/post_data?host=>#{host}&verification=#{verification}" }
it "should return a json response" do
post(url, my_binary)
expect(last_response.status).to eq(200)
expect(last_response.content_type).to eq("application/json")
end

Sending multipart mails and attachments

I am trying to send an E-Mail using the gem 'mail' with Ruby 1.9.3. It contains an text/html and an text/plain part which should be embedded as alternative parts as well an attachment.
This is my current code:
require 'mail'
mail = Mail.new
mail.delivery_method :sendmail
mail.sender = "me#example.com"
mail.to = "someguy#example.com"
mail.subject = "Multipart Test"
mail.content_type = "multipart/mixed"
html_part = Mail::Part.new do
content_type 'text/html; charset=UTF-8'
body "<h1>HTML</h1>"
end
text_part = Mail::Part.new do
body "TEXT"
end
mail.part :content_type => "multipart/alternative" do |p|
p.html_part = html_part
p.text_part = text_part
end
mail.add_file :filename => "file.txt", :content => "FILE"
mail.deliver!
It results in an mail with working alternative parts but no attachment. I am using thunderbird 10.0.12 for testing.
I already posted this on github, but unfortunately the posts don't make me smarter. https://github.com/mikel/mail/issues/118#issuecomment-12276876. Maybe somebody is able to understand the last post a bit better than me ;)
Is somebody able to get this example working?
Thanks,
krissi
I managed to fix it like so:
html_part = Mail::Part.new do
content_type 'text/html; charset=UTF-8'
body html
end
text_part = Mail::Part.new do
body text
end
mail.part :content_type => "multipart/alternative" do |p|
p.html_part = html_part
p.text_part = text_part
end
mail.attachments['some.xml'] = {content: Base64.encode64(theXML), transfer_encoding: :base64}
mail.attachments['some.pdf'] = thePDF
mail.content_type = mail.content_type.gsub('alternative', 'mixed')
mail.charset= 'UTF-8'
mail.content_transfer_encoding = 'quoted-printable'
Not intuitive at all, but reading the Pony source code kinda helped, as well as comparing a working .eml to whatever this gem was generating.
This seems to be a bug regarding the content type of the attachment. See https://github.com/mikel/mail/issues/522

Ruby Mechanize, Nokogiri and Net::HTTP

I am using Net::HTTP for HTTP requests and getting a response back:
uri = URI("http://www.example.com")
http = Net::HTTP.start(uri.host, uri.port, proxy_host, proxy_port)
request = Net::HTTP::Get.new uri.request_uri
response = http.request request # Net::HTTPResponse object
body = response.body
If I have to use the Nokogiri gem in order to parse this HTML response I will do:
nokogiri_obj = Nokogiri::HTML(body)
But if I want to use Mechanize gem I need to do this:
agent = Mechanize.new
mechanize_obj = agent.get("http://www.example.com")
Is it possible for me to use Net::Http for getting the HTML response and then use the Mechanize gem to convert it into a Mechanize object instead of using agent.get()?
EDIT:
The reason for getting around the agent.get() method is because I am trying to use EventMachine::Iterator to make concurrent EM-HTTP requests.
EventMachine.run do
EM::Iterator.new(urls, 3).each do |url,iter|
puts "giving #{url} to httprequest now"
http = EM::HttpRequest.new(url).get
http.callback { |resp|
uri = resp.send(:URI, url)
puts "inside callback of #{url}"
body = resp.response
page = agent.parse(uri, resp, body)
}
iter.next
end
end
But its not working. I am getting an error:
/usr/local/rvm/gems/ruby-1.9.3-p194/gems/mechanize-2.5.1/lib/mechanize.rb:1165:in`parse': undefined method `[]' for #<EventMachine::HttpClient:0x0000001c18eb30> (NoMethodError)
when I use the parse method for Net::HTTP it works fine and I get the Mechanize object:
uri = URI("http://www.example.com")
http = Net::HTTP.start(uri.host, uri.port, proxy_host, proxy_port)
request = Net::HTTP::Get.new uri.request_uri
response = http.request request # Net::HTTPResponse object
body = response.body
agent = Mechanize.new
page = agent.parse(uri, response, body)
Am I passing the wrong arguments for the parse method while using em-http?
I'm not sure why you think using Net::HTTP would be better. Mechanize will handle redirects and cookies, plus provides ready access to Nokogiri's parsed document.
require 'mechanize'
agent = Mechanize.new
page = agent.get('http://www.example.com')
# Use Nokogiri to find the content of the <h1> tag...
puts page.at('h1').content # => "Example Domains"
Note, setting the user_agent isn't necessary to reach example.com.
If you want to use a threaded engine to retrieve pages, take a look at Typhoeous and Hydra.
Looks like Mechanize has a parse method, so this could work:
mechanize_obj = Mechanize.parse(uri, response, body)

Resources