rework backends and split them up,
[enigma2-plugins.git] / growlee / src / GrowlTalk.py
1 from netgrowl import GrowlRegistrationPacket, GrowlNotificationPacket, \
2                 GROWL_UDP_PORT, md5_constructor
3 from twisted.internet.protocol import DatagramProtocol
4 from twisted.internet import reactor
5 from struct import unpack
6
7 from Tools import Notifications
8 from Components.config import config
9
10 from GrowleeConnection import emergencyDisable
11 from . import NOTIFICATIONID
12
13 class GrowlTalk(DatagramProtocol):
14         addr = None
15
16         def gotIP(self, ip):
17                 self.addr = (ip, GROWL_UDP_PORT)
18                 if config.plugins.growlee.enable_outgoing.value:
19                         p = GrowlRegistrationPacket(application="growlee", password=config.plugins.growlee.password.value)
20                         p.addNotification()
21                         payload = p.payload()
22
23                         self.transport.write(payload, self.addr)
24
25         def noIP(self, error):
26                 emergencyDisable()
27
28         def startProtocol(self):
29                 reactor.resolve(config.plugins.growlee.address.value).addCallback(self.gotIP).addErrback(self.noIP)
30
31         def sendNotification(self, *args, **kwargs):
32                 if not self.transport or not self.addr or not config.plugins.growlee.enable_outgoing.value:
33                         return
34
35                 kwargs["application"] = "growlee"
36                 kwargs["password"] = config.plugins.growlee.password.value
37                 p = GrowlNotificationPacket(*args, **kwargs)
38                 payload = p.payload()
39
40                 self.transport.write(payload, self.addr)
41
42         def datagramReceived(self, data, addr):
43                 if not config.plugins.growlee.enable_incoming.value:
44                         return
45
46                 Len = len(data)
47                 if Len < 16:
48                         return
49
50                 # ver == GROWL_PROTOCOL_VERSION
51                 if data[0] != '\x01':
52                         return
53
54                 # type == GROWL_TYPE_NOTIFICATION
55                 if data[1] == '\x01':
56                         digest = data[-16:]
57                         password = config.plugins.growlee.password.value
58                         checksum = md5_constructor()
59                         checksum.update(data[:-16])
60                         if password:
61                                 checksum.update(password)
62                         if digest != checksum.digest():
63                                 return
64
65                         nlen, tlen, dlen, alen = unpack("!HHHH",str(data[4:12]))
66                         notification, title, description = unpack("%ds%ds%ds" % (nlen, tlen, dlen), data[12:Len-alen-16])
67                 # type == GROWL_TYPE_NOTIFICATION_NOAUTH
68                 elif data[1] == '\x05':
69                         nlen, tlen, dlen, alen = unpack("!HHHH",str(data[4:12]))
70                         notification, title, description = unpack("%ds%ds%ds" % (nlen, tlen, dlen), data[12:Len-alen])
71                 else:
72                         # don't handle any other packet yet
73                         return
74
75                 Notifications.AddNotificationWithID(
76                         NOTIFICATIONID,
77                         MessageBox,
78                         text = title + '\n' + description,
79                         type = MessageBox.TYPE_INFO,
80                         timeout = 5,
81                         close_on_any_key = True,
82                 )
83
84 class GrowlTalkAbstraction:
85         def __init__(self):
86                 self.growltalk = GrowlTalk()
87                 self.serverPort = reactor.listenUDP(GROWL_UDP_PORT, self.growltalk)
88
89         def sendNotification(self, *args, **kwargs):
90                 # map timeout -> sticky
91                 if "timeout" in kwargs:
92                         if kwargs["timeout"] == -1:
93                                 kwargs["sticky"] = True
94                         del kwargs["timeout"]
95
96                 self.growltalk.sendNotification(*args, **kwargs)
97
98         def stop(self):
99                 return self.serverPort.stopListening()
100