cleanup
[enigma2-plugins.git] / simplerss / src / RSSPoller.py
1 # for localized messages
2 from . import _
3
4 from Components.config import config
5 from enigma import eTimer
6
7 from Tools.Notifications import AddPopup
8 from Screens.MessageBox import MessageBox
9
10 from RSSFeed import BaseFeed, UniversalFeed
11
12 from twisted.web.client import getPage
13 from xml.etree.cElementTree import fromstring as cElementTree_fromstring
14
15 from GoogleReader import GoogleReader
16
17 NOTIFICATIONID = 'SimpleRSSUpdateNotification'
18
19 update_callbacks = []
20
21 class RSSPoller:
22         """Keeps all Feed and takes care of (automatic) updates"""
23
24         def __init__(self, poll = True):
25                 # Timer
26                 self.poll_timer = eTimer()
27                 self.poll_timer.callback.append(self.poll)
28                 self.do_poll = poll
29
30                 # this indicates we're reloading the list of feeds
31                 self.reloading = False
32
33                 self.newItemFeed = BaseFeed(
34                         "",
35                         _("New Items"),
36                         _("New Items since last Auto-Update"),
37                 )
38
39                 # Generate Feeds
40                 self.feeds = [
41                         UniversalFeed(
42                                 x.uri.value,
43                                 x.autoupdate.value
44                         )
45                                 for x in config.plugins.simpleRSS.feed
46                 ]
47
48                 if not config.plugins.simpleRSS.enable_google_reader.value:
49                         if poll:
50                                 self.poll_timer.start(0, 1)
51                 else:
52                         self.googleReader = GoogleReader(config.plugins.simpleRSS.google_username.value, config.plugins.simpleRSS.google_password.value)
53                         self.googleReader.login().addCallback(self.googleLoggedIn).addErrback(self.googleLoginFailed)
54
55                 # Initialize Vars
56                 self.current_feed = 0
57
58         def googleLoggedIn(self, sid = None):
59                 self.googleReader.getSubscriptionList().addCallback(self.googleSubscriptionList).addErrback(self.googleSubscriptionFailed)
60
61         def googleLoginFailed(self, res = None):
62                 AddPopup(
63                         _("Failed to login to Google Reader."),
64                         MessageBox.TYPE_ERROR,
65                         5,
66                 )
67
68                 self.reloading = False
69                 if self.do_poll:
70                         self.poll_timer.start(0, 1)
71
72         def googleSubscriptionList(self, subscriptions = None):
73                 self.feeds.extend(subscriptions)
74
75                 self.reloading = False
76                 if self.do_poll:
77                         self.poll_timer.start(0, 1)
78
79         def googleSubscriptionFailed(self, res = None):
80                 AddPopup(
81                         _("Failed to get subscriptions from Google Reader."),
82                         MessageBox.TYPE_ERROR,
83                         5,
84                 )
85
86                 self.reloading = False
87                 if self.do_poll:
88                         self.poll_timer.start(0, 1)
89
90         def addCallback(self, callback):
91                 if callback not in update_callbacks:
92                         update_callbacks.append(callback)
93
94         def removeCallback(self, callback):
95                 if callback in update_callbacks:
96                         update_callbacks.remove(callback)
97
98         def doCallback(self, id = None):
99                 for callback in update_callbacks:
100                         try:
101                                 callback(id)
102                         except Exception:
103                                 pass
104
105         def error(self, error = ""):
106                 print "[SimpleRSS] failed to fetch feed:", error
107
108                 # Assume its just a temporary failure and jump over to next feed
109                 self.next_feed()
110
111         def _gotPage(self, data, id = None, callback = False, errorback = None):
112                 # workaround: exceptions in gotPage-callback were ignored
113                 try:
114                         self.gotPage(data, id)
115                         if callback:
116                                 self.doCallback(id)
117                 except NotImplementedError, errmsg:
118                         # Don't show this error when updating in background
119                         if id is not None:
120                                 AddPopup(
121                                         _("Sorry, this type of feed is unsupported:\n%s") % (str(errmsg)),
122                                         MessageBox.TYPE_INFO,
123                                         5,
124                                 )
125                         else:
126                                 # We don't want to stop updating just because one feed is broken
127                                 self.next_feed()
128                 except Exception:
129                         import traceback, sys
130                         traceback.print_exc(file=sys.stdout)
131                         # Errorback given, call it (asumme we don't need do restart timer!)
132                         if errorback is not None:
133                                 errorback()
134                                 return
135                         # Assume its just a temporary failure and jump over to next feed
136                         self.next_feed()
137
138         def gotPage(self, data, id = None):
139                 feed = cElementTree_fromstring(data)
140
141                 # For Single-Polling
142                 if id is not None:
143                         self.feeds[id].gotFeed(feed)
144                         print "[SimpleRSS] single feed parsed..."
145                         return
146
147                 new_items = self.feeds[self.current_feed].gotFeed(feed)
148
149                 print "[SimpleRSS] feed parsed..."
150
151                 # Append new items to locally bound ones
152                 if new_items is not None:
153                         self.newItemFeed.history.extend(new_items)
154
155                 # Start Timer so we can either fetch next feed or show new_items
156                 self.next_feed()
157
158         def singlePoll(self, id, callback = False, errorback = None):
159                 getPage(self.feeds[id].uri).addCallback(self._gotPage, id, callback, errorback).addErrback(errorback)
160
161         def poll(self):
162                 # Reloading, reschedule
163                 if self.reloading:
164                         print "[SimpleRSS] timer triggered while reloading, rescheduling"
165                         self.poll_timer.start(10000, 1)
166                 # End of List
167                 elif len(self.feeds) <= self.current_feed:
168                         # New Items
169                         if self.newItemFeed.history:
170                                 print "[SimpleRSS] got new items, calling back"
171                                 self.doCallback()
172
173                                 # Inform User
174                                 update_notification_value = config.plugins.simpleRSS.update_notification.value
175                                 if update_notification_value == "preview":
176                                         from RSSScreens import RSSFeedView
177
178                                         from Tools.Notifications import AddNotificationWithID, RemovePopup
179
180                                         RemovePopup(NOTIFICATIONID)
181
182                                         AddNotificationWithID(
183                                                 NOTIFICATIONID,
184                                                 RSSFeedView,
185                                                 self.newItemFeed,
186                                                 newItems = True
187                                         )
188                                 elif update_notification_value == "notification":
189                                         AddPopup(
190                                                 _("Received %d new news item(s).") % (len(self.newItemFeed.history)),
191                                                 MessageBox.TYPE_INFO,
192                                                 5,
193                                                 NOTIFICATIONID
194                                         )
195                         # No new Items
196                         else:
197                                 print "[SimpleRSS] no new items"
198
199                         self.current_feed = 0
200                         self.poll_timer.startLongTimer(config.plugins.simpleRSS.interval.value*60)
201                 # It's updating-time
202                 else:
203                         # Assume we're cleaning history if current feed is 0
204                         clearHistory = self.current_feed == 0
205                         if config.plugins.simpleRSS.update_notification.value != "none":
206                                 from Tools.Notifications import current_notifications, notifications
207                                 for x in current_notifications:
208                                         if x[0] == NOTIFICATIONID:
209                                                 print "[SimpleRSS] timer triggered while preview on screen, rescheduling"
210                                                 self.poll_timer.start(10000, 1)
211                                                 return
212
213                                 if clearHistory:
214                                         for x in notifications:
215                                                 if x[4] and x[4] == NOTIFICATIONID:
216                                                         print "[SimpleRSS] wont wipe history because it was never read"
217                                                         clearHistory = False
218                                                         break
219
220                         if clearHistory:
221                                 del self.newItemFeed.history[:]
222
223                         # Feed supposed to autoupdate
224                         feed = self.feeds[self.current_feed]
225
226                         if feed.autoupdate:
227                                 getPage(feed.uri).addCallback(self._gotPage).addErrback(self.error)
228                         # Go to next feed
229                         else:
230                                 print "[SimpleRSS] passing feed"
231                                 self.next_feed()
232
233         def next_feed(self):
234                 self.current_feed += 1
235                 self.poll_timer.start(1000, 1)
236
237         def shutdown(self):
238                 self.poll_timer.callback.remove(self.poll)
239                 self.poll_timer = None
240
241         def triggerReload(self):
242                 self.reloading = True
243
244                 newfeeds = []
245                 oldfeeds = self.feeds
246                 found = False
247                 for x in config.plugins.simpleRSS.feed:
248                         for feed in oldfeeds:
249                                 if x.uri.value == feed.uri:
250                                         # Update possibly different autoupdate value
251                                         feed.autoupdate = x.autoupdate.value
252                                         newfeeds.append(feed) # Append to new Feeds
253                                         oldfeeds.remove(feed) # Remove from old Feeds
254                                         found = True
255                                         break
256                         if not found:
257                                 newfeeds.append(
258                                         UniversalFeed(
259                                                 x.uri.value,
260                                                 x.autoupdate.value
261                                 ))
262                         found = False
263
264                 self.feeds = newfeeds
265
266                 if config.plugins.simpleRSS.enable_google_reader.value:
267                         self.googleReader = GoogleReader(config.plugins.simpleRSS.google_username.value, config.plugins.simpleRSS.google_password.value)
268                         self.googleReader.login().addCallback(self.googleLoggedIn).addErrback(self.googleLoginFailed)
269                 else:
270                         self.reloading = False
271