关于这个网站

毫无疑问,这是一个blog。

在Google app engine发布之后,我第一个想法就是学习Python——当时的GAE只支持Python,然后在上面写出一个自己的blog程序。在阅读他人的blog的时候,如果发现作者使用的是自己写的程序,就会景仰一下,慢慢地生出了“写一个自己的blog程序”的想法。现成的blog平台,譬如WordPress,movabletype并非不好,相反,他们是如此的强大,强大到我觉得无福消受。我试图从学习php开始,然而可耻地失败了,失败在想法中的开始从未开始。GAE发布之后,我感觉这是一个机会,让我学习一种编程语言的机会。于是,下载了教程,在一台配置落伍的TCL笔记本上安装了Python环境。

和我预料的一样,在看完《Python简明教程》之后,我对学习本身很快丧失了兴趣。于是动手编程。这种摸着石头过河的方法未必错误,可是如果你连石头的位置都摸不到,那肯定是走错了方向。“重复造轮子的行为时愚蠢的”,这是我的理由,所以我下载了其他人编写的blog程序,然后按照自己的想法修改,于是就有了现在这个blog程序。

和所有的blog程序一样,这个程序的功能包括但不限于:

  • 发布文章和页面
  • 评论。文章评论可关闭
  • tag和按月(年)存档
  • RSS和sitemap输出
  • 写作API

除此之外的功能有:

  • post有4种类型,分别为文章、页面、评论和短消息(微博),你没有看错,这个blog程序中,评论和文章的地位是相等的
  • 文章和页面可以另外设置一个链接
  • 文章和页面可以相互转换
  • 每条评论有属于自己的URL;在任何一个页面上都可以评论,甚至包括评论本身
  • 支持HTML,纯文本,Markdown,Textile等4种格式写作
  • WordPress格式的导入和导出
  • 集成了一些应用,譬如豆瓣、flickr、Google统计等

这是一个完全按照自己的想法拼凑的blog程序,加入的都是我认为有用或者有趣的零件,未必适合他人。我仍然把它放在了网上供人围观。

Hello world!

Welcome to WordPress. This is your first post. Edit or delete it, then start blogging! 不知道这是第几个blog。从2005年1月在Windows live spaces开始到现在,不知道设立过多少个blog,并且没有一个持续地写过,似乎折腾的热情比写blog本身更大。光就这个blog本身来说,也是2005年就已经诞生,然后被自己清空过几次,换过几次域名,直到前段时间迁移到新的服务器,才把过去的几篇文章导入进来,为的是不让光秃秃的页面太过难看,然后请求管理员绑定了自己的域名。从安全的角度出发,删除和隐藏了几篇可能较为敏感的文章。 坚持写blog利大于弊,这是早就知晓的道理,然而,坚持这两个字实在难以做到。这次又是一个开始?

门户网站与微博

作为微博客的始祖,twitter从一开始公司内部的通讯工具到设想中“地球的脉搏”,一直呈现上升的趋势,并且在可见的未来,上升的方向和速度都不会改变。在twitter开辟了一块疆土之后,世界各地的网民蜂拥而至,这自然引起了其他网站的注意,他们争先恐后地推出自己的微博客服务,试图在twitter完全垄断这个市场之前,圈起自己的一亩三分地。相对而言,国外的网站更有理性和创造性。Yahoo!的meme成为了分享精彩图片和语言的集散地,Google新近推出的buzz则在社会化联系上做出了深层次的尝试。转过来看看国内各大门户网站的微博客服务,试用之后,只能说乏善可陈。在twitter等网站被防火墙挡在国门之外的时期,对于国内门户网站来说,不啻一次极好的机会。用户已然经过twitter的教导,它们要做的不过是收割而已。只是它们收割的姿势是如此的拙劣。

