plugin.py split up,\nfeed overview and single feed view in different screens,\nyellow...
[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 SimpleRSSScreens import SimpleRSSFeed
6 from Feed import Feed
7
8 from httpclient import getPage
9 from urlparse import urlsplit
10 from xml.dom.minidom import parseString as minidom_parseString
11
12 class RSSPoller:
13         def __init__(self, session):
14                 self.poll_timer = eTimer()
15                 self.poll_timer.timeout.get().append(self.poll)
16                 self.poll_timer.start(0, 1)
17
18                 self.update_callbacks = [ ]
19                 self.session = session
20                 self.dialog = None
21                 self.reloading = False
22         
23                 self.feeds = [ ]
24                 for i in range(0, config.plugins.simpleRSS.feedcount.value):
25                         self.feeds.append(Feed(config.plugins.simpleRSS.feed[i].uri.value, config.plugins.simpleRSS.feed[i].autoupdate.value))
26                 self.new_items = [ ]
27                 self.current_feed = 0
28
29         def addCallback(self, callback):
30                 if callback not in self.update_callbacks:
31                         self.update_callbacks.append(callback)
32
33         def removeCallback(self, callback):
34                 if callback in self.update_callbacks:
35                         self.update_callbacks.remove(callback)
36
37         def doCallback(self, id = None):
38                 for callback in self.update_callbacks:
39                         try:
40                                 callback(id)
41                         except:
42                                 pass
43
44         # Wrap boundFunction over real function
45         def _gotSinglePage(self, id, callback, errorback, data):
46                 self._gotPage(data, id, callback, errorback)
47
48         def error(self, error = ""):
49                 if not self.session:
50                         print "[SimpleRSS] error polling"
51                 else:
52                         self.session.open(MessageBox, "Sorry, failed to fetch feed.\n" + error, type = MessageBox.TYPE_INFO, timeout = 5)
53                         # Assume its just a temporary failure and jump over to next feed                          
54                         self.current_feed += 1                     
55                         self.poll_timer.start(1000, 1)
56
57         def _gotPage(self, data, id = None, callback = False, errorback = None):
58                 # workaround: exceptions in gotPage-callback were ignored
59                 try:
60                         self.gotPage(data, id)
61                         if callback:
62                                 self.doCallback(id)
63                 except NotImplementedError, errmsg:
64                         # TODO: Annoying with Multifeed?
65                         self.session.open(MessageBox, "Sorry, this type of feed is unsupported.\n"+ str(errmsg), type = MessageBox.TYPE_INFO, timeout = 5)
66                 except:
67                         import traceback, sys
68                         traceback.print_exc(file=sys.stdout)
69                         # Errorback given, call it (asumme we don't need do restart timer!)
70                         if errorback is not None:
71                                 errorback()
72                                 return
73                         # Assume its just a temporary failure and jump over to next feed                          
74                         self.current_feed += 1                     
75                         self.poll_timer.start(1000, 1)
76         
77         def gotPage(self, data, id = None):
78                 print "[SimpleRSS] parsing.."
79
80                 # sometimes activates spinner :-/
81                 dom = minidom_parseString(data)
82
83                 print "[SimpleRSS] xml parsed.."
84
85                 # For Single-Polling
86                 if id is not None:
87                         self.feeds[id].gotDom(dom)
88                         print "[SimpleRSS] single feed parsed.."
89                         return
90                 else:
91                         new_items = self.feeds[self.current_feed].gotDom(dom)
92
93                 print "[SimpleRSS] feed parsed.."
94
95                 # Append new items to locally bound ones
96                 self.new_items.extend(new_items)
97
98                 # Start Timer so we can either fetch next feed or show new_items
99                 self.current_feed += 1
100                 self.poll_timer.start(1000, 1)
101
102         def singlePoll(self, id, callback = False, errorback = None):
103                 from Tools.BoundFunction import boundFunction
104                 remote = urlsplit(self.feeds[id].uri)
105                 print "[SimpleRSS] updating", remote.geturl()
106                 hostname = remote.hostname
107                 port = remote.port or 80
108                 path = '?'.join([remote.path, remote.query])
109                 print "[SimpleRSS] hostname:", hostname, ", port:", port, ", path:", path
110                 getPage(hostname, port, path, callback=boundFunction(self._gotSinglePage, id, callback, errorback), errorback=errorback)
111
112         def poll(self):
113                 # Reloading, reschedule
114                 if self.reloading:
115                         print "[SimpleRSS] timer triggered while reloading, rescheduling"
116                         self.poll_timer.start(10000, 1)
117                 # Dialog shown, hide
118                 elif self.dialog:
119                         print "[SimpleRSS] hiding"
120                         self.dialog.hide()
121                         self.dialog = None
122                         self.new_items = [ ]
123                         self.current_feed = 0
124                         self.poll_timer.startLongTimer(config.plugins.simpleRSS.interval.value*60)
125                 # End of List
126                 elif len(self.feeds) <= self.current_feed:
127                         # New Items
128                         if len(self.new_items):
129                                 print "[SimpleRSS] got", len(self.new_items), "new items"
130                                 print "[SimpleRSS] calling back"
131                                 self.doCallback()
132                                 # Inform User
133                                 if config.plugins.simpleRSS.show_new.value:
134                                         self.dialog = self.session.instantiateDialog(SimpleRSSFeed, self.new_items, newItems=True)
135                                         self.dialog.show()
136                                         self.poll_timer.startLongTimer(5)
137                         # No new Items
138                         else:
139                                 print "[SimpleRSS] no new items"
140                                 self.new_items = [ ]
141                                 self.current_feed = 0
142                                 self.poll_timer.startLongTimer(config.plugins.simpleRSS.interval.value*60)
143                 # Feed is supposed to auto-update
144                 elif self.feeds[self.current_feed].autoupdate:
145                         remote = urlsplit(self.feeds[self.current_feed].uri)
146                         hostname = remote.hostname
147                         port = remote.port or 80
148                         path = '?'.join([remote.path, remote.query])
149                         print "[SimpleRSS] hostname:", hostname, ", port:", port, ", path:", path
150                         self.d = getPage(hostname, port, path, callback=self._gotPage, errorback=self.error)
151                 # Go to next feed in 100ms
152                 else:
153                         print "[SimpleRSS] passing feed"
154                         self.current_feed += 1
155                         self.poll_timer.start(100, 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                 # TODO: Fix this evil way of updating feeds
165                 newfeeds = []
166                 for i in range(0, config.plugins.simpleRSS.feedcount.value):
167                         newfeeds.append(Feed(config.plugins.simpleRSS.feed[i].uri.value, config.plugins.simpleRSS.feed[i].autoupdate.value))
168
169                 self.feeds = newfeeds
170
171                 self.reloading = False