#!/usr/bin/env python
"""
ch05_ipod_notes_aggregator.py
Poll subscriptions, load iPod up with notes.
"""
import sys, os, os.path, shutil, time, md5
from agglib import *
FEEDS_FN = "ipod_feeds.txt"
FEED_DB_FN = "ipod_feeds_db"
ENTRY_DB_FN = "ipod_entry_seen_db"
IPOD_NOTES_PATH = "/Volumes/Spirit of Radio/Notes"
IPOD_FEEDS_IDX_TITLE = "Feeds"
IPOD_FEEDS_IDX = "feeds.linx"
IPOD_FEEDS_DIR = "zz_feeds"
NOTE_TMPL = """
%(title)s
%(content)s
"""
FEED_LINK_TMPL = """%(title)s
\n"""
ENTRY_LINK_TMPL = """* %(title)s
\n"""
ENTRY_TMPL = """%(entry.title)s
%(date)s - %(time)s
%(entry.summary)s
"""
def main():
"""
Poll subscribed feeds and load the iPod up with notes.
"""
# Open the aggregator databases
feed_db, entry_db = openDBs(FEED_DB_FN, ENTRY_DB_FN)
# Clean up and recreate feed notes directory
ipod_feeds_path = os.path.join(IPOD_NOTES_PATH, IPOD_FEEDS_DIR)
shutil.rmtree(ipod_feeds_path, ignore_errors=True)
os.makedirs(ipod_feeds_path)
# Load up the list of subscriptions
feeds = [ x.strip() for x in open(FEEDS_FN, "r").readlines() ]
# Build the notes for all feeds, gathering links to the feed indexes
feed_links = buildNotesForFeeds(feed_db, entry_db, ipod_feeds_path, feeds)
# Write the feed index note with links to all feed indexes
index_out = "".join([FEED_LINK_TMPL % f for f in feed_links])
writeNote(filename = os.path.join(IPOD_NOTES_PATH, IPOD_FEEDS_IDX),
title = IPOD_FEEDS_IDX_TITLE,
content = index_out)
# Close the aggregator databases
closeDBs(feed_db, entry_db)
def buildNotesForFeeds(feed_db, entry_db, ipod_feeds_path, feeds):
"""
Iterate through feeds, produce entry notes, feed index notes,
and return list of links to feed index notes.
"""
feed_links = []
for feed_url in feeds:
# Get new entries for the current feed
entries = getNewFeedEntries([feed_url], feed_db, entry_db)
if len(entries) > 0:
# Derive current feed path via md5 hash, create it if needed
feed_dir_name = md5_hash(feed_url)
feed_dir = os.path.join(ipod_feeds_path, feed_dir_name)
if not os.path.isdir(feed_dir):
os.makedirs(feed_dir)
# Get a clean title for this feed.
feed_title = feed_db[feed_url].get('title', 'Untitled').strip()
# Build the notes for the new entries, gathering links
feed_entry_links = buildNotesForEntries(feed_dir, feed_title, entries)
# Write out the index note for this feed, based on entry notes.
feed_out = "".join([ENTRY_LINK_TMPL % f for f in feed_entry_links])
writeNote(filename = os.path.join(feed_dir, 'index.txt'),
title = feed_title,
content = feed_out)
# Include this feed in the top-level index.
feed_links.append({
'href' : '%s/%s/index.txt' % (IPOD_FEEDS_DIR, feed_dir_name),
'title' : feed_title
})
return feed_links
def buildNotesForEntries(feed_dir, feed_title, entries):
"""
Iterate through a set of entries, build a note for each in the
appropriate feed directory, return list of links to generated
notes.
"""
feed_entry_links = []
for entry in entries:
# Build note name on MD5 hash, possibly redundant but oh well!
entry_note_name = '%s.txt' % md5_hash(entry.hash())
# Get a clean title for the entry note
entry_title = entry['entry.title'].strip()
# Write out the index note for this feed.
writeNote(filename = os.path.join(feed_dir, entry_note_name),
title = feed_title,
content = ENTRY_TMPL % entry)
# Include this feed in the top-level index
feed_entry_links.append({
'href' : entry_note_name,
'title' : entry_title
})
return feed_entry_links
def writeNote(filename, title, content):
"""
Given a filename, title, and content, write a note to the iPod.
"""
print "\t\tWrote note: %s" % filename
fout = open(filename, "w")
fout.write(NOTE_TMPL % { 'title':title, 'content':content })
fout.close()
def md5_hash(data):
"""
Convenience function to generate an MD5 hash.
"""
m = md5.md5()
m.update(data)
return m.hexdigest()
if __name__ == "__main__": main()