SystemPlugins/CrashlogAutoSubmit/plugin.py: - don't start crashlogmailer on firstrun.
[enigma2.git] / lib / python / Plugins / SystemPlugins / CrashlogAutoSubmit / plugin.py
1 from Plugins.Plugin import PluginDescriptor
2 from Components.config import config, getConfigListEntry, ConfigSubsection, ConfigText, ConfigSelection, ConfigYesNo,ConfigText
3 from Components.ConfigList import ConfigListScreen
4 from Components.ActionMap import ActionMap
5 from Components.Label import Label
6 from Components.Pixmap import Pixmap
7 from Screens.Screen import Screen
8 from Screens.VirtualKeyBoard import VirtualKeyBoard
9 from Screens.ChoiceBox import ChoiceBox
10 from Screens.MessageBox import MessageBox
11 from enigma import ePoint
12
13 import os
14 from twisted.mail import smtp, relaymanager
15
16 config.plugins.crashlogautosubmit = ConfigSubsection()
17 config.plugins.crashlogautosubmit.sendmail = ConfigSelection(default = "send", choices = [
18         ("send", _("Always ask before sending")), ("send_always", _("Don't ask, just send")), ("send_never", _("Disable crashlog reporting"))])
19 config.plugins.crashlogautosubmit.sendlog = ConfigSelection(default = "rename", choices = [
20         ("delete", _("Delete crashlogs")), ("rename", _("Rename crashlogs"))])
21 config.plugins.crashlogautosubmit.attachemail = ConfigYesNo(default = False)
22 config.plugins.crashlogautosubmit.email = ConfigText(default = "myemail@home.com", fixed_size = False)
23 config.plugins.crashlogautosubmit.name = ConfigText(default = "Dreambox User", fixed_size = False)
24
25
26 class CrashlogAutoSubmitConfiguration(Screen, ConfigListScreen):
27
28         oldMailEntryValue = config.plugins.crashlogautosubmit.sendmail.value
29
30         skin = """
31                 <screen name="CrashlogAutoSubmitConfiguration" position="80,80" size="560,400" title="CrashlogAutoSubmit settings..." >
32                         <widget name="config" zPosition="2" position="5,5" size="550,360" scrollbarMode="showOnDemand" transparent="1" />
33                         <ePixmap pixmap="skin_default/div-h.png" position="0,300" zPosition="10" size="560,2" transparent="1" alphatest="on" />
34                         <widget name="status" position="10,300" zPosition="10" size="540,50" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
35                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,360" zPosition="2" size="140,40" transparent="1" alphatest="on" />
36                         <widget name="closetext" position="0,360" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
37                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,360" zPosition="2" size="140,40" transparent="1" alphatest="on" />
38                         <widget name="installtext" position="140,360" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
39                         <widget name="VKeyButton" pixmap="skin_default/buttons/button_yellow.png" position="285,370" zPosition="2" size="15,16" transparent="1" alphatest="on" />
40                         <widget name="VKeyIcon" pixmap="skin_default/vkey_icon.png" position="300,355" zPosition="10" size="60,48" transparent="1" alphatest="on" />
41                         <widget name="HelpWindow" position="175,250" zPosition="1" size="1,1" transparent="1" />
42                 </screen>"""
43
44         def __init__(self, session):
45                 Screen.__init__(self, session)
46                 self.session = session
47                 self.MailEntry = None
48                 self.LogEntry = None
49                 self.addEmailEntry = None
50                 self.EmailEntry = None
51                 self.NameEntry = None
52                 self.msgCrashlogMailer = False
53
54                 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
55                 {
56                         "ok": self.keySave,
57                         "cancel": self.keyCancel,
58                         "red": self.keyCancel,
59                         "green": self.keySave,
60                 }, -2)
61
62                 self["VirtualKB"] = ActionMap(["ColorActions" ],
63                 {
64                         "yellow": self.KeyYellow,
65                 }, -1)
66
67                 self.list = []
68                 ConfigListScreen.__init__(self, self.list,session = self.session)
69                 self.createSetup()
70
71                 self["VKeyButton"] = Pixmap()
72                 self["VKeyIcon"] = Pixmap()
73                 self["closetext"] = Label(_("Close"))
74                 self["installtext"] = Label(_("Save"))
75                 self["HelpWindow"] = Label()
76                 self["status"] = Label()
77
78                 self["VKeyButton"].hide()
79                 self["VKeyIcon"].hide()
80                 self["VirtualKB"].setEnabled(False)
81                 self.onShown.append(self.setWindowTitle)
82                 self.onClose.append(self.msgCrashlogNotifier)
83
84
85         def setWindowTitle(self):
86                 self.setTitle(_("CrashlogAutoSubmit settings..."))
87
88         def keyLeft(self):
89                 ConfigListScreen.keyLeft(self)
90                 self.newConfig()
91
92         def keyRight(self):
93                 ConfigListScreen.keyRight(self)
94                 self.newConfig()
95
96         def KeyYellow(self):
97                         if self["config"].getCurrent() == self.EmailEntry:
98                                 self.session.openWithCallback(self.EmailCallback, VirtualKeyBoard, title = (_("Please enter your email address here:")), text = config.plugins.crashlogautosubmit.email.value)
99                         if self["config"].getCurrent() == self.NameEntry:
100                                 self.session.openWithCallback(self.NameCallback, VirtualKeyBoard, title = (_("Please enter your name here (optional):")), text = config.plugins.crashlogautosubmit.name.value)
101
102         def EmailCallback(self, callback = None):
103                 if callback is not None and len(callback):
104                         config.plugins.crashlogautosubmit.email.setValue(callback)
105                         self["config"].invalidate(self.EmailEntry)
106
107         def NameCallback(self, callback = None):
108                 if callback is not None and len(callback):
109                         config.plugins.crashlogautosubmit.name.setValue(callback)
110                         self["config"].invalidate(self.NameEntry)
111
112         def createSetup(self):
113                 self.list = []
114                 self.MailEntry = getConfigListEntry(_("How to handle found crashlogs?"), config.plugins.crashlogautosubmit.sendmail)
115                 self.LogEntry = getConfigListEntry(_("What to do with submitted crashlogs?"), config.plugins.crashlogautosubmit.sendlog)
116                 self.addEmailEntry = getConfigListEntry(_("Include your email and name (optional) in the mail?"), config.plugins.crashlogautosubmit.attachemail)
117                 self.EmailEntry = getConfigListEntry(_("Your email address:"), config.plugins.crashlogautosubmit.email)
118                 self.NameEntry = getConfigListEntry(_("Your name (optional):"), config.plugins.crashlogautosubmit.name)
119                 self.list.append( self.MailEntry )
120                 if config.plugins.crashlogautosubmit.sendmail.value is not "send_never":
121                         self.list.append( self.LogEntry )
122                         self.list.append( self.addEmailEntry )
123                         if config.plugins.crashlogautosubmit.attachemail.value is True:
124                                 self.list.append( self.EmailEntry )
125                                 self.list.append( self.NameEntry )
126
127                 self["config"].list = self.list
128                 self["config"].l.setList(self.list)
129                 if not self.selectionChanged in self["config"].onSelectionChanged:
130                         self["config"].onSelectionChanged.append(self.selectionChanged)
131
132                 if not self.sendmailChanged in config.plugins.crashlogautosubmit.sendmail.notifiers:
133                         config.plugins.crashlogautosubmit.sendmail.notifiers.append(self.sendmailChanged)
134
135         def sendmailChanged(self, configElement):
136                 if configElement.value != CrashlogAutoSubmitConfiguration.oldMailEntryValue:
137                         self.msgCrashlogMailer = True
138                 else:
139                         self.msgCrashlogMailer = False
140
141         def newConfig(self):
142                 if self["config"].getCurrent() == self.MailEntry:
143                         self.createSetup()
144                 if self["config"].getCurrent() == self.addEmailEntry:
145                         self.createSetup()
146
147         def selectionChanged(self):
148                 current = self["config"].getCurrent()
149                 if current == self.MailEntry:
150                         self["status"].setText(_("Decide what should be done when crashlogs are found."))
151                         self.disableVKeyIcon()
152                 elif current == self.LogEntry:
153                         self["status"].setText(_("Decide what should happen to the crashlogs after submission."))
154                         self.disableVKeyIcon()
155                 elif current == self.addEmailEntry:
156                         self["status"].setText(_("Do you want to submit your email address and name so that we can contact you if needed?"))
157                         self.disableVKeyIcon()
158                 elif current == self.EmailEntry:
159                         self["status"].setText(_("Enter your email address so that we can contact you if needed."))
160                         self.enableVKeyIcon()
161                         self.showKeypad()
162                 elif current == self.NameEntry:
163                         self["status"].setText(_("Optionally enter your name if you want to."))
164                         self.enableVKeyIcon()
165                         self.showKeypad()
166
167         def enableVKeyIcon(self):
168                 self["VKeyButton"].show()
169                 self["VKeyIcon"].show()
170                 self["VirtualKB"].setEnabled(True)
171
172         def showKeypad(self):
173                 current = self["config"].getCurrent()
174                 helpwindowpos = self["HelpWindow"].getPosition()
175                 if hasattr(current[1], 'help_window'):
176                         if current[1].help_window.instance is not None:
177                                 current[1].help_window.instance.show()
178                                 current[1].help_window.instance.move(ePoint(helpwindowpos[0],helpwindowpos[1]))
179
180         def disableVKeyIcon(self):
181                 self["VKeyButton"].hide()
182                 self["VKeyIcon"].hide()
183                 self["VirtualKB"].setEnabled(False)
184
185         def hideKeypad(self):
186                 current = self["config"].getCurrent()
187                 if hasattr(current[1], 'help_window'):
188                         if current[1].help_window.instance is not None:
189                                 current[1].help_window.instance.hide()
190
191         def cancelConfirm(self, result):
192                 if not result:
193                         self.showKeypad()
194                         return
195                 for x in self["config"].list:
196                         x[1].cancel()
197                 self.close()
198
199         def keyCancel(self):
200                 print "cancel"
201                 if self["config"].isChanged():
202                         self.hideKeypad()
203                         self.session.openWithCallback(self.cancelConfirm, MessageBox, _("Really close without saving settings?"))
204                 else:
205                         self.close()
206
207         def keySave(self):
208                 print "saving"
209                 CrashlogAutoSubmitConfiguration.oldMailEntryValue = config.plugins.crashlogautosubmit.sendmail.value
210                 ConfigListScreen.keySave(self)
211
212         def msgCrashlogNotifier(self):
213                 if self.msgCrashlogMailer is True:
214                         try:
215                                 callCrashMailer(True, self.session)
216                         except AttributeError:
217                                 print "error, not restarting crashlogmailer"
218
219
220 def mxServerFound(mxServer,session):
221         print "[CrashlogAutoSubmit] - mxServerFound -->", mxServer
222         attachments = []
223         crashLogFilelist = []
224         mailFrom = "enigma2@crashlog.dream-multimedia-tv.de"
225         mailTo = "enigma2@crashlog.dream-multimedia-tv.de"
226         subject = "Automatically generated crashlogmail"
227         mailtext = "\nHello\n\nHere are some crashlogs i found for you.\n"
228         mailfooter = "\n\nThis is an automatically generated email from the CrashlogAutoSubmit plugin.\n\n\nHave a nice day.\n"
229         if  str(config.plugins.crashlogautosubmit.email.value) == "myemail@home.com":
230                 user_email = ""
231         else:
232                 user_email = "\nUser supplied email address: " + str(config.plugins.crashlogautosubmit.email.value)
233         if str(config.plugins.crashlogautosubmit.name.value) ==  "Dreambox User":
234                 user_name = ""
235         else:
236                 user_name = "\n\nOptional supplied name: " + str(config.plugins.crashlogautosubmit.name.value)
237         headers = { 'from': 'CrashlogAutoSubmitter <enigma2@crashlog.dream-multimedia-tv.de>', 'to': 'dream-multimedia-crashlogs <enigma2@crashlog.dream-multimedia-tv.de>', 'subject' : str(subject) }
238         mailData = mailtext + user_email + user_name + mailfooter
239         if config.plugins.crashlogautosubmit.attachemail.value is True:
240                 if  str(config.plugins.crashlogautosubmit.email.value) != "myemail@home.com":
241                         headers["reply-to"] = str(config.plugins.crashlogautosubmit.email.value)
242
243         list = (
244                 (_("Yes"), "send"),
245                 (_("Yes, and don't ask again"), "send_always"),
246                 (_("No, not now"), "send_not"),
247                 (_("No, send them never"), "send_never")
248         )
249
250         def handleError(error):
251                 print "[CrashlogAutoSubmit] - Message send Error -->", error.getErrorMessage()
252
253         def handleSuccess(result):
254                 print "[CrashlogAutoSubmit] - Message sent successfully -->",result
255                 if len(crashLogFilelist):
256                         for crashlog in crashLogFilelist:
257                                 if config.plugins.crashlogautosubmit.sendlog.value == "delete":
258                                         os.remove(crashlog)
259                                 elif config.plugins.crashlogautosubmit.sendlog.value == "rename":
260                                         currfilename = str(os.path.basename(crashlog))
261                                         newfilename = "/media/hdd/" + currfilename + ".sent"
262                                         os.rename(crashlog,newfilename)
263
264         def send_mail():
265                 print "[CrashlogAutoSubmit] - send_mail"
266                 attachments = []
267                 if len(crashLogFilelist):
268                         for crashlog in crashLogFilelist:
269                                 filename = str(os.path.basename(crashlog))
270                                 mimetype = "text/plain"
271                                 f = open (crashlog, 'r')
272                                 attachment = str(f.read())
273                                 f.close()
274                                 attachments.append ((filename,mimetype,attachment))
275                 sending = smtp.sendEmail(str(mxServer), mailFrom, mailTo, str(mailData), headers, attachments)
276                 sending.addCallback(handleSuccess).addErrback(handleError)
277
278         def handleAnswer(answer):
279                 answer = answer and answer[1]
280                 print "[CrashlogAutoSubmit] - handleAnswer --> ",answer
281                 if answer == "send":
282                         send_mail()
283                 elif answer == "send_always":
284                         config.plugins.crashlogautosubmit.sendmail.value = "send_always"
285                         config.plugins.crashlogautosubmit.sendmail.save()
286                         config.plugins.crashlogautosubmit.save()
287                         config.plugins.save()
288                         config.save()
289                         send_mail()
290                 elif answer in ( None, "send_never"):
291                         config.plugins.crashlogautosubmit.sendmail.value = "send_never"
292                         config.plugins.crashlogautosubmit.sendmail.save()
293                         config.plugins.crashlogautosubmit.save()
294                         config.plugins.save()
295                         config.save()
296                 elif answer == "send_not":
297                         print "[CrashlogAutoSubmit] - not sending crashlogs for this time."
298
299
300         for crashlog in os.listdir('/media/hdd'):
301                 if crashlog.startswith("enigma2_crash_") and crashlog.endswith(".log"):
302                         print "[CrashlogAutoSubmit] - found crashlog: ",os.path.basename(crashlog)
303                         crashLogFilelist.append('/media/hdd/' + crashlog)
304
305         if len(crashLogFilelist):
306                 if config.plugins.crashlogautosubmit.sendmail.value == "send":
307                         session.openWithCallback(handleAnswer, ChoiceBox, title=_("Crashlogs found!\nSend them to Dream Multimedia ?"), list = list)
308                 elif config.plugins.crashlogautosubmit.sendmail.value == "send_always":
309                         send_mail()
310         else:
311                 print "[CrashlogAutoSubmit] - no crashlogs found."
312
313
314 def getMailExchange(host):
315         print "[CrashlogAutoSubmit] - getMailExchange"
316
317         def handleMXError(error):
318                 print "[CrashlogAutoSubmit] - DNS-Error, sending aborted -->", error.getErrorMessage()
319
320         def cbMX(mxRecord):
321                 return str(mxRecord.name)
322
323         return relaymanager.MXCalculator().getMX(host).addCallback(cbMX).addErrback(handleMXError)
324
325
326 def startMailer(session):
327         if config.plugins.crashlogautosubmit.sendmail.value == "send_never":
328                 print "[CrashlogAutoSubmit] - not starting CrashlogAutoSubmit"
329                 return False
330
331         if not config.misc.firstrun.value:
332                 getMailExchange('crashlog.dream-multimedia-tv.de').addCallback(mxServerFound,session)
333
334
335 def callCrashMailer(result,session):
336         if result is True:
337                 print "[CrashlogAutoSubmit] - config changed"
338                 startMailer(session)
339         else:
340                 print "[CrashlogAutoSubmit] - config not changed"
341
342
343 def autostart(reason, **kwargs):
344         print "[CrashlogAutoSubmit] - autostart"
345         if "session" in kwargs:
346                 try:
347                         startMailer(kwargs["session"])
348                 except ImportError, e:
349                         print "[CrashlogAutoSubmit] Twisted-mail not available, not starting CrashlogAutoSubmitter", e
350
351
352 def openconfig(session, **kwargs):
353         session.open(CrashlogAutoSubmitConfiguration)
354
355
356 def selSetup(menuid, **kwargs):
357         if menuid != "system":
358                 return [ ]
359
360         return [(_("Crashlog settings") + "...", openconfig, "crashlog_config", 70)]
361
362
363 def Plugins(**kwargs):
364         return [PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc = autostart),
365                 PluginDescriptor(name=_("CrashlogAutoSubmit"), description=_("CrashlogAutoSubmit settings"),where=PluginDescriptor.WHERE_MENU, fnc=selSetup)]
366