Twilio Quickstart Code for SMS Conversations not incrementing - ruby

I'm using labcoder's Twilio-Hackpack-for-Heroku-and-Sinatra then am following the Ruby Quickstart on Twilio's site. I've literally copied and pasted the code and it refuses to increment the counter.
The only difference between the quickstart code and my code is I use get_or_post:
get_or_post '/sms/?' do
Instead of their:
get '/sms-quickstart' do
When I use their get method with the /sms-quickstart, I get an ERROR (11200) HTTP Retrieval Failure. When I use get_or_post with /sms/?, it works, but my counter will not increment and I just keep getting the same "Hello, thanks for the new message." Here is the code from my app.rb
get_or_post '/sms/?' do
session["counter"] ||= 0
sms_count = session["counter"]
if sms_count == 0
message = "Hello, thanks for the new message."
else
message = "Hello, thanks for message number #{sms_count + 1}"
end
twiml = Twilio::TwiML::Response.new do |r|
r.Sms message
end
session["counter"] += 1
twiml.text
end

Sinatra doesn't enable sessions by default. Need to add the following to app.rb:
enable :sessions
See documentation here

Related

Unable to fetch a link from an email in the gmail when run on jenkins but works and fetches desired result locally (in the WATIR framework using ruby)

The following code when run on jenkins throws the error as 'The set password url is
invalid argument(Session info: chrome=100.0.4896.88) (Selenium::WebDriver::Error::InvalidArgumentError)
Backtrace: Ordinal0 [0x00A67413+2389011]"
STEP FILE:
When(/^the user clicks on activate online account link$/) do
on(CheckoutPage) do |page|
#sleep for 30 seconds for the email to be received
sleep 30
p #set_password_link = page.get_password_token
puts "The set password url is #{#set_password_link}"
page.navigate_to(#set_password_link)
end
end
Code FILE:
def get_password_token
begin
retries ||= 0
Gmail.new("xxxxxxx#gmail.com", "xxxxxxxx") do |gmail|
email = gmail.inbox.emails(:from => 'orders#cottonon.com', :subject => 'Activate your online account').last
html = email.html_part.body.to_s
urls = URI.extract(html, %w(https))
return urls[1]
end
rescue
retry if (retries += 1) < $code_retry
end
end
it could be number of things, maybe you just need URI.parse(urls[1]) or fetched url is invalid
also it seems like your gmail code always fetches last mail, which can return wrong one if email is still not received
Here is a gmail_check method that should be more resistant to mail content and time received
def gmail_check(url_part, receiver, timeout = 30)
time = (Time.now-5.minutes).to_i
Gmail.connect("xxxxxxx#gmail.com", "xxxxxxxx") do |gmail|
puts("Reading emails to: #{receiver}")
while (timeout > 0)
gmail.inbox.find(:gm => "\"after:#{time}\"").each do |mail|
if mail.message.to.first == receiver
content = mail.multipart? ? mail.html_part.decoded : mail.message.decoded
Nokogiri::HTML(content).css("a").each do |a|
href = a.attributes["href"].to_s
return href if href.include?(url_part)
end
end
end
puts("Waiting 5 seconds before reading mail again.")
timeout = timeout - 5
sleep 5
end
end
end
but you should be able to easily debug the problem by ssh-ing into jenkins machine,
type irb
type require gmail
paste your code there
check the url
good luck :)

Can I test that a Sinatra post method successfully saves to a YAML store?

