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