diff options
-rwxr-xr-x[-rw-r--r--] | COPYING | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | cfg/pyAggr3g470r.cfg | 6 | ||||
-rwxr-xr-x[-rw-r--r--] | css/img/blogmarks.png | bin | 195 -> 195 bytes | |||
-rwxr-xr-x[-rw-r--r--] | css/img/delicious.png | bin | 266 -> 266 bytes | |||
-rwxr-xr-x[-rw-r--r--] | css/img/digg.png | bin | 358 -> 358 bytes | |||
-rwxr-xr-x[-rw-r--r--] | css/img/reddit.png | bin | 525 -> 525 bytes | |||
-rwxr-xr-x[-rw-r--r--] | css/img/scoopeo.png | bin | 295 -> 295 bytes | |||
-rwxr-xr-x[-rw-r--r--] | css/style.css | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | feedgetter.py | 20 | ||||
-rwxr-xr-x[-rw-r--r--] | pyAggr3g470r.py | 79 | ||||
-rwxr-xr-x[-rw-r--r--] | tuxdroid.py | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | utils.py | 33 | ||||
-rwxr-xr-x[-rw-r--r--] | var/feed.lst | 0 |
13 files changed, 105 insertions, 33 deletions
diff --git a/cfg/pyAggr3g470r.cfg b/cfg/pyAggr3g470r.cfg index b31a1233..73e4d25f 100644..100755 --- a/cfg/pyAggr3g470r.cfg +++ b/cfg/pyAggr3g470r.cfg @@ -1,3 +1,7 @@ [global] -path = /home/cedric/prog/python/pyaggr3g470r/ +path = /home/cedric/prog/python/projects/pyaggr3g470r/ sqlitebase = ./var/feed.db +[mail] +mail_from = pyAggr3g470r@mail.com +mail_to = example@mail.com +smtp = smtp.orange.fr
\ No newline at end of file diff --git a/css/img/blogmarks.png b/css/img/blogmarks.png Binary files differindex 2464e5bb..2464e5bb 100644..100755 --- a/css/img/blogmarks.png +++ b/css/img/blogmarks.png diff --git a/css/img/delicious.png b/css/img/delicious.png Binary files differindex a96f8c00..a96f8c00 100644..100755 --- a/css/img/delicious.png +++ b/css/img/delicious.png diff --git a/css/img/digg.png b/css/img/digg.png Binary files differindex 097c4600..097c4600 100644..100755 --- a/css/img/digg.png +++ b/css/img/digg.png diff --git a/css/img/reddit.png b/css/img/reddit.png Binary files differindex 2d615f2a..2d615f2a 100644..100755 --- a/css/img/reddit.png +++ b/css/img/reddit.png diff --git a/css/img/scoopeo.png b/css/img/scoopeo.png Binary files differindex 052c7dc8..052c7dc8 100644..100755 --- a/css/img/scoopeo.png +++ b/css/img/scoopeo.png diff --git a/css/style.css b/css/style.css index 67537a82..67537a82 100644..100755 --- a/css/style.css +++ b/css/style.css diff --git a/feedgetter.py b/feedgetter.py index eea8bfbb..68c90aa2 100644..100755 --- a/feedgetter.py +++ b/feedgetter.py @@ -16,6 +16,8 @@ import feedparser from datetime import datetime +import utils + 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]*)?"), \ @@ -40,7 +42,8 @@ class FeedGetter(object): self.c = self.conn.cursor() self.c.execute('''create table if not exists feeds (feed_title text, feed_site_link text, \ - feed_link text PRIMARY KEY, feed_image_link text)''') + feed_link text PRIMARY KEY, feed_image_link text, + mail text)''') self.c.execute('''create table if not exists articles (article_date text, article_title text, \ article_link text PRIMARY KEY, article_description text, \ @@ -108,12 +111,14 @@ class FeedGetter(object): except: feed_image = "/css/img/feed-icon-28x28.png" try: - self.c.execute('insert into feeds values (?,?,?,?)', (\ + self.c.execute('insert into feeds values (?,?,?,?,?)', (\ a_feed.feed.title.encode('utf-8'), \ a_feed.feed.link.encode('utf-8'), \ feed_link, \ - feed_image)) + feed_image, + "0")) except sqlite3.IntegrityError: + # feed already in the base pass for article in a_feed['entries']: try: @@ -129,7 +134,16 @@ class FeedGetter(object): description, \ "0", \ feed_link)) + result = self.c.execute("SELECT mail from feeds WHERE feed_site_link='" + \ + a_feed.feed.link.encode('utf-8') + "'").fetchall() + print result + if result[0][0] == "1": + print "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + # send the article + utils.send_mail(utils.mail_from, utils.mail_to, \ + a_feed.feed.title.encode('utf-8'), description) except sqlite3.IntegrityError: + # article already in the base pass diff --git a/pyAggr3g470r.py b/pyAggr3g470r.py index ed52f67f..fc5bce84 100644..100755 --- a/pyAggr3g470r.py +++ b/pyAggr3g470r.py @@ -12,38 +12,32 @@ import time import sqlite3 import cherrypy import threading -import ConfigParser from cherrypy.lib.static import serve_file import utils import feedgetter -config = ConfigParser.RawConfigParser() -config.read("./cfg/pyAggr3g470r.cfg") -path = config.get('global','path') -sqlite_base = os.path.abspath(config.get('global', 'sqlitebase')) - bindhost = "0.0.0.0" cherrypy.config.update({ 'server.socket_port': 12556, 'server.socket_host': bindhost}) path = {'/css/style.css': {'tools.staticfile.on': True, \ - 'tools.staticfile.filename':path+'css/style.css'}, \ + 'tools.staticfile.filename':utils.path+'css/style.css'}, \ '/css/img/feed-icon-28x28.png': {'tools.staticfile.on': True, \ - 'tools.staticfile.filename':path+'css/img/feed-icon-28x28.png'}, \ + 'tools.staticfile.filename':utils.path+'css/img/feed-icon-28x28.png'}, \ '/css/img/delicious.png': {'tools.staticfile.on': True, \ - 'tools.staticfile.filename':path+'css/img/delicious.png'}, \ + 'tools.staticfile.filename':utils.path+'css/img/delicious.png'}, \ '/css/img/digg.png': {'tools.staticfile.on': True, \ - 'tools.staticfile.filename':path+'css/img/digg.png'}, \ + 'tools.staticfile.filename':utils.path+'css/img/digg.png'}, \ '/css/img/reddit.png': {'tools.staticfile.on': True, \ - 'tools.staticfile.filename':path+'css/img/reddit.png'}, \ + 'tools.staticfile.filename':utils.path+'css/img/reddit.png'}, \ '/css/img/scoopeo.png': {'tools.staticfile.on': True, \ - 'tools.staticfile.filename':path+'css/img/scoopeo.png'}, \ + 'tools.staticfile.filename':utils.path+'css/img/scoopeo.png'}, \ '/css/img/blogmarks.png': {'tools.staticfile.on': True, \ - 'tools.staticfile.filename':path+'css/img/blogmarks.png'}, \ + 'tools.staticfile.filename':utils.path+'css/img/blogmarks.png'}, \ '/var/histogram.png':{'tools.staticfile.on': True, \ - 'tools.staticfile.filename':path+'var/histogram.png'}} + 'tools.staticfile.filename':utils.path+'var/histogram.png'}} htmlheader = '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' + \ '<head>' + \ @@ -119,6 +113,10 @@ class Root: html += "<br />\n" html += """<a href="/all_articles/%s">All articles</a>""" % (rss_feed_id,) + if self.feeds[rss_feed_id][6] == "0": + html += """ <a href="/tuned/start:%s">Stay tuned</a>""" % (rss_feed_id,) + else: + html += """ <a href="/tuned/stop:%s">Stop staying tuned</a>""" % (rss_feed_id,) html += """ <a href="/mark_as_read/Feed_FromMainPage:%s">Mark all as read</a>""" % (rss_feed_id,) if self.feeds[rss_feed_id][1] != 0: html += """ <a href="/unread/%s" title="Unread article(s)" @@ -155,7 +153,7 @@ class Root: <a href="/unread/All">%s unread article(s)</a>.<br />""" % \ (self.nb_articles, sum([feed[1] for feed in self.feeds.values()])) html += """Database: %s.\n<br />Size: %s bytes.</p>\n""" % \ - (os.path.abspath(sqlite_base), os.path.getsize(sqlite_base)) + (os.path.abspath(utils.sqlite_base), os.path.getsize(utils.sqlite_base)) html += """<form method=get action="/fetch/">\n<input type="submit" value="Fetch all feeds"></form>\n""" @@ -525,7 +523,7 @@ class Root: LOCKER.acquire() param, _, identifiant = target.partition(':') try: - conn = sqlite3.connect(sqlite_base, isolation_level = None) + conn = sqlite3.connect(utils.sqlite_base, isolation_level = None) c = conn.cursor() # Mark all articles as read. if param == "All": @@ -554,6 +552,33 @@ class Root: mark_as_read.exposed = True + def tuned(self, param): + """ + """ + try: + action, feed_id = param.split(':') + except: + return self.error_page("Bad URL") + conn = sqlite3.connect(utils.sqlite_base, isolation_level = None) + c = conn.cursor() + if action == "start": + try: + c.execute("UPDATE feeds SET mail=1 WHERE feed_site_link='" + + self.feeds[feed_id][5].encode('utf-8') + "'") + except: + pass + else: + try: + c.execute("UPDATE feeds SET mail=0 WHERE feed_site_link='" + + self.feeds[feed_id][5].encode('utf-8') + "'") + except: + pass + conn.commit() + c.close() + + tuned.exposed = True + + def update(self, path=None, event = None): """ Synchronizes transient objects with the database, @@ -566,9 +591,9 @@ class Root: self.top_words = utils.top_words(self.articles, 10) if "pylab" not in utils.IMPORT_ERROR: utils.create_histogram(self.top_words) - print "Base (%s) loaded" % sqlite_base + print "Base (%s) loaded" % utils.sqlite_base else: - print "Base (%s) empty!" % sqlite_base + print "Base (%s) empty!" % utils.sqlite_base def watch_base(self): @@ -578,15 +603,15 @@ class Root: When a change is detected, reload the base. """ mon = gamin.WatchMonitor() - mon.watch_file(sqlite_base, self.update) + mon.watch_file(utils.sqlite_base, self.update) time.sleep(10) ret = mon.event_pending() try: - print "Watching %s" % sqlite_base + print "Watching %s" % utils.sqlite_base while True: ret = mon.event_pending() if ret > 0: - print "The base of feeds (%s) has changed.\nReloading..." % sqlite_base + print "The base of feeds (%s) has changed.\nReloading..." % utils.sqlite_base ret = mon.handle_one_event() time.sleep(2) except KeyboardInterrupt: @@ -603,17 +628,17 @@ class Root: """ old_size = 0 try: - print "Watching %s" % sqlite_base + print "Watching %s" % utils.sqlite_base while True: time.sleep(5) # very simple test - if os.path.getsize(sqlite_base) != old_size: - print "The base of feeds (%s) has changed.\nReloading..." % sqlite_base + if os.path.getsize(utils.sqlite_base) != old_size: + print "The base of feeds (%s) has changed.\nReloading..." % utils.sqlite_base self.update() - old_size = os.path.getsize(sqlite_base) + old_size = os.path.getsize(utils.sqlite_base) except KeyboardInterrupt: pass - print "Stop watching", sqlite_base + print "Stop watching", utils.sqlite_base if __name__ == '__main__': @@ -626,7 +651,7 @@ if __name__ == '__main__': thread_watch_base = threading.Thread(None, root.watch_base, None, ()) except: print "The gamin module is not installed." - print "The base of feeds will be monitored" + print "The base of feeds will be monitored with the simple method." thread_watch_base = threading.Thread(None, root.watch_base_classic, None, ()) thread_watch_base.setDaemon(True) thread_watch_base.start() diff --git a/tuxdroid.py b/tuxdroid.py index c48fadf2..c48fadf2 100644..100755 --- a/tuxdroid.py +++ b/tuxdroid.py @@ -17,6 +17,9 @@ except: import sqlite3 import hashlib +import smtplib +from email.mime.text import MIMEText + from datetime import datetime from string import punctuation from collections import defaultdict @@ -33,6 +36,17 @@ except: import threading LOCKER = threading.Lock() +import os +import ConfigParser +config = ConfigParser.RawConfigParser() +config.read("./cfg/pyAggr3g470r.cfg") +path = config.get('global','path') +sqlite_base = os.path.abspath(config.get('global', 'sqlitebase')) +mail_from = config.get('mail','mail_from') +mail_to = config.get('mail','mail_to') +mail_smtp = config.get('mail','smtp') + + def detect_language(text): """ Detect the language of a text. @@ -114,6 +128,21 @@ def create_histogram(words, file_name="./var/histogram.png"): pylab.savefig(file_name, dpi = 80) pylab.close() +def send_mail(mfrom, mto, feed_title, message): + """Send the warning via mail + """ + mail = MIMEText(message) + mail['From'] = mfrom + mail['To'] = mto + mail['Subject'] = '[pyAggr3g470r] News from ' + feed_title + #email['Text'] = message + + server = smtplib.SMTP(mail_smtp) + server.sendmail(mfrom, \ + mto, \ + mail.as_string()) + server.quit() + def compare(stringtime1, stringtime2): """ Compare two dates in the format 'yyyy-mm-dd hh:mm:ss'. @@ -157,7 +186,7 @@ def load_feed(): # article_link, article_description, article_readed, # article_language) # feeds[feed_id] = (nb_article, nb_article_unreaded, feed_image, - # feed_title, feed_link, feed_site_link) + # feed_title, feed_link, feed_site_link, mail) articles, feeds = {}, {} if list_of_feeds != []: for feed in list_of_feeds: @@ -198,7 +227,7 @@ def load_feed(): feeds[feed_id] = (len(articles[feed_id]), \ len([article for article in articles[feed_id] \ if article[5]=="0"]), \ - feed[3], feed[0], feed[2], feed[1] \ + feed[3], feed[0], feed[2], feed[1] , feed[4]\ ) c.close() LOCKER.release() diff --git a/var/feed.lst b/var/feed.lst index 43b89680..43b89680 100644..100755 --- a/var/feed.lst +++ b/var/feed.lst |