<commit_before>require 'faraday'
require 'faraday_middleware'
require 'ostruct'
require 'findface_api/version'

# Findface API
module FindfaceApi
  ENDPOINT_URI = "https://api.findface.pro/v#{API_VERSION}/".freeze

  # Exceptions
  module Error
    class Error < StandardError; end
    class ClientError < Error; end
  end

  # Configuration
  module Configuration
    attr_accessor :access_token, :proxy, :logger, :adapter
    def configure
      yield self
      true
    end
  end

  # Connection
  module Connection
    def connection
      raise 'No access token specified' if access_token.nil?
      @connection ||= begin
        conn = Faraday.new ENDPOINT_URI do |c|
          c.authorization :Token, access_token
          c.request :multipart
          c.request :json # either :json or :url_encoded
          c.response :logger, logger, headers: false, bodies: true unless logger.nil?
          c.response :json, content_type: /\bjson$/
          c.proxy proxy unless proxy.nil?
          c.adapter adapter.nil? ? Faraday.default_adapter : adapter
        end
        conn
      end
    end
  end

  # API Entities
  module Entities
    # Bounding box
    # Represents a rectangle on a photo. Usually used as a face's bounding box.
    class BBox
      attr_accessor :x1, :x2, :y1, :y2

      def initialize(x1:, x2:, y1:, y2:)
        @x1, @x2, @y1, @y2 = x1, x2, y1, y2
      end

      def width
        x2 - x1
      end

      def height
        y2 - y1
      end

      def to_h
        { x1: x1, x2: x2, y1: y1, y2: y2 }
      end
    end

    # Face
    # Represents a human face. Note that it might be several faces on a single photo.
    # Different photos of the same person as also considered to be different faces.
    class Face
      attr_reader :id, :timestamp, :photo, :photo_hash, :thumbnail, :bbox, :meta, :galleries
    end
  end

  # Helpers
  module Helpers
    def symbolize(myhash)
      myhash.keys.each do |key|
        myhash[(key.to_sym rescue key) || key] = myhash.delete(key)
      end
      myhash
    end

    def request_body(keys, options, **args)
      options.reject { |key, _| !keys.include? key }
      options.merge(args)
    end

    def request_path(path, options)
      path
        .gsub(':gallery', options.fetch(:gallery, :default).to_s)
        .gsub(':meta', options.fetch(:meta, '').to_s)
    end

    def post(uri, data)
      response = connection.post uri, data
      if !response.success? || response.body.include?('code')
        message = response.body.fetch('reason', 'API Error')
        raise FindfaceApi::Error::ClientError, message
      end
      response.body
    end
  end

  # API Methods
  module APIMethods<commit_msg>Add middleware<commit_after>require 'faraday'
require 'faraday_middleware'
require 'findface_api/version'

# Findface API
module FindfaceApi
  ENDPOINT_URI = "https://api.findface.pro/v#{API_VERSION}/".freeze

  # Exceptions
  module Error
    class Error < StandardError; end
    class ClientError < Error; end
  end

  # Configuration
  module Configuration
    attr_accessor :access_token, :proxy, :logger, :adapter
    def configure
      yield self
      true
    end
  end

  # Faraday middleware
  module Middleware
    # Raise API Exception
    class RaiseApiError < ::Faraday::Response::Middleware
      def on_complete(env)
        return unless env[:body].is_a?(Hash) && env[:body].include?('reason')
        raise FindfaceApi::Error::ClientError, env[:body]['reason']
      end
    end
  end

  # Connection
  module Connection
    def connection
      raise 'No access token specified' if access_token.nil?
      @connection ||= begin
        conn = Faraday.new ENDPOINT_URI do |c|
          c.authorization :Token, access_token
          c.request :multipart
          c.request :json # either :json or :url_encoded
          c.response :raise_error
          c.use FindfaceApi::Middleware::RaiseApiError
          c.response :logger, logger, headers: false, bodies: true unless logger.nil?
          c.response :json, content_type: /\bjson$/
          c.proxy proxy unless proxy.nil?
          c.adapter adapter.nil? ? Faraday.default_adapter : adapter
        end
        conn
      end
    end
  end

  # API Entities
  module Entities
    # Bounding box
    # Represents a rectangle on a photo. Usually used as a face's bounding box.
    class BBox
      attr_accessor :x1, :x2, :y1, :y2

      def initialize(x1:, x2:, y1:, y2:)
        @x1, @x2, @y1, @y2 = x1, x2, y1, y2
      end

      def width
        x2 - x1
      end

      def height
        y2 - y1
      end

      def to_h
        { x1: x1, x2: x2, y1: y1, y2: y2 }
      end
    end

    # Face
    # Represents a human face. Note that it might be several faces on a single photo.
    # Different photos of the same person as also considered to be different faces.
    class Face
      attr_reader :id, :timestamp, :photo, :photo_hash, :thumbnail, :bbox, :meta, :galleries
    end
  end

  # Helpers
  module Helpers
    def symbolize(myhash)
      myhash.keys.each do |key|
        myhash[(key.to_sym rescue key) || key] = myhash.delete(key)
      end
      myhash
    end

    def request_body(keys, options, **args)
      options.reject { |key, _| !keys.include? key }
      options.merge(args)
    end

    def request_path(path, options)
      path
        .gsub(':gallery', options.fetch(:gallery, :default).to_s)
        .gsub(':meta', options.fetch(:meta, '').to_s)
    end

    def post(uri, data)
      response = connection.post uri, data
      # body = response.body
      # if body.is_a?(Hash) && body.include?('reason')
      #   raise FindfaceApi::Error::ClientError, body.reason
      # end
      # raise Faraday::Error::ClientError, response.to_hash unless response.success?
      response.body
    end
  end

  # API Methods
  module APIMethods
{'fraction_non_alphanumeric': 0.09693440657646857, 'fraction_numerical': 0.009590683336187704, 'mean_word_length': 2.371824480369515, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2714661', 'n_tokens_mistral': 1883, 'n_tokens_neox': 1831, 'n_words': 553}