allow to fetch feeds from google reader
authorMoritz Venn <ritzmo@users.schwerkraft.elitedvb.net>
Tue, 8 Sep 2009 12:24:40 +0000 (12:24 +0000)
committerMoritz Venn <ritzmo@users.schwerkraft.elitedvb.net>
Tue, 8 Sep 2009 12:24:40 +0000 (12:24 +0000)
this is more of a proof of concept since you cannot really sync the feeds or edit them but having them is good enough for now :-)

simplerss/src/GoogleReader.py [new file with mode: 0644]
simplerss/src/RSSFeed.py
simplerss/src/RSSPoller.py
simplerss/src/RSSSetup.py
simplerss/src/plugin.py

diff --git a/simplerss/src/GoogleReader.py b/simplerss/src/GoogleReader.py
new file mode 100644 (file)
index 0000000..a4ee660
--- /dev/null
@@ -0,0 +1,106 @@
+import urllib
+from twisted.web.client import getPage
+from RSSFeed import UniversalFeed
+from twisted.internet.defer import Deferred
+from xml.etree.cElementTree import fromstring as cet_fromstring
+
+class GoogleReader:
+       def __init__(self, username = None, password = None):
+               self.username = username
+               self.password = password
+               self.token = None
+               self.sid = None
+
+       def sendRequest(self, url):
+               print "[GoogleReader] sendRequest:", url
+               cookies = {
+                       'Name': 'SID',
+                       'SID': self.sid,
+                       'Domain': '.google.com',
+                       'Path': '/',
+                       'Expires': '160000000000'
+               }
+
+               return getPage(url, cookies = cookies)
+
+       def login(self):
+               print "[GoogleReader] login"
+               if not self.username or not self.password:
+                       return
+
+               headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'}
+               data = {
+                       'service': 'reader',
+                       'Email': self.username,
+                       'Passwd': self.password,
+                       'source': 'enigma2-plugin-extensions-simplerss',
+                       'continue': 'http://www.google.com/',
+               }
+
+               defer = Deferred()
+               getPage('https://www.google.com/accounts/ClientLogin', method = 'POST', headers = headers, postdata = urllib.urlencode(data)).addCallback(self.loginFinished, defer).addErrback(self.loginFailed, defer)
+               return defer
+
+       def loginFinished(self, res = None, defer = None):
+               print "[GoogleReader] loginFinished:", res
+               pos_beg = res.find('SID=')
+               pos_end = res.find('\n',pos_beg)
+               self.sid = res[pos_beg+4:pos_end]
+               if defer:
+                       defer.callback(self.sid)
+
+       def loginFailed(self, res = None, defer = None):
+               print "[GoogleReader] loginFailed:", res
+               if defer:
+                       # XXX: we might want to give some information here besides "we failed"
+                       defer.errback()
+
+       def getToken(self):
+               print "[GoogleReader] getToken"
+               if not self.sid:
+                       return
+
+               defer = Deferred()
+               self.sendRequest('http://www.google.com/reader/api/0/token').addCallback(self.gotToken, defer).addErrback(seld.errToken, defer)
+               return defer
+
+       def gotToken(self, res = None, defer = None):
+               print "[GoogleReader] gotToken", res
+               self.token = res
+               if defer:
+                       defer.callback(res)
+
+       def errToken(self, res = None, defer = None):
+               print "[GoogleReader] errToken", res
+               self.token = None
+               if defer:
+                       # XXX: we might want to give some information here besides "we failed"
+                       defer.errback()
+
+       def getSubscriptionList(self):
+               print "[GoogleReader] getSubscriptionList"
+               if not self.sid:
+                       return
+
+               defer = Deferred()
+               self.sendRequest('http://www.google.com/reader/api/0/subscription/list').addCallback(self.gotSubscriptionList, defer).addErrback(self.errSubscriptionList, defer)
+               return defer
+
+       def gotSubscriptionList(self, res = None, defer = None):
+               print "[GoogleReader] gotSubscriptionList", res
+               l = []
+               if res:
+                       dom = cet_fromstring(res)
+                       for item in dom.getiterator():
+                               if item.tag == 'string':
+                                       if item.get('name') == 'id':
+                                               l.append(UniversalFeed(item.text[5:], True, True))
+               if defer:
+                       defer.callback(l)
+
+       def errSubscriptionList(self, res = None, defer = None):
+               print "[GoogleReader] errSubscriptionList", res
+               if defer:
+                       # XXX: we might want to give some information here besides "we failed"
+                       defer.errback()
+
index 4ccd55d..77587c0 100644 (file)
@@ -132,11 +132,14 @@ class BaseFeed:
 
 class UniversalFeed(BaseFeed):
        """Feed which can handle rdf, rss and atom feeds utilizing abstraction wrappers."""
-       def __init__(self, uri, autoupdate):
+       def __init__(self, uri, autoupdate, sync = False):
                BaseFeed.__init__(self, uri)
 
                # Set Autoupdate
                self.autoupdate = autoupdate
