前几天看了用《使用Live writter 在OSCHINA上写博客》的文章,又看了站长@红薯的接口程序,真是 Lucky,支持xmlrpc。有很多插件支持wordpress的xmlrpc接口,想尝试着弄过去,就萌生了用VIM来写oschina博客的想法。
当然支持写blog的VIM插件很多,像vimrepress,vimpress等等。基本原理都是利用python的xmlrpclib实现客户端进行远程访问。最后我选择了ultrablog。
因为很大啊,呵呵。ultrablog的主要由python写的,功能很多,支持本地数据库(sqlite),结构很不错,作为学习python的一个example,有消息说,VIM的作者打算在7.4的版本里完善python的支持。
以前是用SuSE来进行日常的工作,不过这回转到ubuntu上来了(SuSE装软件真是太痛苦了),当然系统不是必须的,任何VIM和PYTHON支持的系统都OK啦,硬性的要求有:
其他可选的一些包:
用apt-get很容易的安装这些:
sudo apt-get install python-markdown
python-markdown2要去下源码进行安装,比前一个版本,速度更快且修复了一些BUG, 如下:
git clone https://github.com/trentm/python-markdown2.git
cd python-markdown2
sudo python2 setup.py install
下载ultrablog,并解压到~/.vim/下,当然,可以用vunble等管理VIM插件,不多说了,我没有用,刚开始的时候没有使用,又对插件做了很多更改,也就没有移过去
在.vimrc中加入以下代码:
let ub_blog = {'login_name':'BLOG-USER-NAME',
\'password
':'USER-PASSWORD',
\'url':'http://my.oschina.net/action/xmlrpc',
\'db':'~/.vim/UltraBlog.db' }
其中,用户名和密码就不多说了,第三个是xmlrpc的url(能在前那个几个文章里查到),db是SQLite的文件。因为密码是明文的,所以,注意安全,建议放到单独文件再source进去
OK, 都安装配置好了,能用么? No.还有很长很长的路要走......
第一个错误就是连不服务,直接用python连没问题:
handle=xmlrpclib.ServerProxy('http://my.oschina.net/action/xmlrpc')
其实vimpress不用发生这个问题,因为ultrablog太智能了,他会把url加上'xmlrpc.php',可能这个对wordpress有用,不过对OSCHINA,呵呵! 更改ultrablog/util.py里面的
self.xmlrpc = self.url+'xmlrpc.php'
成为:
self.xmlrpc = self.url#+'xmlrpc.php'
上一个问题更正之后,用命令:
:UBList post remote 100
已经成功的列出服务器的所有文章,这个命令实际上调用了远端的函数:
public Object getRecentPosts(String blogid, String username, String pwd, int numberOfPosts)
实际上这个函数已经反回了Blog文章的所有东西,包括文章内容,但是ultrablog只用了postid及文章标题,可能是wordpress只是返回id及标题吧,不管这个问题,继续下去,想要列出某一文章,问题发生了,‘can't find the remote server function: getPosts(int, String, String)’,类似的问题吧,记不太准确了。 因为python的变量太灵活了,postid是只有数字的字符串,在调用的过程中被转化成int了,而remote server上的函数原型是:
public Object getPost(String postid, String username, String pwd)
所以,由于参数类型不对,远程访问失败。在这里做一些修正,即在远程调用时做了类型的强制转换:
key = str(self.itemKey)
remote_post = api.metaWeblog.getPost(key, cfg.loginName, cfg.password)
同样还是在调用getPost, 同样的地方,调用栈的最后几层简单的变了下,错误的内容大概是'int don't have the function: encode'。估计,python类型又在不知不觉中变了,大概是要调用String的encode函数,但是 这个对象被转成了‘int’。针对这一假设,更改下xmlrpclib.py来测试(有源代码就是好啊,想改就改,不知道这样改有没有问题...),果然是这样!!! 我的python的版本是2.7.3, xmlrpclib.py更改如下(line 183):
return str(string).encode("ascii")
即在出问题的string调用encode的时候做一次类型转化。纯数字的字符串还真是难搞......
Go on! 同样还是只是艰难的走了几步,还没有走出getPost这个函数,不过幸运的是,远程调用有返回值了!错误的地方是数组访问越界,奇怪的错误,一般不会 发生啦,竟然在通用的库里出这种错误, 抓包,打桩测试,原来getPost的返回,有两个类型不支持,导致了parse的错误,以致于parse dict的时候出了单数,key-value不成对了,所以...... 对xmlrpclib.py更改是在class Unmarshaller里加入对不支持的tag:
dispatch["ex:nil"] = end_nil
dispatch["ex:i8"] = end_int
小小的不兼容问题,只是对图片的返回值做修正。上传Media的返回值只有url的dict,不做修正而还要需要file的dict。对返回值做处理:
result = api.metaWeblog.newMediaObject('', cfg.loginName, cfg.password,
dict(name=os.path.basename(file_path), type=file_type, bits=bin_data))
img_tmpl_info = ub_get_option('ub_tmpl_img_url', True)
result['file'] = file_path
img_url = img_tmpl_info['tmpl'] % result