hackertray/hackertray/__init__.py

172 lines
5.2 KiB
Python

#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
import webbrowser
import json
import argparse
from os.path import expanduser
import signal
try:
import appindicator
except ImportError:
import appindicator_replacement as appindicator
from appindicator_replacement import get_icon_filename
##This is to get --version to work
try:
import pkg_resources
__version = pkg_resources.require("hackertray")[0].version
except ImportError:
__version = "Can't read version number."
from hackernews import HackerNews
from chrome import Chrome
class HackerNewsApp:
HN_URL_PREFIX = "https://news.ycombinator.com/item?id="
def __init__(self, comments):
#Load the database
home = expanduser("~")
with open(home + '/.hackertray.json', 'a+') as content_file:
content_file.seek(0)
content = content_file.read()
try:
self.db = set(json.loads(content))
except ValueError:
self.db = set()
# create an indicator applet
self.ind = appindicator.Indicator("Hacker Tray", "hacker-tray", appindicator.CATEGORY_APPLICATION_STATUS)
self.ind.set_status(appindicator.STATUS_ACTIVE)
self.ind.set_icon(get_icon_filename("hacker-tray.png"))
# create a menu
self.menu = gtk.Menu()
#The default state is false, and it toggles when you click on it
self.commentState = comments
# create items for the menu - refresh, quit and a separator
menuSeparator = gtk.SeparatorMenuItem()
menuSeparator.show()
self.menu.append(menuSeparator)
btnComments = gtk.CheckMenuItem("Show Comments")
btnComments.show()
btnComments.set_active(comments)
btnComments.connect("activate", self.toggleComments)
self.menu.append(btnComments)
btnAbout = gtk.MenuItem("About")
btnAbout.show()
btnAbout.connect("activate", self.showAbout)
self.menu.append(btnAbout)
btnRefresh = gtk.MenuItem("Refresh")
btnRefresh.show()
#the last parameter is for not running the timer
btnRefresh.connect("activate", self.refresh, True)
self.menu.append(btnRefresh)
btnQuit = gtk.MenuItem("Quit")
btnQuit.show()
btnQuit.connect("activate", self.quit)
self.menu.append(btnQuit)
self.menu.show()
self.ind.set_menu(self.menu)
self.refresh()
def toggleComments(self, widget):
"""Whether comments page is opened or not"""
self.commentState = not self.commentState
def showAbout(self, widget):
"""Handle the about btn"""
webbrowser.open("https://github.com/captn3m0/hackertray/")
#ToDo: Handle keyboard interrupt properly
def quit(self, widget, data=None):
""" Handler for the quit button"""
l = list(self.db)
home = expanduser("~")
#truncate the file
with open(home + '/.hackertray.json', 'w+') as file:
file.write(json.dumps(l))
gtk.main_quit()
def run(self):
signal.signal(signal.SIGINT, self.quit)
gtk.main()
return 0
def open(self, widget, event=None, data=None):
"""Opens the link in the web browser"""
#We disconnect and reconnect the event in case we have
#to set it to active and we don't want the signal to be processed
if not widget.get_active():
widget.disconnect(widget.signal_id)
widget.set_active(True)
widget.signal_id = widget.connect('activate', self.open)
self.db.add(widget.item_id)
webbrowser.open(widget.url)
if self.commentState:
webbrowser.open(self.HN_URL_PREFIX + widget.hn_id)
def addItem(self, item):
"""Adds an item to the menu"""
#This is in the case of YC Job Postings, which we skip
if item['points'] == 0 or item['points'] is None:
return
i = gtk.CheckMenuItem(
"(" + str(item['points']).zfill(3) + "/" + str(item['comments_count']).zfill(3) + ") " + item['title'])
i.set_active(item['id'] in self.db)
i.url = item['url']
i.signal_id = i.connect('activate', self.open)
i.hn_id = item['id']
i.item_id = item['id']
self.menu.prepend(i)
i.show()
def refresh(self, widget=None, no_timer=False):
"""Refreshes the menu """
data = reversed(HackerNews.getHomePage()[0:20])
#Remove all the current stories
for i in self.menu.get_children():
if hasattr(i, 'url'):
self.menu.remove(i)
#Add back all the refreshed news
for i in data:
self.addItem(i)
#Call every 5 minutes
if not no_timer:
gtk.timeout_add(10 * 60 * 1000, self.refresh)
def main():
parser = argparse.ArgumentParser(description='Hacker News in your System Tray')
parser.add_argument('-v','--version', action='version', version=__version)
parser.add_argument('-c','--comments', dest='comments',action='store_true', help="Load the HN comments link for the article as well")
parser.set_defaults(comments=False)
args = parser.parse_args()
indicator = HackerNewsApp(args.comments)
indicator.run()