Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Account info #9

Merged
merged 3 commits into from
May 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ result.save("processed/image.png")
result.save("image.png", overwrite: true) # Careful!
```

### Fetching account information

To display the [account information][account-info] for the currently configured
API key:

[account-info]: https://www.remove.bg/api#operations-tag-Fetch_account_info

```ruby
account = RemoveBg.account_info # If an API key is set via RemoveBg.configuration
# or
account = RemoveBg.account_info(api_key: "<api_key>")

account.api.free_calls # => 50
account.credits.total # => 200
```

## Examples

- [Bulk processing][bulk-processing] a directory of JPG and PNG files
Expand Down
5 changes: 5 additions & 0 deletions lib/remove_bg.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ def self.from_url(image_url, raw_options = {})
ApiClient.new.remove_from_url(image_url, options)
end

def self.account_info(raw_options = {})
options = RemoveBg::BaseRequestOptions.new(raw_options)
ApiClient.new.account_info(options)
end

def self.configure
yield RemoveBg::Configuration.configuration
end
Expand Down
30 changes: 30 additions & 0 deletions lib/remove_bg/account_info.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module RemoveBg
class AccountInfo
attr_reader :api, :credits

def initialize(attributes)
@api = ApiInfo.new(**attributes.fetch(:api))
@credits = CreditsInfo.new(**attributes.fetch(:credits))
end

class ApiInfo
attr_reader :free_calls, :sizes

def initialize(free_calls:, sizes:)
@free_calls = free_calls
@sizes = sizes
end
end

class CreditsInfo
attr_reader :total, :subscription, :payg, :enterprise

def initialize(total:, subscription:, payg:, enterprise:)
@total = total
@subscription = subscription
@payg = payg
@enterprise = enterprise
end
end
end
end
3 changes: 3 additions & 0 deletions lib/remove_bg/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ module RemoveBg
module Api
URL = "https://api.remove.bg"

V1_ACCOUNT = "/v1.0/account"
private_constant :V1_ACCOUNT

V1_REMOVE_BG = "/v1.0/removebg"
private_constant :V1_REMOVE_BG

Expand Down
37 changes: 34 additions & 3 deletions lib/remove_bg/api_client.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "json"
require_relative "account_info"
require_relative "api"
require_relative "error"
require_relative "http_connection"
Expand All @@ -25,6 +26,10 @@ def remove_from_url(image_url, options)
request_remove_bg(data, options.api_key)
end

def account_info(options)
request_account_info(options.api_key)
end

private

attr_reader :connection
Expand All @@ -34,9 +39,27 @@ def request_remove_bg(data, api_key)
req.headers[HEADER_API_KEY] = api_key
end

if response.status == 200
parse_image_result(response)
else
handle_http_error(response)
end
end

def request_account_info(api_key)
response = connection.get(V1_ACCOUNT) do |req|
req.headers[HEADER_API_KEY] = api_key
end

if response.status == 200
parse_account_result(response)
else
handle_http_error(response)
end
end

def handle_http_error(response)
case response.status
when 200
parse_result(response)
when 400..499
error_message = parse_error_message(response)
raise RemoveBg::ClientHttpError.new(error_message, response)
Expand All @@ -48,7 +71,7 @@ def request_remove_bg(data, api_key)
end
end

def parse_result(response)
def parse_image_result(response)
RemoveBg::Result.new(
data: response.body,
type: response.headers[HEADER_TYPE],
Expand All @@ -58,6 +81,14 @@ def parse_result(response)
)
end

def parse_account_result(response)
attributes = JSON.parse(response.body, symbolize_names: true)
.fetch(:data)
.fetch(:attributes)

RemoveBg::AccountInfo.new(attributes)
end

def parse_error_message(response)
parse_errors(response).first["title"]
end
Expand Down
32 changes: 32 additions & 0 deletions lib/remove_bg/base_request_options.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require_relative "error"

module RemoveBg
class BaseRequestOptions
attr_reader :api_key, :data

def initialize(raw_options = {})
options = raw_options.dup
@api_key = resolve_api_key(options.delete(:api_key))
@data = options
end

private

def resolve_api_key(request_api_key)
api_key = request_api_key || global_api_key

if api_key.nil? || api_key.empty?
raise RemoveBg::Error, <<~MSG
Please configure an API key or specify one per request. API key was:
#{api_key.inspect}
MSG
end

api_key
end

def global_api_key
RemoveBg::Configuration.configuration.api_key
end
end
end
28 changes: 3 additions & 25 deletions lib/remove_bg/request_options.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require_relative "error"
require_relative "base_request_options"

module RemoveBg
class RequestOptions
class RequestOptions < BaseRequestOptions
SIZE_REGULAR = "regular"
SIZE_MEDIUM = "medium"
SIZE_HD = "hd"
Expand All @@ -15,32 +15,10 @@ class RequestOptions
CHANNELS_RGBA = "rgba"
CHANNELS_ALPHA = "alpha"

attr_reader :api_key, :data

def initialize(raw_options = {})
options = raw_options.dup
options[:size] ||= SIZE_AUTO
@api_key = resolve_api_key(options.delete(:api_key))
@data = options
end

private

def resolve_api_key(request_api_key)
api_key = request_api_key || global_api_key

if api_key.nil? || api_key.empty?
raise RemoveBg::Error, <<~MSG
Please configure an API key or specify one per request. API key was:
#{api_key.inspect}
MSG
end

api_key
end

def global_api_key
RemoveBg::Configuration.configuration.api_key
super(options)
end
end
end
42 changes: 42 additions & 0 deletions spec/fixtures/vcr_cassettes/account-invalid-api-key.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions spec/fixtures/vcr_cassettes/account.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions spec/integration/account_info_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
require "remove_bg"

RSpec.describe "fetching account information" do
let(:api_key) { ENV.fetch("REMOVE_BG_API_KEY") }
let(:image_path) do
File.expand_path("../fixtures/images/person-in-field.jpg", __dir__)
end

it "succeeds with a valid API key" do
account = VCR.use_cassette("account") do
RemoveBg.account_info(api_key: api_key)
end

expect(account.api).to have_attributes(
free_calls: be_a_kind_of(Numeric),
sizes: "all"
)

expect(account.credits).to have_attributes(
total: be_a_kind_of(Numeric),
subscription: be_a_kind_of(Numeric),
payg: be_a_kind_of(Numeric),
enterprise: be_a_kind_of(Numeric),
)
end
end
16 changes: 16 additions & 0 deletions spec/remove_bg/api_client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,22 @@
end
end

describe "#account_info" do
context "with an invalid API key" do
it "raises an error with a helpful message" do
request_options = RemoveBg::BaseRequestOptions.new(api_key: "invalid-api-key")

make_request = Proc.new do
VCR.use_cassette("account-invalid-api-key") do
subject.account_info(request_options)
end
end

expect(make_request).to raise_error RemoveBg::HttpError, /API Key invalid/
end
end
end

private

def build_options(options = { api_key: "api-key" })
Expand Down