#!/usr/bin/python # woot-notify is NOT endorsed by or affiliated with Woot # woot-notify version 0.0.2 created by Alex Brown # based off of, and ideas taken from, and idea gotten from: wooty, a perl script that does the like, but without the awsome s**t I added # see (http://freshmeat.net/projects/wooty/?branch_id=65979) # 12/17/06 20:29:25 EST -0500 # Made by Alex Brown ("uh oh spaghetti-o") # Licensed under the GPL version 2.0 # TODO: # X = won't do/finish # ^ = in process # % = done # # ^* Create preferences dialog/window # * Make preferences menu write to a file that affects this app # * About dialog # %* Make program acess modules through pywoot by (ie) pywoot.getwoot() # %* Finish adding timeouts # ^* Fix for how many left: 85% : $69.99 : Logitech MX5000 Bluetooth Keyboard and Laser Mouse # + then add like status = "Highish (85%)" # + 1% : $69.99 : Logitech MX5000 Bluetooth Keyboard and Laser Mouse: SOLD OUT # * Control if summary = "Server too busy" # * Add egg.trayicon interface # * Add gnome panel interface # * Update comments heftly # ^* Move useful functions to pywoot.py as a library, and have woot-notify as just the app # X* Make one callback function, but have it take in an argument that says what to do # * Add visit button to libnotify/pynotify pop-ups which has a call back to Woot.callback_visit() so that both are the same # X* Have pywoot check to see if the icon has already been downloaded # ^* Make pop-up module # * Add that bit of the gpl to my prog __build_date__ = "Sun 17 Dec 2006 08:29:25 PM EST -0500" __program__ = "Woot Notify" __version__ = "0.0.2" __filecall__ = "woot-notify.py" __author__ = "Alex Brown (\"uh oh spaghetti-o\") " __contributors__ = ["mikm (#ubuntu on irc.freenode.net)", "John Ehresman "] __tagline__ = "is a python module to retrieve information on the current woot at http://www.woot.com/" __tagline2__ = "A python module to retrieve information on the current woot at http://www.woot.com/" __usage__ = __filecall__ + " [OPTIONS]\n" + __program__ + __tagline__ __doc__ = __program__ + ", by " + __author__ + ", Version " + __version__ + __tagline__ __copyright__ = __program__ + " - " + __tagline2__ + "\nCopyright (C) 2006 Alex Brown" __license__ = "\t" + __program__ + ' - ' + __tagline2__ + """ Copyright (C) 2006 Alex Brown This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ import sys, os, urllib, time, re, socket, copy import pywoot from pywoot import debug socket.setdefaulttimeout(5.0) from optparse import OptionParser item = "" status = "" price = "" tempdir = "" ifnotify = False notifyimported = False ifegg = False deb = False def main(*args): """Main Function, really f**ked up s**t happens here""" # Try to import pygtk: try: global pygtk; import pygtk pygtk.require("2.0") except ImportError: sys.exit("Error importing module: pygtk") try: global gtk; import gtk global gobject; import gobject except ImportError: sys.exit("Error importing modules: gtk, gobject") version = gtk.pygtk_version # See what sort of system tray module is going to be used: global egg if typeoftray == "gtk" and version[0] == 2 and version[1] < 10: debug("Going to try and use egg.trayicon, pygtk version is not at least 2.10") try: import egg.trayicon except ImportError: sys.exit("Tried importing egg.trayicon since your pygtk version was less than 2.10:\n" + "Error importing module: egg.trayicon") else: print "**woot-notify: Using egg.trayicon for the system tray icon" ifegg = True elif typeoftray == "egg": try: import egg.trayicon except ImportError: debug("**woot-notify: Couldn't import egg.trayicon, trying for gtk.StatusIcon") if version[0] == 2 and version[1] < 10: sys.exit("egg.trayicon could not be found, and could not" + "Use gtk.StatusIcon since your pygtk version is less than 2.10\n" + "Error import module: egg.trayicon") else: print "**woot-notify: Using egg.trayicon for the system tray icon" ifegg = True else: print "**woot-notify: Using gtk.StatusIcon for the system tray icon" debug("**woot-notify: (reached else statement)") # See if python-notify is going to be used for pop-ups if ifnotify == True: global notifyimported try: global pynotify import pynotify except ImportError: print ("Error importing module: pynotify\n" + "If not installed or distributed with this program, you can obtain it from:\n" + "\t http://www.galago-project.org/") notifyimported = False else: print "**woot-notify: Using python-notify for pop-up notifications" notifyimported = True try: wootapp = Woot() wootapp.main() except KeyboardInterrupt: try: wootapp.clean() except: try: Woot.clean() except: sys.exit(1) class Woot: """Class for the Application""" def __init__(self): """Initialization of the PyWoot app""" global price, item, status, typeoftray # Declare the sys. tray icon TrayIcon = gtk.StatusIcon() # Create the menu: Menu = gtk.Menu() # Menu Items for menu: Menu_Visit = gtk.Action('Visit', 'Visit Woot', None, 'gtk-home').create_menu_item() Menu_Refresh = gtk.Action('Refresh', 'Refresh', None, 'gtk-refresh').create_menu_item() Menu_Prefs = gtk.Action('Preferences', 'Preferences', None, 'gtk-preferences').create_menu_item() Menu_About = gtk.Action('About', 'About', None, 'gtk-about').create_menu_item() Menu_Separator = gtk.SeparatorMenuItem() Menu_Quit = gtk.Action('Quit', 'Quit', None, 'gtk-quit').create_menu_item() # Order of items on menu: Menu.append(Menu_Visit) Menu.append(Menu_Refresh) Menu.append(Menu_Prefs) Menu.append(Menu_About) Menu.append(Menu_Separator) Menu.append(Menu_Quit) # Events for when buttons are clicked: Menu_Quit.connect("activate", self.destroy) Menu_Refresh.connect("activate", self.callback_refresh, TrayIcon) Menu_Visit.connect("activate", self.callback_visit) Menu_Prefs.connect("activate", self.callback_prefs) Menu_About.connect("activate", self.callback_about) Menu_Visit.show(); Menu_Refresh.show(); Menu_Separator.show(); Menu_Quit.show() Menu.show_all() # Configure the sys. tray icon TrayIcon.set_from_file(pywoot.get_icon()) self.refresh(TrayIcon, 'first check') gtk.status_icon_position_menu(Menu, TrayIcon) # Connect the icon with the menu TrayIcon.connect("popup-menu", self.menu_popup, Menu) TrayIcon.connect("activate", self.tray_clicked) # Create the preferences window: self.make_prefs() # Create the about dialog: self.make_about() # Every 5 min, update the widget gobject.timeout_add(5 * 60 * 1000, self.refresh, TrayIcon) self.tray_clicked(None) def make_about(self): """Function to create the about dialog""" self.about_dialog = gtk.Dialog(title="About Woot-Notify", flags=gtk.DIALOG_MODAL,buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) self.about_dialog.connect("delete_event", self.callback_about_close) def make_prefs(self): """Function to create the preferences window""" # Create a new window self.prefs_window = gtk.Window(gtk.WINDOW_TOPLEVEL) # Set the window title and icon self.prefs_window.set_title("Preferences") self.prefs_window.set_icon_from_file(pywoot.get_icon(skipget=True)) # Set a handler for delete_event that immediately # exits GTK. self.prefs_window.connect("delete_event", self.callback_prefs_close) # Sets the border width of the window. self.prefs_window.set_border_width(20) # Create a 6x2 table table = gtk.Table(8, 2, False) """ 0 1 2 0+----------+----------+ | timeout: | 0.5 ^v | 1+----------+----------+ | popup: | |N|No|Ot | 2+----------+----------+ | showpic: | [ ] show | 3+----------+----------+ | curpic: | get_pic | 4+----------+----------+ | | | 5+----------+----------+ | | | 6+----------+----------+ | | | 7+----------+----------+ | | | 8+----------+----------+ table.attach(child, left_attach, right_attach, top_attach, bottom_attach, xoptions=EXPAND|FILL, yoptions=EXPAND|FILL, xpadding=0, ypadding=0) """ # Put the table in the main window self.prefs_window.add(table) label = gtk.Label('THIS DIALOG DOES\n NOT DO ANYTHING... (yet)') label.set_use_markup(True) table.attach(label, 0, 1, 7, 8, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK) close_button = gtk.Button() close_hbox = gtk.HBox(homogeneous=False, spacing=0) close_label = gtk.Label("Close") close_icon = gtk.image_new_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_BUTTON) close_hbox.pack_start(close_icon, expand=True, fill=True, padding=0) close_hbox.pack_start(close_label, expand=True, fill=True, padding=0) close_button.add(close_hbox) close_button.connect("clicked", self.callback_prefs_close) table.attach(close_button, 1, 2, 7, 8, xoptions=gtk.SHRINK, xpadding=5, ypadding=5) timeout_label = gtk.Label("Download Timeout (seconds):") timeout_adjustment = gtk.Adjustment(value=5.00, lower=0.50, upper=10, step_incr=0.25, page_incr=0.50) timeout_spinbutton = gtk.SpinButton(adjustment=timeout_adjustment, climb_rate=0.0, digits=2) table.attach(timeout_label, 0, 1, 0, 1) table.attach(timeout_spinbutton, 1, 2, 0, 1) notify_label = gtk.Label("Type of Pop-Up:") notify_button_none = gtk.RadioButton(None, "None") notify_button_normal = gtk.RadioButton(notify_button_none, "Normal") notify_button_other = gtk.RadioButton(notify_button_none, "Other") notify_table = gtk.Table(1, 3, True) notify_table.attach(notify_button_none, 0, 1, 0, 1) notify_table.attach(notify_button_normal, 1, 2, 0, 1) notify_table.attach(notify_button_other, 2, 3, 0, 1) table.attach(notify_label, 0, 1, 1, 2) table.attach(notify_table, 1, 2, 1, 2) showpicture_label = gtk.Label("Show picture in notification:") showpicture_checkbutton = gtk.CheckButton("Show") table.attach(showpicture_label, 0, 1, 2, 3) table.attach(showpicture_checkbutton, 1, 2, 2, 3) currentpicture_label = gtk.Label("Current Picture:") currentpicture_image = gtk.Image() currentpicture_image.set_from_file(pywoot.get_pic(skipget=True, width=200)) table.attach(currentpicture_label, 0, 1, 3, 4) table.attach(currentpicture_image, 1, 2, 3, 4) def callback(self, widget, data=None): """A Test Callback""" print "%s was pressed" % data def callback_visit(self, widget, data=None): """Visit callback for Menu_Visit""" self.open_woot() def callback_refresh(self, widget, data=None): """Refresh callback for Menu_Refresh""" self.refresh(data) def callback_about(self, widget, data=None): response = self.about_dialog.run() if response == gtk.RESPONSE_CLOSE: self.callback_about_close(None) debug("About dialog shown") def callback_about_close(self, widget, data=None): self.about_dialog.hide() return True def callback_prefs(self, widget, data=None): self.prefs_window.show_all() debug("Preferences window shown") def callback_prefs_close(self, widget, data=None): self.prefs_window.hide() return True def callback_clicked(self, widget, data=None): """Click callback for testing""" print "Click!" def tray_clicked(self, widget, data=None): """Callback for when the system tray icon gets clicked""" global notifyimported if notifyimported == True: self.notify(urgency='normal') return True def menu_popup(self, status_icon, button, activate_time, menu, *args): """Callback for popping up a gtk.Menu""" menu.popup(None, None, None, button, activate_time) def refresh(self, staticon, *args): """Refresh Function""" global price, item, status old_price = price; old_item = item; old_status = status (price, item, status) = pywoot.getwoot() staticon.set_tooltip((item + " is " + status.lower() + " and on sale for " + price + ".")) pywoot.get_pic() if len(args) > 0 and args[0].lower() == 'first check': debug("**woot-notify: First refresh") firstcheck = True else: firstcheck = False if old_item != item and firstcheck == False: debug("**woot-notify: New item! " + old_item + " to " + item) self.notify(bold=True, subject="New Item at Woot:", urgency='critical') elif old_status != status and firstcheck == False: debug("**woot-notify: Status change on current item: " + old_status + " to " + status) self.notify(bold=False, message='status_bold', subject="Woot Status Change:", urgency='critical') print "**woot-notify: Refreshed at " + time.ctime() return True def notify(self, bold=False, show_picture=True, subject="Currently on Woot:", message='default', urgency='normal'): global pynotify, price, item, status if not pynotify.init("Woot"): return False if message.lower() == 'default': message = 'Item: ' + item + "\nPrice: " + price + "\nStatus: " + status + '\nhttp://www.woot.com/' elif message.lower() == 'status_bold' or message.lower() == 'status bold': message = 'Item: ' + item + "\nPrice: " + price + "\nStatus: " + status + '\nhttp://www.woot.com/' if bold == True: message = '' + message + '' if show_picture == True: n = pynotify.Notification(subject, message, pywoot.get_pic(skipget=True, width=150)) elif show_picture == False: n = pynotify.Notification(subject, message) if urgency.lower() == 'low': n.set_urgency(pynotify.URGENCY_LOW) elif urgency.lower() == 'normal': n.set_urgency(pynotify.URGENCY_NORMAL) elif urgency.lower() == 'critical' or urgency.lower() == 'high': n.set_urgency(pynotify.URGENCY_CRITICAL) else: sys.exit("Error: urgency argument to Woot.notify() in woot-notify.py was not set correctly.") try: n.show() except: print "Failed to send notification" return False return True def open_woot(self, data=None): os.system("firefox http://www.woot.com/") def window_destroy(self, widget, event, data=None): gtk.main_quit() return False def destroy(self, widget, data=None): print "**woot-notify: recieved message to quit" self.clean() gtk.main_quit() def clean(self): pywoot.get_icon(deletefile=True) print "**woot-notify: deleted icon file for woot-notify" pywoot.get_pic(deletefile=True) print "**woot-notify: deleted picture file for woot-notify" def main(self): gtk.main() if __name__ == '__main__': parser = OptionParser(prog=__program__, usage=__usage__, version="%prog "+__version__) parser.set_defaults(deb=False, iftray="gtk", ifnotify=False, tempdir="/tmp", downgpl=None, ifinto=False) parser.add_option("-d", "--debug", action="store_true", dest="deb", help="Print debug information.") parser.add_option("--tray-gtk", action="store_const", const='egg', dest="iftray", help="Use gtk.StatusIcon to put PyWoot in the system tray (pygtk 2.10 required)") parser.add_option("--tray-egg", action="store_const", const='egg', dest="iftray", help="Use egg.trayicon to put PyWoot in the system tray <>") parser.add_option("--notify", action="store_true", dest="ifnotify", help="Use pynotify to use popup messages on new woot icons <>") parser.add_option("--temp-dir", action="store", type="string", dest="tempdir", metavar="DIRECTORY", help="The temporary directory to use for %prog") parser.add_option("--download-license", "--download-gpl", action="store", type="string", dest="downgpl", metavar="DIRECTORY", help="Download the license to this program to designated directory, enter 'current' to use the one from which you ran the script.\nNote that this downloads the most current gpl, and the one downloaded may not be version 2 after 2006.") parser.add_option("--info", action="store_true", dest="ifinfo", help="Show other important information on this program") (options, args) = parser.parse_args() if options.ifinfo == True: print __copyright__ #print __program__ + """comes with ABSOLUTELY NO WARRANTY; for details see the COPYING file distributed with this program. This is free software, and you are welcome to redistribute it under certain conditions; see the COPYING file distributed with this program for details.""" print '-------------------------' print "Please read the COPYING or other copyright file distributed with this program, it contains more information besides the GPL" print '-------------------------' if options.downgpl != None: if options.downgpl.lower() == 'current': location = os.getcwd() else: location = options.downgpl location = rmfolderslash(location) + '/pywoot_license_gpl.txt' try: urllib.urlretrieve("http://www.gnu.org/licenses/gpl.txt", location) except IOError: print "The download of the gpl was timed-out. You are welcome to try again, or if you are on a linux system, type 'man gpl'" else: print "The license was downloaded to: ", location + '/gpl.txt' sys.exit(0) deb = options.deb pywoot.deb = options.deb typeoftray = options.iftray ifnotify = options.ifnotify tempdir = options.tempdir main() else: print "This program is not meant to be used as a module, but go ahead. You may be looking for PyWoot, the module this program uses to interact with Woot." # Possible discussed alternate names for this program: # woot fucker -- my favorite, it obviously says that this program allows you to fuck woots # woot checker # wewt # python woot # woot python # wootpy # "Current Woot Notifier" # curwoot # curwooter