mailup/mailup-ruby

View on GitHub
lib/mailup.rb

Summary

Maintainability
A
2 hrs
Test Coverage
require 'oauth2'
require 'multi_json'
require "net/https"
require 'json'
require "uri"

require 'mailup/version'
require 'mailup/errors'
require 'mailup/console/base'
require 'mailup/console/email'
require 'mailup/console/group'
require 'mailup/console/images'
require 'mailup/console/import'
require 'mailup/console/list'
require 'mailup/console/recipient'
require 'mailup/console/user'
require 'mailup/public/base'
require 'mailup/public/console'
require 'mailup/stats/base'
require 'mailup/stats/message'
require 'mailup/stats/recipient'

module MailUp
  class API
    attr_accessor :access_token, :debug, :host, :path, :credentials

    # Initialize a new (thread-safe) API instance.
    #
    # @param [Hash] credentials for connecting to the MailUp API.
    #   * client_id [String]
    #   * client_secret [String]
    #   * oauth [Hash]
    #     * token [String]
    #     * refresh_token [String]
    #     * expires_at [Integer]
    # @param [Boolean] debug whether or not to raise errors.
    #
    # @example
    #
    #   credentials = {
    #     client_id: "1324567890",
    #     client_secret: "123abc456def",
    #     oauth: {
    #       token: "1324567890",
    #       refresh_token: "1324567890",
    #       expires_at: 123456789,
    #     }
    #   }
    #   mailup = MailUp::API.new(credentials)
    #
    def initialize(credentials=nil, debug=false)
      @debug = debug
      @host = 'https://services.mailup.com'
      @path = ''
      @credentials = credentials

      # Validate the credentials
      raise Error.new, 'MailUp credentials missing' if credentials.nil? or !credentials.is_a?(Hash)
      [:client_id, :client_secret, :oauth].each do |key|
        raise Error.new, "MailUp credentials must include a #{key.to_s} key" unless credentials.has_key?(key)
      end
      raise Error.new, 'MailUp credentials :oauth must be a hash' unless credentials[:oauth].is_a?(Hash)
      [:token, :refresh_token, :expires_at].each do |key|
        raise Error.new, "MailUp credentials :oauth hash must include a #{key.to_s} key" unless credentials[:oauth].has_key?(key)
      end

      # Create a OAuth2 client instance
      client = OAuth2::Client.new(
        credentials[:client_id],
        credentials[:client_secret],
        site: @host,
        authorize_url: "/Authorization/OAuth/LogOn",
        token_url: "/Authorization/OAuth/Token",
        raise_errors: @debug
      )

      # Create an access_token instance
      @access_token = OAuth2::AccessToken.new(
        client,
        credentials[:oauth][:token],
        {
          refresh_token: credentials[:oauth][:refresh_token],
          expires_at: credentials[:oauth][:expires_at]
        }
      )
    end

    # Make a request with the Access Token.
    #
    # @param [Symbol] verb the HTTP request method
    # @param [String] path the HTTP URL path of the request
    # @param [Hash] opts the options to make the request with
    #
    def request(method, path, opts={}, &block) # :nodoc:
      unless @access_token == nil
        # Refresh token if needed
        @access_token = @access_token.refresh! if @access_token.expired?
        # Ensure the body is JSON
        opts[:body] = MultiJson.dump(opts[:body]) if opts[:body]
        # Set the headers
        opts[:headers] ||= {}
        opts[:headers].merge!(headers)
        # Make the request
        req = @access_token.send(method, path, opts)
        # Handle the response
        handle_response(req)
      end
    end

    # Make a request with for Provisioning Calls.
    #
    # @param [Symbol] verb the HTTP request method
    # @param [String] path the HTTP URL path of the request
    # @param [Hash] opts the options to make the request with
    #
    def provisioning_request(path, body = nil) # :nodoc:
      uri = URI.parse(@host)
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true
      http.verify_mode = OpenSSL::SSL::VERIFY_PEER

      req = Net::HTTP::Post.new(path, initheader = {'Content-Type' =>'application/json'})
      req.basic_auth @credentials[:client_id], @credentials[:client_secret]
      req.body = body.to_json

      http.request(req).body.to_json
    end

    # Make a GET request with the Access Token
    # @see #request
    #
    def get(path, opts={}, &block) # :nodoc:
      request(:get, path, opts, &block)
    end

    # Make a POST request with the Access Token
    # @see #request
    #
    def post(path, opts={}, &block) # :nodoc:
      request(:post, path, opts, &block)
    end

    # Make a PUT request with the Access Token
    # @see #request
    #
    def put(path, opts={}, &block) # :nodoc:
      request(:put, path, opts, &block)
    end

    # Make a PATCH request with the Access Token
    # @see #request
    #
    def patch(path, opts={}, &block) # :nodoc:
      request(:patch, path, opts, &block)
    end

    # Make a DELETE request with the Access Token
    # @see #request
    #
    def delete(path, opts={}, &block) # :nodoc:
      request(:delete, path, opts, &block)
    end

    # Handle the response of a request
    def handle_response(response) # :nodoc:
      case response.status
      when 400
        raise BadRequest.new response.parsed
      when 401
        raise Unauthorized.new
      when 404
        raise NotFound.new
      when 400...500
        raise ClientError.new response.parsed
      when 500...600
        raise ServerError.new
      else
        case response.body
        when ''
          true
        when is_a?(Integer)
          response.body
        else
          response.parsed
        end
      end
    end

    # Set the request headers
    def headers # :nodoc:
      {
        'User-Agent' => "mailup-ruby-#{VERSION}",
        'Content-Type' => 'application/json; charset=utf-8',
        'Accept' => 'application/json'
      }
    end

    # Access the console API methods
    #
    # @example
    #
    #   lists = mailup.console.user.lists
    #
    def console
      Console::Base.new self
    end

    # Access the public API methods
    #
    # @example
    #
    #   activation = mailup.public.activation.new(...)
    #
    def public
      Public::Base.new self
    end

    # Access the email statistics API methods
    #
    # @example
    #
    #   views = mailup.stats.message.views_count(1)
    #
    def stats
      Stats::Base.new self
    end

  end
end