Hikiのエントリをメールで書いてXML-RPCごしにPOST
November 30th, 2006 | Published in hack
Motivation
W-ZERO3でWikiのページをつくるとき、やっぱりブラウザからだとやりづらいのです。
あと、大量にあるBlosxomのエントリを、Wikiにまとめて移行したいけれど、手作業でやるには面倒すぎる。うまいこと自動化したいのです。
これらを解決するために、XML-RPCでWikiにエントリをPOSTするようなスクリプトを書きました。
hiki_client.rb
さっさと書いてみました。 40行程度。
require 'xmlrpc/client'
class HikiClient
def initialize(url)
= url
= XMLRPC::Client.new2()
end
def getAllPages
.call('wiki.getAllPages')
end
def getPage(p)
.call('wiki.getPage', p)
end
def getPageInfo(p)
.call('wiki.getPageInfo', p)
end
def getTaggedPages(tag)
.call('wiki.getTaggedPages', tag)
end
def putPage(p, c, a)
begin
pages = .call('wiki.putPage', p, c, a)
rescue XMLRPC::FaultException => e
puts 'XMLRPC::FaultException : -----------------'
puts e.faultCode
puts e.faultString
puts '-----------------------'
end
end
def set_auth(u, p)
.user = u
.password = p
end
end
見たままのコードです。いちおうBasic認証にも対応。
wiki_post.rb
#!/usr/bin/env ruby
require 'hiki_client'
require 'tmail'
require 'kconv'
WIKI_URL = 'http://some.wiki.host/address/'
hc = HikiClient.new(WIKI_URL)
mail = TMail::Mail.parse(ARGF.read)
body = Kconv.toutf8(mail.body)
body = body.split(/n/)
title = body.shift
keywords = body.shift.split(/,/)
hc.putPage(title, body.join("n"), {'keyword' => keywords})
たったこれだけ。とっても簡単。
まとめ
これで、メールから手軽にWikiエントリが送れるようになりました。編集とかは面倒なのであとまわしです。
やっぱり言語にとって大切なのは、便利なライブラリがそろっていることと、お手軽さだということがよく分かります。実現したい機能をさっとつくれることが何よりも大事。 xmlrpc.rbとtmail.rbサマサマです。
HikiのXMLRPCに対するキーワード拡張
November 26th, 2006 | Published in hack
Hikiで、あるキーワードを持つWikiページの集合を返すようなXML-RPC拡張を書きました。19行程度。
背景
HikiでXML-RPCを使ったmigrationツールを書いています。 あるキーワードを持っているWikiページ郡をまとめて別のWikiにコピーする必要がありました。
Hikiに元々備わっているXML-RPCのインターフェイスを使ってやるには、
def getTaggedPages(tag)
pages = wiki.getAllPage();
acm = []
pages.each do |p|
info = wiki.getPageInfo(p)
if (info['keyword'].include? tag)
acm.push p
end
end
end
みたいなコードを書く必要がありそうです。 このコードでは、すべてのWikiページに対してwiki.getPageInfoのXML-RPCリクエストが飛ぶことになり、Wikiページ数に対してスケールしません。実際、手元でやってみたところえらく時間がかかります。
XML-RPCインターフェイスを拡張する
XML-RPCインターフェイスを定義している $HIKI/hiki/xmlrpc.rb
を見たところ、ちょこっと書き加えるだけでXML-RPCインターフェイスは追加できそうです。なので、ちょこちょこと書いてみました。
--- xmlrpc.rb.orig 2006-11-26 18:51:13.000000000 +0900
+++ xmlrpc.rb 2006-11-26 18:52:49.000000000 +0900
@@ -86,6 +86,25 @@
#add_multicall
#add_introspection
+
+ #
+ # getTaggedPages
+ # retrieve all pages having specified tag.
+ #
+ ('wiki.getTaggedPages') do |tag|
+ tag = utf8_to_euc( tag )
+ conf = Hiki::Config::new
+ db = Hiki::HikiDB::new( conf )
+
+ ret = []
+ db.pages.each do |p|
+ kws = db.get_attribute( p, :keyword )
+ if kws.include? tag
+ ret.push XMLRPC::Base64.new( euc_to_utf8( p ) )
+ end
+ end
+ ret
+ end
end
end
これで、1つのXML-RPCリクエストだけでキーワードを含む全てのWikiページを得ることができます。
まとめ
rubyのXML-RPCライブラリはお手軽で便利。 ActionScriptとかWebServiceKitだとこうさくっとは書けません。
Hikiで使えるXML-RPC API
September 5th, 2006 | Published in Uncategorized
さっきの続き。
Hiki総本山を探したのですがなさそうなので、Hikiで使えるXML-RPCのAPIをざっとリストにしておきます。Hikiのバージョンは0.8.6で。 Rubyコードを読まないひと向けの情報かも。
- wiki.getPage (page)
- wiki.getPageInfo (page)
- wiki.putPage (page, content, attributes)
- wiki.getAllPages()
/hiki/xmlrpc.rbから抽出しました。
各APIについては、あたりが詳しそうです。
Hikiでタグクラウド
August 22nd, 2006 | Published in hack
Rubyで書かれているWikiエンジンであるHikiで、タグクラウドを実現するプラグインを書きました。
ダウンロード
CodeRepos
背景
やっぱりカテゴリよりもタグの方が手軽です。 HIkiにはもともとキーワードというタグのような機能があったので、これを利用できないかと思い、keywordプラグインを使ってみたところ、ほぼ期待通りのことができて小躍りしていました。
んじゃせっかくだし、タグクラウド (tag cloud) みたいな表示もできないかな、とkeywordプラグインを改造してみました。フォントサイズのアルゴリズムなんかは、blosxomでのタグクラウド実装の1つであるBLOGGING IS FUTILE : Blosxom plugin tagging を参考にしました。
ライセンスは、Hiki及びBlosxom plugin taggingに従って、GPL v2以降です。
ソースは続きにて。
ソース
show keywords like tag-cloud
Licensing: GPL v2 or newer, http://www.gnu.org/licenses/gpl.txt
#
Original:
$Id: keyword.rb,v 1.5 2005/09/30 11:45:49 fdiary Exp $
Copyright (C) 2003 TAKEUCHI Hitoshi <>
THRESHOLD = 1
MAX = 156
MIN = 32
def keyword_cloud(key)
# sort by category
list = keywords(key).to_a.sort {|a,b| a[0].downcase <=> b[0].downcase}
max = 1
min = 0
list.each do |j|
sz = j[1].size
next if sz < THRESHOLD
max = sz if sz > max
min = sz if sz < min
end
diff = max - min
s = ''
list.each do |j|
sz = j[1].size
next if sz < THRESHOLD
category = j[0]
p = j[1]
fts = MIN + (((MAX-MIN)/diff.to_f) * (sz-min+1))
## for debug
# s << "<h4>"
# s << [sz, max, min, MIN, (MAX-MIN), diff, (MAX-MIN)/diff.to_f, (sz-min+1), fts].join(', ')
# s << "</h4>"
s << "<span id='tag' style='font-size:#{fts}%'>#{view_title(category)}</span> "
end
s
end
def keywords(*keyword)
keyword.collect! {|a| a.unescapeHTML}
key = Hash::new
do |info|
next unless info.values[0][:keyword]
info.values[0][:keyword].each do |k|
if keyword.size == 0 || keyword.index(k)
key[k] = [] unless key[k]
key[k] << info
end
end
end
key
end
def keyword_entries_n(pages)
p = j[1]
end
export_plugin_methods(:keyword_cloud)