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.
Related
I had a previous question that helped me loop through all users where a certain question is met.
However, I'm realizing I can't hard code that condition. I need to somehow get that data from the submitted form, which doesn't seem to be possible in the mailer.
In other words, I'm trying to loop through all users where the user's state is equal to the home_state of the candidate being entered. Basically when the candidate is created, I want to get the home_state of that candidate, and then loop through all users, and for each user that has same state as that candidate, I want to send them the email via this mailer.
Here's my candidate_mailer.rb file
class CandidateMailer < ApplicationMailer
default from: 'wesleycreations#gmail.com'
def self.send_request(row)
#candidate = Candidate.new(candidate_params) # if I can access this here, how to I create the
# following array?
emails = []
User.where(state: #candidate.home_state).each do |u|
emails << u.email # To insert the user email into the array
end
emails.each do |email|
new_request(email,row).deliver_now
end
end
def new_request(email, row)
#candidate = row
mail(to: email, subject: 'New request')
end
end
But the
#candidate = Candidate.new(candidate_params)
obviously doesn't work because the params aren't available in the mailer.
Here in the candidates_controller.rb I have this
def create
#candidate = Candidate.new(candidate_params) #of course here I can access params
if #candidate.save
row = #candidate
CandidateMailer.send_request(row)
else
render('new')
end
end
SO the question is, how do I access params in rails mailer? And if I can't, then how do I refactor my code so that the lines that check if the user meets certain condition is done in the controller?
I was able to figure this out by doing this. after I saved the candidate, I saved the candidate to a global variable. and THEN I send the mailer.
def create
#candidate = Candidate.new(candidate_params)
if #candidate.save
row = #candidate
$candidate = #candidate
end
CandidateMailer.send_request(row)
else
end
end
This way the mailer had access to the new candidate that been created, and I was able to check my condition in there.
So in my mailer, when I use $candidate.home_state, it returned the correct state, mail went out, and made me very happy :)
emails = []
User.where(state: $candidate.home_state).each do |u|
emails << u.email # To insert the user email into the array
end
Hey Stackoverflow Community,
I'm new to Ruby and working on a small project for a course assignment. I've to create a mobile bot that uses the Google Translate API and returns the translated text.
I'm stuck trying to figure out how to write the code for the bot to get the inputted text and output the translation.
Could anyone have a look, please? Would really appreciate it
def transl8 (input,lang) #method to translate incoming text
# Translates some text into Russian
# Instantiates a client
translate = Google::Cloud::Translate.new project: project-217401
puts input + "Looks like you're speak in #{detection.language}"
puts "Confidence: #{detection.confidence}"
translation = translate.translate input, to: lang
return "In #{lang} that's" + translation
end
def transl8 (input,lang) #method to translate incoming text
detection = $translate.detect input
puts input + "Looks like you're speak in #{detection.language}"
puts "Confidence: #{detection.confidence}"
translation = $translate.translate input, to: lang
return "In #{lang} that's" + translation
end
def listlang #method to show language code
language_code = "en"
languages = $translate.languages
puts "Supported languages:"
languages.each do |language|
puts "#{language.code} #{language.name}"
end
end
configure :development do
require 'dotenv'
Dotenv.load
end
#Translate End-point
https://translation.googleapis.com/language/translate/v2 endpoint
get "/incoming/sms/" do
"Hey! I'm AllSpeak, a translator bot. The list of supported languages are
below. Just ask by typing (TEXT) (space) (Language Code)"
incoming_text = params['Body']
text_to_translate = incoming_text.split(' ')[0]
lang_requested = incoming_text.split(' ')[1]
twiml_body = transl8(text_to_translate, lang_requested)
#return twiml here with twiml_body
end
#Look into Including method to set default language for commonly used
phrases
puts listlang
transl8 (text)
# Build a twilio response object
twiml = Twilio::TwiML::MessagingResponse.new do |r|
r.message do |m|
end
end
Regarding the Translation API Code:
For listlang:
You're missing an end on the do loop and you're not setting the project_id variable
For transl8:
You're not initializing the detection variable
Sample code:
#!/usr/bin/ruby
require "google/cloud/translate"
$translate = Google::Cloud::Translate.new project: "slatebot-217401"
def transl8 (input,lang) #method to translate incoming text
detection = $translate.detect input
puts input + "Looks like you're speak in #{detection.language}"
puts "Confidence: #{detection.confidence}"
translation = $translate.translate input, to: lang
return "In #{lang} that's" + translation
end
def listlang #method to show language code
language_code = "en"
languages = $translate.languages
puts "Supported languages:"
languages.each do |language|
puts "#{language.code} #{language.name}"
end
end
Jarod from Twilio. I noticed your question and wanted to suggest you parse the users SMS that would be incoming to your "incoming/sms". Once you have configured your phone number to make a GET request to "incoming/sms" Twilio will start sending incoming SMS to that URL. When Twilio does this it will also pass you a bunch of information in the http request. The incoming SMS body is passed as the Body in the request. So you could do something like this
get '/incoming/sms' do
incoming_text = params['Body']
text_to_translate = incoming_text.split(' ')[0]
lang_requested = incoming_text.split(' ')[1]
twiml_body = transl8(text_to_translate, lang_requested)
#return twiml here with twiml_body
end
Does that make sense? Looks like your twiml method is mostly ready to go so just insert that at the end of your response and you should be good to go! Fun app. Excited to see it finished!
I've managed to send emails via Google API thanks to the google-api-client gem:
def send_message(from:, to:, subject:, body:)
message = RMail::Message.new
message.header['From'] = from
message.header['To'] = to
message.header['Subject'] = subject
message.body = body
#service.send_user_message(
'me',
upload_source: StringIO.new(message.to_s),
content_type: 'message/rfc822'
)
end
Now I'm trying to attach files to the emails, but I couldn't find examples on how to do it. The example included in the gem's repository doesn't explain the case. I've started doing reverse engineering, but after almost the whole day making attempts I've started doing crazy things.
My last attempt was the following:
upload = Google::Apis::Core::UploadIO.new('/path/to/image.png', 'image/png', 'image.png')
file_part = Google::Apis::Core::FilePart.new(nil, upload)
message_object = Google::Apis::GmailV1::Message.new(payload: file_part, raw: 'this is a test body')
service.send_user_message('me', message_object, content_type: 'message/rfc822')
The Email was bounced.
What's the proper way to attach files?
Turns out it was easier than I expected. Here is an example:
class Client
def initialize(service)
#service = service
end
def send_message(from:, to:, subject:, body:)
message = RMail::Message.new
message.header.set('From', from)
message.header.set('To', to)
message.header.set('Subject', subject)
message.body = [text_part(body), file_part]
#service.send_user_message(
'me',
upload_source: StringIO.new(message.to_s),
content_type: 'message/rfc822'
)
end
private
def text_part(body)
part = RMail::Message.new
part.body = body
part
end
def file_part
part = RMail::Message.new
part.header.set('Content-Disposition', 'attachment', 'filename' => File.basename('/path/to/image.png'))
part.body = File.read('/path/to/image.png')
part
end
end
I'll wait for further responses, maybe there's something I'm not taking into account.
I am working on a project that returns SMS messages to a user who has just sent a SMS message to the server.
The process is:
The user sends a SMS message to the server.
The server will send two SMS messages back to this user. Note that these are two separate short messages and will be sent pretty much at the same time.
I've got the sending part working, but just for sending one SMS message, not two. When I add more code to send another message only the second message part works, which means only the second message has been sent out, the first message has been ignored.
The code looks pretty much like:
else
sms = SMS.create(:body => params['Body'], :from => params['From'], :to => params['To'], :created_at => Time.now)
#return a random saved sms
return_secret = SMS.first(:offset => rand(SMS.count))
twiml = Twilio::TwiML::Response.new do |r|
r.Sms return_secret.body
#send another message to remind user for rating
ask_rating = remind_rating
if ask_rating
twiml = Twilio::TwiML::Response.new do |r|
r.Sms ask_rating
end
twiml.text
end
Does anyone know how to send two messages in Twilio?
You've got some variable shadowing going on with twiml. As you wrote it, the second message's code is inside of the first message's block. Yet, you refer to a variable with the same name as one outside of the block. I would try flattening your code so you aren't nesting like that.
I think the issue here is you're instantiating a second TwiML::Response object when you already have one, so you can just references the previous one which you assigned to r in the first block. You also called it r in the second block so you just remove the block that encloses it:
sms = SMS.create(:body => params['Body'], :from => params['From'], :to => params['To'], :created_at => Time.now)
#return a random saved sms
return_secret = SMS.first(:offset => rand(SMS.count))
twiml = Twilio::TwiML::Response.new do |r|
r.Sms return_secret.body
#send another message to remind user for rating
ask_rating = remind_rating
if ask_rating
r.Sms ask_rating
end
end
Also the blocks weren't balanced in the initial code snippet so I stripped out the else to make it syntactically accurate.
Thank you all, really appreciate your replies.
After consulting with twilio team, they gave me an example like this:
require 'rubygems'
require 'twilio-ruby'
require 'sinatra'
get '/sms-quickstart' do
twiml = Twilio::TwiML::Response.new do |r|
r.Message "Hey Monkey. Thanks for the message!"
r.Message "this is the 2nd message"
end
twiml.text
end
I just deleted
if ask_rating
twiml = Twilio::TwiML::Response.new do |r|
everything works...
Heres a piece of code from my irc bot. What it does is that it checks for new tweets at an specific account, then replies it in the channel.
Now, is there an better way to check for new tweets? that for i in 1..999999999 feels a bit unoptimal, and ddos'y.
tweetzsr = {}
xzsr = {}
zsr = {}
on :message, ".start zsr" do |m|
if zsr[m.channel] == true
m.reply "already doing it.."
else
m.reply "ok."
zsr[m.channel] = true
for i in 1..99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
sleep 60
puts "#{xzsr[m.channel]} = x, tweetzsr = #{tweetzsr[m.channel]}"
tweetzsr[m.channel] = Twitter.user_timeline("twiitterracount").first.text
if xzsr[m.channel] == tweetzsr[m.channel]
nil
else
m.reply "#{tweetzsr[m.channel]} - via twitter feed"
xzsr[m.channel] = tweetzsr[m.channel]
end
end
end
end
First of all, for an infinite loop use the loop method.
Best for this kind of thing is to use Twitter's streaming api. This api will send a single request to Twitter, which will then push any new data to your client. For that there is a gem called TweetStream.
Example usage:
TweetStream::Client.new.userstream do |status|
m.reply "#{status.text} - via twitter"
end
Is that your infinite loop?
Change it to this to improve sanity
loop do
sleep 60
newtweet[m.channel] = Twitter.user_timeline("twitteracount").first.text
next if oldtweet[m.channel] == newtweet[m.channel]
m.reply "#{newtweet[m.channel]} - via twitter"
oldtweet[m.channel] = newtweet[m.channel]
end
You're missing the two end keywords.