diff --git a/lib/rgrb/plugin/url_fetch_title/generator.rb b/lib/rgrb/plugin/url_fetch_title/generator.rb index 261f8646..cfe9058b 100644 --- a/lib/rgrb/plugin/url_fetch_title/generator.rb +++ b/lib/rgrb/plugin/url_fetch_title/generator.rb @@ -17,10 +17,10 @@ module UrlFetchTitle class Generator include ConfigurableGenerator - # HTTP ステータスコード + # HTTP ステータスの Reason-Phrase # @see https://www.iana.org/assignments/http-status-codes/http-status-codes-1.csv # @see http://tools.ietf.org/html/rfc7231#section-6 - HTTP_STATUS_CODES = { + HTTP_STATUS_REASON_PHRASE = { 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', @@ -80,62 +80,87 @@ class Generator 511 => 'Network Authentication Required' } - def initialize(*args) - super - - @agent = Mechanize.new - @agent.user_agent = "RGRB/#{RGRB::VERSION} (Creator's Network IRC bot)" - end - def configure(config_data) @no_ssl_verify = config_data['NoSSLVerify'] || [] - @agent.open_timeout = config_data['OpenTimeout'] - @agent.read_timeout = config_data['ReadTimeout'] + @open_timeout = config_data['OpenTimeout'] + @read_timeout = config_data['ReadTimeout'] @reply_prefix = config_data['ReplyPrefix'] || 'Fetch title: ' @reply_suffix = config_data['ReplySuffix'] || '' end # 誰かが発言した URL にアクセスし、ページの title タグを取得する - # @param [String] タイトルを取得するページのURL + # @param [String] url タイトルを取得するページのURL # @return [String] 取得したタイトル def fetch_title(url) - if no_ssl_verify?(url) - @agent.verify_mode = OpenSSL::SSL::VERIFY_NONE - end + agent = new_agent(url) + body = + begin + page = agent.get(url) - begin - page = @agent.get(url) - body = if page.respond_to?(:title) page.title else - response = page.response - contents = [ - response['Content-Type'], - response['Content-Length'].to_i.to_s(:human_size) - ] - "(#{contents.join('; ')})" + http_header_to_body(page.response) end - rescue SocketError - body = '(サーバーに接続できませんでした)' - rescue Net::HTTP::Persistent::Error - body = '(タイムアウト)' - rescue Mechanize::ResponseCodeError => response_code_error - response_code = response_code_error.response_code.to_i - reason_phrase = - if HTTP_STATUS_CODES.has_key?(response_code) - HTTP_STATUS_CODES[response_code] - else - '不明なエラー' - end - body = "(#{response_code} #{reason_phrase})" - end + rescue SocketError + '(サーバーに接続できませんでした)' + rescue Net::HTTP::Persistent::Error + '(タイムアウト)' + rescue Mechanize::ResponseCodeError => response_code_error + response_code_to_body(response_code_error.response_code.to_i) + end "#{@reply_prefix}#{body}#{@reply_suffix}" end + # HTTP ヘッダをメッセージに変換する + # @param [Mechanize::Headers] header HTTP ヘッダ + # @return [String] + def http_header_to_body(header) + contents = [ + header['Content-Type'], + header['Content-Length'].to_i.to_s(:human_size) + ] + + "(#{contents.join('; ')})" + end + private :http_header_to_body + + # HTTP ステータスコードをメッセージに変換する + # @param [Fixnum] response_code HTTP ステータスコード + # @return [String] + def response_code_to_body(response_code) + reason_phrase = + if HTTP_STATUS_REASON_PHRASE.key?(response_code) + HTTP_STATUS_REASON_PHRASE[response_code] + else + '不明なエラー' + end + + "(#{response_code} #{reason_phrase})" + end + private :response_code_to_body + + # 新しいエージェントを作り、設定して返す + # @param [String] url タイトル取得元の URL + # @return [Mechanize] + def new_agent(url) + agent = Mechanize.new + agent.user_agent = + "RGRB/#{RGRB::VERSION} (Creators Network IRC bot)" + agent.open_timeout = @open_timeout + agent.read_timeout = @read_timeout + + if no_ssl_verify?(url) + agent.verify_mode = OpenSSL::SSL::VERIFY_NONE + end + + agent + end + private :new_agent + # 与えられた URL が、自己署名証明書を許可するドメインか調べる - # @param [String] 調べる URL + # @param [String] url 調べる URL # @return [Boolean] def no_ssl_verify?(url) hostname = URI.parse(url).hostname