Skip to content

Instantly share code, notes, and snippets.

@jashsu
Last active August 29, 2015 13:56
Show Gist options
  • Save jashsu/8954912 to your computer and use it in GitHub Desktop.
Save jashsu/8954912 to your computer and use it in GitHub Desktop.
Spyglass is an email notification script for the Glass Shop.
#!/usr/bin/env python
""" Spyglass is an email notification script for the Glass Shop.
Setup:
------
Install Python 2.7.x and these additional libraries: requests, lxml.
Enter your own smtp server, smtp login details and notification email
recipient into the relevant fields in Spyglass.__init__. In order for
Spyglass to fetch the page, you will also need to copy the cookie
strings from an authenticated browser session (get this by logging
into Google on your browser, visiting getglass, and then open the
debugger and copy the cookie data from the getglass HTTP request)
If you want to use gmail as your smtp server and you have two-factor
authentication enabled, generate an application-specific password here:
https://accounts.google.com/b/0/IssuedAuthSubTokens?hide_authsub=1
Finally, uncomment the self.wishlist line(s) of the item(s) you want
to monitor.
btc: 1PEEenEG7ENJUx12wHjF8aTZBqjXmqTci7
"""
import requests, re, json, time, smtplib, sys
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from lxml import etree
from StringIO import StringIO
class ProgressBar(object):
def __init__(self):
self.counter = 0
def increment(self, n=1):
self.counter += n
def draw(self, tick='.'):
draw_out = ''
if self.counter % 50 == 0: draw_out += '\n[{}] '.format(time.ctime())
if self.counter % 10 == 0: draw_out += tick # For optional fancier gfx
else: draw_out += tick
sys.stdout.write(draw_out)
sys.stdout.flush()
def update(self, tick='.', n=1):
self.draw(tick=tick)
self.increment(n=n)
class Spyglass(object):
def __init__(self):
self.progbar = ProgressBar()
self.session = requests.Session()
self.smtp = smtplib.SMTP()
self.getglass_url = 'https://glass.google.com/getglass'
self.delay = 600 #check every 10 minutes
# vvv---FILL IN YOUR OWN DETAILS BELOW---vvv
self.smtp_server = ('smtp.gmail.com', 587)
self.email_user = 'example@gmail.com'
self.email_pass = 'examplepassword'
self.email_recipient = 'iwantboldcharcoal@example.com'
self.cookies = {
'APISID': '',
'HSID': '',
'NID': '',
'PREF': '',
'SAPISID': '',
'SID': '',
'SSID': '',
'_ga': ''}
self.wishlist = {
# 6: u'Shale Glass',
# 7: u'Charcoal Glass',
# 8: u'Cotton Glass',
# 9: u'Tangerine Glass',
# 10: u'Sky Glass',
# 1001: u'Cable and Charger',
# 1002: u'Pouch',
# 2001: u'Mono Earbud',
# 2002: u'Stereo Earbuds',
# 3001: u'Active Shade',
# 3002: u'Classic Shade',
# 3003: u'Edge Shade',
# 3004: u'Clear Shield',
# 4001: u'Curve Shale Glass Frame',
# 4002: u'Curve Charcoal Glass Frame',
# 4003: u'Curve Cotton Glass Frame',
# 4004: u'Curve Tangerine Glass Frame',
# 4005: u'Curve Sky Glass Frame',
# 4011: u'Bold Shale Glass Frame',
4012: u'Bold Charcoal Glass Frame',
4013: u'Bold Cotton Glass Frame',
# 4014: u'Bold Tangerine Glass Frame',
# 4015: u'Bold Sky Glass Frame',
# 4021: u'Thin Shale Glass Frame',
# 4022: u'Thin Charcoal Glass Frame',
# 4023: u'Thin Cotton Glass Frame',
# 4024: u'Thin Tangerine Glass Frame',
# 4025: u'Thin Sky Glass Frame',
# 4031: u'Split Shale Glass Frame',
# 4032: u'Split Charcoal Glass Frame',
# 4033: u'Split Cotton Glass Frame',
# 4034: u'Split Tangerine Glass Frame',
# 4035: u'Split Sky Glass Frame',
}
# ^^^---FILL IN YOUR OWN DETAILS ABOVE---^^^
def fetch_data(self):
response = self.session.get(self.getglass_url, cookies=self.cookies)
response_tree = etree.parse(StringIO(response.text), etree.HTMLParser(encoding = 'UTF-8'))
a = response_tree.xpath('//*[@id="contentPane"]/script[contains(., "AF_initDataCallback({key: \'ds:0")]')
b = re.findall(r'data:(.*?)}', a[0].text, re.DOTALL|re.MULTILINE)
assert(len(b) == 1)
c = re.sub(r'(,)\1+', r'\1', b[0])
d = json.loads(c)
data = {i[0]: i[1:] for i in d[1]}
return data
def send_email(self, item_name, item_id):
self.smtp.connect(*self.smtp_server)
self.smtp.ehlo()
self.smtp.starttls()
self.smtp.login(self.email_user, self.email_pass)
message = MIMEMultipart()
message['From'] = 'noreply'
message['To'] = self.email_recipient
message['Subject'] = 'ALERT: {} is in stock'.format(item_name)
html = """\
<html>
<head></head>
<body>
<p>{item_name} is in stock.<br><br>
Visit <a href="https://glass.google.com/getglass">https://glass.google.com/getglass</a> to place an order.
</p>
</body>
</html>
""".format(item_name=item_name)
message.attach(MIMEText(html, 'html'))
self.smtp.sendmail('noreply', self.email_recipient, message.as_string())
self.smtp.close()
self.progbar.update(tick='x')
def monitor(self):
sys.stdout.write('[{}] Monitoring items {}...'.format(time.ctime(), str(self.wishlist.keys())))
sys.stdout.flush()
done = False
while not done:
data = self.fetch_data()
for item_id in self.wishlist.keys():
if data[item_id][4] == 1:
self.send_email(item_name=data[item_id][5][1], item_id=item_id)
del self.wishlist[item_id]
self.progbar.update()
if len(self.wishlist) == 0:
done = True
else:
time.sleep(self.delay)
def main(args):
myspyglass = Spyglass()
myspyglass.monitor()
sys.stdout.write('\n\n')
if __name__ == '__main__':
sys.exit(main(sys.argv))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment