add two missing lines and do not add authorization header when no un and pw set
[vuplus_dvbapp-plugin] / remotetimer / src / plugin.py
1 # -*- coding: utf-8 -*-
2 #===============================================================================
3 # Remote Timer Setup by Homey
4 #
5 # This is free software; you can redistribute it and/or modify it under
6 # the terms of the GNU General Public License as published by the Free
7 # Software Foundation; either version 2, or (at your option) any later
8 # version.
9 #
10 # Copyright (C) 2009 by nixkoenner@newnigma2.to
11 # http://newnigma2.to
12 #
13 # License: GPL
14 #
15 # $Id$
16 #
17 #===============================================================================
18
19 from Plugins.Plugin import PluginDescriptor
20 from Screens.Screen import Screen
21
22 from Components.ActionMap import NumberActionMap
23 from Components.Button import Button
24
25 from Components.ConfigList import ConfigList, ConfigListScreen
26 from Components.config import getConfigListEntry, config, \
27         ConfigSubsection, ConfigText, ConfigIP, ConfigYesNo, \
28         ConfigPassword, ConfigNumber, KEY_LEFT, KEY_RIGHT, KEY_0
29
30 from Screens.TimerEntry import TimerEntry
31 from Screens.MessageBox import MessageBox
32 from Screens.MovieSelection import getPreferredTagEditor
33 from RecordTimer import AFTEREVENT
34 from enigma import eEPGCache
35
36 from Tools.BoundFunction import boundFunction
37
38 import time
39 from twisted.web.client import getPage 
40 from xml.dom.minidom import parseString
41 from base64 import encodestring
42
43 import urllib
44 #------------------------------------------------------------------------------------------
45
46 config.plugins.remoteTimer = ConfigSubsection()
47 config.plugins.remoteTimer.httphost = ConfigText(default = "" , fixed_size = False)
48 config.plugins.remoteTimer.httpip = ConfigIP(default = [0, 0, 0, 0])
49 config.plugins.remoteTimer.httpport = ConfigNumber(default = "0")
50 config.plugins.remoteTimer.username = ConfigText(default = "root", fixed_size = False)
51 config.plugins.remoteTimer.password = ConfigPassword(default = "", fixed_size = False)
52
53 class RemoteTimerSetup(Screen, ConfigListScreen):
54         skin = """
55                 <screen position="80,160" size="560,330" title="Settings" >
56                         <widget name="config" position="5,40" size="480,335" scrollbarMode="showOnDemand" />
57                         <ePixmap name="red" position="120,280" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
58                         <ePixmap name="green" position="320,280" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
59                         <widget name="key_red" position="120,280" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
60                         <widget name="key_green" position="320,280" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
61                 </screen>"""
62         
63         def __init__(self, session):
64                 Screen.__init__(self, session)
65
66                 self["actions"] = NumberActionMap(["SetupActions", "ColorActions"],
67                 {
68                         "ok": self.keySave,
69                         "green": self.keySave,
70                         "red": self.Exit,
71                         "cancel": self.Exit,
72                         "left": self.keyLeft,
73                         "right": self.keyRight,
74                         "0": self.keyNumber,
75                         "1": self.keyNumber,
76                         "2": self.keyNumber,
77                         "3": self.keyNumber,
78                         "4": self.keyNumber,
79                         "5": self.keyNumber,
80                         "6": self.keyNumber,
81                         "7": self.keyNumber,
82                         "8": self.keyNumber,
83                         "9": self.keyNumber
84                 }, -1)
85
86                 self["key_red"] = Button(_("Cancel"))
87                 self["key_green"] = Button(_("OK"))
88
89                 ConfigListScreen.__init__(self, [
90                         getConfigListEntry(_("Remote Timer - Hostname"), config.plugins.remoteTimer.httphost),
91                         getConfigListEntry(_("Remote Timer - Network IP"), config.plugins.remoteTimer.httpip),
92                         getConfigListEntry(_("Remote Timer - WebIf Port"), config.plugins.remoteTimer.httpport),
93                         getConfigListEntry(_("Remote Timer - Username"), config.plugins.remoteTimer.username),
94                         getConfigListEntry(_("Remote Timer - Password"), config.plugins.remoteTimer.password),
95                 ], session)
96                 
97
98         def keyLeft(self):
99                 self["config"].handleKey(KEY_LEFT)
100
101         def keyRight(self):
102                 self["config"].handleKey(KEY_RIGHT)
103                 
104         def keyNumber(self, number):
105                 self["config"].handleKey(KEY_0 + number)
106
107         def keySave(self):
108                 #print "################################"
109                 #print config.plugins.remoteTimer.httphost.value
110                 #print "################################"
111                 config.plugins.remoteTimer.save()
112                 timerInit()
113                 self.close()
114                 
115         def Exit(self):
116                 self.close()
117
118 baseTimerEntrySetup = None
119 baseTimerEntryGo = None
120
121 def timerInit():
122         global baseTimerEntrySetup, baseTimerEntryGo
123         if baseTimerEntrySetup is None:
124                 baseTimerEntrySetup = TimerEntry.createSetup
125         if baseTimerEntryGo is None:
126                 baseTimerEntryGo = TimerEntry.keyGo
127         TimerEntry.createSetup = createNewnigma2Setup
128         TimerEntry.keyGo = newnigma2KeyGo
129
130 def createNewnigma2Setup(self, widget):
131         baseTimerEntrySetup(self, widget)
132         self.timerentry_remote = ConfigYesNo()
133         self.list.insert(0, getConfigListEntry(_("Remote Timer"), self.timerentry_remote))
134
135         # force re-reading the list
136         self[widget].list = self.list
137
138 def newnigma2SubserviceSelected(self, service):
139         if service is not None:
140                 # ouch, this hurts a little
141                 service_ref = timerentry_service_ref
142                 self.timerentry_service_ref = ServiceReference(service[1])
143                 eit = self.timer.eit
144                 self.timer.eit = None
145
146                 newnigma2KeyGo(self)
147
148                 self.timerentry_service_ref = service_ref
149                 self.timer.eit = eit
150
151 def newnigma2KeyGo(self):
152         if not self.timerentry_remote.value:
153                 baseTimerEntryGo(self)
154         else:
155                 service_ref = self.timerentry_service_ref
156                 if self.timer.eit is not None:
157                         event = eEPGCache.getInstance().lookupEventId(service_ref.ref, self.timer.eit)
158                         if event:
159                                 n = event.getNumOfLinkageServices()
160                                 if n > 1:
161                                         tlist = []
162                                         ref = self.session.nav.getCurrentlyPlayingServiceReference()
163                                         parent = service_ref.ref
164                                         selection = 0
165                                         for x in range(n):
166                                                 i = event.getLinkageService(parent, x)
167                                                 if i.toString() == ref.toString():
168                                                         selection = x
169                                                 tlist.append((i.getName(), i))
170                                         self.session.openWithCallback(boundFunction(newnigma2SubserviceSelected, self), ChoiceBox, title=_("Please select a subservice to record..."), list = tlist, selection = selection)
171                                         return
172                                 elif n > 0:
173                                         parent = service_ref.ref
174                                         service_ref = ServiceReference(event.getLinkageService(parent, 0))
175
176                 # XXX: this will - without any hassle - ignore the value of repeated
177                 begin, end = self.getBeginEnd()
178
179                 # when a timer end is set before the start, add 1 day
180                 if end < begin:
181                         end += 86400
182         
183                 rt_name = urllib.quote(self.timerentry_name.value.decode('utf8').encode('utf8','ignore'))
184                 rt_description = urllib.quote(self.timerentry_description.value.decode('utf8').encode('utf8','ignore'))
185                 rt_disabled = 0 # XXX: do we really want to hardcode this? why do we offer this option then?
186                 rt_repeated = 0 # XXX: same here
187         
188                 if self.timerentry_justplay.value == "zap":
189                         rt_justplay = 1
190                 else:
191                         rt_justplay = 0
192
193                 # XXX: this one is tricky since we do not know if the remote box offers afterEventAuto so lets just keep it simple for now
194                 rt_afterEvent = {
195                         "deepstandby": AFTEREVENT.DEEPSTANDBY,
196                         "standby": AFTEREVENT.STANDBY,
197                 }.get(self.timerentry_afterevent.value, AFTEREVENT.NONE)
198
199                 # Add Timer on RemoteBox via WebIf Command
200                 # http://192.168.178.20/web/timeradd?sRef=&begin=&end=&name=&description=&disabled=&justplay=&afterevent=&repeated=
201                 remoteip = "%d.%d.%d.%d" % tuple(config.plugins.remoteTimer.httpip.value)
202                 remoteurl = "http://%s:%s/web/timeradd?sRef=%s&begin=%s&end=%s&name=%s&description=%s&disabled=%s&justplay=%s&afterevent=%s&repeated=%s" % (
203                         remoteip,
204                         config.plugins.remoteTimer.httpport.value,
205                         service_ref,
206                         begin,
207                         end,
208                         rt_name,
209                         rt_description,
210                         rt_disabled,
211                         rt_justplay,
212                         rt_afterEvent,
213                         rt_repeated
214                 )
215                 print "######### debug remote", remoteurl
216
217                 username = config.plugins.remoteTimer.username.value
218                 password = config.plugins.remoteTimer.password.value
219                 if username and password:
220                         basicAuth = encodestring("%s:%s" % (username, password))
221                         authHeader = "Basic " + basicAuth.strip()
222                         headers = {"Authorization": authHeader}
223                 else:
224                         headers = {}
225
226                 defer = getPage(remoteurl, headers = headers)
227                 defer.addCallback(boundFunction(_gotPageLoad, self.session, self))
228                 defer.addErrback(boundFunction(errorLoad, self.session))
229
230 def _gotPageLoadCb(timerEntry, doClose, *args):
231         if doClose:
232                 timerEntry.keyCancel()
233
234 def _gotPageLoad(session, timerEntry, html):
235         remoteresponse = parseXml( html)
236         #print "_gotPageLoad remoteresponse:", remoteresponse
237         # XXX: should be improved...
238         doClose = remoteresponse == "Timer added successfully!"
239         session.openWithCallback(
240                 boundFunction(_gotPageLoadCb, timerEntry, doClose),
241                 MessageBox,
242                 _("Set Timer on Remote DreamBox via WebIf:\n%s") % (remoteresponse),
243                 MessageBox.TYPE_INFO
244         )
245
246 def errorLoad(session, error):
247         #print "errorLoad ERROR:", error
248         session.open(
249                 MessageBox,
250                 _("ERROR - Set Timer on Remote DreamBox via WebIf:\n%s") % (error),
251                 MessageBox.TYPE_INFO
252         )
253
254 def parseXml(string):
255         try:
256                 dom = parseString(string)
257                 for entry in dom.firstChild.childNodes:
258                         if entry.nodeName == 'e2statetext':
259                                 result = entry.firstChild.data.encode("utf-8")
260                 #print "parseXml debug result:", result
261                 return result
262         except:
263                 return "ERROR XML PARSE"
264
265 #------------------------------------------------------------------------------------------
266
267 def autostart(reason, **kwargs):
268         if "session" in kwargs:
269                 session = kwargs["session"]
270                 try:
271                         if config.plugins.remoteTimer.httpip.value:
272                                 timerInit()
273                 except:
274                         print "####### NO remoteTimer.httpip.value"
275
276 def main(session, **kwargs):
277         session.open(RemoteTimerSetup)
278
279 def Plugins(**kwargs):
280         return [
281                 PluginDescriptor(name="Remote Timer",description="Remote Timer Setup", where = [ PluginDescriptor.WHERE_PLUGINMENU ], fnc = main),
282                 PluginDescriptor(name="Remote Timer", where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=main),
283                 PluginDescriptor(where = PluginDescriptor.WHERE_SESSIONSTART, fnc = autostart)
284         ]
285