2008年5月27日

有备无患:增强豆瓣收藏对话框的 Greasemonkey 脚本

经常使用 del.icio.us 的人,一定也很熟悉 del.icio.us 的跟随键盘输入自动提示标签(Tag Suggest)的功能。它为用户管理大量的标签带来方便,比如不必去费神记忆单词的拼写,避免为同一语义定义多个标签等。这是靠我们的大脑来记忆管理,或者类似豆瓣只提供10个最常用的标签,不能做到的。

这个 Greasemonkey 脚本的主要功能,是为豆瓣收藏对话框提供类似 del.icio.us 的标签提示功能。另外还重新布置了读过/在读/想读等按钮的布局,并添加了删除收藏的按钮。

目前脚本的版本为0.1,欢迎试用。有什么建议或意见,欢迎留言:-)


Screenshot - Enhanced Douban Collecting Dialog

功能

  • 类似 del.icio.us 的随输入自动提示标签(Tag Suggest)
  • 重新安排了读过/在读/想读等按钮的布局,保证 UI 路径的一致性
  • 增加了删除收藏的按钮

下载

下载脚本


2008-05-31 UPDATE

脚本更新至0.2,有下列更新

  • 增加了对个人收藏页,标签页,豆瓣猜,TOP250等页面中的收藏对话框的支持
  • 修正了之前脚本中已知的 BUG

2008-09-18 UPDATE

脚本更新至0.3

  • 支持更新后的收藏对话框
  • 默认展开标签
  • 支持豆瓣全域的收藏对话框

2008年5月19日

有备无患:在 Gentoo 上部署 Git + Gitosis 服务器的笔记

GitLinus Torvalds 为了帮助管理 Linux 内核开发而开发的分布式版本控制软件(Distributed SCM)。Git 汲取了 Torvalds 在维护大型的分布式项目开发方面的经验和对文件系统性能的丰富知识,正如其文档所描述的,“是一个快速、可扩展的分布式版本控制系统,它具有极为丰富的命令集,对内部系统提供了高级操作和完全访问。”目前,Linux 内核、X.org 服务器和 Ruby on Rails 等开源项目的版本控制系统都已经切换到 Git。

GitosisTommi Virtanen 为了更方便和安全的辅助 Git 架设和管理软件版本库 (Software Repository) 而开发的工具软件。虽然 Git 本身也提供 git-daemon 以架设版本库,但在用户访问控制上做的并不严格。而 Gitosis 允许单个用户帐号管理多个版本库,使用 SSH keys 管理用户认证,不需要 shell 帐号就可以解决多用户访问集中版本库的问题。

需要说明的是,我使用的 Gitosis 是 robbat2 为了部署新的 Gentoo Overlays 而开发的 Gentoo 分支版本 (Gentoo Fork Version),和上游版本 (Origin Upstream Version) 相比有如下不同:

  • 支持 git+ssh://HOST/REPO 风格的相对路径;
  • 支持以命令行参数方式导入 keys,如 gitosis-init --adminkey=FILE --adminname=STRING;
  • 智能处理 SSH keys,支持 SSH1 和 SSH2 keys;
  • 将上游版本默认的目录权限 0750 更改为 0755,以便用 nobody:nobody 运行 git-daemon。

这篇文章详细记录了我在本地安装和部署 Git + Gitosis 的过程和遇到的问题,希望为大家提供一些参考。欢迎 Fix-Me :-)

安装 Git + Gitosis

安装 git 和 gitosis-gentoo。安装完后,Gentoo 会自动添加 git 用户和组,并将版本库的主目录设为 /var/spool/gitosis/repositories。
# echo ">=dev-util/git-1.5.5" >> /etc/portage/package.keywords
# echo ">=dev-util/gitosis-gentoo-0.2_p20080203" >> /etc/portage/package.keywords
# emerge -av git gitosis-gentoo

如果你的主机上没有装 SSH 的话,还要安装 openssh, 以及 keychain 用来管理 ssh-agents(可选)。
# emerge -av openssh keychain

安装完后,启动 sshd,并加入默认启动。
# /etc/init.d/sshd start
# rc-update add sshd default

配置 Gitosis

首先生成一个 ssh key。
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/wyt/.ssh/id_rsa):(回车)
Created directory '/home/wyt/.ssh'.
Enter passphrase (empty for no passphrase):(直接回车)
Enter same passphrase again: (直接回车)
Your identification has been saved in /home/wyt/.ssh/id_rsa.
Your public key has been saved in /home/wyt/.ssh/id_rsa.pub.
The key fingerprint is:
dd:33:cc:99:33:00:66:77:ff:00:bb:99:00:22:55:88 wyt@gentoo

