diff --git a/plugins/events_dump/plugin.py b/plugins/events_dump/plugin.py index 44cf46348..055af8772 100644 --- a/plugins/events_dump/plugin.py +++ b/plugins/events_dump/plugin.py @@ -51,7 +51,37 @@ class EventsDumpPlugin(GajimPlugin): 'Subscribe', 'Subscribed', 'Unsubscribed', 'NewAccount', 'VcardInfo', 'LastStatusTime', 'OsInfo', 'GCPresence', 'GCMessage', 'RosterInfo', - 'NewGmail'] + 'NewGmail','ROSTER', 'WARNING', 'ERROR', + 'INFORMATION', 'ERROR_ANSWER', 'STATUS', + 'NOTIFY', 'MSGERROR', 'MSGSENT', 'MSGNOTSENT', + 'SUBSCRIBED', 'UNSUBSCRIBED', 'SUBSCRIBE', + 'AGENT_ERROR_INFO', 'AGENT_ERROR_ITEMS', + 'AGENT_REMOVED', 'REGISTER_AGENT_INFO', + 'AGENT_INFO_ITEMS', 'AGENT_INFO_INFO', + 'QUIT', 'NEW_ACC_CONNECTED', + 'NEW_ACC_NOT_CONNECTED', 'ACC_OK', 'ACC_NOT_OK', + 'MYVCARD', 'VCARD', 'LAST_STATUS_TIME', 'OS_INFO', + 'GC_NOTIFY', 'GC_MSG', 'GC_SUBJECT', 'GC_CONFIG', + 'GC_CONFIG_CHANGE', 'GC_INVITATION', + 'GC_AFFILIATION', 'GC_PASSWORD_REQUIRED', + 'BAD_PASSPHRASE', 'ROSTER_INFO', 'BOOKMARKS', + 'CON_TYPE', 'CONNECTION_LOST', 'FILE_REQUEST', + 'GMAIL_NOTIFY', 'FILE_REQUEST_ERROR', + 'FILE_SEND_ERROR', 'STANZA_ARRIVED', 'STANZA_SENT', + 'HTTP_AUTH', 'VCARD_PUBLISHED', + 'VCARD_NOT_PUBLISHED', 'ASK_NEW_NICK', 'SIGNED_IN', + 'METACONTACTS', 'ATOM_ENTRY', 'FAILED_DECRYPT', + 'PRIVACY_LISTS_RECEIVED', 'PRIVACY_LIST_RECEIVED', + 'PRIVACY_LISTS_ACTIVE_DEFAULT', + 'PRIVACY_LIST_REMOVED', 'ZC_NAME_CONFLICT', + 'PING_SENT', 'PING_REPLY', 'PING_ERROR', + 'SEARCH_FORM', 'SEARCH_RESULT', + 'RESOURCE_CONFLICT', 'PEP_CONFIG', + 'UNIQUE_ROOM_ID_UNSUPPORTED', + 'UNIQUE_ROOM_ID_SUPPORTED', 'SESSION_NEG', + 'GPG_PASSWORD_REQUIRED', 'SSL_ERROR', + 'FINGERPRINT_ERROR', 'PLAIN_CONNECTION', + 'PUBSUB_NODE_REMOVED', 'PUBSUB_NODE_NOT_REMOVED'] self.events_handlers = {} self._set_handling_methods() @@ -75,6 +105,6 @@ class EventsDumpPlugin(GajimPlugin): def _generate_handling_method(self, event_name): def handler(self, *args): - print "Event '%s' occured. Arguments: %s"%(event_name, pformat(*args)) + print "Event '%s' occured. Arguments: %s\n\n===\n"%(event_name, pformat(*args)) return handler \ No newline at end of file diff --git a/plugins/snarl_notifications/PySnarl.py b/plugins/snarl_notifications/PySnarl.py new file mode 100755 index 000000000..f75ccd5c1 --- /dev/null +++ b/plugins/snarl_notifications/PySnarl.py @@ -0,0 +1,772 @@ +""" +A python version of the main functions to use Snarl +(http://www.fullphat.net/snarl) + +Version 1.0 + +This module can be used in two ways. One is the normal way +the other snarl interfaces work. This means you can call snShowMessage +and get an ID back for manipulations. + +The other way is there is a class this module exposes called SnarlMessage. +This allows you to keep track of the message as a python object. If you +use the send without specifying False as the argument it will set the ID +to what the return of the last SendMessage was. This is of course only +useful for the SHOW message. + +Requires one of: + pywin32 extensions from http://pywin32.sourceforge.net + ctypes (included in Python 2.5, downloadable for earlier versions) + +Creator: Sam Listopad II (samlii@users.sourceforge.net) + +Copyright 2006-2008 Samuel Listopad II + +Licensed under the Apache License, Version 2.0 (the "License"); you may not +use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required +by applicable law or agreed to in writing, software distributed under the +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +OF ANY KIND, either express or implied. See the License for the specific +language governing permissions and limitations under the License. +""" + +import array, struct + +def LOWORD(dword): + """Return the low WORD of the passed in integer""" + return dword & 0x0000ffff +#get the hi word +def HIWORD(dword): + """Return the high WORD of the passed in integer""" + return dword >> 16 + +class Win32FuncException(Exception): + def __init__(self, value): + self.value = value + + def __str__(self): + return repr(self.value) + +class Win32Funcs: + """Just a little class to hide the details of finding and using the +correct win32 functions. The functions may throw a UnicodeEncodeError if +there is not a unicode version and it is sent a unicode string that cannot +be converted to ASCII.""" + WM_USER = 0x400 + WM_COPYDATA = 0x4a + #Type of String the functions are expecting. + #Used like function(myWin32Funcs.strType(param)). + __strType = str + #FindWindow function to use + __FindWindow = None + #FindWindow function to use + __FindWindowEx = None + #SendMessage function to use + __SendMessage = None + #SendMessageTimeout function to use + __SendMessageTimeout = None + #IsWindow function to use + __IsWindow = None + #RegisterWindowMessage to use + __RegisterWindowMessage = None + #GetWindowText to use + __GetWindowText = None + + def FindWindow(self, lpClassName, lpWindowName): + """Wraps the windows API call of FindWindow""" + if lpClassName is not None: + lpClassName = self.__strType(lpClassName) + if lpWindowName is not None: + lpWindowName = self.__strType(lpWindowName) + return self.__FindWindow(lpClassName, lpWindowName) + + def FindWindowEx(self, hwndParent, hwndChildAfter, lpClassName, lpWindowName): + """Wraps the windows API call of FindWindow""" + if lpClassName is not None: + lpClassName = self.__strType(lpClassName) + if lpWindowName is not None: + lpWindowName = self.__strType(lpWindowName) + return self.__FindWindowEx(hwndParent, hwndChildAfter, lpClassName, lpWindowName) + + def SendMessage(self, hWnd, Msg, wParam, lParam): + """Wraps the windows API call of SendMessage""" + return self.__SendMessage(hWnd, Msg, wParam, lParam) + + def SendMessageTimeout(self, hWnd, Msg, + wParam, lParam, fuFlags, + uTimeout, lpdwResult = None): + """Wraps the windows API call of SendMessageTimeout""" + idToRet = None + try: + idFromMsg = array.array('I', [0]) + result = idFromMsg.buffer_info()[0] + response = self.__SendMessageTimeout(hWnd, Msg, wParam, + lParam, fuFlags, + uTimeout, result) + if response == 0: + raise Win32FuncException, "SendMessageTimeout TimedOut" + + idToRet = idFromMsg[0] + except TypeError: + idToRet = self.__SendMessageTimeout(hWnd, Msg, wParam, + lParam, fuFlags, + uTimeout) + + if lpdwResult is not None and lpdwResult.typecode == 'I': + lpdwResult[0] = idToRet + + return idToRet + + def IsWindow(self, hWnd): + """Wraps the windows API call of IsWindow""" + return self.__IsWindow(hWnd) + + def RegisterWindowMessage(self, lpString): + """Wraps the windows API call of RegisterWindowMessage""" + return self.__RegisterWindowMessage(self.__strType(lpString)) + + def GetWindowText(self, hWnd, lpString = None, nMaxCount = None): + """Wraps the windows API call of SendMessageTimeout""" + text = '' + if hWnd == 0: + return text + + if nMaxCount is None: + nMaxCount = 1025 + + try: + arrayType = 'c' + if self.__strType == unicode: + arrayType = 'u' + path_string = array.array(arrayType, self.__strType('\x00') * nMaxCount) + path_buffer = path_string.buffer_info()[0] + result = self.__GetWindowText(hWnd, + path_buffer, + nMaxCount) + if result > 0: + if self.__strType == unicode: + text = path_string[0:result].tounicode() + else: + text = path_string[0:result].tostring() + except TypeError: + text = self.__GetWindowText(hWnd) + + if lpString is not None and lpString.typecode == 'c': + lpdwResult[0:len(text)] = array.array('c',str(text)); + + if lpString is not None and lpString.typecode == 'u': + lpdwResult[0:len(text)] = array.array('u',unicode(text)); + + return text + + def __init__(self): + """Load up my needed functions""" + # First see if they already have win32gui imported. If so use it. + # This has to be checked first since the auto check looks for ctypes + # first. + try: + self.__FindWindow = win32gui.FindWindow + self.__FindWindowEx = win32gui.FindWindowEx + self.__GetWindowText = win32gui.GetWindowText + self.__IsWindow = win32gui.IsWindow + self.__SendMessage = win32gui.SendMessage + self.__SendMessageTimeout = win32gui.SendMessageTimeout + self.__RegisterWindowMessage = win32gui.RegisterWindowMessage + self.__strType = unicode + + #Something threw a NameError, most likely the win32gui lines + #so do auto check + except NameError: + try: + from ctypes import windll + self.__FindWindow = windll.user32.FindWindowW + self.__FindWindowEx = windll.user32.FindWindowExW + self.__GetWindowText = windll.user32.GetWindowTextW + self.__IsWindow = windll.user32.IsWindow + self.__SendMessage = windll.user32.SendMessageW + self.__SendMessageTimeout = windll.user32.SendMessageTimeoutW + self.__RegisterWindowMessage = windll.user32.RegisterWindowMessageW + self.__strType = unicode + + #FindWindowW wasn't found, look for FindWindowA + except AttributeError: + try: + self.__FindWindow = windll.user32.FindWindowA + self.__FindWindowEx = windll.user32.FindWindowExA + self.__GetWindowText = windll.user32.GetWindowTextA + self.__IsWindow = windll.user32.IsWindow + self.__SendMessage = windll.user32.SendMessageA + self.__SendMessageTimeout = windll.user32.SendMessageTimeoutA + self.__RegisterWindowMessage = windll.user32.RegisterWindowMessageA + # Couldn't find either so Die and tell user why. + except AttributeError: + import sys + sys.stderr.write("Your Windows TM setup seems to be corrupt."+ + " No FindWindow found in user32.\n") + sys.stderr.flush() + sys.exit(3) + + except ImportError: + try: + import win32gui + self.__FindWindow = win32gui.FindWindow + self.__FindWindowEx = win32gui.FindWindowEx + self.__GetWindowText = win32gui.GetWindowText + self.__IsWindow = win32gui.IsWindow + self.__SendMessage = win32gui.SendMessage + self.__SendMessageTimeout = win32gui.SendMessageTimeout + self.__RegisterWindowMessage = win32gui.RegisterWindowMessage + self.__strType = unicode + + except ImportError: + import sys + sys.stderr.write("You need to have either"+ + " ctypes or pywin32 installed.\n") + sys.stderr.flush() + sys.exit(2) + + +myWin32Funcs = Win32Funcs() + + +SHOW = 1 +HIDE = 2 +UPDATE = 3 +IS_VISIBLE = 4 +GET_VERSION = 5 +REGISTER_CONFIG_WINDOW = 6 +REVOKE_CONFIG_WINDOW = 7 +REGISTER_ALERT = 8 +REVOKE_ALERT = 9 +REGISTER_CONFIG_WINDOW_2 = 10 +GET_VERSION_EX = 11 +SET_TIMEOUT = 12 + +EX_SHOW = 32 + +GLOBAL_MESSAGE = "SnarlGlobalMessage" +GLOBAL_MSG = "SnarlGlobalEvent" + +#Messages That may be received from Snarl +SNARL_LAUNCHED = 1 +SNARL_QUIT = 2 +SNARL_ASK_APPLET_VER = 3 +SNARL_SHOW_APP_UI = 4 + +SNARL_NOTIFICATION_CLICKED = 32 #notification was right-clicked by user +SNARL_NOTIFICATION_CANCELLED = SNARL_NOTIFICATION_CLICKED #Name clarified +SNARL_NOTIFICATION_TIMED_OUT = 33 +SNARL_NOTIFICATION_ACK = 34 #notification was left-clicked by user + +#Snarl Test Message +WM_SNARLTEST = myWin32Funcs.WM_USER + 237 + +M_ABORTED = 0x80000007L +M_ACCESS_DENIED = 0x80000009L +M_ALREADY_EXISTS = 0x8000000CL +M_BAD_HANDLE = 0x80000006L +M_BAD_POINTER = 0x80000005L +M_FAILED = 0x80000008L +M_INVALID_ARGS = 0x80000003L +M_NO_INTERFACE = 0x80000004L +M_NOT_FOUND = 0x8000000BL +M_NOT_IMPLEMENTED = 0x80000001L +M_OK = 0x00000000L +M_OUT_OF_MEMORY = 0x80000002L +M_TIMED_OUT = 0x8000000AL + +ErrorCodeRev = { + 0x80000007L : "M_ABORTED", + 0x80000009L : "M_ACCESS_DENIED", + 0x8000000CL : "M_ALREADY_EXISTS", + 0x80000006L : "M_BAD_HANDLE", + 0x80000005L : "M_BAD_POINTER", + 0x80000008L : "M_FAILED", + 0x80000003L : "M_INVALID_ARGS", + 0x80000004L : "M_NO_INTERFACE", + 0x8000000BL : "M_NOT_FOUND", + 0x80000001L : "M_NOT_IMPLEMENTED", + 0x00000000L : "M_OK", + 0x80000002L : "M_OUT_OF_MEMORY", + 0x8000000AL : "M_TIMED_OUT" + } + +class SnarlMessage(object): + """The main Snarl interface object. + + ID = Snarl Message ID for most operations. See SDK for more info + as to other values to put here. + type = Snarl Message Type. Valid values are : SHOW, HIDE, UPDATE, + IS_VISIBLE, GET_VERSION, REGISTER_CONFIG_WINDOW, REVOKE_CONFIG_WINDOW + all which are constants in the PySnarl module. + timeout = Timeout in seconds for the Snarl Message + data = Snarl Message data. This is dependant upon message type. See SDK + title = Snarl Message title. + text = Snarl Message text. + icon = Path to the icon to display in the Snarl Message. + """ + __msgType = 0 + __msgID = 0 + __msgTimeout = 0 + __msgData = 0 + __msgTitle = "" + __msgText = "" + __msgIcon = "" + __msgClass = "" + __msgExtra = "" + __msgExtra2 = "" + __msgRsvd1 = 0 + __msgRsvd2 = 0 + __msgHWnd = 0 + + lastKnownHWnd = 0 + + def getType(self): + """Type Attribute getter.""" + return self.__msgType + def setType(self, value): + """Type Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgType = value + type = property(getType, setType, doc="The Snarl Message Type") + + def getID(self): + """ID Attribute getter.""" + return self.__msgID + def setID(self, value): + """ID Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgID = value + ID = property(getID, setID, doc="The Snarl Message ID") + + def getTimeout(self): + """Timeout Attribute getter.""" + return self.__msgTimeout + def updateTimeout(self, value): + """Timeout Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgTimeout = value + timeout = property(getTimeout, updateTimeout, + doc="The Snarl Message Timeout") + + def getData(self): + """Data Attribute getter.""" + return self.__msgData + def setData(self, value): + """Data Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgData = value + data = property(getData, setData, doc="The Snarl Message Data") + + def getTitle(self): + """Title Attribute getter.""" + return self.__msgTitle + def setTitle(self, value): + """Title Attribute setter.""" + if( isinstance(value, basestring) ): + self.__msgTitle = value + title = property(getTitle, setTitle, doc="The Snarl Message Title") + + def getText(self): + """Text Attribute getter.""" + return self.__msgText + def setText(self, value): + """Text Attribute setter.""" + if( isinstance(value, basestring) ): + self.__msgText = value + text = property(getText, setText, doc="The Snarl Message Text") + + def getIcon(self): + """Icon Attribute getter.""" + return self.__msgIcon + def setIcon(self, value): + """Icon Attribute setter.""" + if( isinstance(value, basestring) ): + self.__msgIcon = value + icon = property(getIcon, setIcon, doc="The Snarl Message Icon") + + def getClass(self): + """Class Attribute getter.""" + return self.__msgClass + def setClass(self, value): + """Class Attribute setter.""" + if( isinstance(value, basestring) ): + self.__msgClass = value + msgclass = property(getClass, setClass, doc="The Snarl Message Class") + + def getExtra(self): + """Extra Attribute getter.""" + return self.__msgExtra + def setExtra(self, value): + """Extra Attribute setter.""" + if( isinstance(value, basestring) ): + self.__msgExtra = value + extra = property(getExtra, setExtra, doc="Extra Info for the Snarl Message") + + def getExtra2(self): + """Extra2 Attribute getter.""" + return self.__msgExtra2 + def setExtra2(self, value): + """Extra2 Attribute setter.""" + if( isinstance(value, basestring) ): + self.__msgExtra2 = value + extra2 = property(getExtra2, setExtra2, + doc="More Extra Info for the Snarl Message") + + def getRsvd1(self): + """Rsvd1 Attribute getter.""" + return self.__msgRsvd1 + def setRsvd1(self, value): + """Rsvd1 Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgRsvd1 = value + rsvd1 = property(getRsvd1, setRsvd1, doc="The Snarl Message Field Rsvd1") + + def getRsvd2(self): + """Rsvd2 Attribute getter.""" + return self.__msgRsvd2 + def setRsvd2(self, value): + """Rsvd2 Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgRsvd2 = value + rsvd2 = property(getRsvd2, setRsvd2, doc="The Snarl Message Field Rsvd2") + + def getHwnd(self): + """hWnd Attribute getter.""" + return self.__msgHWnd + def setHwnd(self, value): + """hWnd Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgHWnd = value + + hWnd = property(getHwnd, setHwnd, doc="The hWnd of the window this message is being sent from") + + + def __init__(self, title="", text="", icon="", msg_type=1, msg_id=0): + self.__msgTimeout = 0 + self.__msgData = 0 + self.__msgClass = "" + self.__msgExtra = "" + self.__msgExtra2 = "" + self.__msgRsvd1 = 0 + self.__msgRsvd2 = 0 + self.__msgType = msg_type + self.__msgText = text + self.__msgTitle = title + self.__msgIcon = icon + self.__msgID = msg_id + + def createCopyStruct(self): + """Creates the struct to send as the copyData in the message.""" + return struct.pack("ILLL1024s1024s1024s1024s1024s1024sLL", + self.__msgType, + self.__msgID, + self.__msgTimeout, + self.__msgData, + self.__msgTitle.encode('utf-8'), + self.__msgText.encode('utf-8'), + self.__msgIcon.encode('utf-8'), + self.__msgClass.encode('utf-8'), + self.__msgExtra.encode('utf-8'), + self.__msgExtra2.encode('utf-8'), + self.__msgRsvd1, + self.__msgRsvd2 + ) + __lpData = None + __cds = None + + def packData(self, dwData): + """This packs the data in the necessary format for a +WM_COPYDATA message.""" + self.__lpData = None + self.__cds = None + item = self.createCopyStruct() + self.__lpData = array.array('c', item) + lpData_ad = self.__lpData.buffer_info()[0] + cbData = self.__lpData.buffer_info()[1] + self.__cds = array.array('c', + struct.pack("IIP", + dwData, + cbData, + lpData_ad) + ) + cds_ad = self.__cds.buffer_info()[0] + return cds_ad + + def reset(self): + """Reset this SnarlMessage to the default state.""" + self.__msgType = 0 + self.__msgID = 0 + self.__msgTimeout = 0 + self.__msgData = 0 + self.__msgTitle = "" + self.__msgText = "" + self.__msgIcon = "" + self.__msgClass = "" + self.__msgExtra = "" + self.__msgExtra2 = "" + self.__msgRsvd1 = 0 + self.__msgRsvd2 = 0 + + + def send(self, setid=True): + """Send this SnarlMessage to the Snarl window. +Args: + setid - Boolean defining whether or not to set the ID + of this SnarlMessage to the return value of + the SendMessage call. Default is True to + make simple case of SHOW easy. + """ + hwnd = myWin32Funcs.FindWindow(None, "Snarl") + if myWin32Funcs.IsWindow(hwnd): + if self.type == REGISTER_CONFIG_WINDOW or self.type == REGISTER_CONFIG_WINDOW_2: + self.hWnd = self.data + try: + response = myWin32Funcs.SendMessageTimeout(hwnd, + myWin32Funcs.WM_COPYDATA, + self.hWnd, self.packData(2), + 2, 500) + except Win32FuncException: + return False + + idFromMsg = response + if setid: + self.ID = idFromMsg + return True + else: + return idFromMsg + print "No snarl window found" + return False + + def hide(self): + """Hide this message. Type will revert to type before calling hide +to allow for better reuse of object.""" + oldType = self.__msgType + self.__msgType = HIDE + retVal = bool(self.send(False)) + self.__msgType = oldType + return retVal + + def isVisible(self): + """Is this message visible. Type will revert to type before calling +hide to allow for better reuse of object.""" + oldType = self.__msgType + self.__msgType = IS_VISIBLE + retVal = bool(self.send(False)) + self.__msgType = oldType + return retVal + + def update(self, title=None, text=None, icon=None): + """Update this message with given title and text. Type will revert +to type before calling hide to allow for better reuse of object.""" + oldType = self.__msgType + self.__msgType = UPDATE + if text: + self.__msgText = text + if title: + self.__msgTitle = title + if icon: + self.__msgIcon = icon + retVal = self.send(False) + self.__msgType = oldType + return retVal + + def setTimeout(self, timeout): + """Set the timeout in seconds of the message""" + oldType = self.__msgType + oldData = self.__msgData + self.__msgType = SET_TIMEOUT + #self.timeout = timeout + #self.__msgData = self.__msgTimeout + self.__msgData = timeout + retVal = self.send(False) + self.__msgType = oldType + self.__msgData = oldData + return retVal + + def show(self, timeout=None, title=None, + text=None, icon=None, + replyWindow=None, replyMsg=None, msgclass=None, soundPath=None): + """Show a message""" + oldType = self.__msgType + oldTimeout = self.__msgTimeout + self.__msgType = SHOW + if text: + self.__msgText = text + if title: + self.__msgTitle = title + if timeout: + self.__msgTimeout = timeout + if icon: + self.__msgIcon = icon + if replyWindow: + self.__msgID = replyMsg + if replyMsg: + self.__msgData = replyWindow + if soundPath: + self.__msgExtra = soundPath + if msgclass: + self.__msgClass = msgclass + + if ((self.__msgClass and self.__msgClass != "") or + (self.__msgExtra and self.__msgExtra != "")): + self.__msgType = EX_SHOW + + + retVal = bool(self.send()) + self.__msgType = oldType + self.__msgTimeout = oldTimeout + return retVal + + +def snGetVersion(): + """ Get the version of Snarl that is running as a tuple. (Major, Minor) + +If Snarl is not running or there was an error it will +return False.""" + msg = SnarlMessage(msg_type=GET_VERSION) + version = msg.send(False) + if not version: + return False + return (HIWORD(version), LOWORD(version)) + +def snGetVersionEx(): + """ Get the internal version of Snarl that is running. + +If Snarl is not running or there was an error it will +return False.""" + sm = SnarlMessage(msg_type=GET_VERSION_EX) + verNum = sm.send(False) + if not verNum: + return False + return verNum + +def snGetGlobalMessage(): + """Get the Snarl global message id from windows.""" + return myWin32Funcs.RegisterWindowMessage(GLOBAL_MSG) + +def snShowMessage(title, text, timeout=0, iconPath="", + replyWindow=0, replyMsg=0): + """Show a message using Snarl and return its ID. See SDK for arguments.""" + sm = SnarlMessage( title, text, iconPath, msg_id=replyMsg) + sm.data = replyWindow + if sm.show(timeout): + return sm.ID + else: + return False + +def snShowMessageEx(msgClass, title, text, timeout=0, iconPath="", + replyWindow=0, replyMsg=0, soundFile=None, hWndFrom=None): + """Show a message using Snarl and return its ID. See SDK for arguments. + One added argument is hWndFrom that allows one to make the messages appear + to come from a specific window. This window should be the one you registered + earlier with RegisterConfig""" + sm = SnarlMessage( title, text, iconPath, msg_id=replyMsg) + sm.data = replyWindow + if hWndFrom is not None: + sm.hWnd = hWndFrom + else: + sm.hWnd = SnarlMessage.lastKnownHWnd + if sm.show(timeout, msgclass=msgClass, soundPath=soundFile): + return sm.ID + else: + return False + +def snUpdateMessage(msgId, msgTitle, msgText, icon=None): + """Update a message""" + sm = SnarlMessage(msg_id=msgId) + if icon: + sm.icon = icon + return sm.update(msgTitle, msgText) + +def snHideMessage(msgId): + """Hide a message""" + return SnarlMessage(msg_id=msgId).hide() + +def snSetTimeout(msgId, timeout): + """Update the timeout of a message already shown.""" + sm = SnarlMessage(msg_id=msgId) + return sm.setTimeout(timeout) + +def snIsMessageVisible(msgId): + """Returns True if the message is visible False otherwise.""" + return SnarlMessage(msg_id=msgId).isVisible() + +def snRegisterConfig(replyWnd, appName, replyMsg): + """Register a config window. See SDK for more info.""" + global lastRegisteredSnarlMsg + sm = SnarlMessage(msg_type=REGISTER_CONFIG_WINDOW, + title=appName, + msg_id=replyMsg) + sm.data = replyWnd + SnarlMessage.lastKnownHWnd = replyWnd + + return sm.send(False) + +def snRegisterConfig2(replyWnd, appName, replyMsg, icon): + """Register a config window. See SDK for more info.""" + global lastRegisteredSnarlMsg + sm = SnarlMessage(msg_type=REGISTER_CONFIG_WINDOW_2, + title=appName, + msg_id=replyMsg, + icon=icon) + sm.data = replyWnd + SnarlMessage.lastKnownHWnd = replyWnd + return sm.send(False) + +def snRegisterAlert(appName, classStr) : + """Register an alert for an already registered config. See SDK for more info.""" + sm = SnarlMessage(msg_type=REGISTER_ALERT, + title=appName, + text=classStr) + return sm.send(False) + +def snRevokeConfig(replyWnd): + """Revoke a config window""" + sm = SnarlMessage(msg_type=REVOKE_CONFIG_WINDOW) + sm.data = replyWnd + if replyWnd == SnarlMessage.lastKnownHWnd: + SnarlMessage.lastKnownHWnd = 0 + return sm.send(False) + +def snGetSnarlWindow(): + """Returns the hWnd of the snarl window""" + return myWin32Funcs.FindWindow(None, "Snarl") + +def snGetAppPath(): + """Returns the application path of the currently running snarl window""" + app_path = None + snarl_handle = snGetSnarlWindow() + if snarl_handle != 0: + pathwin_handle = myWin32Funcs.FindWindowEx(snarl_handle, + 0, + "static", + None) + if pathwin_handle != 0: + try: + result = myWin32Funcs.GetWindowText(pathwin_handle) + app_path = result + except Win32FuncException: + pass + + + return app_path + +def snGetIconsPath(): + """Returns the path to the icons of the program""" + s = snGetAppPath() + if s is None: + return "" + else: + return s + "etc\\icons\\" + +def snSendTestMessage(data=None): + """Sends a test message to Snarl. Used to make sure the +api is connecting""" + param = 0 + command = 0 + if data: + param = struct.pack("I", data) + command = 1 + myWin32Funcs.SendMessage(snGetSnarlWindow(), WM_SNARLTEST, command, param) diff --git a/plugins/snarl_notifications/__init__.py b/plugins/snarl_notifications/__init__.py new file mode 100644 index 000000000..ad9c96aaa --- /dev/null +++ b/plugins/snarl_notifications/__init__.py @@ -0,0 +1 @@ +from plugin import SnarlNotificationsPlugin \ No newline at end of file diff --git a/plugins/snarl_notifications/plugin.py b/plugins/snarl_notifications/plugin.py new file mode 100644 index 000000000..e6ef5ae18 --- /dev/null +++ b/plugins/snarl_notifications/plugin.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +## +## This file is part of Gajim. +## +## Gajim is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 3 only. +## +## Gajim is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Gajim. If not, see . +## +''' +Events notifications using Snarl + +Fancy events notifications under Windows using Snarl infrastructure. + +:note: plugin is at proof-of-concept state. + +:author: Mateusz Biliński +:since: 15th August 2008 +:copyright: Copyright (2008) Mateusz Biliński +:license: GPL +''' + +import new +from pprint import pformat + +import PySnarl + +from common import gajim +from plugins import GajimPlugin +from plugins.helpers import log_calls, log +from common import ged + +class SnarlNotificationsPlugin(GajimPlugin): + name = u'Snarl Notifications' + short_name = u'snarl_notifications' + version = u'0.1' + description = u'''Shows events notification using Snarl (http://www.fullphat.net/) under Windows. Snarl needs to be installed in system. +PySnarl bindings are used (http://code.google.com/p/pysnarl/).''' + authors = [u'Mateusz Biliński '] + homepage = u'http://blog.bilinski.it' + + @log_calls('SnarlNotificationsPlugin') + def init(self): + self.config_dialog = None + #self.gui_extension_points = {} + #self.config_default_values = {} + + self.events_handlers = {'NewMessage' : (ged.POSTCORE, self.newMessage)} + + def activate(self): + pass + + def deactivate(self): + pass + + def newMessage(self, args): + event_name = "NewMessage" + data = args[0] + account = data[0] + jid = data[1][0] + jid_without_resource = gajim.get_jid_without_resource(jid) + msg = data[1][1] + msg_type = data[1][4] + if msg_type == 'chat': + nickname = gajim.get_contact_name_from_jid(account, + jid_without_resource) + elif msg_type == 'pm': + nickname = gajim.get_resource_from_jid(jid) + + print "Event '%s' occured. Arguments: %s\n\n===\n"%(event_name, pformat(*args)) + print "Event '%s' occured. Arguments: \naccount = %s\njid = %s\nmsg = %s\nnickname = %s"%( + event_name, account, jid, msg, nickname) + + + if PySnarl.snGetVersion() != False: + (major, minor) = PySnarl.snGetVersion() + print "Found Snarl version",str(major)+"."+str(minor),"running." + PySnarl.snShowMessage(nickname, msg[:20]+'...') + else: + print "Sorry Snarl does not appear to be running" + \ No newline at end of file diff --git a/src/common/connection.py b/src/common/connection.py index e9ffba607..c5cc190a2 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -168,12 +168,14 @@ class Connection(ConnectionHandlers): # END __init__ def put_event(self, ev): + if gajim.handlers.has_key(ev[0]): gajim.handlers[ev[0]](self.name, ev[1]) def dispatch(self, event, data): '''always passes account name as first param''' self.put_event((event, data)) + gajim.ged.raise_event(event, data) def _reconnect(self):