jimmycuadra/lita-wordnik

View on GitHub
lib/lita/handlers/wordnik.rb

Summary

Maintainability
A
1 hr
Test Coverage
require "lita"

module Lita
  module Handlers
    class Wordnik < Handler
      NO_RESULTS = "Wordnik doesn't have any results for that."

      config :api_key, type: String, required: true

      route(/define\s+(.+)/i, :define, command: true, help: {
        "define WORD" => "Get the definition for WORD."
      })
      route(/^syn(?:onyms)?\s+(.*)$/i, :synonyms, command: true, help: {
        "synonyms WORD" => "Get synonyms for WORD."
      })
      route(/^words\s*like\s+(.*)$/i, :synonyms, command: true, help: {
        "words like WORD" => "Get synonyms for WORD."
      })
      route(/^ant(?:onyms)?\s+(.*)$/i, :antonyms, command: true, help: {
        "antonyms WORD" => "Get antonyms for WORD."
      })
      route(/^words\s*unlike\s+(.*)$/i, :antonyms, command: true, help: {
        "words unlike WORD" => "Get antonyms for WORD."
      })

      class << self
        def define_wordnik_method(name, getter_name)
          define_method(name) do |response|
            word = encode_word(response.matches[0][0])
            result = send(getter_name, word)
            response.reply(result)
          end
        end
      end

      define_wordnik_method :define, :definition_for
      define_wordnik_method :synonyms, :synonyms_for
      define_wordnik_method :antonyms, :antonyms_for

      private

      def definition_for(word)
        url = "http://api.wordnik.com/v4/word.json/#{word}/definitions"
        Lita.logger.debug("Making Wordnik API request to #{url}.")
        process_response http.get(
          url,
          api_key: Lita.config.handlers.wordnik.api_key,
          limit: 1,
          includeRelated: false,
          useCanonical: true,
          includeTags: false
        )
      end

      def synonyms_for(word)
        url = "http://api.wordnik.com/v4/word.json/#{word}/relatedWords"
        Lita.logger.debug("Making Wordnik API request to #{url}.")
        process_response http.get(
          url,
          api_key: Lita.config.handlers.wordnik.api_key,
          useCanonical: true,
          relationshipTypes: "synonym",
          limitPerRelationshipType: 5
        )
      end

      def antonyms_for(word)
        url = "http://api.wordnik.com/v4/word.json/#{word}/relatedWords"
        Lita.logger.debug("Making Wordnik API request to #{url}.")
        process_response http.get(
          url,
          api_key: Lita.config.handlers.wordnik.api_key,
          useCanonical: true,
          relationshipTypes: "antonym",
          limitPerRelationshipType: 5
        )
      end

      def encode_word(word)
        begin
          URI.parse(word)
          return word
        rescue URI::InvalidURIError
          return URI.encode(word)
        end
      end

      def process_response(response)
        case response.status
        when 400
          "Wordnik didn't understand that word."
        when 404
          NO_RESULTS
        when 200
          data = MultiJson.load(response.body).first

          if data
            case data["relationshipType"]
            when "synonym"
              "(synonyms): #{data["words"].join(', ')}"
            when "antonym"
              "(antonyms): #{data["words"].join(', ')}"
            else
              "#{data["word"]} (#{data["partOfSpeech"]}): #{data["text"]}"
            end
          else
            NO_RESULTS
          end
        else
          Lita.logger.error("Wordnik request failed: #{response.inspect}")
          "Wordnik request failed. See the Lita logs."
        end
      end

      Lita.register_handler(Wordnik)
    end
  end
end