首先反应过来的是新浪。尽管某新浪内部人士声称“很多人会认为新浪微博是模仿Twitter而生,但事实上,在2009年5月我第一次和CEO曹国伟谈起设想已久的“一句话博客”之前,我从未上过Twitter,或者任何与之形态相近的网站”。但是这样苍白的声明毫无意义,人们不会因为新浪微博模仿twitter而去指责它,事实上,这是中国互联网的传统。新浪在运营微博的时候,毫无保留地继承了新浪博客的特色,即名人效应。新浪博客依靠明星的光环照耀,一度也确实非常耀眼。正是这样经受过验证的成功,让他们理所当然地认为,复制这种运营模式更加稳妥。于是,新浪微博成为了小字辈的新浪博客。新浪完全没有意识到,twitter的成功不是依靠明星,或者说后来的验证账户,而是实实在在的草根,那种你在街头会擦肩而过的人。也许,它也意识到了,只是相信在中国,光环效应的影响力更加强大。

随后上线的搜狐微博网易微博同样没有任何值得称道之处。再宽容的用户,也不会将网易微博字数限制扩大到163个这样的细节称之为“创新”。搜狐将微博内置在博客中,试图公用博客好友联系人,这样一来,却彻底地让微博沦为了博客的附属品。相对于搜狐微博,自家的chinaren校园微博反而更像是一款独立的产品。在门户网站中比较有锐气的网易,则反新浪之道而行之,在页面上醒目地写道:“我们没有名人认证”。这不是贵族学校和平民学校的区别,只是招生的手段不同而已。

好戏还在后头。腾讯作为中国互联网最成功的企业,依靠着庞大的用户基数,在市场竞争中杀伤力极强。模仿然后超越,这就是腾讯的一贯战略。让对手感到可怕的是,你找不到遏制它的办法,除非你“上面有人”。腾讯之前的滔滔几乎是试水的产品,同时培养用户习惯。即使这样,滔滔在数据上显示仍然非常成功。腾讯随后将中心放在了另一款重点产品邮箱上,在邮箱中植入了微博。可以想象,腾讯的目标是将邮箱、微博、空间等产品融和在一起,筑起一道牢固的篱笆,而微博在其中起着连接的作用。

Tagged microblog and twitter

把你的appspot转向自定义域名

GAE支持绑定自己的域名,所以很多用户都在使用自定义域名。和blogger.com不同,GAE绑定域名之后,原来的yourname.appspot.com并不会自动转向自定义域名。需要做301转向的话,可以使用以下的代码:

def redirect_from_appspot(wsgi_app):
    def redirect_if_needed(env, start_response):
        if env["HTTP_HOST"].startswith('my_app_name.appspot.com'):
            import webob, urlparse
            request = webob.Request(env)
            scheme, netloc, path, query, fragment = urlparse.urlsplit(request.url)
            url = urlparse.urlunsplit([scheme, 'www.my_domain.com', path, query, fragment])
            start_response('301 Moved Permanently', [('Location', url)])
            return ["301 Moved Peramanently","Click Here %s" % url]
        else:
            return wsgi_app(env, start_response)
    return redirect_if_needed

然后定义一下application:

from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
...
def main():
    application = webapp.WSGIApplication(ROUTES, debug = True)
    application = redirect_from_appspot(application)
    util.run_wsgi_app(application)

需要注意的是,如果启用了XMPP服务,在转向之后,XMPP不能正常工作。

Tagged gae

我的独立微博客

在GAE上搭建了一个独立的微博客,所谓独立,就是没有和访问者的交流,纯粹记录型的。在编写初期,也考虑过增加互动性,想到现在交流的途径是如此之多,这里没有也无所谓,这才作罢。以前一直有这个程序存在,由于不支持IM显得很不方便,很久都没有使用。在Google增加了XMPP之后,搭建一个机器人变得容易,又兴起了这个念头。这个微博客目前的功能有:

  • 支持页面、IM、email、移动等方式发布
  • 支持导入twitter导出的XML文件
  • 和 twitter 的双向同步
  • 消息字数不再局限于140个字,当超过140字时,同步到twitter的消息将截断并增加指向原消息的链接