我把 ssh key 保存在默认的 ~/.ssh/id_rsa,你也可以选择其他地方。接下来把 id_rsa.pub 上传到服务器。其中的root@gentoo,root 是根用户名,gentoo 是主机名,可以从 /etc/conf.d/hostname 得知。
$ cat /etc/conf.d/hostname
hostname="gentoo"
$ scp ~/.ssh/id_rsa.pub root@gentoo:
Password: (输入 root 帐户密码)
id_rsa.pub                                    100%  392     0.4KB/s   00:00

上传完毕后,用 gitosis-init 初始化版本库。
$ sudo su -
# sudo -H -u git gitosis-init < ~/id_rsa.pub
Initialized empty Git repository in ./
Reinitialized existing Git repository in ./

上面第二条命令中,-u 表示 sudo 将切换至 git 用户,-H 表示 sudo 将切换至该用户的主目录。初始化完成后,将创建一个名为 gitosis-admin 的版本库,用于 Gitosis 的设置和管理。你需要把它 clone 到相应目录。
$ mkdir git
$ cd git
$  git clone git@gentoo:gitosis-admin.git
$ cd gitosis-admin
$ ls -lh
-rw-r--r-- 1 wyt wyt 80 2008-05-19 00:10 gitosis.conf
drwxr-xr-x 2 wyt wyt 80 2008-05-19 00:10 keydir

gitosis-admin 目录下有一个 gitosis.conf 文件和一个 keydir 目录。gitosis.conf 用来保存项目,用户和权限等版本库配置,而 keydir 用来保存用户的 ssh key。因为 gitosis-admin 也是 Git 的版本库,所以在修改完配置之后,只需要简单的 commit & push,就可以很快很方便的更新服务器的配置了。接下来就用 Gitosis 创建新版本库和添加授权用户。

创建新的版本库

gitosis.conf 里有 gitosis-admin 的默认配置,只要依样画葫芦创建一个新版本库即可。下面举例创建 local_test 版本库,把下面这段 code 追加到 gitosis.conf。

gitosis.conf

[group localteam]
writable = local_test
members = wyt@gentoo

这段 code 定义了新的版本库,包括开发小组的名称 "localteam",版本库的名称 "local_test",以及拥有写权限的小组成员 "wyt@gentoo"。接下来把新的版本库所配置 commit & push 到服务器上。
$ git commit -a -m "添加新的版本库 local_test"
$ git push

接下来在本地创建版本库,然后将其上传到服务器
$ mkdir local_test
$ cd local_test
$ git init
$ git remote add origin git@gentoo:local_test.git

# add & commit 一些文件,然后……

$ git push origin master:refs/heads/master

添加成员用户

添加版本库的成员用户的步骤可以分为两步。一是将用户的 SSH 公钥复制到 keydir/ 目录。二是编辑 gitosis.conf,将这些用户的名字加入 "members"。
$ cd gitosis-admin/
$ cp ~/zhangsan@gentoo.pub keydir/
$ cp ~/lisi@gentoo.pub keydir/
$ git add keydir/zhangsan@gentoo.pub keydir/lisi@gentoo.pub

编辑 gitosis.conf

gitosis.conf

[group localteam]
writable = local_test
members = wyt@gentoo zhangsan@gentoo lisi@gentoo

接下来,将设置提交到服务器
$ git commit -a -m '添加 local_test 版本库成员:张三、李四'
$ git push

选择需要输出的版本库


输出所有版本库

编辑 /etc/conf.d/git-daemon
GITDAEMON_OPTS="--syslog --base-path=/var/spool/gitosis/repositories/ --export-all"

选择输出版本库

编辑 /etc/conf.d/git-daemon
GITDAEMON_OPTS="--syslog --base-path=/var/spool/gitosis/repositories/"

然后在每个选择输出的版本库目录中,添加一个 git-daemon-export-ok 文件
$ sudo touch /var/spool/gitosis/repositories/local_test.git/git-daemon-export-ok

启动 git-daemon

# /etc/init.d/git-daemon start
# rc-update add git-daemon default

如果一切正常的话,我们应该已经大功告成,完成部署 Git + Gitosis 服务器了。现在可以试一下远程 clone。
$ git clone git://169.254.64.95/local_test.git



参考链接



2008-05-20 UPDATE

clone 只读版本库:
$ git clone git://169.254.64.95/local_test.git

clone 可读写版本库:
$ git clone git+ssh://git@169.254.64.95/local_test.git

创建新的可读写版本库:
$ git remote add origin git+ssh://git@169.254.64.95/new_local_test.git
$ git push origin master:refs/heads/master

2008年5月10日

有备无患:绕过 GHS 用自定义域名发布 Blogger

2007年1月,Google Blogger 的自定义域名功能推出不到一个星期,就被 GFW 给废了。原因就是 GFW 隔断了国内用户对 Google 的免费主机托管服务 ghs.google.com 的访问。