I can't find a basic explanation anywhere about how I can test, with Rack::Test, that a Ruby/Sinatra post method successfully saves data to a YAML store/file. (This explains testing get, which I can do(!), but not post; other mentions of testing post methods with rack/test seem irrelevant.) For self-study, I'm building a "to do" app in Ruby/Sinatra and I'm trying to use TDD everything and unit test like a good little boy. A requirement I have is: When a user posts a new task, it is saved in the YML store.
I was thinking of testing this either by seeing if a "Task saved" was shown in the response to the user (which of course isn't directly testing the thing itself...but is something I'd also like to test):
assert last_response.body.include?("Task saved")
or by somehow testing that a test task's description is now in the YML file. I guess I could open up the YML file and look, and then delete it from the YML file, but I'm pretty sure that's not what I'm supposed to do.
I've confirmed post does correctly save to a YML file:
get('/') do |*user_message|
# prepare erb messages
#user_message = session[:message] if session[:message]
#overlong_description = session[:overlong_description] if
session[:overlong_description]
session[:message] = nil # clear message after being used
session[:overlong_description] = nil # ditto
#tasks = store.all
erb :index #, user_message => {:user_message => params[:user_message]}
end
post('/newtask') do
#task = Task.new(store, params)
# decide whether to save & prepare user messages
if #task.complete == true # task is complete!
#task.message << " " + "Task saved!"
session[:message] = #task.message # use session[:message] for user messages
#task.message = ""
store.save(#task)
else
#task.message << " " + "Not saved." # task incomplete
session[:message] = #task.message # use session[:message] for user messages
session[:overlong_description] = #task.overlong_description if
#task.overlong_description
#task.message = ""
#task.overlong_description = nil
end
redirect '/'
end
As you can see, it ends in a redirect...one response I want to test is actually on the slash route, not on the /newtask route.
So of course the test doesn't work:
def test_post_newtask
post('/newtask', params = {"description"=>"Test task 123"})
# Test that "saved" message for user is in returned page
assert last_response.body.include?("Task saved") # boooo
end
Github source here
If you can give me advice on a book (chapter, website, blog, etc.) that goes over this in a way accessible to a relative beginner, I'd be most grateful.
Be gentle...I'm very new to testing (and programming).
Nobody answered my question and, since I have figured out what the answer is, I thought I would share it here.
First of all, I gather that it shouldn't be necessary to check if the data is actually saved to the YAML store; the main thing is to see if the web page returns the correct result (we assume the database is groovy if so).
The test method I wrote above was correct; it was simply missing the single line follow_redirect!. Apparently I didn't realize that I needed to instruct rake/test to follow the redirect.
Part of the problem was that I simply hadn't found the right documentation. This page does give the correct syntax, but doesn't give much detail. This page helped a lot, and this bit covers redirects.
Here's the updated test method:
def test_post_newtask
post "/newtask", params = {"description" => "Write about quick brown foxes",
"categories" => "writing823"}
follow_redirect!
assert last_response.body.include?("Task saved")
assert last_response.body.include?("Write about quick brown foxes")
end
(With thanks to the Columbus Ruby Brigade.)

Cleverbot ruby irc bot

I wrote this auto-reply bot with ruby, it is supposed to autoreply with cleverbot messages when im away:
require "cleverbot"
require "cinch"
$client = Cleverbot::Client.new
def get_answer(text)
reply = $client.write text
return reply
end
bot = Cinch::Bot.new do
configure do |c|
c.nick = "mybotsnickname"
c.server = "my.irc.testserver"
c.channels = ["#mychannel"]
end
on :message do |m|
m.reply m.user
m.reply get_answer(m.message)
end
end
bot.start
It works fine but the session id changes every message. What do i have to change to keep it? best case scenario is every user writing me gets a different session id at cleverbot so they have individual conversations.
I'm pretty new to ruby.
I used: https://github.com/benmanns/cleverbot
and https://github.com/cinchrb/cinch
Comparing this to the structure of my cinch bot, I'd try the following:
1) Make get_answer a helper block and place it inside the bot = Cinch::Bot.new block:
helpers do
def get_answer(text)
reply = $client.write text
return reply
end
end
2) Replace
on :message do |m|
with
on :message do |m, text|
3) Replace
m.reply get_answer(m.message)
with
m.reply get_answer(text)
I suspect this should work. But I'm a relatively new to Ruby as well.

How to detach an attachment for POP3 using ruby net/pop?

