You are not logged in.
Pages: 1
Hi folks. I don't know if any of you follow Steep And Cheap (SAC), but I'm a climber and a runner and I like paying very little for things I don't really need, so I do. All of their notification tools are slow or windows-only, so I wrote my own.
No, I don't work for them.
sac.py
#!/usr/bin/python
"""
SAC Notification Tool v0.1
(c) 2007 Michael Seiler
"""
import urllib, htmllib, formatter
from pynotify import *
import time
class MyParser(htmllib.HTMLParser):
"""
MyParser
Parse incoming SAC data into a product name and price details
"""
def start_div(self, attrs):
if len(attrs) > 0:
for attr in attrs:
if attr[0] == 'id':
if attr[1] == 'price':
self.price_flag = 1
elif attr[1] == 'percent_off':
self.price_flag = 1
elif attr[1] == 'product':
self.product_flag = 1
def end_div(self):
self.price_flag = 0
self.product_flag = 0
def start_h2(self, attrs):
if self.product_flag:
self.product_title_flag = 1
def end_h2(self):
self.product_title_flag = 0
def handle_data(self, text):
if self.price_flag:
self.pricing.append(text)
elif self.product_title_flag:
self.product = text
def clear_buffers(self):
self.pricing = []
self.product = ""
def __init__(self):
null_format = formatter.NullFormatter()
htmllib.HTMLParser.__init__(self, null_format)
self.pricing = []
self.product = ""
self.price_flag = 0
self.product_flag = 0
self.product_title_flag = 0
def notify(title, message):
"""Show notification"""
init('sac.py')
a = Notification(title, message)
a.set_urgency(URGENCY_LOW)
a.set_timeout(EXPIRES_DEFAULT)
a.show()
if __name__ == '__main__':
old_product = ""
p = MyParser()
while True:
data = urllib.urlopen('http://www.steepandcheap.com').read()
p.feed(data)
p.close()
new_product = p.product
new_pricing = " - ".join(p.pricing)
if new_product != old_product:
if new_product:
notify(new_product, new_pricing)
old_product = new_product
p.clear_buffers()
time.sleep(15)
This requires python-notify, which is in community. And python, obviously.
It checks SAC for updates every 15 seconds and pops up (using libnotify) a little window with the item and the pricing details (Price - Percent Off) if it finds something new.
To run, just run sac.py and forget about it.
If for some reason you want to check slower (or, better yet, check faster), change time.sleep(15) to time.sleep(SECONDS), where SECONDS is how long you want it to wait. The windows desktop tool checks every 30 seconds, for reference.
Hope there's someone out there that can use this!
Last edited by buttons (2007-12-08 22:39:32)
Cthulhu For President!
Offline
Update.
Changelog:
Now adds a buy link. And an icon, to make it look nice.
Added comments, so you can follow along at home
Made it easier to change the time between checks (it's in the constants)
Won't die if your internet connection does, or SAC goes down
#!/usr/bin/python
"""
SAC Notification Tool v0.2
(c) 2007 Michael Seiler
"""
import urllib, htmllib, formatter
from pynotify import *
import gtk, gobject
#Global Constants
TIMEOUT = EXPIRES_DEFAULT #Time in milliseconds for the popup to stick around
#Use EXPIRE_DEFAULT for the default or EXPIRE_NEVER for forever
WEBSITE = 'http://www.steepandcheap.com' #SAC Website
CHECK_DELAY = 15 #Time in seconds between website checks
class MyParser(htmllib.HTMLParser):
"""
MyParser
Parse incoming SAC data into a product name and price details
USAGE: p = MyParser()
p.feed(some_html)
p.close()
Methods:
clearbuffers()
Clears cached price and product data
getproduct()
Returns the product name
getpricing()
Returns the price and percent off
"""
def start_div(self, attrs):
"""Called at the start of each DIV tag"""
if len(attrs) > 0:
for attr in attrs:
if attr[0] == 'id':
if attr[1] == 'price':
self.price_flag = 1
elif attr[1] == 'percent_off':
self.price_flag = 1
elif attr[1] == 'product':
self.product_flag = 1
def end_div(self):
"""Called at the end of each DIV tag"""
self.price_flag = 0
self.product_flag = 0
def start_h2(self, attrs):
"""Called at the start of each H2 tag"""
if self.product_flag:
self.product_title_flag = 1
def end_h2(self):
"""Called at the end of each H2 tag"""
self.product_title_flag = 0
def handle_data(self, text):
"""Called on any text between tags"""
if self.price_flag:
self.pricing.append(text)
elif self.product_title_flag:
self.product = text
def clear_buffers(self):
"""Clear cached price and product data"""
self.pricing = []
self.product = ""
def getproduct(self):
"""Return product name"""
return self.product
def getpricing(self):
"""Return price and percent off"""
return " - ".join(self.pricing)
def __init__(self):
null_format = formatter.NullFormatter()
htmllib.HTMLParser.__init__(self, null_format)
self.pricing = []
self.product = ""
self.price_flag = 0
self.product_flag = 0
self.product_title_flag = 0
class SACNotify(object):
"""
SACNotify
Handle notification and gtk interaction
USAGE: s = SACNotify()
s.main()
Creates a timeout that downloads information from SAC every 15s,
then pops up a notification using pynotify if it finds a different product.
"""
def notify(self, title, message):
"""Show notification, adding a buy link"""
init('sac.py')
message += "\n<a href='%s'>Buy this item</a>" % WEBSITE
a = Notification(title, message, gtk.STOCK_DIALOG_WARNING)
a.set_urgency(URGENCY_LOW)
a.set_timeout(TIMEOUT)
a.show()
def read_data(self):
"""Read data from the SAC website, then call the parser"""
try:
self.data = urllib.urlopen(WEBSITE).read()
except:
#No interweb connection? SAC down?
self.data = None
if self.data:
self.parser.feed(self.data)
self.parser.close()
def site_poll_timeout(self):
"""Timeout called every 15s, which calls read_data, then notify if the item changed"""
self.read_data()
if self.data:
self.new_product = self.parser.getproduct()
if self.new_product != self.old_product:
self.new_pricing = self.parser.getpricing()
if self.new_product:
self.notify(self.new_product, self.new_pricing)
self.old_product = self.new_product
self.parser.clear_buffers()
return True
def main(self):
"""Create the timeout object and let the program sit in gtk.main()"""
self.site_poller = gobject.timeout_add(self.seconds_to_check, self.site_poll_timeout)
gtk.main()
def __init__(self):
self.parser = MyParser()
self.old_product = ""
self.new_product = ""
self.new_pricing = ""
self.data = None
self.seconds_to_check = CHECK_DELAY * 1000
self.site_poll_timeout()
if __name__ == '__main__':
s = SACNotify()
s.main()
Last edited by buttons (2007-12-10 03:00:07)
Cthulhu For President!
Offline
This is great. I'm in the midst of un-windows-ing myself, and the SAC notifier was one thing I really missed. Thanks.
Do you mind if I modify this code---perhaps to display the item and add a notification-area icon---and eventually distribute it (with due credit)?
Eric
Offline
I'm sure the website would appreciate lengthening the polling delay as well. I'd call every 15 seconds "hammering" myself.
Cheers,
~djc
Offline
Thanks to Rob for pointing out this had borked.
SAC added an ad to their site, which confused the parser. So...here's a new version:
NOTE: I've made other changes to this! You *must* set the BROWSER variable at the top of the script to be the full path to your browser. I happen to use swiftfox, so that's the default. The reason for this is this version has significant changes to the way GTK is handled, and now has a button rather than a link.
NOTE2: This version also fixes the strange problem SAC had with coming up with old items for a split second inexplicably.
#!/usr/bin/python
"""
SAC Notification Tool v0.7
(c) 2007 Michael Seiler
"""
import urllib, htmllib, formatter
from pynotify import *
import gtk, gobject
import subprocess
#Global Constants
TIMEOUT = EXPIRES_DEFAULT #Time in milliseconds for the popup to stick around
#Use EXPIRE_DEFAULT for the default or EXPIRE_NEVER for forever
WEBSITE = 'http://www.steepandcheap.com' #SAC Website
CHECK_DELAY = 15 #Time in seconds between website checks
BROWSER = '/opt/swiftfox/swiftfox' #No symlinks!
class MyParser(htmllib.HTMLParser):
"""
MyParser
Parse incoming SAC data into a product name and price details
USAGE: p = MyParser()
p.feed(some_html)
p.close()
Methods:
clearbuffers()
Clears cached price and product data
getproduct()
Returns the product name
getpricing()
Returns the price and percent off
"""
def start_div(self, attrs):
"""Called at the start of each DIV tag"""
if len(attrs) > 0:
for attr in attrs:
if attr[0] == 'id':
if attr[1] == 'price':
self.price_flag = 1
elif attr[1] == 'percent_off':
self.price_flag = 1
elif attr[1] == 'product':
self.product_flag = 1
elif attr[1][:8] == 'ad_space':
self.ad_flag = 1
def end_div(self):
"""Called at the end of each DIV tag"""
self.price_flag = 0
if not self.ad_flag:
self.product_flag = 0
def start_h2(self, attrs):
"""Called at the start of each H2 tag"""
if self.product_flag:
self.product_title_flag = 1
def end_h2(self):
"""Called at the end of each H2 tag"""
self.product_title_flag = 0
self.ad_flag = 0
def handle_data(self, text):
"""Called on any text between tags"""
if self.price_flag:
self.pricing.append(text)
elif self.product_title_flag:
self.product = text
def clear_buffers(self):
"""Clear cached price and product data"""
self.pricing = []
self.product = ""
def getproduct(self):
"""Return product name"""
return self.product
def getpricing(self):
"""Return price and percent off"""
return " - ".join(self.pricing)
def __init__(self):
null_format = formatter.NullFormatter()
htmllib.HTMLParser.__init__(self, null_format)
self.pricing = []
self.product = ""
self.ad_flag = 0
self.price_flag = 0
self.product_flag = 0
self.product_title_flag = 0
class MyNotify(object):
"""
MyNotify
Create and maintain the notification window and corresponding action methods
USAGE: n = MyNotify()
n.notify(title, message)
"""
def notify(self, title, message):
"""Show notification with a buy button"""
self.notification.update(title, message, gtk.STOCK_DIALOG_WARNING)
self.notification.show()
gtk.main()
def open_site(self, n, action):
"""Called if the user clicks the buy button"""
subprocess.Popen([BROWSER, WEBSITE])
def destroy(self, n, action=None):
"""Called whenever the window disappears"""
gtk.main_quit()
def __init__(self):
init('sac.py')
self.notification = Notification("Product", "Pricing", gtk.STOCK_DIALOG_WARNING)
self.notification.set_urgency(URGENCY_LOW)
self.notification.set_timeout(TIMEOUT)
self.notification.connect('closed', self.destroy)
self.notification.add_action('buy', 'Buy this item', self.open_site) #User clicks button
class SAC_notifier(MyNotify):
"""
SAC_notifier
Handle timing, notification, and gtk interaction
USAGE: s = SAC_notifier()
s.main()
Creates a timeout that downloads information from SAC every CHECK_DELAY seconds,
then pops up a notification using pynotify if it finds a different product.
"""
def read_data(self):
"""Read data from the SAC website, then call the parser"""
try:
self.data = urllib.urlopen(WEBSITE).read()
except:
#No interweb connection? SAC down?
self.data = None
if self.data:
self.parser.feed(self.data)
self.parser.close()
def site_poll_timeout(self):
"""Timeout called every CHECK_DELAY secs, which calls read_data, then notify if the item changed"""
self.read_data()
if self.data:
self.new_product = self.parser.getproduct()
if self.new_product != self.old_product and not self.new_product in self.seen_products:
self.new_pricing = self.parser.getpricing()
if self.new_product:
self.notify(self.new_product, self.new_pricing)
self.seen_products.append(self.new_product)
self.old_product = self.new_product
self.parser.clear_buffers()
return True
def main(self):
"""Create the timeout object and let the program sit in gtk.main()"""
self.site_poller = gobject.timeout_add(self.seconds_to_check, self.site_poll_timeout)
gtk.main()
def __init__(self):
MyNotify.__init__(self)
self.parser = MyParser()
self.old_product = ""
self.new_product = ""
self.new_pricing = ""
self.seen_products = list()
self.data = None
self.seconds_to_check = CHECK_DELAY * 1000
self.site_poll_timeout()
if __name__ == '__main__':
s = SAC_notifier()
s.main()
Cthulhu For President!
Offline
Is there some reason you didn't use the RSS feed (http://feeds.feedburner.com/SteepandCheap) instead of parsing the HTML of the main site? Seems like it would be less prone to problems due to them changing site layout, plus you might be able to grab the product image easily.
Last edited by Eric89GXL (2008-05-20 16:55:53)
Offline
I've changed the code to use the RSS feed, pull an image of the item, and (optionally) display a tray icon so that you can close or activate the notifier as you please. Have a try:
#!/usr/bin/python
"""
SAC RSS Notification Tool v0.2
(c) 2008 Michael Seiler and Eric Larson
"""
import urllib
import Image, cStringIO
from xml.dom import minidom
from pynotify import *
import gtk, gobject
import subprocess
#Global Constants
TIMEOUT = EXPIRES_DEFAULT #Time in milliseconds for the popup to stick around
#Use EXPIRES_DEFAULT for the default or EXPIRE_NEVER for forever
WEBSITE = 'http://www.steepandcheap.com' #SAC Website
CHECK_DELAY = 15 #Time in seconds between website checks
BROWSER = '/usr/lib/firefox-3.0/firefox.sh' #No symlinks!
FEEDADDRESS = 'http://feeds.feedburner.com/SteepandCheap' # SAC RSS Feed
ICONURL = 'http://images.steepandcheap.com/images/icon/steepcheap.ico' # SAC statusbar icon URL
SHOW_NOTIFICATION_ICON = True # Show SAC icon in notification area?
RECHECK_ON_CLICK = False # Check the SAC deal every time the notifier is activated by clicking the icon?
def url2pixbuf(imgurl):
img_feed = None
try:
img_feed = urllib.urlopen(imgurl).read()
except:
img_feed = None
if img_feed:
im = Image.open(cStringIO.StringIO(img_feed)).convert("RGB")
return gtk.gdk.pixbuf_new_from_data(im.tostring(),gtk.gdk.COLORSPACE_RGB,False,8,im.size[0],im.size[1],3*im.size[0])
else:
return None
class MyNotify(object):
"""
MyNotify
Create and maintain the notification window and corresponding action methods
USAGE: n = MyNotify()
n.notify(title, message)
"""
def notify(self, title, message, imgPixbuf):
"""Show notification with a buy button and image"""
self.notification.update(title, message)
if imgPixbuf:
self.notification.set_icon_from_pixbuf(imgPixbuf)
self.notification.show()
self.isvisible = True
def icon_clicked(icon,event,self):
if self.isvisible:
self.notification.close()
else:
if RECHECK_ON_CLICK and not self.checkingnow:
self.site_poll_timeout()
self.notification.show()
self.isvisible = True
def show_menu(self, icon, button, time):
self.menu.popup(None, None, gtk.status_icon_position_menu, button, time, icon)
def quit_clicked(self, menuItem):
if self.isvisible:
self.notification.close()
gtk.main_quit()
def open_site(self, n, action):
"""Called if the user clicks the buy button"""
subprocess.Popen([BROWSER, WEBSITE])
def destroy(self, n, action=None):
"""Called whenever the window disappears"""
self.isvisible = False
def __init__(self):
init('sacrss.py')
self.notification = Notification("Product", "Pricing", gtk.STOCK_DIALOG_WARNING)
self.notification.set_urgency(URGENCY_LOW)
self.notification.set_timeout(TIMEOUT)
self.notification.connect('closed', self.destroy)
self.notification.add_action('buy', 'Buy this item', self.open_site) #User clicks button
class SAC_notifier(MyNotify):
"""
SAC_notifier
Handle timing, notification, and gtk interaction
USAGE: s = SAC_notifier()
s.main()
Creates a timeout that downloads information from SAC every CHECK_DELAY seconds,
then pops up a notification using pynotify if it finds a different product.
"""
def read_data(self):
"""Read data from the SAC website, then parse it"""
self.checkingnow = True
self.new_product = ""
self.description = ""
self.imgLocation = ""
self.priceCurrent = ""
self.priceRegular = ""
self.imgPixbuf = None
try:
self.file_feed = urllib.urlopen(FEEDADDRESS).read()
except:
#No interweb connection? SAC down?
self.file_feed = None
if self.file_feed:
self.file_xml = minidom.parseString(self.file_feed)
self.item_node = self.file_xml.getElementsByTagName("item")
for childNode in self.item_node[0].childNodes:
if childNode.nodeType == childNode.ELEMENT_NODE:
if childNode.tagName == 'title':
self.new_product = childNode.firstChild.data
if childNode.tagName == 'sac:listDescription':
self.description = childNode.firstChild.data
if childNode.tagName == 'sac:priceCurrent':
self.priceCurrent = childNode.firstChild.data
if childNode.tagName == 'sac:priceRegular':
self.priceRegular = childNode.firstChild.data
if childNode.tagName == 'sac:tinyImage':
self.imgLocation = childNode.firstChild.data
self.imgPixbuf = url2pixbuf(self.imgLocation)
self.checkingnow = False
def site_poll_timeout(self):
"""Timeout called every CHECK_DELAY secs, which calls read_data, then notify if the item changed"""
self.read_data()
if self.file_feed:
if self.new_product != self.old_product and not self.new_product in self.seen_products:
if self.new_product:
percOff = '%d' % round(100.0*(float(self.priceRegular) - float(self.priceCurrent))/float(self.priceRegular))
descriptionString = "\n<b>Price: $" + self.priceCurrent + " (" + percOff + "% off!)</b>\nRegularly: $" + self.priceRegular + "\n\n" + self.description
self.notify(self.new_product, descriptionString, self.imgPixbuf)
self.seen_products.append(self.new_product)
self.old_product = self.new_product
return True
def main(self):
"""Create the timeout object and let the program sit in gtk.main()"""
self.site_poller = gobject.timeout_add(self.seconds_to_check, self.site_poll_timeout)
if SHOW_NOTIFICATION_ICON:
self.icon = gtk.StatusIcon()
iconBuf = url2pixbuf(ICONURL)
if iconBuf:
self.icon.set_from_pixbuf(iconBuf)
else:
self.icon.set_from_stock(gtk.STOCK_DIALOG_ERROR)
self.menu = gtk.Menu()
quit = gtk.MenuItem("Quit")
quit.connect("activate", self.quit_clicked)
quit.show()
self.menu.append(quit)
self.icon.connect("activate", self.icon_clicked, self)
self.icon.connect("popup-menu", self.show_menu)
gtk.main()
def __init__(self):
MyNotify.__init__(self)
self.old_product = ""
self.new_product = ""
self.priceCurrent = ""
self.priceRegular = ""
self.imgPixbuf = None
self.isvisible = False
self.seen_products = list()
self.seconds_to_check = CHECK_DELAY * 1000
self.checkingnow = False
self.site_poll_timeout()
if __name__ == '__main__':
s = SAC_notifier()
s.main()
Last edited by Eric89GXL (2008-05-31 22:12:45)
Offline
I don't know if any of you guys have been following the golden deal days or one dollar deal days on steepandcheap but if you have you probably have missed out on a few deals because you were too slow to purchase the item. I would love to create a script that could alert me when ever there was a item up for 1 dollar on any of the backcounty.com sites (steepandcheap.com, chainlove.com, brociety.com, tramdock.com, bonktown.com, and whiskeymilitia.com). It would be sweet if it could automatically purchase the item as well, but that may be too difficult.
The problem is I know nothing about scripting and by the time I could learn the one dollar deal days will probably be over. If one of you guys could create something like this maybe we could all benefit.
Offline
Why yes I am necroing this thread.
I messed with the script and made it work for whiskeymilitia.com...since I'm not all that into hiking and climbing gear.
I also changed the delay to 120 secs (2mins) because every 15 secs seemed a bit excessive..the deals only change every 20mins or so.
Feeling a bit paranoid and you might miss a deal? Just change the CHECK_DELAY field back to 15 if you want.
I also have it set to use Chromium for the "Buy now!" button. If you want to change it to something else just change the BROWSER field.
Im not claiming any credit here for this, all did was setup a feedburner for it and changed literally 4 or 5 things in the script.
#!/usr/bin/python
"""
MhiskeyMilitia RSS Notification Tool v0.2
(c) 2008 Michael Seiler and Eric Larson
"""
import urllib
import Image, cStringIO
from xml.dom import minidom
from pynotify import *
import gtk, gobject
import subprocess
#Global Constants
TIMEOUT = EXPIRES_DEFAULT #Time in milliseconds for the popup to stick around
#Use EXPIRES_DEFAULT for the default or EXPIRE_NEVER for forever
WEBSITE = 'http://www.whiskeymilitia.com/' #WM Website
CHECK_DELAY = 120 #Time in seconds between website checks
BROWSER = '/usr/lib/chromium-browser/chromium-browser' #No symlinks!
FEEDADDRESS = 'http://feeds.feedburner.com/whiskeymilitia/rtzq' # WM RSS Feed
ICONURL = 'http://images.whiskeymilitia.com/images/icon/wm.ico' # WM statusbar icon URL
SHOW_NOTIFICATION_ICON = True # Show WM icon in notification area?
RECHECK_ON_CLICK = False # Check the WM deal every time the notifier is activated by clicking the icon?
def url2pixbuf(imgurl):
img_feed = None
try:
img_feed = urllib.urlopen(imgurl).read()
except:
img_feed = None
if img_feed:
im = Image.open(cStringIO.StringIO(img_feed)).convert("RGB")
return gtk.gdk.pixbuf_new_from_data(im.tostring(),gtk.gdk.COLORSPACE_RGB,False,8,im.size[0],im.size[1],3*im.size[0])
else:
return None
class MyNotify(object):
"""
MyNotify
Create and maintain the notification window and corresponding action methods
USAGE: n = MyNotify()
n.notify(title, message)
"""
def notify(self, title, message, imgPixbuf):
"""Show notification with a buy button and image"""
self.notification.update(title, message)
if imgPixbuf:
self.notification.set_icon_from_pixbuf(imgPixbuf)
self.notification.show()
self.isvisible = True
def icon_clicked(icon,event,self):
if self.isvisible:
self.notification.close()
else:
if RECHECK_ON_CLICK and not self.checkingnow:
self.site_poll_timeout()
self.notification.show()
self.isvisible = True
def show_menu(self, icon, button, time):
self.menu.popup(None, None, gtk.status_icon_position_menu, button, time, icon)
def quit_clicked(self, menuItem):
if self.isvisible:
self.notification.close()
gtk.main_quit()
def open_site(self, n, action):
"""Called if the user clicks the buy button"""
subprocess.Popen([BROWSER, WEBSITE])
def destroy(self, n, action=None):
"""Called whenever the window disappears"""
self.isvisible = False
def __init__(self):
init('WMrss.py')
self.notification = Notification("Product", "Pricing", gtk.STOCK_DIALOG_WARNING)
self.notification.set_urgency(URGENCY_LOW)
self.notification.set_timeout(TIMEOUT)
self.notification.connect('closed', self.destroy)
self.notification.add_action('buy', 'Buy this item', self.open_site) #User clicks button
class WM_notifier(MyNotify):
"""
WM_notifier
Handle timing, notification, and gtk interaction
USAGE: s = WM_notifier()
s.main()
Creates a timeout that downloads information from WM every CHECK_DELAY seconds,
then pops up a notification using pynotify if it finds a different product.
"""
def read_data(self):
"""Read data from the WM website, then parse it"""
self.checkingnow = True
self.new_product = ""
self.description = ""
self.imgLocation = ""
self.priceCurrent = ""
self.priceRegular = ""
self.imgPixbuf = None
try:
self.file_feed = urllib.urlopen(FEEDADDRESS).read()
except:
#No interweb connection? WM down?
self.file_feed = None
if self.file_feed:
self.file_xml = minidom.parseString(self.file_feed)
self.item_node = self.file_xml.getElementsByTagName("item")
for childNode in self.item_node[0].childNodes:
if childNode.nodeType == childNode.ELEMENT_NODE:
if childNode.tagName == 'title':
self.new_product = childNode.firstChild.data
if childNode.tagName == 'odat:listDescription':
self.description = childNode.firstChild.data
if childNode.tagName == 'odat:priceCurrent':
self.priceCurrent = childNode.firstChild.data
if childNode.tagName == 'odat:priceRegular':
self.priceRegular = childNode.firstChild.data
if childNode.tagName == 'odat:tinyImage':
self.imgLocation = childNode.firstChild.data
self.imgPixbuf = url2pixbuf(self.imgLocation)
self.checkingnow = False
def site_poll_timeout(self):
"""Timeout called every CHECK_DELAY secs, which calls read_data, then notify if the item changed"""
self.read_data()
if self.file_feed:
if self.new_product != self.old_product and not self.new_product in self.seen_products:
if self.new_product:
percOff = '%d' % round(100.0*(float(self.priceRegular) - float(self.priceCurrent))/float(self.priceRegular))
descriptionString = "\n<b>Price: $" + self.priceCurrent + " (" + percOff + "% off!)</b>\nRegularly: $" + self.priceRegular + "\n\n" + self.description
self.notify(self.new_product, descriptionString, self.imgPixbuf)
self.seen_products.append(self.new_product)
self.old_product = self.new_product
return True
def main(self):
"""Create the timeout object and let the program sit in gtk.main()"""
self.site_poller = gobject.timeout_add(self.seconds_to_check, self.site_poll_timeout)
if SHOW_NOTIFICATION_ICON:
self.icon = gtk.StatusIcon()
iconBuf = url2pixbuf(ICONURL)
if iconBuf:
self.icon.set_from_pixbuf(iconBuf)
else:
self.icon.set_from_stock(gtk.STOCK_DIALOG_ERROR)
self.menu = gtk.Menu()
quit = gtk.MenuItem("Quit")
quit.connect("activate", self.quit_clicked)
quit.show()
self.menu.append(quit)
self.icon.connect("activate", self.icon_clicked, self)
self.icon.connect("popup-menu", self.show_menu)
gtk.main()
def __init__(self):
MyNotify.__init__(self)
self.old_product = ""
self.new_product = ""
self.priceCurrent = ""
self.priceRegular = ""
self.imgPixbuf = None
self.isvisible = False
self.seen_products = list()
self.seconds_to_check = CHECK_DELAY * 1000
self.checkingnow = False
self.site_poll_timeout()
if __name__ == '__main__':
s = WM_notifier()
s.main()
Proof?
<.<
Dont judge my wallpaper.
Last edited by whaevr (2010-02-15 22:20:27)
Offline
Oh wow! Sweet! I'm glad this is getting love.
Cthulhu For President!
Offline
Especially for the $1.00 items, the RSS feed is too slow. It is cached much more aggressively by the load balancing servers. It can take 30-40 seconds for it to get updated. Just look at the HTTP headers coming back. The web server isn't even the same:
js.header:Server: ECS (sjo/5226)
rss.header:Server: lighttpd/1.4.20
You'll also notice that you can use the 'If-Modified-Since:' HTTP header for the RSS feed, and http keepalives. You can poll much more often since each each request is only a couple hundred bytes. In fact, the internal javascript on the SAC pages (see dynodat.js) sets and uses this header.
Their servers also take 'Accept-Encoding'. These files compress pretty well, so this can further reduce bandwidth usage. Any bandwidth reduction is good because it means you can poll more often.
Offline
Pages: 1