今天试着将 App Engine 应用部署到自己域名的时候,发现 App Engine 不需要将 CNAME record 指向 ghs.google.com,从而可以避开 GFW。而同样的方法也可以适用于 Blogger。方法如下:

  1. 把 Blogger 的发布方式切换成“自定义域名(Custom Domain)”。在“你的域名(Your Domain)”一栏中填上域名,比如,py.thonic.org。保存设置(Save Settings)。
  2. 在你的域名注册商那里,修改域名(thonic.org)的 DNS 设置。为子域名(py)添加一条 A record,指向下面四个 IP 地址的其中之一。举例来说,就是添加这样一条记录:py.thonic.org 86400 IN A 216.239.34.21
    • 216.239.32.21
    • 216.239.34.21
    • 216.239.36.21
    • 216.239.38.21

DNS 设置的改动需要一段时间来完成,一般不会超过24小时。这样就可以重新使用 Blogger 的自定义域名功能了,只是,这次又可以持续多久呢?

2008-06-26 UPDATE

我把上面的 IP 绑定到自己的域名了,ghs.luliban.com。以后也可以像 ghs.google.com 一样,添加一条 CNAME 记录到 ghs.luliban.com 来绑定 Google Blogger 或者 Google Apps 了。

2008年5月9日

有备无患:在 Google App Engine上应用豆瓣 API 的授权认证

上次说到了在 App Engine 上应用的豆瓣的 Python 客户端,但是那个版本(0.1.1)的客户端并没有包括 OAuth 授权认证的功能。如果想要让用户授权,以访问那些受保护的资源,以及添加、修改或删除用户的收藏,需要从豆瓣 Python 客户端的 SVN 中获取最新的开发版本(r22)。据豆瓣的开发人员 hongqn 说,OAuth Client 基本开发完毕,已经进入内测 bug 的阶段。

和 GData Python 客户端一样,开发版本的 OAuth Client 也是用 Python 自带的 httplib 模块来处理 HTTP 请求,所以原始的客户端不能直接在 App Engine 上使用,必须先将 httplib 替换成 urlfetch。现在只需要修改两个函数,但是豆瓣如果能像 GData Python 客户端一样把使用 httplib 的部分封装起来,甚至提供一个使用 urlfetch 的替换模块就更好了,希望豆瓣能采纳这个建议。下面是具体步骤,如果有什么问题,还请留言告知。

1,从 trunk 中 checkout 最新的豆瓣 Python 客户端开发版本
$ svn co http://douban-python.googlecode.com/svn/trunk/ douban-python/

2,修改客户端的 OAuth Client
$ cp douban-python/douban ~/doupye/douban -rf
$ cd ~/doupye/douban/
$ gvim client.py

client.py

# import httplib
from google.appengine.api import urlfetch

class OAuthClient:
    ... ...
    def fetch_token(self, oauth_request):
        # 被注释掉的是原来使用 httplib 的部分
        # connection = httplib.HTTPConnection("%s:%d" % (self.server, 80))
        # connection.request('GET', oauth_request.http_url,
        #     headers=oauth_request.to_header())
        # response = connection.getresponse()
        # r = response.read()
        url = oauth_request.http_url
        result = urlfetch.fetch(url, headers=oauth_request.to_header())
        r = result.content
        ... ...

    def access_resource(self, method, url, body=None):
        ... ...
        # connection = httplib.HTTPConnection("%s:%d" % (self.server, 80))
        # connection.request(method, url, body=body,
        #     headers=headers)
        # return connection.getresponse()
        result = urlfetch.fetch(url, payload=body, method=method, headers=headers)
        return result.content

3,使用 OAuth 授权的过程如下,在 App Engine SDK 提供的控制台(Interactive Console)中运行:
from douban.client import OAuthClient

client = OAuthClient(key=MY_API_KEY, secret=MY_SECRET)

# 获取未授权的Request Token
key, secret = client.get_request_token()
print key, secret
>>> c14023315549fe3743c17993ff4dfaa5 91af6245103ec3b7

# 获取请求用户授权的页面的 URL
url = client.get_authorization_url(key, secret)
print url
>>> http://www.douban.com/service/auth/authorize?oauth_token=a9e487ac36e0ba9efdba970534a22fce

# 将 URL 复制到浏览器中,用户可以选择同意或者拒绝授权

# 用户完成授权后,使用授权后的 Request Token 换取 Access Token
key, secret = client.get_access_token(key, secret)
if key:
    # 使用 Access Token 登录
    login = client.login(key, secret)
    print login
>>> True

# 访问受保护资源
collections = client.access_resource(method='GET',
    url='http://api.douban.com/people/wyt/collection?cat=book')
for entry in collections.entry:
    print entry.title.text
>>>
听过 人として軸がぶれている
想读 Antipatterns
想读 新企业的起源与演进
看过 .hack//G.U. Trilogy
想听 ワイルドストロベリー
在听 The Flower Book
在听 E=MC²
听过 越长大越孤单
想读 Investing 101
想读 The Ecology of Commerce

订阅我的博客

搜索我的博客

正在加载...

我的豆瓣广播

分享阅读

豆瓣秀

休斯敦火箭

我的文章归档

版权申明