1. Marcin Kasperski
  2. mekk.feeds

Commits

Marcin Kasperski  committed a4d69bc

Wyniesione do osobnego modułu

  • Participants
  • Parent commits 891639d
  • Branches default

Comments (0)

Files changed (7)

File sample/test_postrank_client.py

-# -*- coding: utf-8 -*-
-
-from mekk.feeds.postrank_client import PostRankClient
-from pprint import pprint
-
-pr = PostRankClient("mekk.waw.pl/test")
-
-for url in [
-    "http://feeds.feedburner.com/SmashingMagazine",
-    "http://feeds.mekk.waw.pl/NotatnikZapisywanyWieczorami",
-    ]:
-    print 
-    print url
-    print
-    pprint(pr.feed_info(url))
-

File sample/test_reader_client.py

-# -*- coding: utf-8 -*-
-
-"""
-Prosty test
-"""
-
-from mekk.feeds import GoogleReaderClient
-from _SECRET_ import LOGIN, PASSWORD
-from pprint import pprint
-
-rc = GoogleReaderClient(LOGIN, PASSWORD)
-
-############################################################
-
-#print rc.get_subscription_list('xml')
-#print rc.get_subscription_list()
-#print rc.get_tag_list()
-#print rc.get_preference_list('json')
-#print rc.get_unread_count()
-
-test_feed = 'http://rss.gazeta.pl/pub/rss/sport.xml'
-test_tag = "000000: Kontrolne"
-test_tag_bis = u"000000: NieByłoTego"
-
-#print rc.get_feed_atom(test_feed)
-test_feed_2 = 'http://lekcjawychowania.pl/feed'
-if False:
-    print rc.get_feed_atom(test_feed_2, count = 2, format = 'xml')
-    print
-    print
-if False:
-    r = rc.get_feed_atom(test_feed_2, count = 2, format = 'etree')
-    print r
-    print
-if True:
-    r = rc.get_feed_atom(test_feed_2, count = 2)
-    print r.generator
-    print r.entry.id
-    print r.entry[1].id
-    print r.entry.category.get('term')
-
-
-if False:
-    rc.subscribe_feed(test_feed, u"Sport Gazetą Zażółć")
-    rc.add_feed_tag(test_feed, u"Sport Bis", test_tag)
-    # Efekty widać po zamknięciu readera i jego otwarciu na nowo
-
-if False:
-    # To chyba nie działa!!!
-    rc.add_feed_tag(test_feed, test_tag_bis) 
-#pprint( rc.get_tag_list() )
-
-#print rc.get_tagged_atom(test_tag)
-#print rc.get_tagged_atom(test_tag_bis)
-
-if False:
-    rc.remove_feed_tag(test_feed, u"Sport Tris", test_tag)
-    rc.change_feed_title(test_feed, u"Zmieniony tytuł Sport")
-
-if False:
-    rc.unsubscribe_feed(test_feed)

File setup.py

