import sys import array import struct import win32gui import win32con import win32api import ctypes SCA_ATTACH_NOT_CONNECTED = -1 SCA_ATTACH_SUCCESS = 0 SCA_ATTACH_PENDING_AUTHORIZATION = 1 SCA_ATTACH_REFUSED = 2 SCA_ATTACH_NOT_AVAILABLE = 3 SCA_ATTACH_API_AVAILABLE = 0x8001 class _CopyData(ctypes.Structure): _fields_ = [("dwData", ctypes.c_void_p), ("cbData", ctypes.c_ulong), ("lpData", ctypes.c_char_p)] class SimpleSkypeHandler: """ Simple Skype callback handler. This handler is print out message to stander output from SKype. """ def __getattr__(self, name): """ Create every callback function from Skype, dynamically. The created function is simply ouput the skype message to standerd ouput. """ if name.startswith("do_"): def func(*args): n = name print "skype ---> %s %s" % (name, " ".join(args)) return func return None class SkypeError(Exception): """ Skype Error class """ pass class SkypeNotConnectedError(SkypeError): pass class SkypeNotAuthorizationError(SkypeError): pass class SkypeRefusedError(SkypeError): pass class SkypeRawServer: """ Skype API wrapper class. If you want to send Skype API to Skype, try the following code. :: import skypeserver import win32gui skype = skypeserver.SkypeRawServer(skypeserver.SimpleSkypeHandler) skype.connect() # run Win32 message loop. win32gui.PumpMessages() The message to skpe is start with 'skype_'. For example, you want to search friends, :: obj.skype_SEARCH_FRIENDS() The whole example is like this:: def mythread(sapi): import time #wait for starting the message loop. time.sleep(3) sapi.skype_SEARCH_FRIENDS() sapi.skype_ import thread import win32gui import skypeserver win32gui.InitCommonControls() sapi = skypeserver.SkypeRawServer() thread.start_new_thread(mythread, (sapi,)) win32gui.PumpMessages() """ def __init__(self, handler = SimpleSkypeHandler()): """ Constructor of SkypeRawServer handler is callback handler from Skype. When we get the message from Skype, The do_xxx method is called from SkypeRawSever. The xxx is the Skype message's first word. If the skype send us 'USERS username1, username2', do_USERS methon in handler is called. For Example, you call the following:: sapi.skype_SEARCH_FRIENDS() Then the following method in your handler is called. :: def do_USERS(self, *args): # args must be array of users print args """ hInst = win32api.GetModuleHandle(None) self._status = SCA_ATTACH_NOT_CONNECTED self._handler = handler api_attach = win32gui.RegisterWindowMessage("SkypeControlAPIAttach"); self.api_discover = api_discover = win32gui.RegisterWindowMessage("SkypeControlAPIDiscover"); wc = win32gui.WNDCLASS() wc.hInstance = hInst wc.lpfnWndProc = { api_attach: self._attached, api_discover: self._discovered, win32con.WM_CREATE: self._created, win32con.WM_COPYDATA: self._copydata} wc.lpszClassName = className = "SkypePythonHandler" rc = win32gui.RegisterClass(wc) self._win = win32gui.CreateWindow(rc, "SkypePython", 0, 0, 0, 0, 0, 0, 0, hInst, None) def connect(self): """ Connect to skype. """ win32gui.SendMessageTimeout(win32con.HWND_BROADCAST, self.api_discover, self._win, win32con.SMTO_NORMAL, 0, 5*1000) def _created(self, hwnd, message, wparam, lparam): print "created" def _copydata(self, hwnd, message, wparam, lparam): try: cbs = _CopyData.from_address(lparam) s = cbs.lpData # print "skype ---> " + s l = s.split(" ") cmd = l[0].strip(":") args = l[1:] func_name = "do_%s" % (cmd) if hasattr(self._handler, func_name): func = getattr(self._handler, func_name) func(*args) else: print "NO HANDLER for " + func_name except Exception, err: print func_name + ": " + str(err) return 1 def _attached(self, hwnd, message, wparam, lparam): self._status = lparam if lparam == SCA_ATTACH_SUCCESS: self.skypeWin = wparam #self._send("PROTOCOL 6") #self._send("GET CURRENTUSERHANDLE") #self._send("SEARCH FRIENDS") elif lparam == SCA_ATTACH_PENDING_AUTHORIZATION: print "Pending Authorization" elif lparam == SCA_ATTACH_REFUSED: print "Connection is Refused." elif lparam == SCA_ATTACH_NOT_AVAILABLE: print "API is not available" elif lparam == SCA_ATTACH_API_AVAILABLE: print "API is avaialble" else: print "cannot handle attached event" return 1 def _discovered(self, hwnd, message, wparam, lparam): # what is this. pass def _wndProc(self, hwnd, message, wparam, lparam): print message fn = self._msg_map[message] if fn: return fn(hwnd, message, wparam, lparam) return win32gui.DefWindowProc(hwnd, message, wparam, lparam) def _send(self, s): #print "skype <--- " + s if self._status == SCA_ATTACH_NOT_CONNECTED: raise SkypeNotConnectedError() elif self._status == SCA_ATTACH_PENDING_AUTHORIZATION: raise SkypeNotAuthorizationError() elif self._status == SCA_ATTACH_REFUSED: raise SkypeRefusedError() s = s + '\0' int_buf = array.array("L", [0]) char_buf = array.array("c", s) int_buf_addr = int_buf.buffer_info()[0] char_buf_addr, char_buf_size = char_buf.buffer_info() copy_struct = struct.pack("LLL", # dword *, dword, char * int_buf_addr, char_buf_size, char_buf_addr) return win32gui.SendMessage(self.skypeWin, win32con.WM_COPYDATA, self._win, copy_struct) def __getattr__(self, name): def func(*args): command = name.upper() cmd = command.split("_")[1:] return self._send(" ".join(cmd + list(args))) if name.find("skype_") == 0: return func return None