Monday, December 24, 2007

Twitter はじめました

なんか周り(*1, *2)で twitterを使いはじめている人が増えてきたみたいなので、今さらながらはじめてみる。出遅れすぎているので ukai とかはとられていたのでフルネームで。http://twitter.com/fumitoshi_ukai
いちいちtwitter.comのページみにいったりするのは面倒なので Google Talk経由の設定をした。 こういうのは携帯からもやりたいよなーと思いつつ、少し探してみた。movatwitterだとパスワードを渡さないといけないのがすごく嫌だなぁ。そもそも携帯で Google Talk (XMPP/Jabber) client があればいいのにと思いつつ探してみたがこれも日本の携帯向けはあんまりなさげ。 というわけで keitaircぽいのをへろへろっと自作。code.google.comあたりにおいといたほうがいいかな。
#!/usr/bin/ruby1.8
#
# Copyright (c) 2007 Fumitoshi Ukai <ukai@debian.or.jp>
# This program is covered by the GNU General Public License 2 or later
#
# depends: ruby1.8, libxmpp4r-ruby1.8, libwebrick-ruby1.8,
#
# Configuration file: ~/.keitaixmpprc
# The file should contains the following variables:
## configuration file for keitaixmpp
# MYJID = 'yourname@gmail.com/XmppProxy'
# MYJIDPASSWD = 'your-gmail-password'
# TARGETJID = 'twitter@twitter.com'
# HTTPADDR = '0.0.0.0'
# HTTPPORT = 8088
# HTTPUSER = 'username'
# HTTPPASSWD = 'password'
#
$KCODE = "u"
require 'kconv'
require 'xmpp4r'
require 'webrick'
require 'webrick/httpauth'
require 'webrick/httputils'

class XmppProxy
 attr_reader :messages
 attr_reader :targetjid
 MAX_LINES = 50

 def initialize(jid, pass, targetjid)
   # Jabber::debug = true
   @pass = pass
   @targetjid = targetjid
   @client = Jabber::Client.new(Jabber::JID.new(jid))
   @messages = []
   @closed = false

   @client.connect
   @client.auth(@pass)
   @client.send(Jabber::Presence::new)
   @client.add_message_callback do |message|
     if message.type == :error
       return
     end
     from = message.from
     if from.nil?
       return
     end
     if from.strip == @targetjid.strip
       addmsg(message.body)
     end
   end
   @client.on_exception do |ex, stream, event|
     $stderr.puts "Exception #{ex} #{event}"
     if @closed
       $stderr.puts "closed, bye"
     end
     @client.connect
     @client.auth(@pass)
     @client.send(Jabber::Presence::new)
   end
   @keepalive = Thread.new do
     while not @closed
       if @client.is_connected?
         @client.send(Jabber::Presence::new)
       end
       sleep 30
     end
   end
 end

 def send(msg)
   @client.send(Jabber::Message.new(@targetjid, msg).set_type(:chat))
   addmsg("me #{msg}")
 end

 def addmsg(msg)
   if msg.nil?
     return
   end
   @messages.unshift(msg)
   if @messages.length > MAX_LINES
     @messages.pop
   end
 end

 def close()
   @client.close
   @closed = true
   @keepalive.join
 end
end # XmppProxy

class XmppServlet < WEBrick::HTTPServlet::AbstractServlet
 def initialize(server, *options)
   @xmppproxy, @user, @pass, = options
 end

 def auth(req, res)
   unless @user.nil? and @pass.nil?
     WEBrick::HTTPAuth.basic_auth(req, res, "XmppServlet") do |user, pass|
       user == @user && pass == @pass
     end
   end
 end

 def do_GET(req, res)
   auth(req, res)
   show_page(req, res)
 end

 def do_POST(req, res)
   auth(req, res)
   if ! req.query["m"].empty?
     @xmppproxy.send(Kconv.kconv(req.query["m"], Kconv::UTF8, Kconv::SJIS))
   end
   show_page(req, res)
 end

 def show_page(req, res)
   res.status = 200
   res.content_type = "text/html; charset=Shift_JIS"
   msg = WEBrick::HTMLUtils::escape(@xmppproxy.messages.join("\n"))
   res.body = <<HTML
<html>
<head> <meta http-equiv="Cache-Control" Content="max-age=0"/>
<title>XmppProxy</title>
</head>
<body>
<form action="#{req.request_uri.path}" method="POST">
<input type="text" name="m" size="10">
<input type="submit" accesskey="1" value="OK[1]">
</form>
<pre>
#{Kconv.kconv(msg, Kconv::SJIS, Kconv::UTF8)}
</pre>
<p>#{@xmppproxy.targetjid}</p>
</body></html>
HTML
 end
end # XmppServlet

if __FILE__ == $0
 CONFIGFILE = "~/.keitaixmpprc"

 load CONFIGFILE
 xmpp = XmppProxy.new(MYJID, MYJIDPASSWD, TARGETJID)
 server = WEBrick::HTTPServer.new({:BindAddress => HTTPADDR,
                                    :Port => HTTPPORT})
 ['INT', 'TERM'].each do |signal|
   Signal.trap(signal) { server.shutdown }
 end
 server.mount('/', XmppServlet, xmpp, HTTPUSER, HTTPPASSWD)
 server.start
end
追記(2007/12/27 02:30): code.google.com/hostingにおいてみました