Pages

Wednesday, August 31, 2011

Install Ruby gems when behind a proxy

There are many posts out there on the net instructing you to do certain thing when behind a proxy. Different things work for different people, but none of that worked for me. So, try this one if you are facing trouble with proxy too, and keep your fingers crossed! I am using Ruby 1.9.2, with gems version 1.7.2 on Windows 7. The below command allowed me to use proxy and download and install any gem.


gem install gemname -p http://username:password@proxyaddress:port --platform=ruby

Thursday, August 25, 2011

Send SMS Using Ruby and Send Email using Ruby with Gmail SMTP Server

There was a HP Touchpad sale event where HP tablets where being sold out for $99 yesterday. Instead of manually monitoring the HP website, I decided to write a small Ruby script that will monitor and send SMS and Email to notify. I wanted to use Gmail SMTP server for mail, but that does work by default with Ruby SMTP support as it uses TLS. Finally, I found a ruby script on the internet which provides that support. I have copy pasted it from that website. There are many scripts out there on web, but none really work with gmail. Hence, it is important to spread this script. To send SMS I use the free http://www.textsurprise.com service by making GET request using open-uri. The best thing about Ruby syntax is, its readable and need no explanation.

# Requests the HP page for 16GB Tablet URL:http://www.shopping.hp.com/product/rts_tablet/rts_tablet/1/storefronts/FB355UA%2523ABA?aoid=35252
# If status "Coming soon" is not displayed then alert using SMS and email
# SMS: http://www.textsurprise.com
# Email: Uses gmail as sender smtp

require 'open-uri'
require 'net/smtp'
require_relative 'smtp_tls'

URL_16GB = 'http://www.shopping.hp.com/product/rts_tablet/rts_tablet/1/storefronts/FB355UA%2523ABA?aoid=35252'
URL_32GB = 'http://www.shopping.hp.com/webapp/product/rts_tablet/rts_tablet/1/storefronts/FB359UA%2523ABA?aoid=35252'
$carriers = {:auto => 0, :att => 3, :tmobile => 11, :metropcs => 12, :verizon => 16, :virgin => 21, :sprint => 9}
$numbers = {"XXXXXXXXXX" => :att}
$emails = ["xxxxxx@gmail.com"]
$notInterestedStatuses = ["Coming soon", "not found", "outofstock"]
$urls = {[URL_16GB,"HP_Website_16GB",$notInterestedStatuses] => false, [URL_32GB,"HP_Website_32GB",$notInterestedStatuses] => false}
$running = true;
$sleepTimeInSec = 240

def send_email(to,subject,message)
username = 'xxxxxxxxx'
password = 'yyyyyyyyyy'
emailMessage = <<MESSAGE_END
From: Shreyas Purohit <xxxxxxxxxx@gmail.com>
To: #{to} <#{to}>
Subject: #{subject}

#{message}
MESSAGE_END

Net::SMTP.start( 'smtp.gmail.com' ,
587,
'gmail.com',
username,
password,
'plain' ){ |smtp|
smtp.send_message( emailMessage,
"xxxxxxxxxx@gmail.com",
to)
}
end

def readWebsite(url)
uriContent = ""
open(url){|f| uriContent = f.read }
return uriContent
end

def notifyObservers(customMessage, url)
# Send SMS using URL
$numbers.each do |key, value|
open("http://www.textsurprise.com/a.php?api=true&from=purohit@hotmail.com&phone=#{key.to_s}&amount=1&message=Check_HP_website_,_status_changed_#{customMessage}&carrier=#{$carriers[value].to_s}&data=0"){|f|
p f.read}
end

send_email($emails,"Alert- Website Update","Alert! Website Status Changed. Please Check Online (#{customMessage}) (#{url})")

end

def checkStatusOnWebsiteString(uriContent, statusNotOfInterestOnSite)
statusNotOfInterestOnSite.each do |status|
if (uriContent.include? status)
return false
end
end
return true
end

def logToFile(fileName, mode, content)
File.open(fileName, mode) {|f| f.write(content) }
end

def process(urls)
checkedStatusOnce = false
statusChangedKeys = []

urls.each do |key, status|
url = key[0];
customMessage = key[1];
if !status
checkedStatusOnce = true
p "#{Time.now} : Trying HP Site #{customMessage} Now..."
uriContent = readWebsite(url);
statusChanged = checkStatusOnWebsiteString(uriContent,key[2])
logToFile("alter_#{customMessage}.log", "w+", "URI DATA AT " + Time.now.to_s + " for url #{url} \n" + uriContent)
if statusChanged
p "Status changed..(#{customMessage}) Notifying Observers.."
notifyObservers(customMessage, url)
statusChangedKeys << key
else
p "Status Not Changed... (#{customMessage})"
end
end
end

statusChangedKeys.each do |key|
urls[key] = true
end

if !checkedStatusOnce
$running = false
end
end

while $running do
p "#{Time.now} : Sleeping #{$sleepTimeInSec} sec(#{$sleepTimeInSec/60.0} min)..."
sleep($sleepTimeInSec)
process($urls)
end

Also, The script smtp_tls.rb is below that is required for the above script to run.
require "openssl"
require "net/smtp"

Net::SMTP.class_eval do
private
def do_start(helodomain, user, secret, authtype)
raise IOError, 'SMTP session already started' if @started
check_auth_args user, secret, authtype if user or secret

sock = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
@socket = Net::InternetMessageIO.new(sock)
@socket.read_timeout = 60 #@read_timeout
@socket.debug_output = STDERR #@debug_output

check_response(critical { recv_response() })
do_helo(helodomain)

raise 'openssl library not installed' unless defined?(OpenSSL)
starttls
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.sync_close = true
ssl.connect
@socket = Net::InternetMessageIO.new(ssl)
@socket.read_timeout = 60 #@read_timeout
@socket.debug_output = STDERR #@debug_output
do_helo(helodomain)

authenticate user, secret, authtype if user
@started = true
ensure
unless @started
# authentication failed, cancel connection.
@socket.close if not @started and @socket and not @socket.closed?
@socket = nil
end
end

def do_helo(helodomain)
begin
if @esmtp
ehlo helodomain
else
helo helodomain
end
rescue Net::ProtocolError
if @esmtp
@esmtp = false
@error_occured = false
retry
end
raise
end
end

def starttls
getok('STARTTLS')
end
end

So, that’s it! Have fun reusing code!!