class Skimlinks::Client

Constants

API_ENDPOINTS

Public Class Methods

new(args = {}) click to toggle source
# File lib/skimlinks/client.rb, line 15
def initialize(args = {})
  config = Skimlinks.configuration.current.merge(args)

  Skimlinks.configuration.rules.keys.each do |key|
    self.send "#{key}=", config[key]
  end

  @product_api  = RestClient::Resource.new(API_ENDPOINTS[:product_api])
  @merchant_api = RestClient::Resource.new(API_ENDPOINTS[:merchant_api])
  @mechanize    = Mechanize.new do |m|
    m.agent.redirect_ok      = false
    m.agent.http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  end
end

Public Instance Methods

affiliate(url, publisher_id) click to toggle source

Link API

# File lib/skimlinks/client.rb, line 86
def affiliate(url, publisher_id)
  link_api url, publisher_id
end
merchant_categories() click to toggle source

Merchant API

# File lib/skimlinks/client.rb, line 46
def merchant_categories
  @merchant_categories ||= merchant_api('categories')
end
merchant_category_ids() click to toggle source
# File lib/skimlinks/client.rb, line 50
def merchant_category_ids
  @merchant_category_ids ||= flatten(self.merchant_categories).grep(/^\d+$/).uniq.map(&:to_i)
end
merchants_in_category(category_id) click to toggle source
# File lib/skimlinks/client.rb, line 54
def merchants_in_category(category_id)
  [].tap do |merchants|
    start, found = 0, nil

    while found.nil? || start < found
      data = merchant_api('category', category_id, 'limit', 200, 'start', start)

      merchants.concat data['merchants'] if data['merchants'].present?

      start = data['numStarted'].to_i + data['numReturned'].to_i
      found = data['numFound']
    end
  end
end
product_categories() click to toggle source
# File lib/skimlinks/client.rb, line 40
def product_categories
  @product_categories ||= product_api('categories')['skimlinksProductAPI']['categories']
end
product_count(args) click to toggle source
# File lib/skimlinks/client.rb, line 36
def product_count(args)
  product_count_and_products(args.merge(rows: 0)).first
end

Private Instance Methods

flatten(object) click to toggle source
# File lib/skimlinks/client.rb, line 92
def flatten(object)
  case object
  when Hash
    object.to_a.map { |v| flatten(v) }.flatten
  when Array
    object.flatten.map { |v| flatten(v) }
  else
    object
  end
end
get(api, path, params = {}) click to toggle source
# File lib/skimlinks/client.rb, line 134
def get(api, path, params = {})
  raise Skimlinks::InvalidParameters, 'Only JSON format is supported right now.' unless Skimlinks.configuration.format == :json

  do_get = lambda do
    returning_json do
      api[URI.escape(path)].get params: params
    end
  end

  if Skimlinks.configuration.cache.nil?
    do_get.call
  else
    cache_key = [
      'skimlinks',
      'api',
      Digest::MD5.hexdigest(api.to_s + path + params.to_s)
    ].join(':')
    cache_options = Skimlinks.configuration.cache_ttl > 0 ? { expires_in: Skimlinks.configuration.cache_ttl } : {}
    Skimlinks.configuration.cache.fetch cache_key, cache_options do
      do_get.call
    end
  end
rescue RestClient::Exception => e
  message = [e.message].tap do |message_parts|
    error = JSON.parse(e.response)['skimlinksProductAPI']['message'] rescue nil
    message_parts << error if error.present?
  end.join(' - ')
  raise Skimlinks::ApiError, message
end
merchant_api(method, *params) click to toggle source
# File lib/skimlinks/client.rb, line 177
def merchant_api(method, *params)
  raise Skimlinks::InvalidParameters, 'API key not configured' if Skimlinks.configuration.api_key.blank?

  path = [
    Skimlinks.configuration.format,
    Skimlinks.configuration.api_key,
    method,
    *params.compact
  ].join('/')

  get(@merchant_api, path).tap do |response|
    raise Skimlinks::InvalidParameters, 'API key is invalid' if response.is_a?(Array) && response.first =~ /^Invalid API key/
  end
end
product_api(method, params = {}) click to toggle source
# File lib/skimlinks/client.rb, line 164
def product_api(method, params = {})
  raise Skimlinks::InvalidParameters, 'API key not configured' if Skimlinks.configuration.api_key.blank?

  params = params.reverse_merge(
    format: Skimlinks.configuration.format,
    key:    Skimlinks.configuration.api_key
  )

  get(@product_api, method, params).tap do |response|
    raise Skimlinks::InvalidParameters, 'API key is invalid' if response.is_a?(Array) && response.first =~ /^Invalid API key/
  end
end
product_count_and_products(args) click to toggle source
# File lib/skimlinks/client.rb, line 111
def product_count_and_products(args)
  api_query = []
  api_query << %(id:(#{args[:ids].join(' ')}))                                                          if args[:ids].present?
  api_query << %((#{%w(title description).map { |field| %(#{field}:"#{args[:query]}") }.join(' OR ')})) if args[:query].present?
  api_query << %(price:[#{args[:min_price].presence || '*'} TO #{args[:max_price].presence || '*'}])    if args[:min_price].present? || args[:max_price].present?
  api_query << %(categoryId:(#{args[:category_ids].join(' ')}))                                         if args[:category_ids].present?
  api_query << %(merchantId:"#{args[:merchant_id]}")                                                    if args[:merchant_id].present?
  api_query << %(country:"#{args[:country]}")                                                           if args[:country].present?
  api_query << %(currency:"#{args[:currency]}")                                                         if args[:currency].present?

  # TODO: Check for categoryId 0, '' or nil, missing categoryId

  query_params = {
    q: api_query.join(' AND ')
  }
  query_params[:rows]  = args[:rows]  if args[:rows].present?
  query_params[:start] = args[:start] if args[:start].present?

  product_data = product_api('query', query_params)['skimlinksProductAPI']

  [product_data['numFound'], product_data['products']]
end
returning_json(&block) click to toggle source
# File lib/skimlinks/client.rb, line 103
def returning_json(&block)
  JSON.parse block.call
end
returning_xml(&block) click to toggle source
# File lib/skimlinks/client.rb, line 107
def returning_xml(&block)
  Nokogiri::XML block.call
end