POPFile の XMLRPC インタフェースを Ruby で叩く

XMLRPC::Client.call() を都度呼ぶのは苦痛なので、セッションキーの扱いも含めてラッパーを書いてみた。

# popfile.rb -- Using POPFile XMLRPC API in easier way
# by Autch, placed in *public domain*

require 'xmlrpc/client'

module POPFile
  class Session
    def initialize(*args)
      self.init(:new, *args) unless args.empty?
    end

    class << self
      def new2(*args)
        self.new.init(:new2, *args)
      end
      alias :new_from_uri :new2

      def new3(*args)
        self.new.init(:new3, *args)
      end
      alias :new_from_hash :new3
    end

    def init(name, *args)
      @serv = XMLRPC::Client.send(name, *args)
      self
    end

    def start
      proxy = @serv.proxy('POPFile/API')
      key = proxy.get_session_key('admin')
      client = Client.new(proxy, key)
      begin
        yield(client)
      ensure
        proxy.release_session_key(key) rescue nil
      end
    end

    class Client
      attr_reader :key

      def initialize(proxy, key)
        @proxy = proxy
        @key = key
      end

      def method_missing(name, *args)
        @proxy.send(name, @key, *args)
      end
    end
  end
end

if $0 == __FILE__ then
  s = POPFile::Session.new2('http://localhost:8081/RPC2')
  s.start do |client|
    client.get_buckets.each{|b|
      p [b, client.get_bucket_word_count(b), client.get_bucket_color(b) ]
    } 
  end
end

お試し部分にあるとおり、まず POPFile::Session を作る。new/new2/new3 の使い分けは XMLRPC::Client と同じなのでそっち参照。URI でつくれる new2 が便利。
そして POPFile::Session.start() をブロックつきで呼ぶと、ブロック引数に POPFile::Session::Client が来るので、これを POPFile XMLRPC API のメソッド名で叩くだけ。

こいつを使って、Maildir MH の inbox にあるメールを分類させてみるには、

autch@shion:~$ irb -rpopfile
irb(main):001:0> s = POPFile::Session.new2('http://localhost:8081/RPC2')
=> #<POPFile::Session:0x2ab55eb3ee88 @serv=#<XMLRPC::Client:0x2ab55eb3e4b0 @password=nil,
@http_header_extra=nil, @use_ssl=false, @host="localhost", @user=nil, @proxy_port=nil,
@cookie=nil, @create=nil, @port=8081, @http=#<Net::HTTP localhost:8081 open=false>,
@proxy_host=nil, @http_last_response=nil, @parser=nil, @auth=nil, @timeout=30,
@path="/RPC2">>
irb(main):002:0> s.start{|c|
                   Dir.glob('/home/autch/Mail/inbox/*').each{|f|
                     p [f, (c.classify(f) rescue nil) ]
                   } 
                   nil
                 }
["/home/autch/Mail/inbox/161", "general"]
["/home/autch/Mail/inbox/180", "mailmag"]
["/home/autch/Mail/inbox/179", "sourceforge"]
["/home/autch/Mail/inbox/145", "unclassified"]
["/home/autch/Mail/inbox/\267\350\272\321\241\246\273\331\312\247", nil]
["/home/autch/Mail/inbox/160", "general"]
["/home/autch/Mail/inbox/168", "spam"]
["/home/autch/Mail/inbox/172", "general"]
["/home/autch/Mail/inbox/49", "general"]
["/home/autch/Mail/inbox/169", "general"]
["/home/autch/Mail/inbox/7", "general"]
["/home/autch/Mail/inbox/197", "unclassified"]
(snip)
=> nil
irb(main):003:0>