Hikiのエントリをメールで書いてXML-RPCごしにPOST

November 30th, 2006  |  Published in hack

Motivation

W-ZERO3でWikiのページをつくるとき、やっぱりブラウザからだとやりづらいのです。

あと、大量にあるBlosxomのエントリを、Wikiにまとめて移行したいけれど、手作業でやるには面倒すぎる。うまいこと自動化したいのです。

これらを解決するために、XML-RPCでWikiにエントリをPOSTするようなスクリプトを書きました。

hiki_client.rb

さっさと書いてみました。 40行程度。

#
# Hiki Client
# $Id: hiki_client.rb 537 2006-11-28 00:25:58Z takayama $
#
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
#
# Wiki post from mail using XML-RPC.
#
# $Id: wiki_post.rb 547 2006-11-29 15:16:19Z takayama $
#
# mail format:
#   1st line : Title
#   2nd line : Keywords
#   others   : content


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サマサマです。

Tags: ,

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だとこうさくっとは書けません。

Tags: ,

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については、あたりが詳しそうです。

Tags:

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)

Tags: , , ,