mcorp/locasms

View on GitHub
lib/locasms/rest_client.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

require 'json'
require 'net/http'

module LocaSMS
  # Class that handle http calls to LocaSMS api
  # @see https://github.com/mcorp/locasms/wiki/A-API-de-envio
  #   List of avaiable services
  class RestClient
    attr_accessor :base_url, :base_params

    # Creates a new instance of the RestClient class
    # @param [String] base_url a well formed url
    # @param [Hash] base_params base params to send on every call
    def initialize(base_url, base_params = {})
      @base_url    = base_url
      @base_params = base_params
    end

    # Performs a GET call for an action
    # @param [String, Symbol] action the given action to perform
    # @param [Hash] params given parameters to send
    # @return [Hash] json parsed response
    #
    # @example Calling with no extra parameters
    #
    #     client = LocaSMS::RestClient('http://localhost:3000', lgn: 'LOGIN', pwd: 'PASSWORD')
    #     # => GET http://localhost:3000?lgn=LOGIN&pws=PASSWORD&action=getballance
    #     client.get :getballance
    #     # => {"status"=>1,"data"=>341,"msg"=>nil}
    #
    # @example Calling with extra parameters
    #
    #     client = LocaSMS::RestClient('http://localhost:3000', lgn: 'LOGIN', pwd: 'PASSWORD')
    #     # => GET http://localhost:3000?lgn=LOGIN&pws=PASSWORD&action=holdsms&id=345678
    #     client.get :holdsms, id: 345678
    #     # => {"status"=>1,"data"=>nil,"msg"=>"SUCESSO"}
    #
    # @see https://github.com/mcorp/locasms/wiki/A-API-de-envio#lista-das-a%C3%A7%C3%B5es-dispon%C3%ADveis
    #   List of avaiable actions
    # @raise [LocaSMS::InvalidOperation] when asked for an invalid operation
    # @raise [LocaSMS::InvalidLogin] when the given credentials are invalid
    def get(action, params = {})
      params = params_for action, params

      uri = URI.parse(base_url)
      uri.query = URI.encode_www_form(params)
      response = Net::HTTP.get_response(uri).body

      parse_response(action, response)
    end

    # Composes the parameters hash
    # @param [String, Symbol] action the given action to perform
    # @param [Hash] params given parameters to send
    # @return [Hash]
    #
    # @example
    #
    #    client = LocaSMS::RestClient('http://localhost:3000', lgn: 'LOGIN', pwd: 'PASSWORD')
    #    client.params_for :ACTION, a: 1, b: 2
    #    # => { action: :ACTION, lgn: 'LOGIN', pwd: 'PASSWORD', a: 1, b: 2 }
    #
    # @see https://github.com/mcorp/locasms/wiki/A-API-de-envio#lista-das-a%C3%A7%C3%B5es-dispon%C3%ADveis
    #   List of avaiable actions
    def params_for(action, params = {})
      { action: action }.merge(base_params).merge(params).select { |_k, v| v }
    end

    # Parses a result trying to get it in json
    # @param [String, Symbol] action the given action to perform
    # @param [String] response body
    # @return [Hash] json parsed response
    # @raise [LocaSMS::InvalidOperation] when asked for an invalid operation
    # @raise [LocaSMS::InvalidLogin] when the given credentials are invalid
    def parse_response(action, response)
      raise InvalidOperation.new(action: action) if response.match?(/^0:OPERACAO INVALIDA$/i)

      j = begin
        MultiJson.load(response)
      rescue StandardError
        { 'status' => 1, 'data' => response, 'msg' => nil }
      end

      return j if (j['status'] == 1) || (action == :getstatus)

      raise InvalidLogin.new(action: action) if j['msg'].match?(/^falha ao realizar login$/i)

      raise LocaSMS::Exception.new(message: j['msg'], raw: response, action: action)
    end
  end
end