aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README3
-rwxr-xr-xfeedgetter.py16
-rwxr-xr-xpyAggr3g470r.py11
-rwxr-xr-xtuxdroid.py88
-rwxr-xr-xutils.py15
5 files changed, 36 insertions, 97 deletions
diff --git a/README b/README
index 3be66923..b725dba6 100644
--- a/README
+++ b/README
@@ -9,8 +9,7 @@ based on CherryPy. Articles are stored in a SQLite base.
* export articles (HTML and raw text);
* mark or unmark an article as favorites;
* share an article on Google Buzz, del.icio.us, Digg, reddit, Scoopeo and Blogmarks;
-* language detection and search articles by language;
-* TuxDroid support (for the notification of unread articles).
+* language detection and search articles by language.
diff --git a/feedgetter.py b/feedgetter.py
index 6b875c64..56e61662 100755
--- a/feedgetter.py
+++ b/feedgetter.py
@@ -103,15 +103,17 @@ class FeedGetter(object):
for article in a_feed['entries']:
description = ""
try:
+ # article content
description = article.content[0].value.encode('utf-8')
except AttributeError:
try:
+ # article description
description = article.description.encode('utf-8')
except Exception, e:
description = ""
try:
- self.c.execute('insert into articles values (?,?,?,?,?,?,?)', (\
+ self.c.execute('insert into articles values (?, ?, ?, ?, ?, ?, ?)', (\
datetime(*article.updated_parsed[:6]), \
utils.clear_string(article.title.encode('utf-8')), \
article.link.encode('utf-8'), \
@@ -123,10 +125,14 @@ class FeedGetter(object):
a_feed.feed.link.encode('utf-8') + "'").fetchall()
if result[0][0] == "1":
# send the article by e-mail
- threading.Thread(None, utils.send_mail, \
- None, (utils.mail_from, utils.mail_to, \
- a_feed.feed.title.encode('utf-8'), description) \
- ).start()
+ try:
+ threading.Thread(None, utils.send_mail, \
+ None, (utils.mail_from, utils.mail_to, \
+ a_feed.feed.title.encode('utf-8'), description) \
+ ).start()
+ except Exception, e:
+ # SMTP acces denied, to many SMTP connections, etc.
+ print e
except sqlite3.IntegrityError:
# article already in the base
pass
diff --git a/pyAggr3g470r.py b/pyAggr3g470r.py
index 85605b88..1d530137 100755
--- a/pyAggr3g470r.py
+++ b/pyAggr3g470r.py
@@ -24,6 +24,7 @@ bindhost = "0.0.0.0"
cherrypy.config.update({ 'server.socket_port': 12556, 'server.socket_host': bindhost})
+# static files
path = {'/css/style.css': {'tools.staticfile.on': True, \
'tools.staticfile.filename':utils.path+'/css/style.css'}, \
'/css/img/feed-icon-28x28.png': {'tools.staticfile.on': True, \
@@ -56,6 +57,10 @@ path = {'/css/style.css': {'tools.staticfile.on': True, \
'tools.staticdir.dir': os.path.join(utils.path, './var/qrcode')}}
def htmlheader(nb_unread_articles=""):
+ """
+ Return the header of the HTML page with the number of unread articles
+ in the 'title' HTML tag..
+ """
return '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' + \
'<head>' + \
'\n\t<title>'+ nb_unread_articles +'pyAggr3g470r - RSS Feed Reader</title>\n' + \
@@ -76,6 +81,10 @@ htmlnav = '<body>\n<h1><div class="right innerlogo"><a href="/"><img src="/css/i
class Root:
+ """
+ Root class.
+ All pages of pyAggr3g470r are described in this class.
+ """
def index(self):
"""
Main page containing the list of feeds and articles.
@@ -97,6 +106,8 @@ class Root:
html += """<a href="/unread/All">Unread article(s): %s</a>\n""" % \
(self.nb_unread_articles,)
+
+ # The main page display all the feeds.
for rss_feed_id in self.feeds.keys():
html += """<h2><a name="%s"><a href="%s" rel="noreferrer"
target="_blank">%s</a></a>
diff --git a/tuxdroid.py b/tuxdroid.py
deleted file mode 100755
index c48fadf2..00000000
--- a/tuxdroid.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#! /usr/local/bin/python
-#-*- coding: utf-8 -*-
-
-"""Communication interface with Tux Droid.
-"""
-
-__author__ = "Cedric Bonhomme"
-__version__ = "$Revision: 0.1 $"
-__date__ = "$Date: 2010/02/26 $"
-__copyright__ = "Copyright (c) 2010 Cedric Bonhomme"
-__license__ = "GPL v3"
-
-import time
-import sqlite3
-
-try:
- from tuxisalive.api import *
-except:
- raise NameError("The module tuxisalive is missing.")
-
-class Tux(object):
- """Manage the connection with Tux Droid.
- """
- def __init__(self, locutor = "Julie "):
- """Connection to the server.
- """
- self.tux = TuxAPI('127.0.0.1', 270)
- self.tux.server.autoConnect(CLIENT_LEVEL_RESTRICTED, 'none', 'none')
- print "Connection with Tux Droid..."
-
- if not self.tux.server.waitConnected(10.0):
- raise Exception("The server of Tux Droid is not ready.")
- print "Connected to the server of Tux Droid."
-
- if not self.tux.dongle.waitConnected(10.0):
- raise Exception("Not connected to the dongle.")
- print "Connected to the dongle."
-
- if not self.tux.radio.waitConnected(10.0):
- raise Exception("Connection between Tux Droid and the dongle unpossible.")
- print "Tux Droid connected to the dongle."
-
- if self.tux.access.waitAcquire(10.0, ACCESS_PRIORITY_NORMAL):
- self.tux.tts.setLocutor(locutor) # set the locutor
- self.tux.tts.setPitch(110) # set the Pitch
- self.tux.tts.speakAsync("Hello")
-
- def disconnect(self):
- """Disconnect.
- """
- self.tux.server.disconnect()
- self.tux.destroy()
-
- def onStart(self):
- """
- """
- self.tux.flippers.onAsync(4, finalState = 'DOWN', speed = 3)
- self.tux.tts.speakAsync("Hello !")
-
- def say_something(self, message):
- """
- """
- self.tux.tts.speakAsync(message)
-
- def check_feeds(self):
- """
- """
- unread_articles = []
- try:
- conn = sqlite3.connect("./var/feed.db", isolation_level = None)
- c = conn.cursor()
- unread_articles = c.execute("SELECT * FROM articles WHERE article_readed='0'")
- c.close()
- except Exception, e:
- pass
- self.say_something("News to read !")
- #self.say_something(str(len(unread_articles)))
- #for unread_article in unread_articles:
- #self.say_something()
-
-
-if __name__ == "__main__":
- # Point of entry in execution mode
- tux_reader = Tux()
- while True:
- time.sleep(10)
- tux_reader.check_feeds()
- tux_reader.disconnect()
diff --git a/utils.py b/utils.py
index 0b93fb1f..780ebf91 100755
--- a/utils.py
+++ b/utils.py
@@ -50,6 +50,7 @@ LOCKER = threading.Lock()
import os
import ConfigParser
+# load the configuration
config = ConfigParser.RawConfigParser()
config.read("./cfg/pyAggr3g470r.cfg")
path = os.path.abspath(".")
@@ -60,6 +61,7 @@ smtp_server = config.get('mail','smtp')
username = config.get('mail','username')
password = config.get('mail','password')
+# regular expression to chech URL
url_finders = [ \
re.compile("([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}|(((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+)(:[0-9]*)?/[-A-Za-z0-9_\\$\\.\\+\\!\\*\\(\\),;:@&=\\?/~\\#\\%]*[^]'\\.}>\\),\\\"]"), \
re.compile("([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}|(((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+)(:[0-9]*)?"), \
@@ -70,6 +72,7 @@ url_finders = [ \
def detect_url_errors(list_of_urls):
"""
Detect URL errors.
+ Return a list of error(s).
"""
errors = []
for url in list_of_urls:
@@ -108,8 +111,8 @@ def clear_string(data):
Clear a string by removing HTML tags, HTML special caracters
and consecutive white spaces (more that one).
"""
- p = re.compile(r'<[^<]*?/?>')
- q = re.compile(r'\s')
+ p = re.compile(r'<[^<]*?/?>') # HTML tags
+ q = re.compile(r'\s') # consecutive white spaces
return p.sub('', q.sub(' ', data))
def unescape(text):
@@ -157,10 +160,12 @@ def tag_cloud(tags, query="word_count"):
"""
tags.sort(key=operator.itemgetter(0))
if query == "word_count":
+ # tags cloud from the management page
return ' '.join([('<font size="%d"><a href="/q/?querystring=%s" title="Count: %s">%s</a></font>\n' % \
(min(1 + count * 7 / max([tag[1] for tag in tags]), 7), word, count, word)) \
for (word, count) in tags])
if query == "year":
+ # tags cloud for the history
return ' '.join([('<font size="%d"><a href="/history/?querystring=%s:%s" title="Count: %s">%s</a></font>\n' % \
(min(1 + count * 7 / max([tag[1] for tag in tags]), 7), query, word, count, word)) \
for (word, count) in tags])
@@ -213,6 +218,7 @@ def add_feed(feed_url):
if os.path.exists("./var/feed.lst"):
for line in open("./var/feed.lst", "r"):
if feed_url in line:
+ # if the feed is already in the file
return False
with open("./var/feed.lst", "a") as f:
f.write(feed_url + "\n")
@@ -266,10 +272,12 @@ def create_base():
sqlite3.register_adapter(str, lambda s : s.decode('utf-8'))
conn = sqlite3.connect(sqlite_base, isolation_level = None)
c = conn.cursor()
+ # table of feeds
c.execute('''create table if not exists feeds
(feed_title text, feed_site_link text, \
feed_link text PRIMARY KEY, feed_image_link text,
mail text)''')
+ # table of articles
c.execute('''create table if not exists articles
(article_date text, article_title text, \
article_link text PRIMARY KEY, article_description text, \
@@ -329,6 +337,7 @@ def load_feed():
sha1_hash.update(article[2].encode('utf-8'))
article_id = sha1_hash.hexdigest()
+ # check the presence of the module for language detection
if "oice" not in IMPORT_ERROR:
if article[3] != "":
language = detect_language(clear_string(article[3][:80]).encode('utf-8') + \
@@ -338,6 +347,7 @@ def load_feed():
else:
language = "IMPORT_ERROR"
+ # informations about an article
article_list = [article_id, article[0], unescape(article[1]), \
article[2], unescape(article[3]), \
article[4], language, article[6]]
@@ -350,6 +360,7 @@ def load_feed():
else:
articles[feed_id].append(article_list)
+ # informations about a feed
feeds[feed_id] = (len(articles[feed_id]), \
len([article for article in articles[feed_id] \
if article[5]=="0"]), \
bgstack15