| /BotRules /XchatGuile /XchatPerl /XchatPython /XchatPython/AutoNick /XchatPythonZh |
XChat 2.0 Python 插件接口文档
Contents
- XChat 2.0 Python 插件接口文档
- 关于
- 功能和特点
- Python插件接口相关命令
- 自动加载模块
- 模块开发
- “上下文”原理
- Hello world
- xchat 模块
- 一般函数
- 信息获取函数
- 挂钩函数
- 优先级
- word 和 word_eol 参数
- userdata 参数
- 回调返回常量 ( EAT_* )
- xchat.hook_command(name, callback, userdata=None, priority=PRI_NORM, help=None)
- xchat.hook_print(name, callback, userdata=None, priority=PRI_NORM)
- xchat.hook_server(name, callback, userdata=None, priority=PRI_NORM)
- xchat.hook_timer(timeout, callback, userdata=None)
- xchat.hook_unload(timeout, callback, userdata=None)
- xchat.unhook(handler)
- “上下文”处理
- 下载
- 示例程序
- 作者
- 鸣谢
关于
本页描述了 XChat 2.0 的 Python 插件接口。该接口允许用户使用 Python 语言为 XChat 这个 IRC 客户端开发扩展脚本。
功能和特点
下面是 XChat 2.0 Python 插件接口提供的部分功能/特点列表:
- 全面,一致和直接的应用程序接口;
- 栽入,卸载,重新栽入以及自动栽入支持;
- 每个插件都拥有独立的解释器状态;
- 交互式Python终端控制台;
- 交互式Python命令执行能力;
- 完全支持多线程;
- 标准输出及标准错误输出重定向至 XChat 终端;
- 动态列表管理;
- 出色的上下文处理;
Python插件接口相关命令
加载 Python 插件接口模块之后,XChat 将能够解释/执行下述命令。
- /py load <filename>
- 栽入文件名为 filename 的模块。
- /py unload <filename|module name>
- 卸载文件名为 filename 或者模块名为 module name 的模块。
- /py reload <filename|module name>
- 重新载入文件名为 filename 或者模块名为 module name 的模块。
- /load <filename>
- 与 /py load 作用相同,但仅在 filename 的扩展名为 .py (建议统一使用此扩展名)时才起作用。
- /unload <filename>
- 与 /py unload 作用相同,但它只接受扩展名为 .py 的多个 filename 参数。
- /py list
- 列出已加载的 Python 模块。
- /py exec <command>
- 交互式执行 Python 命令。例如,
/py exec import xchat
/py exec print xchat.get_info('channel')
- /py console
打开交互式 Python 终端。这个终端其实就是你与一个使用特殊昵称的对象(>>python<<)进行的私聊。你在这个私聊窗口中输入的任何信息都将被转发给 Python 插件接口解释执行。需要注意的是,该终端与 /py exec 命令共享同一个解释器状态。
- /py about
- 显示 Python 插件接口的相关信息。
自动加载模块
如果你有需要与 Python 插件接口(通常在程序启动的时候加载)同时加载,只要保证它使用 .py 扩展名并把它放在你的 xchat 目录(可能就是 ~/.xchat2 目录)即可。
模块开发
“上下文”原理
在解释 API 提供的功能之前,我们要先介绍一下 XChat 中的“上下文”概念。它并不难理解,而且如果你理解了我们所说的内容将使你能够更好理解 API 解释。
你可以把“上下文”想象成一个 XChat 中的频道、服务器、或者对话标签。每个标签都有它自己的“上下文”并且每个标签都属于一个给定的服务器或者频道(对话是一种特殊的频道)。
当前“上下文”是指当前在 XChat 中拥有控制权的模块。例如,当 XChat 收到某个特定频道中的命令,并且你要求 XChat 在发生该事件时通知你,XChat 将会在调用你的模块之前把当前“上下文”将设置为这个频道。
Hello world
这里是传统方式的 Hello world 模块示例。
1 __module_name__ = "helloworld"
2 __module_version__ = "1.0"
3 __module_description__ = "Python module example"
4
5 print "Hello world!"
该模块将在 XChat 的终端中输出 "Hello world!" ,并且一直休眠到它被卸载为止。它是一个简单的模块,但已经引入了一些概念。注意模块信息是怎样设置的。这些信息是必须提供的,它们将会被显示在“已经加载的 XChat 模块列表”中。
xchat 模块
xchat 模块是你使用 Python 插件接口提供的各种 XChat 功能的通行证。下面是一个简单示例:
1 import xchat
2 xchat.prnt("Hi everyone!")
xchat 模块提供了如下函数。
一般函数
xchat.prnt(string)
该函数将 string 输出到当前上下文。因为普通的 print 语句可以得到同样的结果,这个函数主要被用来作为参数传递给其他函数。参见上面的使用示例。
因为 "print" 在 Python 语言中是保留关键字,所以我们才给这个函数取了一个诡异的名字。
xchat.emit_print(event_name, *args)
这个函数将使用给定的参数产生一个 print 事件 。要得到可利用的事件列表,以及数字和各参数的意义,请查看 设置 > 列表 > 文本事件 窗口。函数示例如下:
1 xchat.emit_print("Channel Message", "John", "Hi there", "@")
xchat.command(string)
在当前“上下文”执行给定的命令。它的效果和你在 xchat 窗口执行命令是一样的,但要注意这里不需要使用 / 前缀。函数示例如下:
1 xchat.command("server irc.openprojects.net")
xchat.nickcmp(s1, s2)
该函数将使用符合 RFC1459 的字符比较方法比较 s1 和 s2 ,适于比较频道名及昵称。当存在 s1 时,返回值小于,等于,大于零分别表示 s1 在 s2 之前,正好匹配 s2 , s1 在 s2 之后。例如:
1 if xchat.nickcmp(nick, "mynick") == 0:
2 print "They are the same!"
信息获取函数
xchat.get_info(type)
在当前“上下文”中取得 type 字符指定的信息。在写这篇文章的时候,共有如下信息类型可以被请求:
- away
- 离开理由,如果你没有处于离开状态返回 None 。
- channel
- 当前“上下文”的频道名称。
- host
- 你所连接的服务器的真实主机名。
- network
- 当前的 IRC 网络名称,没有则返回 None 。
- nick
- 你正在使用的昵称。
- server
- 当前服务器名(服务器声明的那个名字),如果你没有处于联机状态返回 None 。
- topic
- 当前频道的主题。
- version
- XChat 的版本号。
- xchatdir
- XChat 配置文件目录,例如:"/home/user/.xchat2".
示例:
1 if xchat.get_info("server") is None:
2 print "Not connected!"
这些信息来自 XChat 的插件文档。你可能会在新的 XChat 文档中找到到这里没有提及的其他类型(如果真的存在的话)。任何能被 XChat 接受的新信息类型将自动被 Python 插件接口接受。
xchat.get_prefs(name)
获取 name 字符串所代表的配置信息,这些信息通常是用 /set 命令设置的。例如:
1 print "Current preferred nick:", xchat.get_prefs("irc_nick1")
xchat.get_list(type)
通过这个函数你可以取得一个选定信息的列表,比如一个 DCC 列表,一个频道列表,一个用户昵称列表,等等。每个列表的属性都将根据其列表类型所能代表的信息动态生成。
下面的例子重写了 XChat 的插件 API 文档实例。它将输出一个包含当前所有正在进行的 DCC 传输的列表。看,这个接口相比 XChat 提供的 C API 是多么的简捷啊。
1 list = xchat.get_list("dcc")
2 if list:
3 print "--- DCC LIST ------------------"
4 print "File To/From KB/s Position"
5 for i in list:
6 print "%6s %10s %.2f %d" % (i.file, i.nick, i.cps/1024, i.pos)
你可以在下面找出都有哪些列表类型可以传递给本函数的。
这些信息来自 XChat 的插件文档。你可能会在新的 XChat 文档中找到到这里没有提及的其他类型(如果真的存在的话)。任何能被 XChat 接受的新信息类型将自动被 Python 插件接口接受。
channels
channels 列表类型使你能够访问关于频道,对话,和它们的服务器的信息。每个 channels 列表都将包含下面的属性:
- channel
- 频道或对话的名称。
- context
- 一个“上下文”对象,通过它可以访问对应的频道/服务器。
- network
- 这个频道所属的 IRC 网络的网络名称。
- server
- 这个频道所属的服务器的名称。
- type
- “上下文”类型(1=服务器,2=频道,3=对话)
dcc
dcc 列表类型使你可以访问一个 DCC 文件传输列表。每个 DCC 文件传输列表都拥有以下属性:
- address32
- 对方用户地址(使用 int 类型表示的 ipv4 地址)。
- cps
- 每秒传输的字节数(速率)。
- destfile
- 目标文件的完整路径。
- file
- 文件名。
- nick
- 文件 来自/发给 的用户的昵称。
- port
- TCP 端口号。
- pos
- 已经 接收/发送 的字节数量。
- resume
- 文件续传起始点(如果没有发生续传则为零)。
- size
- 用字节数表示的文件大小。
- status
- DCC 状态(正在发送请求=0,活动中=1,失败=2,完成=3,正在连接=4,被用户中断=5)。
- type
- DCC 类型(发送=0,接收=1,被动接受 DCC 聊天=2,主动提供 DCC 聊天=3)。
users
users 列表类型使你可以访问一个正在当前频道聊天的用户列表。每个用户类表都拥有如下属性:
- nick
- 昵称。
- host
- 使用 user@host 形式表示的主机地址(如果未知则为 None )。
- prefix
- 模式/权限 前缀字符,例如:@ 或者 + 。此属性指向单个字符。
ignore
ignore 列表类型允许你访问当前忽略的用户列表。每个忽略列表都拥有如下属性:
- mask
- 忽略掩码(例如,"*!*@*.aol.com")。
- flags
- 比特标识符(0=私有,1=通知,2=频道,3=ctcp,4=邀请,5=取消忽略,6=不保存,7=dcc)。
挂钩函数
这些函数允许你把自己的代码挂入 XChat 的事件处理过程。
优先级
当一个优先级关键字被接受,就说明这个回调可能以五种不同的优先级被挂入:PRI_HIGHEST, PRI_HIGH, PRI_NORM, PRI_LOW,和 PRI_LOWEST。这些可在 xchat 模块中使用的常量将帮你定义你的插件被回调的顺序。多数情况下,你不需要修改它的默认值(PRI_NORM)。
word 和 word_eol 参数
在一个回调中,当这些参数可用时,它们是由用户输入的特定命令的各个参数字符串所构成的数组。例如,当你执行了:
/command NICK Hi there!
word[0] 的值是 command
word[1] 的值是 NICK
word[2] 的值是 Hi
word[3] 的值是 there!
word_eol[0] 的值是 command NICK Hi there!
word_eol[1] 的值是 NICK Hi there!
word_eol[2] 的值是 Hi there!
word_eol[3] 的值是 there!
userdata 参数
当使用 userdata 时,它允许你把一个自定义的对象传递给你的回调。
回调返回常量 ( EAT_* )
假如一个回调返回了 EAT_* 中的某个宏,它将能够控制 XChat 在回调返回后做何种处理。下面是可用的常量及其意义:
- EAT_PLUGIN
- 使其它插件不能接收到这个事件。
- EAT_XCHAT
- 使 XChat 不以通常的方式对待该事件。
- EAT_ALL
- 把这个事件完全吞噬。
- EAT_NONE
- 使事件处理过程按通常的方式进行。
返回 None 与返回 EAT_NONE 效果相同。
xchat.hook_command(name, callback, userdata=None, priority=PRI_NORM, help=None)
该函数允许你挂入 name XChat 名令。它表示任何时候你输入 /name ... 时 回调 将被调用。参数 userdata 和 priority 的意义见前面的解释,当存在 help 参数时它的值会在执行 /help name 命令时显示。这个函数返回一个可以被 xchat.unhook() 函数使用的挂钩处理器。例如:
1 def onotice_cb(word, word_eol, userdata):
2 if len(word) < 2:
3 print "Second arg must be the message!"
4 else:
5 xchat.command("NOTICE @%s %s" % (xchat.get_info("channel"), word_eol[1]))
6 return xchat.EAT_ALL
7
8 xchat.hook_command("ONOTICE", onotice_cb, help="/ONOTICE <message> Sends a notice to all ops")
你可以像上面描述的那样返回 EAT_* 中的某个常量来控制 XChat 的行为。
xchat.hook_print(name, callback, userdata=None, priority=PRI_NORM)
通过这个函数你可以注册一个回调来捕捉任何 print 事件。事件名称可以从 编辑文本事件 窗口找到。参数 userdata 和 priority 的意义见前面的解释。这个函数返回一个可以被 xchat.unhook() 函数使用的挂钩处理器。例如:
1 def youpart_cb(word, word_eol, userdata):
2 print "You have left channel", word[2]
3 return xchat.EAT_XCHAT # Don't let xchat do its normal printing
4
5 xchat.hook_print("You Part", youpart_cb)
你可以像上面描述的那样返回 EAT_* 中的某个常量来控制 XChat 的行为。
xchat.hook_server(name, callback, userdata=None, priority=PRI_NORM)
通过这个函数你可以注册一个当某个服务器事件发生时被调用的回调。你可以用它来捕捉 PRIVMSG,NOTICE,PART,来自服务器的数字指令等等。参数 userdata 和 priority 的意义见前面的解释。这个函数返回一个可以被 xchat.unhook() 函数使用的挂钩处理器。例如:
1 def kick_cb(word, word_eol, userdata):
2 print "%s was kicked from %s (%s)" % (word[3], word[2], word_eol[4])
3 # Don't eat this event, let other plugins and xchat see it too
4 return xchat.EAT_NONE
5
6 xchat.hook_server("KICK", kick_cb)
你可以像上面描述的那样返回 EAT_* 中的某个常量来控制 XChat 的行为。
xchat.hook_timer(timeout, callback, userdata=None)
通过这个函数你可以注册一个每隔 timeout 微秒都被调用的回调。参数 userdata 和 priority 的意义见前面的解释。这个函数返回一个可以被 xchat.unhook() 函数使用的挂钩处理器。例如:
1 myhook = None
2
3 def stop_cb(word, word_eol, userdata):
4 global myhook
5 if myhook is not None:
6 xchat.unhook(myhook)
7 myhook = None
8 print "Timeout removed!"
9
10 def timeout_cb(userdata):
11 print "Annoying message every 5 seconds! Type /STOP to stop it."
12 return 1 # Keep the timeout going
13
14 myhook = xchat.hook_timer(5000, timeout_cb)
15 xchat.hook_command("STOP", stop_cb)
若你让该回调返回真值,计数器将被保留,否则计数器被移除。
xchat.hook_unload(timeout, callback, userdata=None)
通过该函数你可以注册一个在插件即将被卸载时调用的回调。参数 userdata 和 priority 的意义见前面的解释。这个函数返回一个可以被 xchat.unhook() 函数使用的挂钩处理器。例如:
1 def unload_cb(userdata):
2 print "We're being unloaded!"
3
4 xchat.hook_unload(unload_cb)
xchat.unhook(handler)
接触任何使用上述挂钩函数挂载的挂钩。
“上下文”处理
下面你将看到关于如何处理“上下文”的信息。
“上下文”对象
就像前面的 “上下文”理论 阐述的那样,“上下文”使我们能够访问 XChat 的 频道/对话/服务器 标签。xchat 模块中的每个函数都将在当前“上下文”中被执行,当前“上下文”是 XChat 在将控制权传递给模块之前从内部指定的。但有些时候你需要使代码工作在特殊的“上下文”中,这时就需要使用“上下文”对象了。
要创建一个“上下文”对象,你可以使用 xchat.get_context() 、 xchat.find_context() 函数,或者使用下面即将讲述的函数,又或者你可以使用前面讲述过的 xchat.get_list() 函数。
每个上下文对象都提供如下方法:
- context.set()
- 将这个“上下文”对象所代表的“上下文”设置成当前“上下文”。
- context.prnt(string)
- 与 xchat.prnt() 函数作用相同,不过它是在给定的“上下文”中执行的。
- context.emit_print(event_name, *args)
- 与 emit_print() 函数作用相同,不过是在给定的“上下文”中执行的。
- context.command(string)
- 与 xchat.command() 函数作用相同,不过是在给定的“上下文”中执行的。
- context.get_info(type)
- 与 xchat.get_info() 函数作用相同,不过是在给定的“上下文”中执行的。
- context.get_list(type)
- 与 xchat.get_list() 函数作用相同,不过是在给定的“上下文”中执行的。
xchat.get_context()
返回当前“上下文”所对应的“上下文”对象。
xchat.find_context(server=None, channel=None)
取得一个基于频道和服务器名的“上下文”。如果 server 的值为 None 它将返回任意符合给定名称的频道(或者对话)。如果 channel 的值为 None ,它将返回给定符合服务器名称并且显示在最前面的 标签/窗口 。例如:
1 cnc = xchat.find_context(channel='#conectiva')
2 cnc.command('whois niemeyer')
下载
你可以从 XChat 2.0+ 的网站找到本插件。
本插件在 XChat 2.0.5 版本之后进行了一些修正和改进。如果你恰好使用的是这个版本的 XChat 请使用这个模块替换你的版本中相应文件。注意,此模块可能不兼容先前的版本。
示例程序
utf8decoder.py - 这个插件将检测任何其它用户发送的信息,如果碰到 UTF8 编码的则将其转化为 ISO-8859-1 编码。更多内容参见这里。
作者
GustavoNiemeyer <niemeyer AT conectiva DOT com>
鸣谢
- 感谢原作者写出如此详尽的文档。
感谢 IRC 中的 sake!feng@* Dinosaur!Dinosaur@* 为翻译工作提供的帮助。
如果您发现了翻译错误,可以直接登录 Wiki 修改或者您也可在 WikiSandBox 中对该错误进行简要描述。如果您发现了 API 描述错误,请先对照英文文档,确认不是翻译错误后再联系原文作者。