pop = Net::POP3.new mailhost
pop.start mailuser, mailpass
if pop.mails.empty?
puts "Mailbox empty."
else
pop.mails.each do |mail|
if mail.pop.has_attachments?
mail.pop.attachments.each do |attachment|
puts attachment.original_filename
end
end
end
end
gives undefined method 'has_attachments?' for #<String:0xb7cc4f7c>.
Is this example no longer working?
mail.pop returns string representation of email see corresponding docs. If you want to parse it and work with mail object you can do it like this:
email = Mail.new(mail.pop)
I really recommend you to take a look into docs - if you'll have big attachments you can run into memory issues and this thing is explained in docs.

Catching timeout errors with ruby mechanize

I have a mechanize function to log me out of a site but on very rare occasions it times me out. The function involves going to a specific page, and then clicking on a logout button. On the occasional that mechanize suffers a timeout when either going to the logout page or clicking the logout button the code crashes. So I put in a small rescue and it seems to be working as seen below the first piece of code.
def logmeout(agent)
page = agent.get('http://www.example.com/')
agent.click(page.link_with(:text => /Log Out/i))
end
Logmeout with rescue:
def logmeout(agent)
begin
page = agent.get('http://www.example.com/')
agent.click(page.link_with(:text => /Log Out/i))
rescue Timeout::Error
puts "Timeout!"
retry
end
end
Assuming I understand rescue correctly, it will do both actions over even if just the clicking timed out, so in the effort to be efficient I am was wondering if I could use a proc in this situation and pass it a code block. Would something like this work:
def trythreetimes
tries = 0
begin
yield
rescue
tries += 1
puts "Trying again!"
retry if tries <= 3
end
end
def logmeout(agent)
trythreetimes {page = agent.get('http://www.example.com/')}
trythreetimes {agent.click(page.link_with(:text => /Log Out/i))}
end
Note in my trythreetimes function I left it as generic rescue so the function would be more re-usable.
Thanks so much for any help anyone can provide, I realize there are a couple different questions in here but they are all things I am trying to learn!
Instead of retrying some timeouts on some mechanize requests I think you'd better set Mechanize::HTTP::Agent::read_timeout attribute to a reasonable amount of seconds like 2 or 5, anyway one that prevent timeouts errors for this request.
Then, it seem's that your log out procedure only required access to a simple HTTP GET request. I mean there is no form to fill in so no HTTP POST request.
So if I were you, I would prefere inspected the page source code (Ctrl+U with Firefox or Chrome) in order to identify the link which is reached by your agent.click(page.link_with(:text => /Log Out/i))
It should be faster because these type of pages are usually blank and Mechanize will not have to load a full html web page in memory.
Here is the code I would prefer use :
def logmeout(agent)
begin
agent.read_timeout=2 #set the agent time out
page = agent.get('http://www.example.com/logout_url.php')
agent.history.pop() #delete this request in the history
rescue Timeout::Error
puts "Timeout!"
puts "read_timeout attribute is set to #{agent.read_timeout}s" if !agent.read_timeout.nil?
#retry #retry is no more needed
end
end
but you can use your retry function too :
def trythreetimes
tries = 0
begin
yield
rescue Exception => e
tries += 1
puts "Error: #{e.message}"
puts "Trying again!" if tries <= 3
retry if tries <= 3
puts "No more attempt!"
end
end
def logmeout(agent)
trythreetimes do
agent.read_timeout=2 #set the agent time out
page = agent.get('http://www.example.com/logout_url.php')
agent.history.pop() #delete this request in the history
end
end
hope it helps ! ;-)
Using mechanize 1.0.0 I got this problem from a different source of error.
In my case I was blocked by proxy and then SSL. This worked for me:
ag = Mechanize.new
ag.set_proxy('yourproxy', yourport)
ag.agent.http.verify_mode = OpenSSL::SSL::VERIFY_NONE
ag.get( url )

Resources