root/lang/ruby/misc/socialskk/socialskk.rb

Revision 30522, 3.7 kB (checked in by shunirr, 12 months ago)

lang/ruby/misc/socialskk/socialskk.rb fix cache bug

  • Property svn:executable set to *
Line 
1#!/usr/bin/env ruby
2
3require 'optparse'
4require "ostruct"
5require "thread"
6require 'socket'
7require 'uri'
8require 'net/http'
9require 'timeout'
10require 'yaml'
11
12Net::HTTP.version_1_2
13
14class SocialSKK
15  VERSION_STRING   = "SocialSKK0.2 "
16
17  CLIENT_END       = ?0
18  CLIENT_REQUEST   = ?1
19  CLIENT_VERSION   = ?2
20  CLIENT_HOST      = ?3
21  SERVER_ERROR     = ?0
22  SERVER_FOUND     = ?1
23  SERVER_NOT_FOUND = ?4
24
25  BUFSIZE    = 512
26  TIMEOUT    = 10
27
28  def initialize(host, port, proxy, cache_time, cache=nil)
29    @host  = host
30    @port  = port
31    @proxy = proxy
32    @cache = cache || {}
33    @cache_time = cache_time
34    @ts = TCPServer.open(@host, @port)
35    puts "server is on #{@ts.addr[1..-1].join(":")}"
36    puts "proxy is #{@proxy.to_s}" if @proxy
37    puts "cache keep time #{@cache_time}sec"
38  end
39
40  def mainloop
41    loop do
42      Thread.start(@ts.accept) do |s|
43        while cmdbuf = s.sysread(BUFSIZE)
44          case cmdbuf[0]
45          when CLIENT_END
46            break
47          when CLIENT_REQUEST
48            cmdend = cmdbuf.index(?\ ) || cmdbuf.index(?\n)
49            kana = cmdbuf[1 .. (cmdend - 1)]
50            ret = ''
51            begin
52              if kanji = search(kana)
53                ret.concat(SERVER_FOUND)
54                ret.concat(kanji)
55              else
56                ret.concat(SERVER_NOT_FOUND)
57                ret.concat(cmdbuf[1 .. -1])
58              end
59              ret.concat("\n")
60            rescue Exception
61              ret.concat(SERVER_ERROR)
62              ret.concat($!)
63            end
64            s.write(ret)
65          when CLIENT_VERSION
66            s.write(VERSION_STRING)
67          when CLIENT_HOST
68            ret = host(s)
69            s.write(ret)
70          end
71        end
72        s.close
73      end
74    end
75  end
76
77  private
78  def host(sock = nil)
79    if sock.nil?
80      hostname = Socket.gethostname
81      ipaddr = TCPSocket.getaddress(hostname)
82    else
83      hostname, ipaddr = sock.addr[2], sock.addr[3]
84    end
85
86    hostname + ':' + ipaddr + ': '
87  end
88
89  def search(kana)
90    if @cache[kana] and Time.now < (@cache[kana][:ctime] + @cache_time)
91      @cache[kana][:kanji]
92    else
93      kanji = social_ime_search(kana)
94      @cache[kana] = {
95        :kanji => kanji,
96        :ctime => Time.now
97      }
98      kanji
99    end
100  end
101
102  def social_ime_search(kana)
103    size = kana.size / 2
104    kanji = '/'
105    begin
106      timeout(TIMEOUT) do
107        http = Net::HTTP.new('www.social-ime.com', 80)
108        http = Net::HTTP.new('www.social-ime.com', 80, @proxy.host, @proxy.port) if @proxy
109        http.start do |h|
110          res = h.get("/api/?string=#{URI.escape(kana)}&resize[0]=+#{size}")
111          kanji += res.body.to_s.split("\n").join('/').gsub(/\t/, '/')
112        end
113      end
114    rescue
115      kanji = nil
116    end
117    kanji
118  end
119end
120
121def time_parse(str)
122  n, u = str.scan(/(\d+)([dhms]?)/)[0]
123  n = n.to_i
124  case (u)
125  when "d"
126    n *= 24 * 60 * 60
127  when "h"
128    n *= 60 * 60
129  when "m"
130    n *= 60
131  end
132  n
133end
134
135opts = OpenStruct.new({
136  :port   => 55100,
137  :host   => '0.0.0.0',
138  :proxy  => nil,
139  :cache_time => 3600,
140})
141
142OptionParser.new do |parser|
143  parser.instance_eval do
144    self.banner  = "Usage: #{$0} [opts]"
145
146    separator ''
147    separator 'Options:'
148    on('-p', '--port 55100', 'Listen port number') do |port|
149      opts.port = port
150    end
151    on('-h', '--host "0.0.0.0"', 'Listen hostname') do |host|
152      opts.host = host
153    end
154    on('-x', '--proxy "http://proxy.example.com:8080"', 'HTTP Proxy server') do |proxy|
155      opts.proxy = URI.parse(proxy)
156    end
157    on('-c', '--cache-time 1h', 'Cache keep time') do |ct|
158      opts.cache_time = time_parse(ct)
159    end
160
161    parse!(ARGV)
162  end
163end
164
165ss = SocialSKK.new(opts.host, opts.port, opts.proxy, opts.cache_time)
166ss.mainloop
167
Note: See TracBrowser for help on using the browser.