nadoka/nadoka

View on GitHub
plugins/opensearchbot.nb

Summary

Maintainability
Test Coverage
# -*-ruby-*- #
# Copyright (C) 2011 Kazuhiro NISHIYAMA
#
# This program is free software with ABSOLUTELY NO WARRANTY.
# You can re-distribute and/or modify this program under
# the same terms of the Ruby's license.
#

=begin

== Usage with irc client

  bing> keyword
    -> search keyword by bing

  googlecode> keyword
    -> search keyword by Google Code Search Data API (Deprecated)

  koders> keyword
    -> search keyword by koders

== Configuration:

  BotConfig << {
    :name => :OpenSearchBot,
    :bot_name => 'bing',
    :ch => //,
    :referer => 'https://github.com/nadoka/nadoka',
    :ch_kcode => :jis,
    :html => 'http://www.bing.com/search?q={searchTerms}',
    :rss => 'http://api.search.live.com/rss.aspx?source=web&query={searchTerms}'
,
  }

  BotConfig << {
    :name => :OpenSearchBot,
    :bot_name => 'googlecode',
    :ch => //,
    :ch_kcode => :jis,
    :referer => 'https://github.com/nadoka/nadoka',
    # Google Code Search Data API (Deprecated)
    # http://code.google.com/intl/ja/apis/codesearch/docs/2.0/developers_guide.h
tml
    :html => 'http://www.google.com/codesearch?q={searchTerms}',
    :rss => 'http://www.google.com/codesearch/feeds/search?q={searchTerms}',
  }

  BotConfig << {
    :name => :OpenSearchBot,
    :bot_name => 'koders',
    :ch => //,
    :referer => 'https://github.com/nadoka/nadoka',
    :ch_kcode => :jis,
    # http://www.koders.com/search/KodersDescriptionOS1_1.xml
    :html => 'http://www.koders.com/?s={searchTerms}',
    :rss => 'http://www.koders.com/?s={searchTerms}&results=code&output=rss&OSve
rsion=1.1',
  }

=end

require 'open-uri'
require 'uri'
require 'cgi'

class OpenSearch
  def initialize(options)
    @html = options[:html]
    @rss = options[:rss]
    @referer = options[:referer] || 'https://github.com/nadoka/nadoka'
  end

  def result(key)
    escaped_key = CGI.escape(key)
    link = @html.sub(/\{searchTerms\}/) { escaped_key }
    uri = @rss.sub(/\{searchTerms\}/) { escaped_key }
    open(uri, "Referer" => @referer) do |f|
      result = f.read
      if /<([A-Za-z]+):totalResults>(\d+)<\/\1:totalResults>/ =~ result
        total = $2.to_i
        return "#{total.to_s.gsub(/\d(?=\d{3}+\z)/,'\&,')} result#{total > 1 ? 's' : ''} in #{link}"
      else
        return "#{key} - not found in #{link}"
      end
    end
  end
end

if __FILE__ == $0
  h = {
    'bing' => {
      :referer => 'https://github.com/nadoka/nadoka',
      :html => 'http://www.bing.com/search?q={searchTerms}',
      :rss => 'http://api.search.live.com/rss.aspx?source=web&query={searchTerms}',
    },
    'googlecode' => {
      :referer => 'https://github.com/nadoka/nadoka',
      # Google Code Search Data API (Deprecated)
      # http://code.google.com/intl/ja/apis/codesearch/docs/2.0/developers_guide.html
      :html => 'http://www.google.com/codesearch?q={searchTerms}',
      :rss => 'http://www.google.com/codesearch/feeds/search?q={searchTerms}',
    },
    'koders' => {
      :referer => 'https://github.com/nadoka/nadoka',
      # http://www.koders.com/search/KodersDescriptionOS1_1.xml
      :html => 'http://www.koders.com/?s={searchTerms}',
      :rss => 'http://www.koders.com/?s={searchTerms}&results=code&output=rss&OSversion=1.1',
    },
    'youtube' => {
      :referer => 'https://github.com/nadoka/nadoka',
      :html => 'http://www.youtube.com/results?search_query={searchTerms}',
      :rss => 'http://gdata.youtube.com/feeds/api/videos?q={searchTerms}',
    },
  }
  engine = ARGV.shift
  if h.key?(engine)
    open_search = OpenSearch.new(h[engine])
    ARGV.each do |key|
      result = open_search.result(key)
      puts result
    end
  else
    STDERR.puts "usage: #{$0} {#{h.keys.sort.join('|')}} key ..."
  end
  exit
end

class OpenSearchBot < Nadoka::NDK_Bot
  def bot_initialize
    if @bot_config.key?(:channels)
      channels = '\A(?:' + @bot_config[:channels].collect{|ch|
        Regexp.quote(ch)
      }.join('|') + ')\z'
      @available_channel = Regexp.compile(channels)
    else
      @available_channel = @bot_config[:ch] || //
    end

    @bot_name = @bot_config[:bot_name] || 'OpenSearchBot'
    @open_search = OpenSearch.new(@bot_config)
    @pattern = @bot_config[:pattern] || /\A#{Regexp.quote(@bot_name)}\s*[<:>]\s*(.+)/
    @ch_kcode = @bot_config[:ch_kcode]
  end

  def on_privmsg prefix, ch, msg
    if @pattern =~ msg
      key = $1
      if @ch_kcode == :jis
        ret = @open_search.result(key.toutf8).tojis
      else
        ret = @open_search.result(key)
      end
      send_notice ch, "#{@bot_name} bot: #{ret}"
    end
  end
end