关于开源。有些朋友对这个程序感兴趣,询问过是否开源,感谢你们的关心。不过,暂时没有开源的打算。第一,因为自己觉得代码写得非常糟糕,只是能勉强运行而已。将如此质量的代码开源,恐怕会贻笑大方。其实,这个微博客并没有过多的技术含量,随便找一套运行在GAE上的开源博客程序略作修改就可以达到目的。第二,这个微博客完全模仿了 twitter 的样式,甚至可以说是剽窃,将不完全属于自己的程序开源也是不合适的。

Tagged microblog, twitter and gae

两分钟搭建自己的twitter机器人

在Google App Engine支持XMPP之后,搭建一个属于自己的twitter发布机器人已经变得非常容易,在此之前,这项工作显得很复杂,即使有imified这样专业的机器人服务的存在。简单介绍一下如何搭建,实现最简单的发布功能。

在app.yaml中启用xmpp消息服务:

inbound_services:
- xmpp_message

这行代码是加在handlers内容区块之外的。

具体的代码:

from google.appengine.api import xmpp
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

TWITTER_USERNAME = "your twitter name"
TWITTER_PASSWORD = "your twitter password"
YOUR_EMAIL = "your email"

class XMPPHandler(webapp.RequestHandler):
    def post(self):
        message = xmpp.Message(self.request.POST)
        if message.sender.split('/')[0] == YOUR_EMAIL:
            authStr = TWITTER_USERNAME +':'+ TWITTER_PASSWORD
            msg = message.body
            msg = msg.encode('utf8')
            url='http://twitter.com/statuses/update.json'
            form_fields={'source':'','status':msg}
            form_data=urllib.urlencode(form_fields)
            result=urlfetch.fetch(url=url,
                    payload=form_data,
                    method=urlfetch.POST,
                    headers={"Content-type": "application/x-www-form-urlencoded",
                  "Accept": "text/xml",
                  "Authorization": "Basic "+authStr.encode("base64")[0:-1]})
            if result.status_code == 200:
                message.reply(u"发布成功.")
            else:
                message.reply(u"发布失败,请重试!")

