#!/usr/bin/python -tt # google-reader-directed-shares v1.0 - generates an RSS feed containing # friends' shared items directed at you (e.g., with your name in the # shared item note). # Copyright (c) 2011, John Morrissey # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 # USA. import datetime import getopt import logging import os import re import sys import urllib2 import BeautifulSoup import feedparser import mechanize import PyRSS2Gen GOOGLE_USERNAME = '' GOOGLE_PASSWORD = '' FRIENDS_SHARED_URL = 'https://www.google.com/reader/atom/user/-/state/com.google/broadcast-friends?n=250' FOR_NAMES = [ re.compile(r'STRING TO NOTICE', re.I), ] OUTFILE = '/path/to/rss/file' DEBUG = False def usage(): print 'google-reader-directed-shares v1.0' print 'Usage: %s [-h]' % os.path.basename(sys.argv[0]) print '' print ' -h, --help display this help and exit' try: options = getopt.gnu_getopt(sys.argv[1:], 'h', ['help=']) except getopt.GetoptError, e: print '%s: %s' % (os.path.basename(sys.argv[0]), str(e)) usage() sys.exit(2) if len(options[1]) != 0: usage() sys.exit(2) for option in options[0]: if option[0] == '-h' or option[0] == '--help': usage() sys.exit(0) if not GOOGLE_USERNAME or not GOOGLE_PASSWORD: usage() sys.exit(2) br = mechanize.Browser() br.set_handle_robots(False) br.set_handle_refresh(True, 10, True) br.set_handle_redirect(True) br.addheaders = [ ('User-agent', 'google-reader-directed-shares v1.0'), ] if DEBUG: br.set_debug_http(True) br.set_debug_responses(True) br.set_debug_redirects(True) logger = logging.getLogger('mechanize') logger.addHandler(logging.StreamHandler(sys.stdout)) logger.setLevel(logging.DEBUG) try: br.open('https://www.google.com/accounts/ServiceLogin') except urllib2.HTTPError, e: sys.exit('%d %s' % (e.code, e.msg)) if not br.viewing_html(): sys.exit('Unable to retrieve HTML for login page, has %s changed?' % host) def find_login_form(form): try: form.find_control('Email') form.find_control('Passwd') except: return False return True try: br.select_form(predicate=find_login_form) except mechanize.FormNotFoundError: sys.exit('Unable to locate login form, has google.com changed?') br['Email'] = GOOGLE_USERNAME br['Passwd'] = GOOGLE_PASSWORD try: r = br.submit() except urllib2.HTTPError, e: sys.exit('%d %s' % (e.code, e.msg)) try: r = br.open(FRIENDS_SHARED_URL) except urllib2.HTTPError, e: sys.exit('%d %s' % (e.code, e.msg)) items = [] for entry in feedparser.parse(r.get_data())['entries']: if 'subtitle' not in entry: continue soup = BeautifulSoup.BeautifulSoup(entry['subtitle']) all_bq = soup.findAll('blockquote') if not all_bq: continue for bq in all_bq: txt = ''.join(bq.findAll(text=True)) if txt.startswith('Shared by'): break else: continue for name in FOR_NAMES: if name.search(txt): break else: continue items.append(PyRSS2Gen.RSSItem( title=entry.title, link=entry.link, description=entry.description, guid=PyRSS2Gen.Guid(entry['id']), pubDate=entry.updated)) PyRSS2Gen.RSS2( title='Directed Shared Items for %s' % GOOGLE_USERNAME, link='', description='Shared items directed at %s' % GOOGLE_USERNAME, lastBuildDate=datetime.datetime.now(), items=items).write_xml(open(OUTFILE, 'w'))