Merge branch 'firefox'

This commit is contained in:
Abhay Rana 2014-10-03 19:10:06 +05:30
commit 4224c9c198
7 changed files with 94 additions and 16 deletions

.editorconfig Normal file
View File

@ -0,0 +1,19 @@
# EditorConfig is awesome:
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
end_of_line = lf
insert_final_newline = true
# 4 space indentation
indent_style = space
indent_size = 4
# Matches the exact files either package.json or .travis.yml
indent_style = space
indent_size = 2

View File

@ -57,6 +57,9 @@ HackerTray accepts its various options via the command line. Run `hackertray -h`
1. `-c`: Enables comments support. Clicking on links will also open the comments page on HN. Can be switched off via the UI, but the setting is not remembered.
2. `--chrome PROFILE_PATH`: Specifying a profile path to a chrome directory will make HackerTray read the Chrome History file to mark links as read. Links are checked once every 5 minutes, which is when the History file is copied (to override the lock in case Chrome is open), searched using sqlite and deleted. This feature is still experimental.
3. `--firefox PROFILE_PATH`: Specify path to a firefox profile directory. HackerTray will read your firefox history from this profile, and use it to mark links as read.
Note that the `--chrome` and `--firefox` options are independent, and can be used together. However, they cannot be specified multiple times (so reading from 2 chrome profiles is not possible).
###Google Chrome Profile Path
@ -68,6 +71,9 @@ Where your Profile is stored depends on which version of chrome you are using:
Replace `Default` with `Profile 1`, `Profile 2` or so on if you use multiple profiles on Chrome. Note that the `--chrome` option accepts a `PROFILE_PATH`, not the History file itself. Also note that sometimes `~` might not be set, so you might need to use the complete path (such as `/home/nemo/.config/google-chrome/Default/`).
###Firefox Profile Path
The default firefox profile path is `~/.mozilla/firefox/*.default`, where `*` denotes a random 8 digit string. You can also read `~/.mozilla/firefox/profiles.ini` to get a list of profiles.
1. Minimalist Approach to HN
2. Opens links in your default browser

View File

@ -25,6 +25,7 @@ import signal
from hackernews import HackerNews
from chrome import Chrome
from firefox import Firefox
from version import Version
class HackerNewsApp:
@ -89,7 +90,7 @@ class HackerNewsApp:
self.refresh(, firefox_data_directory=args.firefox)
def toggleComments(self, widget):
"""Whether comments page is opened or not"""
@ -159,14 +160,19 @@ class HackerNewsApp:
def refresh(self, widget=None, no_timer=False, chrome_data_directory=None):
def refresh(self, widget=None, no_timer=False, chrome_data_directory=None, firefox_data_directory=None):
"""Refreshes the menu """
# Create an array of 20 false to denote matches in History
searchResults = [False]*20
data = list(reversed(HackerNews.getHomePage()[0:20]))
urls = [item['url'] for item in data]
urls = [item['url'] for item in data]
searchResults =, chrome_data_directory)
searchResults = self.mergeBoolArray(searchResults,, chrome_data_directory))
searchResults = self.mergeBoolArray(searchResults,, firefox_data_directory))
#Remove all the current stories
for i in
@ -175,10 +181,7 @@ class HackerNewsApp:
#Add back all the refreshed news
for index, item in enumerate(data):
item['history'] = searchResults[index]
item['history'] = False
item['history'] = searchResults[index]
# Catch network errors
except requests.exceptions.RequestException as e:
@ -188,13 +191,18 @@ class HackerNewsApp:
if not no_timer:
gtk.timeout_add(10 * 30 * 1000, self.refresh, widget, no_timer, chrome_data_directory)
# Merges two boolean arrays, using OR operation against each pair
def mergeBoolArray(self, original, patch):
for index, var in enumerate(original):
original[index] = original[index] or patch[index]
return original
def main():
parser = argparse.ArgumentParser(description='Hacker News in your System Tray')
parser.add_argument('-v','--version', action='version', version=Version.current())
parser.add_argument('-c','--comments', dest='comments',action='store_true', help="Load the HN comments link for the article as well")
parser.add_argument('--chrome', dest='chrome', help="Specify a Google Chrome Profile directory to use for matching chrome history")
parser.add_argument('--firefox', dest='firefox', help="Specify a Firefox Profile directory to use for matching firefox history")
args = parser.parse_args()
indicator = HackerNewsApp(args)

hackertray/ Normal file
View File

@ -0,0 +1,30 @@
from __future__ import print_function
import sqlite3
import shutil
import os
import sys
class Firefox:
HISTORY_TMP_LOCATION = '/tmp/hackertray.firefox'
HISTORY_FILE_NAME = '/places.sqlite'
def search(urls, config_folder_path):
conn = sqlite3.connect(Firefox.HISTORY_TMP_LOCATION)
db = conn.cursor()
result = []
for url in urls:
db_result = db.execute('SELECT url from moz_places WHERE url=:url',{"url":url})
if(db.fetchone() == None):
return result
def setup(config_folder_path):
file_name = os.path.abspath(config_folder_path+Firefox.HISTORY_FILE_NAME)
if not os.path.isfile(file_name):
print("ERROR: ", "Could not find Firefox history file", file=sys.stderr)
shutil.copyfile(file_name, Firefox.HISTORY_TMP_LOCATION)

View File

@ -5,11 +5,11 @@ from hackertray import Chrome
class ChromeTest(unittest.TestCase):
def runTest(self):
config_folder_path = os.getcwd()+'/test/'
config_folder_path = os.getcwd()+'/test/'
data =[
self.assertTrue(data == [True,True,True,False])
self.assertTrue(data == [True,True,True,False])

test/ Normal file
View File

@ -0,0 +1,15 @@
import unittest
import os
from hackertray import Firefox
class ChromeTest(unittest.TestCase):
def runTest(self):
config_folder_path = os.getcwd()+'/test/'
data =[
self.assertTrue(data == [True,True,True,False])

test/places.sqlite Normal file

Binary file not shown.