View file
         },
       zip_safe = True,
       install_requires=[
-        'lxml', 'simplejson', 'keyring',
+        'lxml', 'simplejson', 'keyring', 'mekk.greader', 'mekk.postrank'
       ],
       tests_require=[
         'nose',

File src/mekk/feeds/__init__.py

View file
-from reader_client import GoogleReaderClient, GoogleLoginFailed, GoogleOperationFailed
 from postrank_client import PostRankClient

File src/mekk/feeds/greader2org/run.py

View file
 from update_to_google import UpdateToGoogle
 from update_from_postrank import UpdateFromPostrank
 from settings import Settings
-from mekk.feeds import GoogleReaderClient, PostRankClient, GoogleLoginFailed
+from mekk.feeds import PostRankClient
+from mekk.greader import GoogleReaderClient, GoogleLoginFailed, GoogleOperationFailed
 from mekk.feeds.orgfile import OrgFile
 import sys,os
 

File src/mekk/feeds/postrank_client.py

-# -*- coding: utf-8 -*-
-
-"""
-Wybrane elementy klienta PostRank
-"""
-
-import urllib, urllib2
-import re
-import simplejson
-import time
-
-import logging
-log = logging.getLogger("postrank")
-
-POSTRANK = 'http://api.postrank.com/v1/'
-
-class PostRankClient(object):
-    """
-    A few PostRank functions
-    """
-
-    def __init__(self, appkey):
-        """
-        appkey to identyfikator aplikacji, np. domeny
-        """
-        self.appkey = appkey
-
-    def feed_info(self, feed_url):
-        """
-        Dla zadanego feedu zwraca podstawowe informacje na jego temat.
-        
-        Uwaga: funkcja zwykle zwraca rozbudowany słownik ale może
-        zwrócić None gdy dostanie błąd HTTP 202 (co sygnalizuje, że
-        kiedyś się pojawi...)
-        """
-
-        query = {
-            'appkey' : self.appkey,
-            'format' : 'json',
-            'id' : feed_url,
-            }
-        enc_query = urllib.urlencode(query)
-
-        url = "http://api.postrank.com/v2/feed/info?" + enc_query
-
-        request = urllib2.Request(url.encode('utf-8'))
-
-        log.info("Calling: %s" % request.get_full_url())
-        try:
-            f = urllib2.urlopen(request)
-        except urllib2.HTTPError, e:
-            if e.code == 202:
-                log.info("HTTP:202 (accepted) - feed accepted for processing")
-                return None
-            else:
-                raise
-        result = f.read()
-        log.debug("Result: %s" % result)
-
-        return simplejson.loads(result)
-

File src/mekk/feeds/reader_client.py

-# -*- coding: utf-8 -*-
-
-"""
-Klient Google Readera
-"""
-
-# Mocno inspirowane (z kopiowaniem sporych fragmentów kodu włącznie):
-# http://blog.gpowered.net/2007/08/google-reader-api-functions.html
-#
-# Kluczowe informacje:
-# http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI
-
-import urllib
-import urllib2
-import re
-import simplejson
-import time
-from lxml import etree, objectify
-
-import logging
-log = logging.getLogger("reader")
-
-TOKEN_VALID_TIME = 60
-#DUMP_REQUESTS = True
-#DUMP_REQUESTS = False
-#DUMP_REPLIES = False
-#DUMP_REPLIES = True
-
-class GoogleLoginFailed(Exception):
-    pass
-class GoogleOperationFailed(Exception):
-    pass
-
-#SOURCE = 'my-small-script'
-SOURCE = 'mekk'
-
-GOOGLE_URL = 'http://www.google.com'
-READER_URL = GOOGLE_URL + '/reader'
-LOGIN_URL = 'https://www.google.com/accounts/ClientLogin'
-TOKEN_URL = READER_URL + '/api/0/token'
-TAG_LIST_URL = READER_URL + '/api/0/tag/list'
-PREFERENCE_LIST_URL = READER_URL + '/api/0/preference/list'
-UNREAD_COUNT_URL = READER_URL + '/api/0/unread-count'
-SUBSCRIPTION_LIST_URL = READER_URL + '/api/0/subscription/list'
-SUBSCRIPTION_EDIT_URL = READER_URL + '/api/0/subscription/edit'
-TAG_EDIT_URL = READER_URL + '/api/0/edit-tag'
-DISABLE_TAG_URL = READER_URL + '/api/0/disable-tag'
-IN_STATE_URL = READER_URL + '/atom/user/-/state/com.google/%s'
-GET_FEED_URL = READER_URL + '/atom/feed/'
-READING_TAG_URL = READER_URL + '/atom/%s'
-
-class GoogleReaderClient(object):
-
-    """
-    Selected GoogleReader functions. Connects to specified Google Account
-    and retrieves/modifies GoogleReader subscriptions.
-
-    The get_*_atom functions retrieve different articles as Atom feeds.
-    Apart from specific parameters, all those functions handle the following
-    args:
-
-    - count         - how many elements to get (by default Google default, i.e. 20)
-    - continue_from - value of gr:continuation in "previous" call, to implement paging
-    - older_first=True - start from older items, not from newest
-
-    Remaining functions allow one to manage subscription feeds.
-    """
-    
-    def __init__(self, login, password):
-        self.session_id = self._get_session_id(login, password)
-        self.cached_token = None
-        self.cached_token_time = 0
-        self.my_id = '-'
-        self.cached_feed_item_ids = dict()
-
-    ############################################################
-    # Small utilities, used mainly internally
-
-    def tag_id(self, tag):
-        """
-        Converts tag name (say "Życie: Polityka" into 
-        tag id (say "user/-/label/Życie: Polityka").
-        
-        If parameter is already in this form, leaves it as-is
-        """
-        if not tag.startswith('user/'):
-            tag = 'user/%s/label/%s' % (self.get_my_id(), tag)
-        return tag
-
-    def get_my_id(self):
-        if self.my_id == '-':
-            tl = self.get_tag_list()
-            for vl in tl['tags']:
-                m = re.match('user/(\d+)/', vl['id'])
-                if m:
-                    self.my_id = m.group(1)
-                    break
-        return self.my_id
-
-    def feed_item_id(self, feed):
-        """
-        Returns identifier of the first item of given tag feed.
-        Used during sub/unsubscription (for some reason it is needed)
-        """
-        i = self.cached_feed_item_ids.get(feed)
-        if not i:
-            r = self.get_feed_atom(feed, count = 2, format = 'obj')
-            i = str(r.entry.id)
-            self.cached_feed_item_ids[feed] = i
-        return i
-
-    ############################################################
-    # Public API - atom feeds (articles)
-
-    def get_feed_atom(self, url, **kwargs):
-        """
-        Atom feed for any feed. Works also for unsubscribed feeds
-        """
-        return self._get_atom(GET_FEED_URL + url,
-                              **kwargs)
-
-    def get_reading_list_atom(self, **kwargs):
-        """
-        Atom feed of unread items
-        """
-        return self.get_instate_atom('reading-list', **kwargs)
-
-    def get_read_atom(self, **kwargs):
-        """
-        Atom feed of (recent) read items
-        """
-        return self.get_instate_atom('read', **kwargs)
-
-    def get_tagged_atom(self, tag, **kwargs):
-        """
-        Atom feed of (unread?) items for given tag
-        """
-        tagged_url = READING_TAG_URL % self.tag_id(tag)
-        return self._get_atom(tagged_url, **kwargs)
-
-    def get_starred_atom(self, **kwargs):
-        """
-        Atom feed of starred items
-        """
-        return self.get_instate_atom('starred', **kwargs)
-
-    def get_fresh_atom(self, **kwargs):
-        """
-        Atom feed of fresh (newly added) items
-        """
-        return self.get_instate_atom('fresh', **kwargs)
-
-    def get_broadcast_atom(self, **kwargs):
-        """
-        Atom feed of public (shared) items
-        """
-        return self.get_instate_atom('broadcast', **kwargs)
-
-    def get_instate_atom(self, state, **kwargs):
-        """
-        Atom feed of items in any state. Known states:
-
-        read, kept-unread, fresh, starred, broadcast (public items),
-        reading-list (all), tracking-body-link-used, tracking-emailed,
-        tracking-item-link-used, tracking-kept-unread
-
-        get_fresh_atom is equivalent to get_instate_atom('fresh') and so on.
-        """
-        return self._get_atom(IN_STATE_URL % 'state', **kwargs)
-
-
-    ############################################################
-    # Public API - subscription info
-
-    def get_subscription_list(self, format = 'obj'):
-        """
-        Returns info about all subscribed feeds.
-
-        If format = 'xml' returns bare XML text
-
-        If format = 'json', returns bare JSON text
-
-        If format = 'obj', returns parsed JSON (python dictionary)
-        """
-        return self._get_list(SUBSCRIPTION_LIST_URL, format)
-
-    def get_tag_list(self, format = 'obj'):
-        return self._get_list(TAG_LIST_URL, format)
-
-    def get_preference_list(self, format = 'obj'):
-        return self._get_list(PREFERENCE_LIST_URL, format)
-
-    def get_unread_count(self, format = 'obj'):
-        return self._get_list(UNREAD_COUNT_URL, format)
-
-    ############################################################
-    # Public API - subscription modifications
-
-    def subscribe_feed(self, feed_url, title = None):
-        """
-        Subscribe to given feed. Optionally set title
-        """
-        return self._change_feed(feed_url, 'subscribe', title = title)
-
-    def unsubscribe_feed(self, feed_url):
-        """
-        Unsubscribe from the given feed.
-        """
-        return self._change_feed(feed_url, 'unsubscribe')
-
-    def change_feed_title(self, feed_url, title):
-        """
-        Changes the feed title
-        """
-        return self._change_feed(feed_url, 'edit', title = title)
-
-    def add_feed_tag(self, feed_url, title, tag):
-        """
-        Adds feed to new tag (folder).
-        Tag can be specified either as full id copied from the tag list
-        (say "user/04686467480557924617/label/\u017bycie: Polityka")
-        or as the sole name ("Życie: Polityka")
-        
-        It seems that tag may be new (not-yet-existant tags do work)
-        """
-        return self._change_tag(feed_url, title, add_tag = tag)
-
-    def remove_feed_tag(self, feed_url, title, tag):
-        """
-        Removes feed from given tag (folder).
-        Tag can be specified either as full id copied from the tag list
-        (say "user/04686467480557924617/label/\u017bycie: Polityka")
-        or as the sole name ("Życie: Polityka")
-        """
-        return self._change_tag(feed_url, title, remove_tag = tag)
-
-    def disable_tag(self, tag):
-        """
-        Removes tag as a whole
-        """
-        url = TAG_DISABLE_URL +  '?client=%s' % SOURCE
-        post_data = {
-            's' : self.tag_id(tag),
-            'ac' : 'disable-tags',
-            }
-        reply = self._make_call(url, post_data)
-        if reply != "OK":
-            raise GoogleOperationFailed
-        return
-
-    ############################################################
-    # Helper functions
-
-    def _get_session_id(self, login, password):
-        """
-        Logging in (and obtaining the session id)
-        """
-        header = {'User-agent' : SOURCE}
-        post_params = {
-            'Email': login,
-            'Passwd': password,
-            'service': 'reader',
-            'source': SOURCE,
-            'continue': GOOGLE_URL, 
-            }
-        post_data = urllib.urlencode(post_params) 
-        request = urllib2.Request(LOGIN_URL, post_data, header)
-
-        if log.isEnabledFor("info"):
-            pdcopy = post_params.copy()
-            pdcopy['Passwd'] = '*******'
-            log.info("Calling %s with parameters:\n    %s" % (
-                        request.get_full_url(), str(pdcopy)))
-
-        try:
-            f = urllib2.urlopen( request )
-        except urllib2.HTTPError, e:
-            if e.code == 403:
-                raise GoogleLoginFailed
-            else:
-                raise
-        result = f.read()
-
-        log.debug("Result: %s" % result)
-
-        sid = re.search('SID=(\S*)', result).group(1)
-        if not sid:
-            raise GoogleLoginFailed
-        return sid
-
-    def _get_token(self):
-        """
-        Obtain the call protection token
-        """
-        # Token jest jakiś czas ważny...
-        t = time.time()
-        if t - self.cached_token_time > TOKEN_VALID_TIME:
-            self.cached_token = self._make_call(TOKEN_URL)
-            self.cached_token_time = t
-        return self.cached_token
-
-    def _get_atom(self, url, count = None, older_first = False, continue_from = None, format = 'obj'):
-        """
-        Actually get ATOM feed. url is base url (one of the state or label urls).
-        count is the articles count (default 20), ordering_back set to False means older
-        first, continue_from can be set to gr:continuation value from the feed to
-        grab more items
-
-        format can be 'xml' (raw xml text), 'etree' (lxml.etree) or 'obj'
-        (lxml.objectify - default)
-        """
-        args = {}
-        if count is not None:
-            args['n'] = "%d" % count
-        if older_first:
-            args['r'] = 'o'
-        if continue_from:
-            args['c'] = continue_from
-        if args:
-            url = url.encode('utf-8') + '?' + urllib.urlencode(args)
-        r = self._make_call(url)
-        if format == "obj":
-            return objectify.fromstring(r)
-        elif format == "etree":
-            return etree.XML(r)
-        else:
-            return r
-
-    def _change_feed(self, feed_url, operation, title = None, add_tag = None, remove_tag = None):
-        """
-        Subscribe or unsubscribe
-        """
-        url = SUBSCRIPTION_EDIT_URL + '?client=%s' % SOURCE
-        post_data = { 
-            'ac' : operation,
-            's' : "feed/" + feed_url,
-            'T' : self._get_token(),
-            }
-        if title:
-            post_data['t'] = title
-        if add_tag:
-            post_data['a'] = self.tag_id(add_tag)
-        if remove_tag:
-            post_data['r'] = self.tag_id(remove_tag)
-        reply = self._make_call(url, post_data)
-        if reply != "OK":
-            raise GoogleOperationFailed
-        return
-
-    def _change_tag(self, feed_url, title, add_tag = None, remove_tag = None):
-        """
-        Subscribe or unsubscribe
-        """
-        #url = TAG_EDIT_URL + '?client=%s' % SOURCE
-        url = SUBSCRIPTION_EDIT_URL + '?client=%s' % SOURCE
-        post_data = { 
-            'ac' : 'edit',
-            's' : "feed/" + feed_url,
-            't' : title,
-            'T' : self._get_token(),
-            }
-        if add_tag:
-            post_data['a'] = self.tag_id(add_tag)
-        if remove_tag:
-            post_data['r'] = self.tag_id(remove_tag)
-        reply = self._make_call(url, post_data)
-        if reply != "OK":
-            raise GoogleOperationFailed
-
-        # # It is likely refresh, don't work so ...
-#         url = TAG_EDIT_URL + '?client=%s' % SOURCE
-#         post_data = {
-#             'a' : 'user/%s/state/com.google/read' % self.get_my_id(),
-#             'async' : 'true',
-#             'i' : self.feed_item_id(feed_url),
-#             's' : "feed/" + feed_url,
-#             }
-#         reply = self._make_call(url, post_data)
-#         if reply != "OK":
-#             raise GoogleOperationFailed
-
-        return
-
-    def _get_list(self, url, format):
-        if format == 'obj':
-            return simplejson.loads(
-                self._make_call(url + '?output=json'))
-        else:
-            return self._make_call(url + '?output=' + format)
-        
-
-    def _make_call(self, url, post_data=None):
-        header = {'User-agent' : SOURCE}
-        header['Cookie']='Name=SID;SID=%s;Domain=.google.com;Path=/;Expires=160000000000' % self.session_id
-        if post_data is not None:
-            true_data = [ (key, value.encode('utf-8')) for key, value in post_data.iteritems() ]
-            true_data = urllib.urlencode(true_data)
-        else:
-            true_data = None
-        request = urllib2.Request(url.encode('utf-8'), true_data, header)
-
-        if log.isEnabledFor("info"):
-            if post_data:
-                log.info("Calling %s with parameters:\n    %s" % (
-                        request.get_full_url(), str(post_data)))
-            else:
-                log.info("Calling %s" % request.get_full_url())
-
-        f = urllib2.urlopen( request )
-        result = f.read()
-
-        log.debug("Result: %s" % result)
-
-        return result
-