+               
+               # Is this a synced feed?
+               self.sync = sync
 
                # Initialize
                self.last_update = None
index e50f142..d51d2f9 100644 (file)
@@ -4,11 +4,16 @@ from . import _
 from Components.config import config
 from enigma import eTimer
 
+from Tools.Notifications import AddPopup
+from Screens.MessageBox import MessageBox
+
 from RSSFeed import BaseFeed, UniversalFeed
 
 from twisted.web.client import getPage
 from xml.etree.cElementTree import fromstring as cElementTree_fromstring
 
+from GoogleReader import GoogleReader
+
 NOTIFICATIONID = 'SimpleRSSUpdateNotification'
 
 update_callbacks = []
@@ -20,8 +25,7 @@ class RSSPoller:
                # Timer
                self.poll_timer = eTimer()
                self.poll_timer.callback.append(self.poll)
-               if poll:
-                       self.poll_timer.start(0, 1)
+               self.do_poll = poll
 
                # Save Session, Initialize Var to identify triggered Reload
                self.session = session
@@ -42,9 +46,48 @@ class RSSPoller:
                                for x in config.plugins.simpleRSS.feed
                ]
 
+               if not config.plugins.simpleRSS.enable_google_reader.value:
+                       if poll:
+                               self.poll_timer.start(0, 1)
+               else:
+                       self.googleReader = GoogleReader(config.plugins.simpleRSS.google_username.value, config.plugins.simpleRSS.google_password.value)
+                       self.googleReader.login().addCallback(self.googleLoggedIn).addErrback(self.googleLoginFailed)
+
                # Initialize Vars
                self.current_feed = 0
 
+       def googleLoggedIn(self, sid = None):
+               self.googleReader.getSubscriptionList().addCallback(self.googleSubscriptionList).addErrback(self.googleSubscriptionFailed)
+
+       def googleLoginFailed(self, res = None):
+               AddPopup(
+                       _("Failed to login to GoogleReader."),
+                       MessageBox.TYPE_ERROR,
+                       5,
+               )
+
+               self.reloading = False
+               if self.do_poll:
+                       self.poll_timer.start(0, 1)
+
+       def googleSubscriptionList(self, subscriptions = None):
+               self.feeds.extend(subscriptions)
+
+               self.reloading = False
+               if self.do_poll:
+                       self.poll_timer.start(0, 1)
+
+       def googleSubscriptionFailed(self, res = None):
+               AddPopup(
+                       _("Failed to get subscriptions from GoogleReader."),
+                       MessageBox.TYPE_ERROR,
+                       5,
+               )
+
+               self.reloading = False
+               if self.do_poll:
+                       self.poll_timer.start(0, 1)
+
        def addCallback(self, callback):
                if callback not in update_callbacks:
                        update_callbacks.append(callback)
@@ -144,9 +187,6 @@ class RSSPoller:
                                                newItems = True
                                        )
                                elif update_notification_value == "notification":
