AutoTimer: Use named strings for translation
[enigma2-plugins.git] / autotimer / src / AutoTimerResource.py
1 # -*- coding: UTF-8 -*-
2 from AutoTimer import AutoTimer
3 from AutoTimerConfiguration import CURRENT_CONFIG_VERSION
4 from RecordTimer import AFTEREVENT
5 from twisted.internet import reactor
6 from twisted.web import http, resource, server
7 import threading
8 try:
9         from urllib import unquote
10 except ImportError as ie:
11         from urllib.parse import unquote
12 from ServiceReference import ServiceReference
13 from Tools.XMLTools import stringToXML
14 from enigma import eServiceReference
15 from . import _, config, iteritems, plugin
16 from plugin import autotimer, AUTOTIMER_VERSION
17
18 API_VERSION = "1.5"
19
20 class AutoTimerBaseResource(resource.Resource):
21         def returnResult(self, req, state, statetext):
22                 req.setResponseCode(http.OK)
23                 req.setHeader('Content-type', 'application/xhtml+xml')
24                 req.setHeader('charset', 'UTF-8')
25
26                 return """<?xml version=\"1.0\" encoding=\"UTF-8\" ?>
27 <e2simplexmlresult>
28         <e2state>%s</e2state>
29         <e2statetext>%s</e2statetext>
30 </e2simplexmlresult>""" % ('True' if state else 'False', statetext)
31
32 class AutoTimerBackgroundThread(threading.Thread):
33         def __init__(self, req, fnc):
34                 threading.Thread.__init__(self)
35                 self._req = req
36                 if hasattr(req, 'notifyFinish'):
37                         req.notifyFinish().addErrback(self.connectionLost)
38                 self._stillAlive = True
39                 self._fnc = fnc
40                 self.start()
41
42         def connectionLost(self, err):
43                 self._stillAlive = False
44
45         def run(self):
46                 req = self._req
47                 code = http.OK
48                 try: ret = self._fnc(req)
49                 except Exception as e:
50                         ret = str(e)
51                         code = http.INTERNAL_SERVER_ERROR
52                 def finishRequest():
53                         req.setResponseCode(code)
54                         if code == http.OK:
55                                 req.setHeader('Content-type', 'application/xhtml+xml')
56                         req.setHeader('charset', 'UTF-8')
57                         req.write(ret)
58                         req.finish()
59                 if self._stillAlive:
60                         reactor.callFromThread(finishRequest)
61
62 class AutoTimerBackgroundingResource(AutoTimerBaseResource, threading.Thread):
63         def render(self, req):
64                 AutoTimerBackgroundThread(req, self.renderBackground)
65                 return server.NOT_DONE_YET
66
67         def renderBackground(self, req):
68                 pass
69
70 class AutoTimerDoParseResource(AutoTimerBaseResource):
71         def render(self, req):
72                 self._req = req
73                 self._stillAlive = True
74                 if hasattr(req, 'notifyFinish'):
75                         req.notifyFinish().addErrback(self.connectionLost)
76
77                 d = autotimer.parseEPGAsync().addCallback(self.epgCallback).addErrback(self.epgErrback)
78                 def timeout():
79                         if not d.called and self._stillAlive:
80                                 reactor.callFromThread(lambda: req.write("<ignore />"))
81                                 reactor.callLater(50, timeout)
82                 reactor.callLater(50, timeout)
83
84                 req.setResponseCode(http.OK)
85                 req.setHeader('Content-type', 'application/xhtml+xml')
86                 req.setHeader('charset', 'UTF-8')
87                 req.write("""<?xml version=\"1.0\" encoding=\"UTF-8\" ?><e2simplexmlresult>""")
88                 return server.NOT_DONE_YET
89
90         def connectionLost(self, err):
91                 self._stillAlive = False
92
93         def epgCallback(self, ret):
94                 if self._stillAlive:
95                         ret = """<e2state>True</e2state>
96         <e2statetext>"""+ \
97         _("Found a total of %(matches)d matching Events.\n%(timer)d Timer were added and\n%(modified)d modified,\n%(conflicts)d conflicts encountered,\n%(similars)d similars added.") % \
98         {"matches":ret[0], "timer":ret[1], "modified":ret[2], "conflicts":len(ret[4]), "similars":len(ret[5])} + \
99         
100         "</e2statetext></e2simplexmlresult>"
101                         def finishRequest():
102                                 self._req.write(ret)
103                                 self._req.finish()
104                         reactor.callFromThread(finishRequest)
105
106         def epgErrback(self, failure):
107                 if self._stillAlive:
108                         ret = """<e2state>False</e2state>
109         <e2statetext>"""+ _("AutoTimer failed with error %s") % (str(failure),) + "</e2statetext></e2simplexmlresult>"
110                         def finishRequest():
111                                 self._req.write(ret)
112                                 self._req.finish()
113                         reactor.callFromThread(finishRequest)
114
115 class AutoTimerSimulateBackgroundThread(AutoTimerBackgroundThread):
116         def run(self):
117                 req = self._req
118                 if self._stillAlive:
119                         req.setResponseCode(http.OK)
120                         req.setHeader('Content-type', 'application/xhtml+xml')
121                         req.setHeader('charset', 'UTF-8')
122                         reactor.callFromThread(lambda: req.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<e2autotimersimulate api_version=\"" + str(API_VERSION) + "\">\n"))
123
124                 def finishRequest():
125                         req.write('</e2autotimersimulate>')
126                         req.finish()
127
128                 try: autotimer.parseEPG(simulateOnly=True, callback=self.intermediateWrite)
129                 except Exception as e:
130                         def finishRequest():
131                                 req.write('<exception>'+str(e)+'</exception><|PURPOSEFULLYBROKENXML<')
132                                 req.finish()
133
134                 if self._stillAlive:
135                         reactor.callFromThread(finishRequest)
136
137         def intermediateWrite(self, timers, conflicting, similar, skipped):
138                 returnlist = []
139                 extend = returnlist.extend
140
141                 for (name, begin, end, serviceref, autotimername, message) in timers:
142                         ref = ServiceReference(str(serviceref))
143                         extend((
144                                 '<e2simulatedtimer>\n'
145                                 '   <e2servicereference>', stringToXML(serviceref), '</e2servicereference>\n',
146                                 '   <e2servicename>', stringToXML(ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')), '</e2servicename>\n',
147                                 '   <e2name>', stringToXML(name), '</e2name>\n',
148                                 '   <e2timebegin>', str(begin), '</e2timebegin>\n',
149                                 '   <e2timeend>', str(end), '</e2timeend>\n',
150                                 '   <e2autotimername>', stringToXML(autotimername), '</e2autotimername>\n'
151                                 '</e2simulatedtimer>\n'
152                         ))
153
154                 if self._stillAlive:
155                         reactor.callFromThread(lambda: self._req.write(''.join(returnlist)))
156
157 class AutoTimerTestBackgroundThread(AutoTimerBackgroundThread):
158         def run(self):
159                 req = self._req
160                 if self._stillAlive:
161                         req.setResponseCode(http.OK)
162                         req.setHeader('Content-type', 'application/xhtml+xml')
163                         req.setHeader('charset', 'UTF-8')
164                         reactor.callFromThread(lambda: req.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<e2autotimersimulate api_version=\"" + str(API_VERSION) + "\">\n"))
165
166                 def finishRequest():
167                         req.write('</e2autotimersimulate>')
168                         req.finish()
169
170                 id = req.args.get("id")
171                 if id:
172                         self.id = int(id[0])
173                 else:
174                         self.id = None
175                 
176                 try: autotimer.parseEPG(simulateOnly=True, uniqueId=self.id, callback=self.intermediateWrite)
177                 except Exception as e:
178                         def finishRequest():
179                                 req.write('<exception>'+str(e)+'</exception><|PURPOSEFULLYBROKENXML<')
180                                 req.finish()
181
182                 if self._stillAlive:
183                         reactor.callFromThread(finishRequest)
184
185         def intermediateWrite(self, timers, conflicting, similar, skipped):
186                 returnlist = []
187                 extend = returnlist.extend
188
189                 for (name, begin, end, serviceref, autotimername, message) in timers:
190                         ref = ServiceReference(str(serviceref))
191                         extend((
192                                 '<e2simulatedtimer>\n'
193                                 '   <e2servicereference>', stringToXML(serviceref), '</e2servicereference>\n',
194                                 '   <e2servicename>', stringToXML(ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')), '</e2servicename>\n',
195                                 '   <e2name>', stringToXML(name), '</e2name>\n',
196                                 '   <e2timebegin>', str(begin), '</e2timebegin>\n',
197                                 '   <e2timeend>', str(end), '</e2timeend>\n',
198                                 '   <e2autotimername>', stringToXML(autotimername), '</e2autotimername>\n',
199                                 '   <e2state>OK</e2state>\n'
200                                 '   <e2message>', stringToXML(message), '</e2message>\n'
201                                 '</e2simulatedtimer>\n'
202                         ))
203
204                 if skipped:
205                         for (name, begin, end, serviceref, autotimername, message) in skipped:
206                                 ref = ServiceReference(str(serviceref))
207                                 extend((
208                                         '<e2simulatedtimer>\n'
209                                         '   <e2servicereference>', stringToXML(serviceref), '</e2servicereference>\n',
210                                         '   <e2servicename>', stringToXML(ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')), '</e2servicename>\n',
211                                         '   <e2name>', stringToXML(name), '</e2name>\n',
212                                         '   <e2timebegin>', str(begin), '</e2timebegin>\n',
213                                         '   <e2timeend>', str(end), '</e2timeend>\n',
214                                         '   <e2autotimername>', stringToXML(autotimername), '</e2autotimername>\n',
215                                         '   <e2state>Skip</e2state>\n'
216                                         '   <e2message>', stringToXML(message), '</e2message>\n'
217                                         '</e2simulatedtimer>\n'
218                                 ))
219                 
220                 if self._stillAlive:
221                         reactor.callFromThread(lambda: self._req.write(''.join(returnlist)))
222
223 class AutoTimerSimulateResource(AutoTimerBaseResource):
224         def render(self, req):
225                 AutoTimerSimulateBackgroundThread(req, None)
226                 return server.NOT_DONE_YET
227
228 class AutoTimerTestResource(AutoTimerBaseResource):
229         def render(self, req):
230                 AutoTimerTestBackgroundThread(req, None)
231                 return server.NOT_DONE_YET
232
233 class AutoTimerListAutoTimerResource(AutoTimerBaseResource):
234         def render(self, req):
235                 # We re-read the config so we won't display empty or wrong information
236                 try:
237                         autotimer.readXml()
238                 except Exception as e:
239                         return self.returnResult(req, False, _("Couldn't load config file!") + '\n' + str(e))
240
241                 # show xml
242                 req.setResponseCode(http.OK)
243                 req.setHeader('Content-type', 'application/xhtml+xml')
244                 req.setHeader('charset', 'UTF-8')
245                 return ''.join(autotimer.getXml())
246
247 class AutoTimerRemoveAutoTimerResource(AutoTimerBaseResource):
248         def render(self, req):
249                 id = req.args.get("id")
250                 if id:
251                         autotimer.remove(int(id[0]))
252                         return self.returnResult(req, True, _("AutoTimer was removed"))
253                 else:
254                         return self.returnResult(req, False, _("missing parameter \"id\""))
255
256 class AutoTimerAddOrEditAutoTimerResource(AutoTimerBaseResource):
257         # TODO: recheck if we can modify regular config parser to work on this
258         # TODO: allow to edit defaults?
259         def render(self, req):
260                 def get(name, default=None):
261                         ret = req.args.get(name)
262                         return ret[0] if ret else default
263
264                 id = get("id")
265                 timer = None
266                 newTimer = True
267                 if id is None:
268                         id = autotimer.getUniqueId()
269                         timer = autotimer.defaultTimer.clone()
270                         timer.id = id
271                 else:
272                         id = int(id)
273                         for possibleMatch in autotimer.getTimerList():
274                                 if possibleMatch.id == id:
275                                         timer = possibleMatch
276                                         newTimer = False
277                                         break
278                         if timer is None:
279                                 return self.returnResult(req, False, _("unable to find timer with id %i" % (id,)))
280
281                 if id != -1:
282                         # Match
283                         timer.match = unquote(get("match", timer.match))
284                         if not timer.match:
285                                 return self.returnResult(req, False, _("autotimers need a match attribute"))
286
287                         # Name
288                         timer.name = unquote(get("name", timer.name)).strip()
289                         if not timer.name: timer.name = timer.match
290
291                         # Enabled
292                         enabled = get("enabled")
293                         if enabled is not None:
294                                 try: enabled = int(enabled)
295                                 except ValueError: enabled = enabled == "yes"
296                                 timer.enabled = enabled
297
298                         # Timeframe
299                         before = get("before")
300                         after = get("after")
301                         if before and after:
302                                 timer.timeframe = (int(after), int(before))
303                         elif before == '' or after == '':
304                                 timer.timeframe = None
305
306                 # ...
307                 timer.searchType = get("searchType", timer.searchType)
308                 timer.searchCase = get("searchCase", timer.searchCase)
309
310                 # Alternatives
311                 timer.overrideAlternatives = int(get("overrideAlternatives", timer.overrideAlternatives))
312
313                 # Justplay
314                 justplay = get("justplay")
315                 if justplay is not None:
316                         try: justplay = int(justplay)
317                         except ValueError: justplay = justplay == "zap"
318                         timer.justplay = justplay
319                 setEndtime = get("setEndtime")
320                 if setEndtime is not None:
321                         timer.setEndtime = int(setEndtime)
322
323                 # Timespan
324                 start = get("timespanFrom")
325                 end = get("timespanTo")
326                 if start and end:
327                         start = [int(x) for x in start.split(':')]
328                         end = [int(x) for x in end.split(':')]
329                         timer.timespan = (start, end)
330                 elif start == '' and end == '':
331                         timer.timespan = None
332
333                 # Services
334                 servicelist = get("services")
335                 if servicelist is not None:
336                         servicelist = unquote(servicelist).split(',')
337                         appendlist = []
338                         for value in servicelist:
339                                 myref = eServiceReference(str(value))
340                                 if not (myref.flags & eServiceReference.isGroup):
341                                         # strip all after last :
342                                         pos = value.rfind(':')
343                                         if pos != -1:
344                                                 if value[pos-1] == ':':
345                                                         pos -= 1
346                                                 value = value[:pos+1]
347
348                                 if myref.valid():
349                                         appendlist.append(value)
350                         timer.services = appendlist
351
352                 # Bouquets
353                 servicelist = get("bouquets")
354                 if servicelist is not None:
355                         servicelist = unquote(servicelist).split(',')
356                         while '' in servicelist: servicelist.remove('')
357                         timer.bouquets = servicelist
358
359                 # Offset
360                 offset = get("offset")
361                 if offset:
362                         offset = offset.split(',')
363                         if len(offset) == 1:
364                                 before = after = int(offset[0] or 0) * 60
365                         else:
366                                 before = int(offset[0] or 0) * 60
367                                 after = int(offset[1] or 0) * 60
368                         timer.offset = (before, after)
369                 elif offset == '':
370                         timer.offset = None
371
372                 # AfterEvent
373                 afterevent = get("afterevent")
374                 if afterevent:
375                         if afterevent == "default":
376                                 timer.afterevent = []
377                         else:
378                                 try: afterevent = int(afterevent)
379                                 except ValueError:
380                                         afterevent = {
381                                                 "nothing": AFTEREVENT.NONE,
382                                                 "deepstandby": AFTEREVENT.DEEPSTANDBY,
383                                                 "standby": AFTEREVENT.STANDBY,
384                                                 "auto": AFTEREVENT.AUTO
385                                         }.get(afterevent, AFTEREVENT.AUTO)
386                                 start = get("aftereventFrom")
387                                 end = get("aftereventTo")
388                                 if start and end:
389                                         start = [int(x) for x in start.split(':')]
390                                         end = [int(x) for x in end.split(':')]
391                                         timer.afterevent = [(afterevent, (start, end))]
392                                 else:
393                                         timer.afterevent = [(afterevent, None)]
394
395                 # Maxduration
396                 maxduration = get("maxduration")
397                 if maxduration:
398                         timer.maxduration = int(maxduration)*60
399                 elif maxduration == '':
400                         timer.maxduration = None
401
402                 # Includes
403                 title = req.args.get("title")
404                 shortdescription = req.args.get("shortdescription")
405                 description = req.args.get("description")
406                 dayofweek = req.args.get("dayofweek")
407                 if title or shortdescription or description or dayofweek:
408                         includes = timer.include
409                         title = [unquote(x) for x in title] if title else includes[0]
410                         shortdescription = [unquote(x) for x in shortdescription] if shortdescription else includes[1]
411                         description = [unquote(x) for x in description] if description else includes[2]
412                         dayofweek = [unquote(x) for x in dayofweek] if dayofweek else includes[3]
413                         while '' in title: title.remove('')
414                         while '' in shortdescription: shortdescription.remove('')
415                         while '' in description: description.remove('')
416                         while '' in dayofweek: dayofweek.remove('')
417                         timer.include = (title, shortdescription, description, dayofweek)
418
419                 # Excludes
420                 title = req.args.get("!title")
421                 shortdescription = req.args.get("!shortdescription")
422                 description = req.args.get("!description")
423                 dayofweek = req.args.get("!dayofweek")
424                 if title or shortdescription or description or dayofweek:
425                         excludes = timer.exclude
426                         title = [unquote(x) for x in title] if title else excludes[0]
427                         shortdescription = [unquote(x) for x in shortdescription] if shortdescription else excludes[1]
428                         description = [unquote(x) for x in description] if description else excludes[2]
429                         dayofweek = [unquote(x) for x in dayofweek] if dayofweek else excludes[3]
430                         while '' in title: title.remove('')
431                         while '' in shortdescription: shortdescription.remove('')
432                         while '' in description: description.remove('')
433                         while '' in dayofweek: dayofweek.remove('')
434                         timer.exclude = (title, shortdescription, description, dayofweek)
435
436                 tags = req.args.get("tag")
437                 if tags:
438                         while '' in tags: tags.remove('')
439                         timer.tags = [unquote(x) for x in tags]
440
441                 timer.matchCount = int(get("counter", timer.matchCount))
442                 timer.matchFormatString = get("counterFormat", timer.matchFormatString)
443                 if id != -1:
444                         matchLeft = get("left")
445                         timer.matchLeft = int(matchLeft) if matchLeft else (timer.matchCount if newTimer else timer.matchLeft)
446                         timer.matchLimit = get("lastActivation", timer.matchLimit)
447                         timer.lastBegin = int(get("lastBegin", timer.lastBegin))
448
449                 timer.avoidDuplicateDescription = int(get("avoidDuplicateDescription", timer.avoidDuplicateDescription))
450                 timer.searchForDuplicateDescription = int(get("searchForDuplicateDescription", timer.searchForDuplicateDescription))
451                 timer.destination = get("location", timer.destination) or None
452
453                 # vps
454                 enabled = get("vps_enabled")
455                 if enabled is not None:
456                         try: enabled = int(enabled)
457                         except ValueError: enabled = enabled == "yes"
458                         timer.vps_enabled = enabled
459                 vps_overwrite = get("vps_overwrite")
460                 if vps_overwrite is not None:
461                         try: vps_overwrite = int(vps_overwrite)
462                         except ValueError: vps_overwrite = vps_overwrite == "yes"
463                         timer.vps_overwrite = vps_overwrite
464                 if not timer.vps_enabled and timer.vps_overwrite:
465                         timer.vps_overwrite = False
466
467                 # SeriesPlugin
468                 series_labeling = get("series_labeling")
469                 if series_labeling is not None:
470                         try: series_labeling = int(series_labeling)
471                         except ValueError: series_labeling = series_labeling == "yes"
472                         timer.series_labeling = series_labeling
473
474                 if newTimer:
475                         autotimer.add(timer)
476                         message = _("AutoTimer was added successfully")
477                 else:
478                         message = _("AutoTimer was changed successfully")
479
480                 return self.returnResult(req, True, message)
481
482 class AutoTimerChangeSettingsResource(AutoTimerBaseResource):
483         def render(self, req):
484                 for key, value in iteritems(req.args):
485                         value = value[0]
486                         if key == "autopoll":
487                                 config.plugins.autotimer.autopoll.value = True if value == "true" else False
488                         elif key == "interval":
489                                 config.plugins.autotimer.interval.value = int(value)
490                         elif key == "refresh":
491                                 config.plugins.autotimer.refresh.value = value
492                         elif key == "try_guessing":
493                                 config.plugins.autotimer.try_guessing.value = True if value == "true" else False
494                         elif key == "editor":
495                                 config.plugins.autotimer.editor.value = value
496                         elif key == "disabled_on_conflict":
497                                 config.plugins.autotimer.disabled_on_conflict.value = True if value == "true" else False
498                         elif key == "addsimilar_on_conflict":
499                                 config.plugins.autotimer.addsimilar_on_conflict.value = True if value == "true" else False
500                         elif key == "show_in_extensionsmenu":
501                                 config.plugins.autotimer.show_in_extensionsmenu.value = True if value == "true" else False
502                         elif key == "fastscan":
503                                 config.plugins.autotimer.fastscan.value = True if value == "true" else False
504                         elif key == "notifconflict":
505                                 config.plugins.autotimer.notifconflict.value = True if value == "true" else False
506                         elif key == "notifsimilar":
507                                 config.plugins.autotimer.notifsimilar.value = True if value == "true" else False
508                         elif key == "maxdaysinfuture":
509                                 config.plugins.autotimer.maxdaysinfuture.value = int(value)
510                         elif key == "add_autotimer_to_tags":
511                                 config.plugins.autotimer.add_autotimer_to_tags.value = True if value == "true" else False
512                         elif key == "add_name_to_tags":
513                                 config.plugins.autotimer.add_name_to_tags.value = True if value == "true" else False
514                         elif key == "timeout":
515                                 config.plugins.autotimer.timeout.value = int(value)
516                         elif key == "delay":
517                                 config.plugins.autotimer.delay.value = int(value)
518                         elif key == "editdelay":
519                                 config.plugins.autotimer.editdelay.value = int(value)
520                         elif key == "skip_during_records":
521                                 config.plugins.autotimer.skip_during_records.value = True if value == "true" else False
522                         elif key == "skip_during_epgrefresh":
523                                 config.plugins.autotimer.skip_during_epgrefresh.value = True if value == "true" else False
524
525                 if config.plugins.autotimer.autopoll.value:
526                         if plugin.autopoller is None:
527                                 from AutoPoller import AutoPoller
528                                 plugin.autopoller = AutoPoller()
529                         plugin.autopoller.start(initial = False)
530                 else:
531                         if plugin.autopoller is not None:
532                                 plugin.autopoller.stop()
533                                 plugin.autopoller = None
534
535                 return self.returnResult(req, True, _("config changed."))
536
537 class AutoTimerSettingsResource(resource.Resource):
538         def render(self, req):
539                 req.setResponseCode(http.OK)
540                 req.setHeader('Content-type', 'application/xhtml+xml')
541                 req.setHeader('charset', 'UTF-8')
542
543                 try:
544                         from Plugins.SystemPlugins.vps import Vps
545                 except ImportError as ie:
546                         hasVps = False
547                 else:
548                         hasVps = True
549
550                 try:
551                         from Plugins.Extensions.SeriesPlugin.plugin import Plugins
552                 except ImportError as ie:
553                         hasSeriesPlugin = False
554                 else:
555                         hasSeriesPlugin = True
556
557                 return """<?xml version=\"1.0\" encoding=\"UTF-8\" ?>
558 <e2settings>
559         <e2setting>
560                 <e2settingname>config.plugins.autotimer.autopoll</e2settingname>
561                 <e2settingvalue>%s</e2settingvalue>
562         </e2setting>
563         <e2setting>
564                 <e2settingname>config.plugins.autotimer.interval</e2settingname>
565                 <e2settingvalue>%d</e2settingvalue>
566         </e2setting>
567         <e2setting>
568                 <e2settingname>config.plugins.autotimer.refresh</e2settingname>
569                 <e2settingvalue>%s</e2settingvalue>
570         </e2setting>
571         <e2setting>
572                 <e2settingname>config.plugins.autotimer.try_guessing</e2settingname>
573                 <e2settingvalue>%s</e2settingvalue>
574         </e2setting>
575         <e2setting>
576                 <e2settingname>config.plugins.autotimer.editor</e2settingname>
577                 <e2settingvalue>%s</e2settingvalue>
578         </e2setting>
579         <e2setting>
580                 <e2settingname>config.plugins.autotimer.disabled_on_conflict</e2settingname>
581                 <e2settingvalue>%s</e2settingvalue>
582         </e2setting>
583         <e2setting>
584                 <e2settingname>config.plugins.autotimer.addsimilar_on_conflict</e2settingname>
585                 <e2settingvalue>%s</e2settingvalue>
586         </e2setting>
587         <e2setting>
588                 <e2settingname>config.plugins.autotimer.show_in_extensionsmenu</e2settingname>
589                 <e2settingvalue>%s</e2settingvalue>
590         </e2setting>
591         <e2setting>
592                 <e2settingname>config.plugins.autotimer.fastscan</e2settingname>
593                 <e2settingvalue>%s</e2settingvalue>
594         </e2setting>
595         <e2setting>
596                 <e2settingname>config.plugins.autotimer.notifconflict</e2settingname>
597                 <e2settingvalue>%s</e2settingvalue>
598         </e2setting>
599         <e2setting>
600                 <e2settingname>config.plugins.autotimer.notifsimilar</e2settingname>
601                 <e2settingvalue>%s</e2settingvalue>
602         </e2setting>
603         <e2setting>
604                 <e2settingname>config.plugins.autotimer.maxdaysinfuture</e2settingname>
605                 <e2settingvalue>%s</e2settingvalue>
606         </e2setting>
607         <e2setting>
608                 <e2settingname>config.plugins.autotimer.add_autotimer_to_tags</e2settingname>
609                 <e2settingvalue>%s</e2settingvalue>
610         </e2setting>
611         <e2setting>
612                 <e2settingname>config.plugins.autotimer.add_name_to_tags</e2settingname>
613                 <e2settingvalue>%s</e2settingvalue>
614         </e2setting>
615         <e2setting>
616                 <e2settingname>config.plugins.autotimer.timeout</e2settingname>
617                 <e2settingvalue>%s</e2settingvalue>
618         </e2setting>
619         <e2setting>
620                 <e2settingname>config.plugins.autotimer.delay</e2settingname>
621                 <e2settingvalue>%s</e2settingvalue>
622         </e2setting>
623         <e2setting>
624                 <e2settingname>config.plugins.autotimer.editdelay</e2settingname>
625                 <e2settingvalue>%s</e2settingvalue>
626         </e2setting>
627         <e2setting>
628                 <e2settingname>config.plugins.autotimer.skip_during_records</e2settingname>
629                 <e2settingvalue>%s</e2settingvalue>
630         </e2setting>
631         <e2setting>
632                 <e2settingname>config.plugins.autotimer.skip_during_epgrefresh</e2settingname>
633                 <e2settingvalue>%s</e2settingvalue>
634         </e2setting>
635         <e2setting>
636                 <e2settingname>hasVps</e2settingname>
637                 <e2settingvalue>%s</e2settingvalue>
638         </e2setting>
639         <e2setting>
640                 <e2settingname>hasSeriesPlugin</e2settingname>
641                 <e2settingvalue>%s</e2settingvalue>
642         </e2setting>
643         <e2setting>
644                 <e2settingname>version</e2settingname>
645                 <e2settingvalue>%s</e2settingvalue>
646         </e2setting>
647         <e2setting>
648                 <e2settingname>api_version</e2settingname>
649                 <e2settingvalue>%s</e2settingvalue>
650         </e2setting>
651         <e2setting>
652                 <e2settingname>autotimer_version</e2settingname>
653                 <e2settingvalue>%s</e2settingvalue>
654         </e2setting>
655 </e2settings>""" % (
656                                 config.plugins.autotimer.autopoll.value,
657                                 config.plugins.autotimer.interval.value,
658                                 config.plugins.autotimer.refresh.value,
659                                 config.plugins.autotimer.try_guessing.value,
660                                 config.plugins.autotimer.editor.value,
661                                 config.plugins.autotimer.addsimilar_on_conflict.value,
662                                 config.plugins.autotimer.disabled_on_conflict.value,
663                                 config.plugins.autotimer.show_in_extensionsmenu.value,
664                                 config.plugins.autotimer.fastscan.value,
665                                 config.plugins.autotimer.notifconflict.value,
666                                 config.plugins.autotimer.notifsimilar.value,
667                                 config.plugins.autotimer.maxdaysinfuture.value,
668                                 config.plugins.autotimer.add_autotimer_to_tags.value,
669                                 config.plugins.autotimer.add_name_to_tags.value,
670                                 config.plugins.autotimer.timeout.value,
671                                 config.plugins.autotimer.delay.value,
672                                 config.plugins.autotimer.editdelay.value,
673                                 config.plugins.autotimer.skip_during_records.value,
674                                 config.plugins.autotimer.skip_during_epgrefresh.value,
675                                 hasVps,
676                                 hasSeriesPlugin,
677                                 CURRENT_CONFIG_VERSION,
678                                 API_VERSION,
679                                 AUTOTIMER_VERSION
680                         )