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!!
Good stuff.
ReplyDeletethank you for your post.