Commits

Marcin Kasperski committed ca5c5c3

Some renaming, docs, and samples.

Comments (0)

Files changed (2)

sample/search_and_detail_sample.py

+# -*- coding: utf-8 -*-
+
+"""
+mekk.greader example - sample for search and some other methods
+"""
+
+from mekk.greader import GoogleReaderClient, GoogleLoginFailed
+from pprint import pprint
+
+import logging
+logging.basicConfig(level = logging.INFO)
+
+############################################################
+# Login & Password
+############################################################
+
+# Some oversimplistict password management example.
+# Feel free to drop it and get username and password
+# any way you like.
+
+def get_username_and_password(force_fresh_input = False):
+    """
+    Reads username and password from keyring or prompts user for them
+    and saves them to the keyring. force_fresh_input enforces
+    the prompt (to be used after bad login for example).
+    """
+    import keyring, getpass
+
+    username = keyring.get_password("mekk.greader", "default-login")
+    if (not username) or force_fresh_input:
+        while True:
+            username = raw_input("Your Google account name: ")
+            if username:
+                break
+        keyring.set_password("mekk.greader", "default-login", username)
+
+    password = keyring.get_password("mekk.greader", username)
+    if (not password) or force_fresh_input:
+        while True:
+            password = getpass.getpass("Password for %s: " % username)
+            if password:
+                break
+        keyring.set_password("mekk.greader", username, password)
+
+    return username, password
+
+############################################################
+# Client construction
+############################################################
+
+try:
+    username, password = get_username_and_password()
+    reader_client = GoogleReaderClient(username, password)
+except GoogleLoginFailed:
+    username, password = get_username_and_password(True)
+    reader_client = GoogleReaderClient(username, password)
+
+############################################################
+# Example calls - info reading
+############################################################
+
+def title(txt):
+    print "*" * 60
+    print "*", txt
+    print "*" * 60
+
+title("search")
+ids = reader_client.search_for_articles(u"humor graphics", count = 4)
+pprint(ids)
+
+title("article_contents")
+reply = reader_client.article_contents(ids)
+#pprint(reply)
+for item in reply['items']:
+    print u"item %s" % item['id']
+    print u"    categories: %s" % u", ".join(item['categories'])
+    print u"    title: %s" % item['title']
+    for link in item['alternate']:
+        print u"    link: %s" % link['href']
+    print u"    content: %s" % item['content']['content'][:240]
+    print
+
+title("feed_contents")
+reply = reader_client.feed_contents(
+    "http://rss.gazeta.pl/pub/rss/sport.xml", count=4)
+for item in reply['items']:
+    print u"item %s" % item['id']
+    print u"    categories: %s" % u", ".join(item['categories'])
+    print u"    title: %s" % item['title']
+    for link in item['alternate']:
+        print u"    link: %s" % link['href']
+    #print u"    content: %s" % item['content']['content'][:240]
+    print
+

src/mekk/greader/reader_client.py

 # Inspired by (including copying some code snippets):
 # http://blog.gpowered.net/2007/08/google-reader-api-functions.html
 #
-# Key information:
+# Key information I used initially:
 # http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI
+#
+# More docs, not yet fully consumed:
+# http://undoc.in/googlereader.html#search-items-ids
 
 import urllib
 import urllib2
     ############################################################
     # Public API - item
 
-    def search_ids(self, query, format="obj"):
-        if format == 'obj':
-            output = "json"
-        else:
-            output = format
+    def search_for_articles(self, query, count=20):
+        """
+        Searches for articles using given text query.
+        Returns plain list like:
+
+           [ u'7212740130471148824',
+             u'-8654279325215116158',
+             u'8121555931508499120',
+           ]
+
+        Those are short article(entry) identifiers
+        (note that reader also sometimes uses long form
+         'tag:google.com,2005:reader/item/5d0cfa30041d4348',
+         every reader api which requires article id
+         should handle both forms fine)
+        """
+        output = "json"
         url = SEARCH_ITEMS_IDS_URL + "?"\
-              + urllib.urlencode({"q": query,
-                                  "num": "1000",
-                                  "output": output,
-                                  "ck": int(time.mktime(datetime.now().timetuple())),
-                                  "client": SOURCE,
-                                 })
-        if format == 'obj':
-            return json.loads(self._make_call(url))
-        else:
-            return self._make_call(url)
+              + urllib.urlencode({
+                "q": query,
+                "num": count,
+                "output": output,
+                "ck": int(time.mktime(datetime.now().timetuple())),
+                "client": SOURCE,
+                })
+        reply = json.loads(self._make_call(url))
+        return [ item['id'] for item in reply['results'] ]
 
-    def contents(self, ids):
+    def article_contents(self, ids):
+        """
+        Return article (entry) contents of specified articles. ids is
+        a list of identifiers (for example extracted from feed, or
+        returned from search_for_articles).
+
+        Returned structure is a complicated recursive dictionary
+        of which ['items'] list may be of biggest interest. Dump it for
+        details.
+        """
         url = STREAM_ITEMS_CONTENTS_URL + "?" \
               + urllib.urlencode({"ck": int(time.mktime(datetime.now().timetuple())),
                                   "client": SOURCE})
         post_params = [("i", id_) for id_ in ids]
-        post_params.extend([("it", "0")] * len(post_params))
+        #post_params.extend([("it", "0")] * len(post_params))
         post_params.append(("T", self._get_token()))
         return json.loads(self._make_call(url, post_params))
 
-    def contents_feed(self, feed_url, count=20):
+    def feed_contents(self, feed_url, count=20, older_first=False):
+        """
+        Returns list of articles belonging to given feed.
+        """
         url = STREAM_CONTENTS_FEED_URL % urllib.quote_plus(feed_url) + "?" \
-              + urllib.urlencode({"ck": int(time.mktime(datetime.now().timetuple())),
-                                  "n": count,
-                                  "client": SOURCE})
+              + urllib.urlencode({
+                "ck": int(time.mktime(datetime.now().timetuple())),
+                "n": count,
+                "r": (older_first and "o" or "d"),
+                "client": SOURCE})
         return json.loads(self._make_call(url))