Check if new_items is not None before extending
[vuplus_dvbapp-plugin] / simplerss / src / RSSPoller.py
1 from Screens.MessageBox import MessageBox
2 from Components.config import config
3 from enigma import eTimer
4
5 from RSSScreens import RSSFeedView
6 from RSSFeed import UniversalFeed
7
8 from twisted.web.client import getPage
9 from xml.dom.minidom import parseString as minidom_parseString
10
11 class RSSPoller:
12         """Keeps all Feed and takes care of (automatic) updates"""
13         def __init__(self, session):
14                 # Timer
15                 self.poll_timer = eTimer()
16                 self.poll_timer.timeout.get().append(self.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                 # Generate Feeds
27                 self.feeds = [
28                         UniversalFeed(
29                                 config.plugins.simpleRSS.feed[i].uri.value,
30                                 config.plugins.simpleRSS.feed[i].autoupdate.value
31                         )
32                                 for i in range(0, config.plugins.simpleRSS.feedcount.value)
33                 ]
34
35                 # Initialize Vars
36                 self.new_items = [ ]
37                 self.current_feed = 0
38
39         def addCallback(self, callback):
40                 if callback not in self.update_callbacks:
41                         self.update_callbacks.append(callback)
42
43         def removeCallback(self, callback):
44                 if callback in self.update_callbacks:
45                         self.update_callbacks.remove(callback)
46
47         def doCallback(self, id = None):
48                 for callback in self.update_callbacks:
49                         try:
50                                 callback(id)
51                         except:
52                                 pass
53
54         def error(self, error = ""):
55                 if not self.session:
56                         print "[SimpleRSS] error polling"
57                 else:
58                         self.session.open(
59                                 MessageBox,
60                                 "Sorry, failed to fetch feed.\n" + error,
61                                 type = MessageBox.TYPE_INFO,
62                                 timeout = 5
63                         )
64                         # Assume its just a temporary failure and jump over to next feed                          
65                         self.next_feed()
66
67         def _gotPage(self, data, id = None, callback = False, errorback = None):
68                 # workaround: exceptions in gotPage-callback were ignored
69                 try:
70                         self.gotPage(data, id)
71                         if callback:
72                                 self.doCallback(id)
73                 except NotImplementedError, errmsg:
74                         # TODO: Annoying with Multifeed?
75                         self.session.open(
76                                 MessageBox,
77                                 "Sorry, this type of feed is unsupported.\n"+ str(errmsg),
78                                 type = MessageBox.TYPE_INFO,
79                                 timeout = 5
80                         )
81                 except:
82                         import traceback, sys
83                         traceback.print_exc(file=sys.stdout)
84                         # Errorback given, call it (asumme we don't need do restart timer!)
85                         if errorback is not None:
86                                 errorback()
87                                 return
88                         # Assume its just a temporary failure and jump over to next feed                          
89                         self.next_feed()
90         
91         def gotPage(self, data, id = None):
92                 print "[SimpleRSS] parsing.."
93
94                 # sometimes activates spinner :-/
95                 dom = minidom_parseString(data)
96
97                 print "[SimpleRSS] xml parsed.."
98
99                 # For Single-Polling
100                 if id is not None:
101                         self.feeds[id].gotDom(dom)
102                         print "[SimpleRSS] single feed parsed.."
103                         return
104
105                 new_items = self.feeds[self.current_feed].gotDom(dom)
106
107                 print "[SimpleRSS] feed parsed.."
108
109                 # Append new items to locally bound ones
110                 if new_items is not None:
111                         self.new_items.extend(new_items)
112
113                 # Start Timer so we can either fetch next feed or show new_items
114                 self.next_feed()
115
116         def singlePoll(self, id, callback = False, errorback = None):
117                 getPage(self.feeds[id].uri).addCallback(self._gotPage, id, callback, errorback).addErrback(errorback)
118
119         def poll(self):
120                 # Reloading, reschedule
121                 if self.reloading:
122                         print "[SimpleRSS] timer triggered while reloading, rescheduling"
123                         self.poll_timer.start(10000, 1)
124                 # End of List
125                 elif len(self.feeds) <= self.current_feed:
126                         # New Items
127                         if len(self.new_items):
128                                 print "[SimpleRSS] got", len(self.new_items), "new items"
129                                 print "[SimpleRSS] calling back"
130                                 self.doCallback()
131                                 # Inform User
132                                 if config.plugins.simpleRSS.show_new.value:
133                                         self.session.open(RSSFeedView, self.new_items, newItems=True)
134                         # No new Items
135                         else:
136                                 print "[SimpleRSS] no new items"
137                         self.current_feed = 0
138                         self.poll_timer.startLongTimer(config.plugins.simpleRSS.interval.value*60)
139                 # It's updating-time
140                 else:
141                         # Id is 0 -> empty out new items
142                         if self.current_feed == 0:
143                                 self.new_items = [ ]
144                         # Feed supposed to autoupdate
145                         feed = self.feeds[self.current_feed]
146                         if feed.autoupdate:
147                                 getPage(feed.uri).addCallback(self._gotPage).addErrback(self.error)
148                         # Go to next feed
149                         else:
150                                 print "[SimpleRSS] passing feed"
151                                 self.next_feed()
152
153         def next_feed(self):
154                 self.current_feed += 1
155                 self.poll_timer.start(1000, 1)
156
157         def shutdown(self):
158                 self.poll_timer.timeout.get().remove(self.poll)
159                 self.poll_timer = None
160
161         def triggerReload(self):
162                 self.reloading = True
163
164                 newfeeds = []
165                 found = False
166                 for i in range(0, config.plugins.simpleRSS.feedcount.value):
167                         for feed in self.feeds:
168                                 if config.plugins.simpleRSS.feed[i].uri.value == feed.uri:
169                                         # Update possibly different autoupdate value
170                                         feed.autoupdate = config.plugins.simpleRSS.feed[i].autoupdate.value
171                                         newfeeds.append(feed) # Append to new Feeds
172                                         self.feeds.remove(feed) # Remove from old Feeds
173                                         found = True
174                                         break
175                         if not found:
176                                 newfeeds.append(
177                                         UniversalFeed(
178                                                 config.plugins.simpleRSS.feed[i].uri.value,
179                                                 config.plugins.simpleRSS.feed[i].autoupdate.value
180                                 ))
181                         found = False
182
183                 self.feeds = newfeeds
184
185                 self.reloading = False