├── lib ├── kickbox │ ├── error.rb │ ├── error │ │ └── client_error.rb │ ├── client.rb │ ├── http_client │ │ ├── response.rb │ │ ├── response_handler.rb │ │ ├── request_handler.rb │ │ ├── error_handler.rb │ │ └── auth_handler.rb │ ├── api │ │ └── kickbox.rb │ └── http_client.rb └── kickbox.rb ├── .gitignore ├── kickbox.gemspec └── README.md /lib/kickbox/error.rb: -------------------------------------------------------------------------------- 1 | require "kickbox/error/client_error" 2 | 3 | module Kickbox 4 | 5 | module Error 6 | 7 | end 8 | 9 | end 10 | -------------------------------------------------------------------------------- /lib/kickbox.rb: -------------------------------------------------------------------------------- 1 | require "rubygems" 2 | 3 | require "kickbox/client" 4 | require "kickbox/error" 5 | require "kickbox/http_client" 6 | 7 | module Kickbox 8 | end 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | -------------------------------------------------------------------------------- /lib/kickbox/error/client_error.rb: -------------------------------------------------------------------------------- 1 | module Kickbox 2 | 3 | module Error 4 | 5 | class ClientError < ::StandardError 6 | 7 | attr_reader :code 8 | 9 | def initialize(message, code) 10 | @code = code 11 | super message 12 | end 13 | 14 | end 15 | 16 | end 17 | 18 | end 19 | -------------------------------------------------------------------------------- /lib/kickbox/client.rb: -------------------------------------------------------------------------------- 1 | require "faraday" 2 | require "json" 3 | 4 | require "kickbox/api/kickbox" 5 | 6 | module Kickbox 7 | 8 | class Client 9 | 10 | def initialize(auth = {}, options = {}) 11 | @http_client = Kickbox::HttpClient::HttpClient.new(auth, options) 12 | end 13 | 14 | # 15 | def kickbox() 16 | Kickbox::Api::Kickbox.new(@http_client) 17 | end 18 | 19 | end 20 | 21 | end 22 | -------------------------------------------------------------------------------- /lib/kickbox/http_client/response.rb: -------------------------------------------------------------------------------- 1 | module Kickbox 2 | 3 | module HttpClient 4 | 5 | # Response object contains the response returned by the client 6 | class Response 7 | 8 | attr_accessor :body, :code, :headers 9 | 10 | def initialize(body, code, headers) 11 | @body = body 12 | @code = code 13 | @headers = headers 14 | end 15 | 16 | end 17 | 18 | end 19 | 20 | end 21 | -------------------------------------------------------------------------------- /lib/kickbox/http_client/response_handler.rb: -------------------------------------------------------------------------------- 1 | module Kickbox 2 | 3 | module HttpClient 4 | 5 | # ResponseHandler takes care of decoding the response body into suitable type 6 | class ResponseHandler 7 | 8 | def self.get_body(env) 9 | type = env.response_headers["content-type"] || '' 10 | body = env.body 11 | 12 | # Response body is in JSON 13 | if type.include?("json") 14 | body = JSON.parse body 15 | end 16 | 17 | return body 18 | end 19 | 20 | end 21 | 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /lib/kickbox/http_client/request_handler.rb: -------------------------------------------------------------------------------- 1 | module Kickbox 2 | 3 | module HttpClient 4 | 5 | # RequestHandler takes care of encoding the request body into format given by options 6 | class RequestHandler 7 | 8 | def self.set_body(options) 9 | type = options.fetch(:request_type, "raw") 10 | 11 | # Raw body 12 | if type == "raw" 13 | options[:body] = options[:body].is_a?(Hash) ? "" : options[:body] 14 | options[:headers].delete("content-type") 15 | end 16 | 17 | return options 18 | end 19 | 20 | end 21 | 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /kickbox.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | 3 | Gem::Specification.new do |gem| 4 | gem.name = "kickbox" 5 | gem.version = "2.0.5" 6 | gem.description = "Official kickbox API library client for ruby" 7 | gem.summary = "Official kickbox API library client for ruby" 8 | 9 | gem.author = "Chaitanya Surapaneni" 10 | gem.email = "chaitanya.surapaneni@kickbox.com" 11 | gem.homepage = "https://kickbox.com" 12 | gem.license = "MIT" 13 | 14 | gem.require_paths = ['lib'] 15 | 16 | gem.files = Dir["lib/**/*"] 17 | 18 | gem.add_dependency "faraday", "~> 1.0" 19 | gem.add_dependency "json", ">= 1.8" 20 | end 21 | -------------------------------------------------------------------------------- /lib/kickbox/api/kickbox.rb: -------------------------------------------------------------------------------- 1 | module Kickbox 2 | 3 | module Api 4 | 5 | # 6 | class Kickbox 7 | 8 | def initialize(client) 9 | @client = client 10 | end 11 | 12 | # Email Verification 13 | # 14 | # '/verify?email=:email&timeout=:timeout' GET 15 | # 16 | # email - Email address to verify 17 | def verify(email, options = {}) 18 | body = options.fetch("query", {}) 19 | timeout = options.fetch("timeout", 6000) 20 | 21 | email = CGI::escape(email) 22 | 23 | @client.get("/verify?email=#{email}&timeout=#{timeout}", body, options) 24 | end 25 | 26 | # Email Batch Verification 27 | # 28 | # '/verify-batch' PUT 29 | # 30 | # emails - Email addresses to verify 31 | def verify_batch(emails, options = {}) 32 | if options['headers'].blank? 33 | options['headers'] = {} 34 | end 35 | 36 | date = Time.current.strftime('%m-%d-%y %H-%M') 37 | options['headers'].merge!( 38 | 'Content-Type' => 'text/csv', 39 | 'X-Kickbox-Filename' => "Batch Email Verification #{date}" 40 | ) 41 | 42 | emails = emails.join("\n") 43 | @client.put("/verify-batch", emails, options) 44 | end 45 | 46 | # Email Batch Verification Status 47 | # 48 | # '/verify-batch/:id' GET 49 | # 50 | # id - Job ID of the batch verification job 51 | def batch_status(id) 52 | @client.get("/verify-batch/#{id}") 53 | end 54 | 55 | end 56 | 57 | end 58 | 59 | end 60 | -------------------------------------------------------------------------------- /lib/kickbox/http_client/error_handler.rb: -------------------------------------------------------------------------------- 1 | module Kickbox 2 | 3 | module HttpClient 4 | 5 | # ErrorHanlder takes care of selecting the error message from response body 6 | class ErrorHandler < Faraday::Middleware 7 | 8 | def initialize(app) 9 | super(app) 10 | end 11 | 12 | def call(env) 13 | @app.call(env).on_complete do |env| 14 | code = env.status 15 | type = env.response_headers["content-type"] || '' 16 | 17 | case code 18 | when 500...599 19 | raise Kickbox::Error::ClientError.new("Error #{code}", code) 20 | when 400...499 21 | body = Kickbox::HttpClient::ResponseHandler.get_body(env) 22 | message = "" 23 | 24 | # If HTML, whole body is taken 25 | if body.is_a?(String) 26 | message = body 27 | end 28 | 29 | # If JSON, a particular field is taken and used 30 | if type.include?("json") and body.is_a?(Hash) 31 | if body.has_key?("message") 32 | message = body["message"] 33 | else 34 | message = "Unable to select error message from json returned by request responsible for error" 35 | end 36 | end 37 | 38 | if message == "" 39 | message = "Unable to understand the content type of response returned by request responsible for error" 40 | end 41 | 42 | raise Kickbox::Error::ClientError.new message, code 43 | end 44 | end 45 | end 46 | 47 | end 48 | 49 | end 50 | 51 | end 52 | -------------------------------------------------------------------------------- /lib/kickbox/http_client/auth_handler.rb: -------------------------------------------------------------------------------- 1 | require "base64" 2 | 3 | module Kickbox 4 | 5 | module HttpClient 6 | 7 | # AuthHandler takes care of devising the auth type and using it 8 | class AuthHandler < Faraday::Middleware 9 | 10 | HTTP_HEADER = 1 11 | 12 | def initialize(app, auth = {}, options = {}) 13 | @auth = auth 14 | super(app) 15 | end 16 | 17 | def call(env) 18 | if !@auth.empty? 19 | auth = get_auth_type 20 | flag = false 21 | 22 | if auth == HTTP_HEADER 23 | env = http_header(env) 24 | flag = true 25 | end 26 | 27 | if !flag 28 | raise StandardError.new "Unable to calculate authorization method. Please check" 29 | end 30 | else 31 | raise StandardError.new "Server requires authentication to proceed further. Please check" 32 | end 33 | 34 | @app.call(env) 35 | end 36 | 37 | # Calculating the Authentication Type 38 | def get_auth_type() 39 | 40 | if @auth.has_key?(:http_header) 41 | return HTTP_HEADER 42 | end 43 | 44 | return -1 45 | end 46 | 47 | # Authorization with HTTP header 48 | def http_header(env) 49 | env[:request_headers]["Authorization"] = "token #{@auth[:http_header]}" 50 | 51 | return env 52 | end 53 | 54 | def query_params(url) 55 | if url.query.nil? or url.query.empty? 56 | {} 57 | else 58 | Faraday::Utils.parse_query(url.query) 59 | end 60 | end 61 | 62 | def merge_query(env, query) 63 | query = query.update query_params(env[:url]) 64 | 65 | env[:url].query = Faraday::Utils.build_query(query) 66 | 67 | return env 68 | end 69 | end 70 | 71 | end 72 | 73 | end 74 | -------------------------------------------------------------------------------- /lib/kickbox/http_client.rb: -------------------------------------------------------------------------------- 1 | require "kickbox/http_client/auth_handler" 2 | require "kickbox/http_client/error_handler" 3 | require "kickbox/http_client/request_handler" 4 | require "kickbox/http_client/response" 5 | require "kickbox/http_client/response_handler" 6 | 7 | module Kickbox 8 | 9 | module HttpClient 10 | 11 | # Main HttpClient which is used by Api classes 12 | class HttpClient 13 | 14 | attr_accessor :options, :headers 15 | 16 | def initialize(auth = {}, options = {}) 17 | 18 | if auth.is_a?(String) 19 | auth = { :http_header => auth } 20 | end 21 | 22 | @options = { 23 | :base => "https://api.kickbox.com", 24 | :api_version => "v2", 25 | :user_agent => "kickbox-ruby/2.0.3 (https://github.com/kickboxio/kickbox-ruby)" 26 | } 27 | 28 | @options.update(options) 29 | 30 | @headers = { 31 | "user-agent" => @options[:user_agent] 32 | } 33 | 34 | if @options.has_key?(:headers) 35 | @headers.update(Hash[@options[:headers].map { |k, v| [k.downcase, v] }]) 36 | @options.delete(:headers) 37 | end 38 | 39 | @client = Faraday.new(@options[:base]) do |conn| 40 | conn.use(Kickbox::HttpClient::AuthHandler, auth) 41 | conn.use(Kickbox::HttpClient::ErrorHandler) 42 | 43 | conn.adapter(Faraday.default_adapter) 44 | end 45 | end 46 | 47 | def get(path, params = {}, options = {}) 48 | request(path, nil, "get", options.merge({ :query => params })) 49 | end 50 | 51 | def post(path, body = {}, options = {}) 52 | request(path, body, "post", options) 53 | end 54 | 55 | def patch(path, body = {}, options = {}) 56 | request(path, body, "patch", options) 57 | end 58 | 59 | def delete(path, body = {}, options = {}) 60 | request(path, body, "delete", options) 61 | end 62 | 63 | def put(path, body = {}, options = {}) 64 | request(path, body, "put", options) 65 | end 66 | 67 | # Intermediate function which does three main things 68 | # 69 | # - Transforms the body of request into correct format 70 | # - Creates the requests with give parameters 71 | # - Returns response body after parsing it into correct format 72 | def request(path, body, method, options) 73 | options = @options.merge(options) 74 | 75 | options[:headers] = options[:headers] || {} 76 | options[:headers] = @headers.merge(Hash[options[:headers].map { |k, v| [k.downcase, v] }]) 77 | 78 | options[:body] = body 79 | 80 | if method != "get" 81 | options[:body] = options[:body] || {} 82 | options = set_body(options) 83 | end 84 | 85 | response = create_request(method, path, options) 86 | 87 | env = response.env 88 | body = get_body(env) 89 | 90 | Kickbox::HttpClient::Response.new(body, env.status, env.response_headers) 91 | end 92 | 93 | # Creating a request with the given arguments 94 | # 95 | # If api_version is set, appends it immediately after host 96 | def create_request(method, path, options) 97 | version = options.has_key?(:api_version) ? "/#{options[:api_version]}" : "" 98 | 99 | path = "#{version}#{path}" 100 | 101 | instance_eval <<-RUBY, __FILE__, __LINE__ + 1 102 | @client.#{method}(path) do |req| 103 | req.body = options[:body] 104 | req.headers.update(options[:headers]) 105 | req.params.update(options[:query]) if options[:query] 106 | end 107 | RUBY 108 | end 109 | 110 | # Get response body in correct format 111 | def get_body(env) 112 | Kickbox::HttpClient::ResponseHandler.get_body(env) 113 | end 114 | 115 | # Set request body in correct format 116 | def set_body(options) 117 | Kickbox::HttpClient::RequestHandler.set_body(options) 118 | end 119 | 120 | end 121 | 122 | end 123 | 124 | end 125 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |