Growl update
This commit is contained in:
+15
-15
@@ -1,8 +1,8 @@
|
|||||||
import re
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import re
|
||||||
import time
|
import time
|
||||||
|
|
||||||
__version__ = '0.5'
|
__version__ = '0.6'
|
||||||
|
|
||||||
#GNTP/<version> <messagetype> <encryptionAlgorithmID>[:<ivValue>][ <keyHashAlgorithmID>:<keyHash>.<salt>]
|
#GNTP/<version> <messagetype> <encryptionAlgorithmID>[:<ivValue>][ <keyHashAlgorithmID>:<keyHash>.<salt>]
|
||||||
GNTP_INFO_LINE = re.compile(
|
GNTP_INFO_LINE = re.compile(
|
||||||
@@ -50,7 +50,7 @@ class _GNTPBase(object):
|
|||||||
:param string version: GNTP Protocol version
|
:param string version: GNTP Protocol version
|
||||||
:param string encription: Encryption protocol
|
:param string encription: Encryption protocol
|
||||||
"""
|
"""
|
||||||
def __init__(self, messagetype=None, version='1.0', encryption=None):
|
def __init__(self, messagetype = None, version = '1.0', encryption = None):
|
||||||
self.info = {
|
self.info = {
|
||||||
'version': version,
|
'version': version,
|
||||||
'messagetype': messagetype,
|
'messagetype': messagetype,
|
||||||
@@ -80,7 +80,7 @@ class _GNTPBase(object):
|
|||||||
|
|
||||||
return info
|
return info
|
||||||
|
|
||||||
def set_password(self, password, encryptAlgo='MD5'):
|
def set_password(self, password, encryptAlgo = 'MD5'):
|
||||||
"""Set a password for a GNTP Message
|
"""Set a password for a GNTP Message
|
||||||
|
|
||||||
:param string password: Null to clear password
|
:param string password: Null to clear password
|
||||||
@@ -217,7 +217,7 @@ class _GNTPBase(object):
|
|||||||
else:
|
else:
|
||||||
self.headers[key] = unicode('%s' % value, 'utf8', 'replace')
|
self.headers[key] = unicode('%s' % value, 'utf8', 'replace')
|
||||||
|
|
||||||
def decode(self, data, password=None):
|
def decode(self, data, password = None):
|
||||||
"""Decode GNTP Message
|
"""Decode GNTP Message
|
||||||
|
|
||||||
:param string data:
|
:param string data:
|
||||||
@@ -256,7 +256,7 @@ class GNTPRegister(_GNTPBase):
|
|||||||
]
|
]
|
||||||
_requiredNotificationHeaders = ['Notification-Name']
|
_requiredNotificationHeaders = ['Notification-Name']
|
||||||
|
|
||||||
def __init__(self, data=None, password=None):
|
def __init__(self, data = None, password = None):
|
||||||
_GNTPBase.__init__(self, 'REGISTER')
|
_GNTPBase.__init__(self, 'REGISTER')
|
||||||
self.notifications = []
|
self.notifications = []
|
||||||
|
|
||||||
@@ -301,7 +301,7 @@ class GNTPRegister(_GNTPBase):
|
|||||||
#open('register.png','wblol').write(notice['Data'])
|
#open('register.png','wblol').write(notice['Data'])
|
||||||
self.resources[notice.get('Identifier')] = notice
|
self.resources[notice.get('Identifier')] = notice
|
||||||
|
|
||||||
def add_notification(self, name, enabled=True):
|
def add_notification(self, name, enabled = True):
|
||||||
"""Add new Notification to Registration message
|
"""Add new Notification to Registration message
|
||||||
|
|
||||||
:param string name: Notification Name
|
:param string name: Notification Name
|
||||||
@@ -352,7 +352,7 @@ class GNTPNotice(_GNTPBase):
|
|||||||
'Notification-Title'
|
'Notification-Title'
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, data=None, app=None, name=None, title=None, password=None):
|
def __init__(self, data = None, app = None, name = None, title = None, password = None):
|
||||||
_GNTPBase.__init__(self, 'NOTIFY')
|
_GNTPBase.__init__(self, 'NOTIFY')
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
@@ -415,7 +415,7 @@ class GNTPSubscribe(_GNTPBase):
|
|||||||
'Subscriber-Name',
|
'Subscriber-Name',
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, data=None, password=None):
|
def __init__(self, data = None, password = None):
|
||||||
_GNTPBase.__init__(self, 'SUBSCRIBE')
|
_GNTPBase.__init__(self, 'SUBSCRIBE')
|
||||||
if data:
|
if data:
|
||||||
self.decode(data, password)
|
self.decode(data, password)
|
||||||
@@ -431,7 +431,7 @@ class GNTPOK(_GNTPBase):
|
|||||||
"""
|
"""
|
||||||
_requiredHeaders = ['Response-Action']
|
_requiredHeaders = ['Response-Action']
|
||||||
|
|
||||||
def __init__(self, data=None, action=None):
|
def __init__(self, data = None, action = None):
|
||||||
_GNTPBase.__init__(self, '-OK')
|
_GNTPBase.__init__(self, '-OK')
|
||||||
if data:
|
if data:
|
||||||
self.decode(data)
|
self.decode(data)
|
||||||
@@ -448,7 +448,7 @@ class GNTPError(_GNTPBase):
|
|||||||
"""
|
"""
|
||||||
_requiredHeaders = ['Error-Code', 'Error-Description']
|
_requiredHeaders = ['Error-Code', 'Error-Description']
|
||||||
|
|
||||||
def __init__(self, data=None, errorcode=None, errordesc=None):
|
def __init__(self, data = None, errorcode = None, errordesc = None):
|
||||||
_GNTPBase.__init__(self, '-ERROR')
|
_GNTPBase.__init__(self, '-ERROR')
|
||||||
if data:
|
if data:
|
||||||
self.decode(data)
|
self.decode(data)
|
||||||
@@ -460,7 +460,7 @@ class GNTPError(_GNTPBase):
|
|||||||
return self.headers['Error-Code'], self.headers['Error-Description']
|
return self.headers['Error-Code'], self.headers['Error-Description']
|
||||||
|
|
||||||
|
|
||||||
def parse_gntp(data, password=None):
|
def parse_gntp(data, password = None):
|
||||||
"""Attempt to parse a message as a GNTP message
|
"""Attempt to parse a message as a GNTP message
|
||||||
|
|
||||||
:param string data: Message to be parsed
|
:param string data: Message to be parsed
|
||||||
@@ -471,11 +471,11 @@ def parse_gntp(data, password=None):
|
|||||||
raise ParseError('INVALID_GNTP_INFO')
|
raise ParseError('INVALID_GNTP_INFO')
|
||||||
info = match.groupdict()
|
info = match.groupdict()
|
||||||
if info['messagetype'] == 'REGISTER':
|
if info['messagetype'] == 'REGISTER':
|
||||||
return GNTPRegister(data, password=password)
|
return GNTPRegister(data, password = password)
|
||||||
elif info['messagetype'] == 'NOTIFY':
|
elif info['messagetype'] == 'NOTIFY':
|
||||||
return GNTPNotice(data, password=password)
|
return GNTPNotice(data, password = password)
|
||||||
elif info['messagetype'] == 'SUBSCRIBE':
|
elif info['messagetype'] == 'SUBSCRIBE':
|
||||||
return GNTPSubscribe(data, password=password)
|
return GNTPSubscribe(data, password = password)
|
||||||
elif info['messagetype'] == '-OK':
|
elif info['messagetype'] == '-OK':
|
||||||
return GNTPOK(data)
|
return GNTPOK(data)
|
||||||
elif info['messagetype'] == '-ERROR':
|
elif info['messagetype'] == '-ERROR':
|
||||||
|
|||||||
+18
-3
@@ -24,12 +24,17 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
def mini(description, applicationName = 'PythonMini', noteType = "Message",
|
def mini(description, applicationName = 'PythonMini', noteType = "Message",
|
||||||
title = "Mini Message", applicationIcon = None, hostname = 'localhost',
|
title = "Mini Message", applicationIcon = None, hostname = 'localhost',
|
||||||
password = None, port = 23053, sticky = False, priority = None):
|
password = None, port = 23053, sticky = False, priority = None,
|
||||||
|
callback = None):
|
||||||
"""Single notification function
|
"""Single notification function
|
||||||
|
|
||||||
Simple notification function in one line. Has only one required parameter
|
Simple notification function in one line. Has only one required parameter
|
||||||
and attempts to use reasonable defaults for everything else
|
and attempts to use reasonable defaults for everything else
|
||||||
:param string description: Notification message
|
:param string description: Notification message
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
For now, only URL callbacks are supported. In the future, the
|
||||||
|
callback argument will also support a function
|
||||||
"""
|
"""
|
||||||
growl = GrowlNotifier(
|
growl = GrowlNotifier(
|
||||||
applicationName = applicationName,
|
applicationName = applicationName,
|
||||||
@@ -50,6 +55,7 @@ def mini(description, applicationName = 'PythonMini', noteType = "Message",
|
|||||||
icon = applicationIcon,
|
icon = applicationIcon,
|
||||||
sticky = sticky,
|
sticky = sticky,
|
||||||
priority = priority,
|
priority = priority,
|
||||||
|
callback = callback,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -66,6 +72,7 @@ class GrowlNotifier(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
passwordHash = 'MD5'
|
passwordHash = 'MD5'
|
||||||
|
socketTimeout = 3
|
||||||
|
|
||||||
def __init__(self, applicationName = 'Python GNTP', notifications = [],
|
def __init__(self, applicationName = 'Python GNTP', notifications = [],
|
||||||
defaultNotifications = None, applicationIcon = None, hostname = 'localhost',
|
defaultNotifications = None, applicationIcon = None, hostname = 'localhost',
|
||||||
@@ -112,7 +119,8 @@ class GrowlNotifier(object):
|
|||||||
self.register_hook(register)
|
self.register_hook(register)
|
||||||
return self._send('register', register)
|
return self._send('register', register)
|
||||||
|
|
||||||
def notify(self, noteType, title, description, icon = None, sticky = False, priority = None):
|
def notify(self, noteType, title, description, icon = None, sticky = False,
|
||||||
|
priority = None, callback = None):
|
||||||
"""Send a GNTP notifications
|
"""Send a GNTP notifications
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
@@ -124,6 +132,11 @@ class GrowlNotifier(object):
|
|||||||
:param string icon: Icon URL path
|
:param string icon: Icon URL path
|
||||||
:param boolean sticky: Sticky notification
|
:param boolean sticky: Sticky notification
|
||||||
:param integer priority: Message priority level from -2 to 2
|
:param integer priority: Message priority level from -2 to 2
|
||||||
|
:param string callback: URL callback
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
For now, only URL callbacks are supported. In the future, the
|
||||||
|
callback argument will also support a function
|
||||||
"""
|
"""
|
||||||
logger.info('Sending notification [%s] to %s:%s', noteType, self.hostname, self.port)
|
logger.info('Sending notification [%s] to %s:%s', noteType, self.hostname, self.port)
|
||||||
assert noteType in self.notifications
|
assert noteType in self.notifications
|
||||||
@@ -141,6 +154,8 @@ class GrowlNotifier(object):
|
|||||||
notice.add_header('Notification-Icon', self._checkIcon(icon))
|
notice.add_header('Notification-Icon', self._checkIcon(icon))
|
||||||
if description:
|
if description:
|
||||||
notice.add_header('Notification-Text', description)
|
notice.add_header('Notification-Text', description)
|
||||||
|
if callback:
|
||||||
|
notice.add_header('Notification-Callback-Target', callback)
|
||||||
|
|
||||||
self.add_origin_info(notice)
|
self.add_origin_info(notice)
|
||||||
self.notify_hook(notice)
|
self.notify_hook(notice)
|
||||||
@@ -186,7 +201,7 @@ class GrowlNotifier(object):
|
|||||||
logger.debug('To : %s:%s <%s>\n%s', self.hostname, self.port, packet.__class__, data)
|
logger.debug('To : %s:%s <%s>\n%s', self.hostname, self.port, packet.__class__, data)
|
||||||
|
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
s.settimeout(3)
|
s.settimeout(self.socketTimeout)
|
||||||
s.connect((self.hostname, self.port))
|
s.connect((self.hostname, self.port))
|
||||||
s.send(data.encode('utf8', 'replace'))
|
s.send(data.encode('utf8', 'replace'))
|
||||||
recv_data = s.recv(1024)
|
recv_data = s.recv(1024)
|
||||||
|
|||||||
Reference in New Issue
Block a user