利用 twisted 来写 MSN 机器人 (有例子下载)

具体到 MSN 机器人的实现,我倾向于使用 twisted 框架。无奈网上相关的资料非常少,找了半天只有这个中文 blog entry 稍微有些帮助。后来把 twisted 自带的 sample 增加了一些功能,现在放出来供需要的人参考。

msnclient.py (因为是修改自 twisted 的代码,所以也用 MIT license 吧)

这个简单的 MSN 机器人目前可以自动加好友,以及实现了一个消息 echo 机制——对它说的话会原文返回来。为了帮助理解 MSN 协议,我也打印了大量的协议文本到终端上。

如果是在 win32 环境下调试,pyOpenSSL 主页上并没有最新版本的预编译包,我现在用的是 webcleaner 编译好的(http://webcleaner.sourceforge.net/pyOpenSSL-0.6.win32-py2.5.exe),同时还需要安装 OpenSSL 的 win32 库

MSN 的字符流都是 UTF-8 的,本来我在 Linux 下的 zh_CN.UTF-8 环境下信息输出的很好,但在中文 windows 上就不能正确输出,无奈在例子里很多地方增加了 locale 判断

default_locale = locale.getdefaultlocale()
foobar_str.decode('UTF-8').encode(default_locale[1])

Topic: 技术

评论

比如一些可以 map/reduce 执行的任务,可以通过这样的方式远程控制它一下;或者就是最简单的收集一堆状态报告,然后发给管理员看看。msn 这东西其实就是个 agent,可以让他做很多事情,仅做提醒有点儿大材小用了。

在NotificationClient里面重载

def gotContactStatus(self, statusCode, userHandle, screenName):
    contact=self.factory.contacts.getContact(userHandle)
    if contact != None:
        contact.status = statusCode

============================
不知你指的奇怪的状态是不是下面这个异常

2007/05/07 11:51 +0800 [NotificationClient,client] Unhandled Error
    Traceback (most recent call last):
      File "/usr/lib/python2.5/site-packages/twisted/python/log.py", line 48, in callWithLogger
        return callWithContext({"system": lp}, func, *args, **kw)
      File "/usr/lib/python2.5/site-packages/twisted/python/log.py", line 33, in callWithContext
        return context.call({ILogContext: newCtx}, func, *args, **kw)
      File "/usr/lib/python2.5/site-packages/twisted/python/context.py", line 59, in callWithContext
        return self.currentContext().callWithContext(ctx, func, *args, **kw)
      File "/usr/lib/python2.5/site-packages/twisted/python/context.py", line 37, in callWithContext
        return func(*args,**kw)
    --- ---
      File "/usr/lib/python2.5/site-packages/twisted/internet/selectreactor.py", line 139, in _doReadOrWrite
        why = getattr(selectable, method)()
      File "/usr/lib/python2.5/site-packages/twisted/internet/tcp.py", line 362, in doRead
        return self.protocol.dataReceived(data)
      File "/usr/lib/python2.5/site-packages/twisted/protocols/basic.py", line 232, in dataReceived
        why = self.lineReceived(line)
      File "/usr/lib/python2.5/site-packages/twisted/words/protocols/msn.py", line 656, in lineReceived
        handler(params.split())
      File "/usr/lib/python2.5/site-packages/twisted/words/protocols/msn.py", line 863, in handle_ILN
        self.gotContactStatus(params[1], params[2], unquote(params[3]))
      File "/usr/lib/python2.5/site-packages/twisted/words/protocols/msn.py", line 1138, in gotContactStatus
        self.factory.contacts.getContact(userHandle).status = statusCode
    exceptions.AttributeError: 'NoneType' object has no attribute 'status'