-                                       from Tools.Notifications import AddPopup
-                                       from Screens.MessageBox import MessageBox
-
                                        AddPopup(
                                                _("Received %d new news item(s).") % (len(self.newItemFeed.history)),
                                                MessageBox.TYPE_INFO,
@@ -224,5 +264,9 @@ class RSSPoller:
 
                self.feeds = newfeeds
 
-               self.reloading = False
+               if config.plugins.simpleRSS.enable_google_reader.value:
+                       self.googleReader = GoogleReader(config.plugins.simpleRSS.google_username.value, config.plugins.simpleRSS.google_password.value)
+                       self.googleReader.login().addCallback(self.googleLoggedIn).addErrback(self.googleLoginFailed)
+               else:
+                       self.reloading = False
 
index b07dcb3..df32603 100644 (file)
@@ -68,34 +68,14 @@ class RSSSetup(ConfigListScreen, Screen):
 
        def __init__(self, session, rssPoller = None):
                Screen.__init__(self, session)
-
                self.rssPoller = rssPoller
-               simpleRSS = config.plugins.simpleRSS
-
-               # Create List of all Feeds
-               list = [
-                       getConfigListEntry(_("Feed"), x.uri)
-                               for x in simpleRSS.feed
-               ]
-
-               # Attach notifier to autostart and append ConfigListEntry to List
-               simpleRSS.autostart.addNotifier(self.autostartChanged, initial_call = False)
-               list.append(getConfigListEntry(_("Start automatically with Enigma2"), simpleRSS.autostart))
-
-               # Save keep_running in instance as we want to dynamically add/remove it
-               self.keep_running = getConfigListEntry(_("Keep running in background"), simpleRSS.keep_running)
-               if not simpleRSS.autostart.value:
-                       list.append(self.keep_running)
 
-               # Append Last two config Elements
-               list.extend((
-                       getConfigListEntry(_("Show new Messages as"), simpleRSS.update_notification),
-                       getConfigListEntry(_("Update Interval (min)"), simpleRSS.interval)
-               ))
+               self.createSetup()
+               config.plugins.simpleRSS.autostart.addNotifier(self.elementChanged, initial_call = False)
+               config.plugins.simpleRSS.enable_google_reader.addNotifier(self.elementChanged, initial_call = False)
 
                # Initialize ConfigListScreen
-               self.list = list
-               ConfigListScreen.__init__(self, list, session)
+               ConfigListScreen.__init__(self, self.list, session)
 
                self["key_red"] = Button(_("Cancel"))
                self["key_green"] = Button(_("OK"))
@@ -117,15 +97,39 @@ class RSSSetup(ConfigListScreen, Screen):
        def setCustomTitle(self):
                self.setTitle(_("Simple RSS Reader Setup"))
 
-       def autostartChanged(self, instance):
-               # Remove keep_running from list if autostart is active
-               if instance.value:
-                       self.list.remove(self.keep_running)
-               # Otherwise add it at third position from behind
-               else:
-                       self.list.insert(-2, self.keep_running)
+       def createSetup(self):
+               simpleRSS = config.plugins.simpleRSS
+
+               # Create List of all Feeds
+               list = [
+                       getConfigListEntry(_("Feed"), x.uri)
+                               for x in simpleRSS.feed
+               ]
+
+               list.append(getConfigListEntry(_("Start automatically with Enigma2"), simpleRSS.autostart))
+
+               # Save keep_running in instance as we want to dynamically add/remove it
+               self.keep_running = getConfigListEntry(_("Keep running in background"), simpleRSS.keep_running)
+               if not simpleRSS.autostart.value:
+                       list.append(self.keep_running)
+
+               # Append Last two config Elements
+               list.extend((
+                       getConfigListEntry(_("Show new Messages as"), simpleRSS.update_notification),
+                       getConfigListEntry(_("Update Interval (min)"), simpleRSS.interval),
+                       getConfigListEntry(_("Fetch feed from Google Reader?"), simpleRSS.enable_google_reader),
+               ))
+
+               if simpleRSS.enable_google_reader.value:
+                       list.extend((
+                               getConfigListEntry(_("Google Username"), simpleRSS.google_username),
+                               getConfigListEntry(_("Google Password"), simpleRSS.google_password),
+                       ))
+
+               self.list = list
 
-               # Assign new List to ConfigList
+       def elementChanged(self, instance):
+               self.createSetup()
                self["config"].setList(self.list)
 
        def delete(self):
@@ -142,10 +146,9 @@ class RSSSetup(ConfigListScreen, Screen):
                        id = self["config"].getCurrentIndex()
                        del config.plugins.simpleRSS.feed[id]
                        config.plugins.simpleRSS.feedcount.value -= 1
-                       self.list.pop(id)
 
-                       # redraw list
-                       self["config"].l.invalidate()
+                       self.createSetup()
+                       self["config"].setList(self.list)
 
        def ok(self):
                id = self["config"].getCurrentIndex()
@@ -174,8 +177,9 @@ class RSSSetup(ConfigListScreen, Screen):
                if uri.value == "http://":
                        del config.plugins.simpleRSS.feed[id]
                else:
-                       self.list.insert(id, getConfigListEntry(_("Feed"), uri))
                        config.plugins.simpleRSS.feedcount.value = id+1
+                       self.createSetup()
+                       self["config"].setList(self.list)
 
        def keySave(self):
                # Tell Poller to recreate List if present
@@ -188,7 +192,8 @@ class RSSSetup(ConfigListScreen, Screen):
                simpleRSS = config.plugins.simpleRSS
 
                # Remove Notifier
-               simpleRSS.autostart.notifiers.remove(self.autostartChanged)
+               simpleRSS.autostart.notifiers.remove(self.elementChanged)
+               simpleRSS.enable_google_reader.notifiers.remove(self.elementChanged)
 
                # Keep feedcount sane
                simpleRSS.feedcount.value = len(simpleRSS.feed)
index ff35553..d6fb9de 100644 (file)
@@ -2,7 +2,8 @@
 from . import _
 
 from Components.config import config, ConfigSubsection, ConfigSubList, \
-       ConfigEnableDisable, ConfigNumber, ConfigText, ConfigSelection
+       ConfigEnableDisable, ConfigNumber, ConfigText, ConfigSelection, \
+       ConfigYesNo, ConfigPassword
 
 # Initialize Configuration
 config.plugins.simpleRSS = ConfigSubsection()
@@ -22,10 +23,13 @@ simpleRSS.keep_running = ConfigEnableDisable(default=True)
 simpleRSS.feed = ConfigSubList()
 for i in range(0, simpleRSS.feedcount.value):
        s = ConfigSubsection()
-       s.uri = ConfigText(default="http://", fixed_size = False)
+       s.uri = ConfigText(default="http://", fixed_size=False)
        s.autoupdate = ConfigEnableDisable(default=True)
        simpleRSS.feed.append(s)
        del s
+simpleRSS.enable_google_reader = ConfigYesNo(default=False)
+simpleRSS.google_username = ConfigText(default="", fixed_size=False)
+simpleRSS.google_password = ConfigPassword(default="")
 
 del simpleRSS