IRCチャットでWebページのクリップ
http://news.yoosee.net/hiki.cgi?%A5%CB%A5%E5%A1%BC%A5%B9%A5%C8%A1%BC%A5%AD%A5%F3%A5%B0
チャットで出たURLを自動的にニューストーキングにクリップする機能。
これを見て、なかなかいいなと思ったので、似たような仕様で、HikiのBBSプラグインにクリップするものをNadokaさん(http://www.atdot.net/nadoka/nadoka.ja.html)のbotで作ってみた。
仕様はこんなかんじ。
(sshi) 僕の日記 http://d.hatena.ne.jp/sshi (bot) http://d.hatena.ne.jp/sshi < (1)
誰かの発言の中にURLが登場すると、それをHikiのBBSの新しいエントリとして追加し、そのURLにバインドしたIDを返す。上の例では、二行目でbotが結果を返している。ここのURLがID1番にバインドされました。この後、IDを利用してそのURLにコメントがつけられます。
(dareka) つまんない日記だね<1 (sshi) …
というふうに、<とIDを使った発言をすると、その発言をコメントとしてさっきのURLのところにつける。この例では「つまんない日記だね」というコメントがdarekaの名前で登録される。ちなみに、#listと発言すると現在管理しているURL一覧が表示される。IDはたんにそのURLが何番目にはいってるかを示しているだけ。
botの設定では、対象のHikiのURLとBBSプラグインがあるページの名前を指定しておく。いまんとこ一つだけしか指定できない。
以下ソース。長いのでおる。HikiのBBSに登録するコードは正直いってひどい。HikiになにかAPIが欲しいなあ。
# BotConfig = { # :HikiLog => { # :url => 'http://example.com/path/to/hiki/', # :page => 'BBSPageName', # } # } class HikiLog < Nadoka::NDK_Bot require 'kconv' module Utils require 'net/http' require 'open-uri' require 'kconv' module_function def get_title(targeturl) resultstr = get(targeturl) html = Kconv.toeuc(resultstr) if html =~ /<title\s*>(.*?)<\/title\s*>/m return $1.to_s end return nil end def get(url) ret = '' open(url) do |f| ret = f.read end return ret end def post(url,data) urlobj = URI.parse(url) result = nil Net::HTTP.start(urlobj.host,urlobj.port) do |http| result = http.post(urlobj.path,data) end return result end end module HikiBBS require 'cgi' module_function def make_add_data(page,no,name,msg) return {"name"=>CGI.escape(name), "msg"=>CGI.escape(msg), "comment"=>"true", "comment_no"=>no, "c"=>"plugin", "p"=>page, "plugin"=>"comment_post", "style"=>"0" }.map { |name,value| "#{name}=#{value}"}.join('&') end def make_post_data(page,name,subject,msg=' ') return { 'p'=>page, 'name'=>CGI.escape(name), 'subject'=>CGI.escape(subject), 'msg' => CGI.escape(msg), 'bbs_num' => '1', 'c' => 'plugin', 'comment' => 'true', #button 'plugin'=>'bbs_post', }.map { |name,value| "#{name}=#{value}"}.join('&') end def comment_add(url,page,name,no,msg) Utils.post(url,make_add_data(page,no,name,msg)) end def comment_post(url,page,name,subject,msg) Utils.post(url,make_post_data(page,name,subject,msg)) end end def bot_initialize @url = @bot_config[:url] @page = @bot_config[:page] @list = [""] end def get_thread_no_by_url(http) host = "#{@url}?#{@page}" page = Utils.get(host) if page =~ /#{Regexp.escape(http)}.*?<form action.*?"comment_no"\s*value="(\ [^"]*)"/m no = $1.to_i return no end return nil end def comment_add_by_url(name,url,msg) no = get_thread_no_by_url(url) return false if no == nil HikiBBS.comment_add(@url,@page,name,no,msg) return true end def new_comment_post(name,targeturl) msg = Utils.get_title(targeturl) || 'by bot' HikiBBS.comment_post(@url,@page,name,targeturl,msg) end def regist_url(msg,prefix) result = URI.extract(msg,%w(http https)) ret = [] result.each do |target| unless @list.include?(target) if get_thread_no_by_url(target) == nil new_comment_post(prefix.nick.to_s,target) end @list << target ret << [@list.index(target),target] end end return ret end def url_comment?(prefix,msg) if msg =~ /^(.*)<\s*(\d*)(.*)$/ msg = $1 no = $2.to_i return if no == 0 http = @list[no] if http != nil unless comment_add_by_url(prefix.nick.to_s,http,Kconv.toeuc(msg.to_s)) send_notice(ch,"#{msg}<#{http} (#{no}) failed") end end end end def on_privmsg(prefix,ch,msg) url_comment?(prefix,msg) if msg =~ /^#list/ send_notice(ch,@list.inspect) else regist_url(msg,prefix).each do |item| no,http = item send_notice(ch,"#{http} < (#{no})") unless no == nil end end end end