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