#! /usr/bin/python import objc as objc objc.loadBundle("SkypeAPI", globals(), bundle_path = objc.pathForFramework(u'/Applications/Skype.app/Contents/Frameworks/Skype.framework')) from PyObjCTools import AppHelper from AppKit import * from Foundation import * # SKYPE_APPLICATION_NAME = 'pyskypebot' SKYPE_APPLICATION_NAME = 'test' class delegate(NSObject): """ delegate class to be registed to setSkypeDelegate_()""" def clientApplicationName(self): return NSString.alloc().initWithString_(SKYPE_APPLICATION_NAME) def skypeAttachResponse_(self): print "accepted" pass def skypeNotificationReceived_(self, aNotificationString = ''): bot = receiver(aNotificationString) bot.start() def skypeBecameAvailable_(self, aNotification = ''): pass def skypeBecameUnavailable_(self, aNotification = ''): pass from threading import Thread class receiver(Thread): def __init__(self, message = False): self.message = message Thread.__init__(self) def run(self): import re if self.message: msg = self.message self.message = False # run registed tasks task_receiver().run(msg) # result of 'CHAT CREATE' # store chat information to SkypeChat class m = re.compile('(#\S+)? ?CHAT (\S+) STATUS (\S+)$').match(msg) if m: cmd_id = m.group(1) chat_id = m.group(2) chat_status = m.group(3) c = chats() c.set(chat_id, 'chat_id', chat_id) c.set(chat_id, 'status', chat_status) c.set(chat_id, 'command_id', cmd_id) # Notification of received message from someone # send command to retrive the object of chat message m = re.compile('(?:CHAT)?MESSAGE (\d+) STATUS RECEIVED').match(msg) message_props = ['timestamp', 'from_handle', 'from_dispname', 'chatname', 'type', 'body', 'users', 'leavereason'] if m: cmd_string = '|'.join(message_props).upper() message_id = int(m.group(1)) pool = NSAutoreleasePool.alloc().init() msg = messages() for p in message_props: res = SkypeAPI.sendSkypeCommand_("GET CHATMESSAGE %d %s" % (message_id, p.upper())) m = re.compile("MESSAGE (\d+) (%s)(.*)$" % p.upper(), re.DOTALL).match(res) message_id = int(m.group(1)) message_type = m.group(2).lower() message_body = m.group(3).lstrip().rstrip() msg.set(message_id, message_type, message_body) del pool s = bot(msg.get(message_id)) s.start() msg.sent(message_id) class bot(Thread): def __init__(self, message): self.message = message Thread.__init__(self) def run(self): task_bot().run(self.message) class task: """ handle threads executed in bot() """ threads = None __lock = False def __init__(self): if task.threads is None: task.threads = {} def add(self, id, thread): self.lock() self.threads[id] = thread self.unlock() def delete(self, id): self.lock() del self.threads[id] self.unlock() def run(self, message): self.lock() for id in self.threads: s = self.threads[id](message) s.start() self.unlock() def lock(self): while task.__lock is True: pass task.__lock = True def unlock(self): task.__lock = False class task_bot(task): __instance = None def __init__(self): if task_bot.__instance is None: task_bot.__instance = self; task_bot.threads = {} class task_receiver(task): __instance = None def __init__(self): if task_receiver.__instance is None: task_receiver.__instance = self; task_receiver.threads = {} class skypeobject(object): def __init__(self): for attr in self.__slots__: setattr(self,attr,None) def __delattr__(self, attr): setattr(self,attr,None) class skypeobjects: m = None def obj(skypeobject): """ should be override in subclass to set __slots__ """ return skypeobject() def set(self, id, attr, value = None): if self.m.has_key(id) is False: self.m[id] = self.obj() if hasattr(self.m[id], 'id'): self.m[id].id = id if hasattr(self.m[id], attr): setattr(self.m[id], attr, value) else: raise AttributeError("object has no attribute '%s'" % (attr)) def get(self, id, attr = None): if attr: return getattr(self.m[id], attr) else: return self.m[id] def delete(self, id, attr = None): if attr: if getattr(self.m[id], attr): delattr(self.m[id], attr) else: del self.m[id] def ready(self, id, attrs = None): if attrs is None: return True; if hasattr(self.m[id],'_sent'): return False for attr in attrs: if not getattr(self.m[id],attr): return False return True def sent(self, id): setattr(self.m[id], '_sent', True) def gc(self, interval = 3600): import time now = time.time() if self.m: for id in self.m: if self.m[id].timestamp < now + 3600: del self.m[id] __instance = None def __init__(self): if skypeobjects.__instance is None: skypeobjects.__instance = self; class messages(skypeobjects): class message(skypeobject): __slots__ = ['id', 'timestamp', 'from_handle', 'from_dispname', 'chatname', 'type', 'body', 'users', 'leavereason', 'status'] def obj(self): return self.message() __instance = None def __init__(self): if messages.__instance is None: messages.__instance = self; messages.m = {} class chats(skypeobjects): class chat(skypeobject): __slots__ = [ 'command_id', 'chat_id', 'name', 'timestamp', 'adder', 'status', 'posters', 'members', 'topic', 'chatmessages', 'activemembers', 'friendlyname' ] def obj(self): return self.chat() __instance = None def __init__(self): if chats.__instance is None: chats.__instance = self; chats.m = {} class sendMessage(Thread): def __init__(self, chat_id, message, timestamp = 0): self.timestamp = timestamp self.chat_id = chat_id self.message = message self.running = False Thread.__init__(self) def run(self): self.running = True import time while self.running is True and self.timestamp > time.time(): time.sleep(5) pool = NSAutoreleasePool.alloc().init() SkypeAPI.sendSkypeCommand_("CHATMESSAGE %s %s" % (self.chat_id, self.message)) del pool def stop(self): self.running = False # def sendCommand(commands) # pool = NSAutoreleasePool.alloc().init() # SkypeAPI.sendSkypeCommand_() # del pool class dump(Thread): def __init__(self, msg): self.message = msg Thread.__init__(self) def run(self): for i in self.message.__slots__: val = getattr(self.message,i) if val is None: continue print "%s:" % i, if i == 'body': val = val.encode('utf-8') print val print class echo(Thread): def __init__(self, msg): self.message = msg Thread.__init__(self) def run(self): s = sendMessage(self.message.chatname, 'Re: ' + self.message.body) s.start() def main(): import sys bot = delegate.alloc().init() SkypeAPI.setSkypeDelegate_(bot) SkypeAPI.connect() print "connected." # add threads to bot. bot runs the threads at receiving # a message each time. b = task_bot() b.add(1, dump) b.add(2, echo) try: AppHelper.runConsoleEventLoop(installInterrupt=True) except KeyboardInterrupt: print "Keyboard Interrupt" AppHelper.stopEventLoop() SkypeAPI.disconnect() print "disconnected." sys.exit(0) if __name__ == "__main__": main()