Skip to content

Instantly share code, notes, and snippets.

@kainage
Created April 21, 2017 17:52
Show Gist options
  • Save kainage/c18063d49d38c95ed5f2e897eb8674c8 to your computer and use it in GitHub Desktop.
Save kainage/c18063d49d38c95ed5f2e897eb8674c8 to your computer and use it in GitHub Desktop.
Get Dat NES Classic Brah
require 'json'
require 'open-uri'
require 'nokogiri'
require 'byebug'
require 'logger'
# OPTIONS #
# In Seconds
INTERVAL = 5
EMAIL = 'YOUR_EMAIL_HERE'
VERBOSE = ENV['VERBOSE']
USE_PROXY = ENV['PROXY']
# UA #
HEADERS = {
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'
}
# PRICE CHECKS #
# [ <Name (Just for logging & email)>, <Link to product page>, <Desired Price>]
AMAZON_PRICE_CHECKS = [
# ['Amazon.ca: Clippers', 'https://www.amazon.ca/dp/B0009XH6ZA', 100.00]
]
# STOCK CHECKS #
# [ <Name (Just for logging & email)>, <Link to product page>]
AMAZON_CA = {
'Amazon.ca: NES Classic' => 'https://www.amazon.ca/Nintendo-Entertainment-System-NES-Classic/dp/B01IFJBQ1E'
}
AMAZON_IT = {
}
AMAZON_DE = {
}
TRU = {
}
PROXIES = [
['207.99.118.74', 8080],
['45.63.48.26', 3128],
['71.205.192.36', 3128],
]
module StockHunter
module_function
def hunt
attack
rescue => e
log_error(e, 'StandardError')
hunt
end
def attack
loop do
check_amazon_ca_prices
check_amazon_ca
# check_amazon_it
# check_amazon_de
end
end
# PRICE CHECKING #
def check_amazon_ca_prices
AMAZON_PRICE_CHECKS.each do |name, url, target|
doc = fetch_page(name, url)
next unless doc
text = doc.search("span#priceblock_ourprice").text
raw = text.match(/\d+\..+/)
price = raw[0]&.to_f if raw
check_price(doc, name, url, price) do
if price
price < target
else
false
end
end
snooze
end
end
# STOCK CHECKING #
def check_amazon_ca
AMAZON_CA.each do |name, url|
doc = fetch_page(name, url)
next unless doc
stock = doc.css('div#merchant-info').text if doc
check_stock(doc, name, url) do
stock.match('sold by Amazon')
end
snooze
end
end
def check_amazon_it
AMAZON_IT.each do |name, url|
doc = fetch_page(name, url)
next unless doc
stock = doc.css('div#merchant-info').text if doc
check_stock(doc, name, url) do
stock.match('Venduto e spedito da Amazon')
end
snooze
end
end
def check_amazon_de
AMAZON_DE.each do |name, url|
doc = fetch_page(name, url)
next unless doc
stock = doc.css('div#availability_feature_div').text if doc
check_stock(doc, name, url) do
stock.match('Verkauf und Versand durch') && stock.match('Amazon')
end
snooze
end
end
def check_indigo
INDIGO.each do |name, url|
doc = fetch_page(name, url)
next unless doc
stock = doc.css('div.pricing-box').text if doc
check_stock(doc, name, url) do
stock.match('In stock online')
end
snooze
end
end
def check_bb
BB.each do |name, url|
doc = fetch_page(name, url)
next unless doc
stock = doc.css('div#schemaorg-offer').text if doc
check_stock(doc, name, url) do
stock.match('In Stock')
end
snooze
end
end
def check_tru
TRU.each do |name, url|
doc = fetch_page(name, url)
next unless doc
stock = doc.css('div#buy-interior').xpath('//comment()').text if doc
check_stock(doc, name, url) do
stock.match('In Stock')
end
snooze
end
end
# PRICE CHECKING #
def check_price(doc, name, url, price, &block)
if doc && block.call
alert_price(url, name, price)
else
log_not_cheaper(name, price)
end
end
def alert_price(url, name, price)
msg = "🎉 HOLY MOLY! #{name} is #{price}!!"
logger.info msg
puts msg if VERBOSE
send_email(url, msg)
end
def log_not_cheaper(name, price)
msg = "🙁 #{name} is still #{price}"
logger.info msg
puts msg if VERBOSE
end
# STOCK CHECKING #
def check_stock(doc, name, url, &block)
if doc && block.call
alert_in_stock(url, name)
else
log_not_in_stock(name)
end
end
def alert_in_stock(url, name)
msg = "🎉 HOLY MOLY! #{name} is in stock!!"
logger.info msg
puts msg if VERBOSE
send_email(url, msg)
end
def log_not_in_stock(name)
msg = "🙁 #{name} is not in stock"
logger.info msg
puts msg if VERBOSE
end
# COMMON #
def fetch_page(name, url)
ip, port = PROXIES.rotate!.first
file =
if USE_PROXY
open(url, HEADERS.merge(proxy: "http://#{ip}:#{port}"))
else
open(url, HEADERS)
end
Nokogiri::HTML(file)
rescue => e
log_error(e, name, ip)
false
end
def send_email(url, msg)
to = EMAIL
subject = msg
content = url
`echo "#{content}" | mailx -s "#{subject}" #{to}`
end
def log_error(e, name, ip)
msg = "#{ip} -- #{name} - #{e.message}"
logger.error msg
puts msg if VERBOSE
end
def logger
Logger.new('stock_hunter.log')
end
def snooze
sleep(INTERVAL)
end
end
if __FILE__ == $0
puts 'Running ...'
StockHunter.hunt
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment