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