application = webapp.WSGIApplication([('/_ah/xmpp/message/chat/', XMPPHandler)],
                                     debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()

上传就可以用YOUR_EMAIL定义的email地址加[email protected]为好友,然后就可以给它发送twitter了。

Tagged twitter, im and gae

QQ域名邮箱

QQ推出了域名邮箱,瞄准的是企业用户。长久以来,尽管QQ邮箱是腾讯公司在品质上难得一见的好产品,但由于QQ本身的定位更偏向于年轻和娱乐化,导致许多企业级的用户在选择其邮箱产品时采取了更谨慎的态度。QQ域名邮箱的推出,正是对这样难堪的现状试图扭转局面的尝试。Google AppsWindows Live 管理中心已经逐步成熟和占领了很大市场,这对于一向靠模仿然后超越的腾讯来说,现在是已经可以发动的时机。前行者在披荆斩棘中闯出了一条路,并且告诉人们这条路上可以挖掘出黄金,腾讯怎能坐视不理?

同时,腾讯已经发扬了其一切和QQ绑定的原则,所谓的域名邮箱,仍然和用户的QQ邮箱绑定,占用的是原有的空间。换句话说,如果没有QQ号码,仍然无法使用域名邮箱。从QQ邮箱只能创建10个用户的策略来看,这又是一款等级制的产品。应该注意的是,开通域名邮箱需要填写管理员的姓名、联系电话,有经验的用户知道这意味着什么。

Tagged qq and mail

test metaweblog api

Does the metaweblog api work? If it works, I will update this post later.

update:It works!

windows live writer screenshot

Tagged metaweblog

Pubsubhubbub的故事

一般讲故事都是这样开始的:从前有一个……:

从前有一个叫做Sub的人,他天天跑到Pub家去要钱,有一种说法是去讨回被欠的工资。总之,他不管Pub有钱没钱,三天两头地去跑,想想也是,Pub什么时候有钱也不知道,万一哪天有钱了,不就要到了么?

Sub去得太频繁了,Pub终于不胜其烦了,他想出了一个办法。Pub花很少的钱雇佣了一个叫做Hub的人给他看守大门,并且告诉Hub:以后谁来要钱都让他处理。毕竟是给人打工,Hub无可奈何地硬着头皮答应了。

这一天,Sub一如既往地去Pub家,到了以后,他惊讶地发现,Pub家门口贴着一张声明,声称以后所有的财务问题由看大门的Hub先生全权处理。

不管怎样,这个Hub看起来比Pub容易打交道一点。Hub看到Sub以后,问他:你是来要钱的吗?Sub说是。于是Hub说:以后你就别天天跑来了。Pub先生说了,有钱的时候他会让我去通知你一声的。

就这样,Sub回去了。

果然,后来Pub有了钱的时候,会让Hub上门来通知Sub去他家里拿钱。Sub很高兴,天天上门跑不但辛苦,而且不受人待见,现在只在家等着就行了。当然,Pub也很高兴,没有了Sub上门烦他,并且什么时候有钱还是自己说了算。他对Hub的工作很满意。

这个故事被两位Google的员工:Brett Slatkin 和 Brad Fitzpatrick 听说以后,他们从中受到了启发。并因此开发了一种叫做PubSubHubbub的协议。

为了让这个blog支持这种协议,我仿效了当年Pub的做法,雇佣了一个看大门的,不过我比他精明的地方在于:我雇佣的是一个免费的、开源门卫:PubSubHubbub Publisher

然后,我要做的,是在大门上贴一张声明,如果你家大门是RSS结构的话,这种声明看起来是这样子:

<?xml version="1.0"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/>
    ...
  </channel>
</rss>

基于jQuery的文本编辑器markItUp!

markItUp!这个名字很有趣,和Yahoo!一样后面带了一个感叹号的尾巴。markItUp!是一款基于jQuery的轻量级文本编辑器,和一般的WYSIWYG(所见即所得)编辑器不同,呈现在文本框中的依然是代码,编辑器简化了插入代码的工作。

markItUp! html editor

在试用过NicEdit之后,再次选择了markItUp!,因为markItUp!的扩展性更好,支持快捷键,动态预览,自定义皮肤,总体说来,比NicEdit更为成熟。

调用markItUp!编辑器:

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="markitup/jquery.markitup.js"></script>

编辑器格式,如html,ubb,wiki等等:

<script type="text/javascript" src="markitup/sets/default/set.js"></script>

CSS文件,其中有皮肤的样式:

<link rel="stylesheet" type="text/css" href="markitup/skins/markitup/style.css" />
<link rel="stylesheet" type="text/css" href="markitup/sets/default/style.css" />

插件的安装:将插件的set.js文件内容放入sets编辑器格式下的set.js文件中,将插件的css文件内容放入sets编辑器格式下的style.css文件中。

其实,写这篇文章只是为了测试一下新安装的markItUp!使用效果如何。

Tagged editor

时间问题

处在UTC时间差为0的程序员在开发程序时,往往不考虑时间问题,在修改程序时,不得不给它打补丁。

entry.published += datetime.timedelta(hours=UTC_OFFSET)
Tagged datetime

增加了NicEdit文本编辑器

由于这个blog本身使用的是纯文本的编辑器,在写文章的时候,需要手动输入代码,非常麻烦。在网上找了一下HTML编辑器,最常见的是FCKEditorTinyMCE,不过这些编辑器虽然功能强大、插件众多,但代码量和占用的客户端资源也非常巨大,而我需要的是一个轻量级的编辑器。

通过搜索,找到了NicEdit,整个程序才31KB大小,使用也非常方便,在编辑页面引入一行JS文件即可。

Update:这个编辑器产生的代码不符合W3C标准。

Tagged blog and editor

Micolog修改版

Micolog徐明写的运行于GAE上的blog程序,它借鉴了许多WordPress的优点。我在徐明的版本上进行了一点修改,以便更好的使用。目前修改的部分有:

  • 增加了文章评论开关
  • 增加了文章阅读统计
  • 增加了标签云
  • 增加了按月存档
  • 增加了评论feed
  • 可以更改作者名称
  • 可以显示热门文章
  • 修改了其他的一点点内容

在这个修改版本中,我放入了两个新的主题。

下载地址

Tagged gae and micolog