mindee 3.6.0 → 3.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +37 -3
- data/docs/international_id_v2.md +31 -0
- data/lib/mindee/http/endpoint.rb +24 -17
- data/lib/mindee/http/error.rb +11 -4
- data/lib/mindee/http/response_validation.rb +56 -0
- data/lib/mindee/parsing/common/api_response.rb +6 -1
- data/lib/mindee/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d18b48dabb484d078d9fe9ccbe4266d80fde752fb261c13ec6143e69c0ebe0c8
|
4
|
+
data.tar.gz: 9340689c20fa1d161461252a379f0754fe7482dbac8fb89407845fc501ac4ae1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c74414360e4f02582286e8e49e1fbff59dbc654c75876717268f6f3805c7dfbfbd14729828dde8a86d53b8fcbe3eaca0bf0c988dd66919d54c9cfbc719e6b49f
|
7
|
+
data.tar.gz: d14ac158a9d719cdfe2f5ecc5ba0b6a16eb6bae3ce83474a285be980cb00791acfe0e71aa9bb6dbd17945264168ce19f7e5ca75746083994d8a8d0927d76b43f
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Mindee Ruby API Library Changelog
|
2
2
|
|
3
|
+
## v3.6.1 - 2024-03-07
|
4
|
+
### Changes
|
5
|
+
* :recycle: update error handling to account for future evolutions
|
6
|
+
* :memo: update miscellaneous product documentations
|
7
|
+
* :memo: add used environment variables to readme
|
8
|
+
|
9
|
+
|
3
10
|
## v3.6.0 - 2024-02-21
|
4
11
|
### Changes
|
5
12
|
* :sparkles: add support for resume V1
|
data/README.md
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
[![License: MIT](https://img.shields.io/github/license/mindee/mindee-api-ruby)](https://opensource.org/licenses/MIT) [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/mindee/mindee-api-ruby/test.yml)](https://github.com/mindee/mindee-api-ruby) [![Gem Version](https://img.shields.io/gem/v/mindee)](https://rubygems.org/gems/mindee) [![Downloads](https://img.shields.io/gem/dt/mindee.svg)](https://rubygems.org/gems/mindee)
|
2
2
|
|
3
3
|
# Mindee API Helper Library for Ruby
|
4
|
+
|
4
5
|
Quickly and easily connect to Mindee's API services using Ruby.
|
5
6
|
|
6
7
|
## Requirements
|
8
|
+
|
7
9
|
The following Ruby versions are tested and supported: 2.6, 2.7, 3.0, 3.1, 3.2
|
8
10
|
|
9
11
|
## Quick Start
|
12
|
+
|
10
13
|
Here's the TL;DR of getting started.
|
11
14
|
|
12
15
|
First, get an [API Key](https://developers.mindee.com/docs/create-api-key)
|
@@ -18,15 +21,38 @@ gem 'mindee'
|
|
18
21
|
```
|
19
22
|
|
20
23
|
And then execute:
|
24
|
+
|
21
25
|
```sh
|
22
26
|
bundle install
|
23
27
|
```
|
24
28
|
|
25
29
|
Finally, Ruby away!
|
26
30
|
|
31
|
+
### Environment Variables
|
32
|
+
|
33
|
+
This library offers customizable features through environment variables. While there may be instances where you need to
|
34
|
+
rely on them, it's crucial to exercise caution when modifying them to avoid unintended consequences.
|
35
|
+
|
36
|
+
If you're unsure whether you need to adjust these variables, it's advisable to refrain from doing so unless you have a
|
37
|
+
specific reason. Accidentally overwriting them can lead to unexpected behavior.
|
38
|
+
|
39
|
+
Before making any changes, we recommend reviewing the following information to understand the purpose and potential
|
40
|
+
impact of each environment variable:
|
41
|
+
|
42
|
+
* `MINDEE_API_KEY`:
|
43
|
+
* **Description**: Your personal Mindee API Key as shown on the platform. Be careful not to show this publicly!
|
44
|
+
* **Default Value**: `nil`
|
45
|
+
* `MINDEE_BASE_URL`:
|
46
|
+
* **Description**: The default base URL of the API endpoint. Use this variable to specify the root URL for API requests. Modify as needed for proxy configurations or changes in API endpoint location.
|
47
|
+
* **Default Value**: `https://api.mindee.net/v1`
|
48
|
+
* `MINDEE_REQUEST_TIMEOUT`:
|
49
|
+
* **Description**: The default timeout for HTTP requests (in seconds).
|
50
|
+
* **Default Value**: `120`
|
51
|
+
|
27
52
|
### Loading a File and Parsing It
|
28
53
|
|
29
54
|
#### Global Documents
|
55
|
+
|
30
56
|
```ruby
|
31
57
|
require 'mindee'
|
32
58
|
|
@@ -47,26 +73,31 @@ puts result.document
|
|
47
73
|
**Note:** Files can also be loaded from:
|
48
74
|
|
49
75
|
A URL (`https`):
|
76
|
+
|
50
77
|
```rb
|
51
78
|
input_source = mindee_client.source_from_url("https://my-url")
|
52
79
|
```
|
53
80
|
|
54
81
|
A bytes input stream:
|
82
|
+
|
55
83
|
```rb
|
56
84
|
input_source = mindee_client.source_from_bytes('/path/to/the/file.ext', "name-of-my-file.ext")
|
57
85
|
```
|
58
86
|
|
59
87
|
A base64 encoded string:
|
88
|
+
|
60
89
|
```rb
|
61
90
|
input_source = mindee_client.source_from_b64string('/path/to/the/file.ext', "name-of-my-file.ext")
|
62
91
|
```
|
63
92
|
|
64
93
|
A ruby `file` object:
|
94
|
+
|
65
95
|
```rb
|
66
96
|
input_source = mindee_client.source_from_file(input_file, "name-of-my-file.ext")
|
67
97
|
```
|
68
98
|
|
69
99
|
#### Region-Specific Documents
|
100
|
+
|
70
101
|
```ruby
|
71
102
|
require 'mindee'
|
72
103
|
|
@@ -86,6 +117,7 @@ puts result.document
|
|
86
117
|
```
|
87
118
|
|
88
119
|
### Custom Document (API Builder)
|
120
|
+
|
89
121
|
```ruby
|
90
122
|
require 'mindee'
|
91
123
|
|
@@ -119,17 +151,19 @@ end
|
|
119
151
|
## CLI Tool
|
120
152
|
|
121
153
|
A command-line interface tool is available to quickly test documents:
|
154
|
+
|
122
155
|
```sh
|
123
156
|
ruby ./bin/mindee.rb invoice path/to/your/file.ext
|
124
157
|
```
|
125
158
|
|
126
|
-
|
127
159
|
Using the ruby bundler:
|
160
|
+
|
128
161
|
```sh
|
129
162
|
bundle exec ruby ./bin/mindee.rb invoice path/to/your/file.ext
|
130
163
|
```
|
131
164
|
|
132
165
|
## Further Reading
|
166
|
+
|
133
167
|
There's more to it than that for those that need more features, or want to
|
134
168
|
customize the experience.
|
135
169
|
|
@@ -157,15 +191,15 @@ customize the experience.
|
|
157
191
|
* [Invoice Splitter API Ruby](https://developers.mindee.com/docs/invoice-splitter-api-ruby)
|
158
192
|
* [Multi Receipts Detector API Ruby](https://developers.mindee.com/docs/multi-receipts-detector-api-ruby)
|
159
193
|
|
160
|
-
|
161
194
|
You can also take a look at the
|
162
195
|
[Reference Documentation](https://mindee.github.io/mindee-api-ruby/).
|
163
196
|
|
164
|
-
|
165
197
|
## License
|
198
|
+
|
166
199
|
Copyright © Mindee, SA
|
167
200
|
|
168
201
|
Available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
169
202
|
|
170
203
|
## Questions?
|
204
|
+
|
171
205
|
[Join our Slack](https://join.slack.com/t/mindee-community/shared_invite/zt-2d0ds7dtz-DPAF81ZqTy20chsYpQBW5g)
|
data/docs/international_id_v2.md
CHANGED
@@ -31,6 +31,37 @@ puts result.document
|
|
31
31
|
|
32
32
|
**Output (RST):**
|
33
33
|
```rst
|
34
|
+
########
|
35
|
+
Document
|
36
|
+
########
|
37
|
+
:Mindee ID: cfa20a58-20cf-43b6-8cec-9505fa69d1c2
|
38
|
+
:Filename: default_sample.jpg
|
39
|
+
|
40
|
+
Inference
|
41
|
+
#########
|
42
|
+
:Product: mindee/international_id v2.0
|
43
|
+
:Rotation applied: No
|
44
|
+
|
45
|
+
Prediction
|
46
|
+
==========
|
47
|
+
:Document Type: IDENTIFICATION_CARD
|
48
|
+
:Document Number: 12345678A
|
49
|
+
:Surnames: MUESTRA
|
50
|
+
MUESTRA
|
51
|
+
:Given Names: CARMEN
|
52
|
+
:Sex: F
|
53
|
+
:Birth Date: 1980-01-01
|
54
|
+
:Birth Place: CAMPO DE CRIPTANA CIUDAD REAL ESPANA
|
55
|
+
:Nationality: ESP
|
56
|
+
:Personal Number: BAB1834284<44282767Q0
|
57
|
+
:Country of Issue: ESP
|
58
|
+
:State of Issue: MADRID
|
59
|
+
:Issue Date:
|
60
|
+
:Expiration Date: 2030-01-01
|
61
|
+
:Address: C/REAL N13, 1 DCHA COLLADO VILLALBA MADRID MADRID MADRID
|
62
|
+
:MRZ Line 1: IDESPBAB1834284<44282767Q0<<<<
|
63
|
+
:MRZ Line 2: 8001010F1301017ESP<<<<<<<<<<<3
|
64
|
+
:MRZ Line 3: MUESTRA<MUESTRA<<CARMEN<<<<<<<
|
34
65
|
```
|
35
66
|
|
36
67
|
# Field Types
|
data/lib/mindee/http/endpoint.rb
CHANGED
@@ -4,6 +4,7 @@ require 'json'
|
|
4
4
|
require 'net/http'
|
5
5
|
require_relative 'error'
|
6
6
|
require_relative '../version'
|
7
|
+
require_relative 'response_validation'
|
7
8
|
|
8
9
|
module Mindee
|
9
10
|
module HTTP
|
@@ -49,14 +50,15 @@ module Mindee
|
|
49
50
|
# @param all_words [Boolean] Whether the full word extraction needs to be performed
|
50
51
|
# @param close_file [Boolean] Whether the file will be closed after reading
|
51
52
|
# @param cropper [Boolean] Whether a cropping operation will be applied
|
52
|
-
# @return [
|
53
|
+
# @return [Array]
|
53
54
|
def predict(input_source, all_words, close_file, cropper)
|
54
55
|
check_api_key
|
55
56
|
response = predict_req_post(input_source, all_words: all_words, close_file: close_file, cropper: cropper)
|
56
57
|
hashed_response = JSON.parse(response.body, object_class: Hash)
|
57
|
-
return [hashed_response, response.body] if
|
58
|
+
return [hashed_response, response.body] if ResponseValidation.valid_sync_response?(response)
|
58
59
|
|
59
|
-
|
60
|
+
ResponseValidation.clean_request!(response)
|
61
|
+
error = Error.handle_error(@url_name, response)
|
60
62
|
raise error
|
61
63
|
end
|
62
64
|
|
@@ -65,27 +67,29 @@ module Mindee
|
|
65
67
|
# @param all_words [Boolean] Whether the full word extraction needs to be performed
|
66
68
|
# @param close_file [Boolean] Whether the file will be closed after reading
|
67
69
|
# @param cropper [Boolean] Whether a cropping operation will be applied
|
68
|
-
# @return [
|
70
|
+
# @return [Array]
|
69
71
|
def predict_async(input_source, all_words, close_file, cropper)
|
70
72
|
check_api_key
|
71
73
|
response = document_queue_req_get(input_source, all_words, close_file, cropper)
|
72
74
|
hashed_response = JSON.parse(response.body, object_class: Hash)
|
73
|
-
return [hashed_response, response.body] if
|
75
|
+
return [hashed_response, response.body] if ResponseValidation.valid_async_response?(response)
|
74
76
|
|
75
|
-
|
77
|
+
ResponseValidation.clean_request!(response)
|
78
|
+
error = Error.handle_error(@url_name, response)
|
76
79
|
raise error
|
77
80
|
end
|
78
81
|
|
79
82
|
# Calls the parsed async doc.
|
80
83
|
# @param job_id [String]
|
81
|
-
# @return [
|
84
|
+
# @return [Array]
|
82
85
|
def parse_async(job_id)
|
83
86
|
check_api_key
|
84
87
|
response = document_queue_req(job_id)
|
85
88
|
hashed_response = JSON.parse(response.body, object_class: Hash)
|
86
|
-
return [hashed_response, response.body] if
|
89
|
+
return [hashed_response, response.body] if ResponseValidation.valid_async_response?(response)
|
87
90
|
|
88
|
-
|
91
|
+
ResponseValidation.clean_request!(response)
|
92
|
+
error = Error.handle_error(@url_name, response)
|
89
93
|
raise error
|
90
94
|
end
|
91
95
|
|
@@ -95,7 +99,7 @@ module Mindee
|
|
95
99
|
# @param all_words [Boolean] Whether the full word extraction needs to be performed
|
96
100
|
# @param close_file [Boolean] Whether the file will be closed after reading
|
97
101
|
# @param cropper [Boolean] Whether a cropping operation will be applied
|
98
|
-
# @return [Net::
|
102
|
+
# @return [Net::HTTPResponse, nil]
|
99
103
|
def predict_req_post(input_source, all_words: false, close_file: true, cropper: false)
|
100
104
|
uri = URI("#{@url_root}/predict")
|
101
105
|
|
@@ -116,17 +120,18 @@ module Mindee
|
|
116
120
|
form_data.push ['include_mvision', 'true'] if all_words
|
117
121
|
|
118
122
|
req.set_form(form_data, 'multipart/form-data')
|
119
|
-
|
123
|
+
response = nil
|
120
124
|
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, read_timeout: @request_timeout) do |http|
|
121
|
-
http.request(req)
|
125
|
+
response = http.request(req)
|
122
126
|
end
|
127
|
+
response
|
123
128
|
end
|
124
129
|
|
125
130
|
# @param input_source [Mindee::Input::Source::LocalInputSource, Mindee::Input::Source::UrlInputSource]
|
126
131
|
# @param all_words [Boolean] Whether the full word extraction needs to be performed
|
127
132
|
# @param close_file [Boolean] Whether the file will be closed after reading
|
128
133
|
# @param cropper [Boolean] Whether a cropping operation will be applied
|
129
|
-
# @return [Net::HTTPResponse]
|
134
|
+
# @return [Net::HTTPResponse, nil]
|
130
135
|
def document_queue_req_get(input_source, all_words, close_file, cropper)
|
131
136
|
uri = URI("#{@url_root}/predict_async")
|
132
137
|
|
@@ -148,13 +153,15 @@ module Mindee
|
|
148
153
|
|
149
154
|
req.set_form(form_data, 'multipart/form-data')
|
150
155
|
|
156
|
+
response = nil
|
151
157
|
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, read_timeout: @request_timeout) do |http|
|
152
|
-
http.request(req)
|
158
|
+
response = http.request(req)
|
153
159
|
end
|
160
|
+
response
|
154
161
|
end
|
155
162
|
|
156
163
|
# @param job_id [String]
|
157
|
-
# @return [Net::HTTPResponse]
|
164
|
+
# @return [Net::HTTPResponse, nil]
|
158
165
|
def document_queue_req(job_id)
|
159
166
|
uri = URI("#{@url_root}/documents/queue/#{job_id}")
|
160
167
|
|
@@ -171,8 +178,8 @@ module Mindee
|
|
171
178
|
|
172
179
|
if response.code.to_i > 299 && response.code.to_i < 400
|
173
180
|
req = Net::HTTP::Get.new(response['location'], headers)
|
174
|
-
|
175
|
-
http.request(req)
|
181
|
+
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, read_timeout: @request_timeout) do |http|
|
182
|
+
response = http.request(req)
|
176
183
|
end
|
177
184
|
end
|
178
185
|
response
|
data/lib/mindee/http/error.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'json'
|
4
|
+
|
3
5
|
module Mindee
|
4
6
|
module HTTP
|
5
7
|
# Mindee HTTP error module.
|
@@ -50,15 +52,20 @@ module Mindee
|
|
50
52
|
end
|
51
53
|
|
52
54
|
end
|
53
|
-
error_obj
|
55
|
+
error_obj.nil? ? {} : error_obj
|
54
56
|
end
|
55
57
|
|
56
58
|
# Creates an appropriate HTTP error exception, based on retrieved http error code
|
57
59
|
# @param url [String] the url of the product
|
58
60
|
# @param response [Hash] dictionary response retrieved by the server
|
59
|
-
|
60
|
-
|
61
|
-
|
61
|
+
def handle_error(url, response)
|
62
|
+
code = response.code.to_i
|
63
|
+
begin
|
64
|
+
parsed_hash = JSON.parse(response.body, object_class: Hash)
|
65
|
+
rescue JSON::ParserError
|
66
|
+
parsed_hash = response.body.to_s
|
67
|
+
end
|
68
|
+
error_obj = create_error_obj(parsed_hash)
|
62
69
|
case code
|
63
70
|
when 400..499
|
64
71
|
MindeeHttpClientError.new(error_obj, url, code)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'net/http'
|
5
|
+
|
6
|
+
module Mindee
|
7
|
+
module HTTP
|
8
|
+
# Module dedicated to the validation & sanitizing of HTTP responses.
|
9
|
+
module ResponseValidation
|
10
|
+
# Checks if the synchronous response is valid. Returns True if the response is valid.
|
11
|
+
# @param [Net::HTTPResponse] response
|
12
|
+
# @return [Boolean]
|
13
|
+
def self.valid_sync_response?(response)
|
14
|
+
return false unless (200..399).cover?(response.code.to_i)
|
15
|
+
|
16
|
+
begin
|
17
|
+
JSON.parse(response.body, object_class: Hash)
|
18
|
+
rescue StandardError
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
# Checks if the asynchronous response is valid. Also checks if it is a valid synchronous response.
|
25
|
+
# Returns true if the response is valid.
|
26
|
+
# @param [Net::HTTPResponse] response
|
27
|
+
# @return [Boolean]
|
28
|
+
def self.valid_async_response?(response)
|
29
|
+
return false unless valid_sync_response?(response)
|
30
|
+
|
31
|
+
return false unless (200..302).cover?(response.code.to_i)
|
32
|
+
|
33
|
+
hashed_response = JSON.parse(response.body, object_class: Hash)
|
34
|
+
return false if hashed_response.dig('job', 'error') && !hashed_response.dig('job', 'error').empty?
|
35
|
+
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
# Checks and correct the response object depending on the possible kinds of returns.
|
40
|
+
# @param response [Net::HTTPResponse]
|
41
|
+
def self.clean_request!(response)
|
42
|
+
return response if (response.code.to_i < 200) || (response.code.to_i > 302)
|
43
|
+
|
44
|
+
return response unless response.body.empty?
|
45
|
+
|
46
|
+
hashed_response = JSON.parse(response.body, object_class: Hash)
|
47
|
+
if hashed_response.dig('api_request', 'status_code').to_i > 399
|
48
|
+
response.instance_variable_set(:@code, hashed_response['api_request']['status_code'].to_s)
|
49
|
+
end
|
50
|
+
return unless hashed_response.dig('job', 'error').empty?
|
51
|
+
|
52
|
+
response.instance_variable_set(:@code, '500')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -14,6 +14,8 @@ module Mindee
|
|
14
14
|
PROCESSING = :processing
|
15
15
|
# Document parsing is complete.
|
16
16
|
COMPLETED = :completed
|
17
|
+
# Job failed
|
18
|
+
FAILURE = :failed
|
17
19
|
end
|
18
20
|
|
19
21
|
# Potential values for requests.
|
@@ -36,10 +38,13 @@ module Mindee
|
|
36
38
|
attr_reader :status
|
37
39
|
# @return [Integer, nil]
|
38
40
|
attr_reader :millisecs_taken
|
41
|
+
# @return [Hash, nil]
|
42
|
+
attr_reader :error
|
39
43
|
|
40
44
|
# @param http_response [Hash]
|
41
45
|
def initialize(http_response)
|
42
46
|
@id = http_response['id']
|
47
|
+
@error = http_response['error']
|
43
48
|
@issued_at = Time.iso8601(http_response['issued_at'])
|
44
49
|
if http_response.key?('available_at') && !http_response['available_at'].nil?
|
45
50
|
@available_at = Time.iso8601(http_response['available_at'])
|
@@ -108,7 +113,7 @@ module Mindee
|
|
108
113
|
end
|
109
114
|
if http_response.key?('document') &&
|
110
115
|
(!http_response.key?('job') ||
|
111
|
-
|
116
|
+
http_response['job']['status'] == 'completed') &&
|
112
117
|
@api_request.status == RequestStatus::SUCCESS
|
113
118
|
@document = Mindee::Parsing::Common::Document.new(product_class, http_response['document'])
|
114
119
|
end
|
data/lib/mindee/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mindee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.6.
|
4
|
+
version: 3.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mindee, SA
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: marcel
|
@@ -181,6 +181,7 @@ files:
|
|
181
181
|
- lib/mindee/http/.rubocop.yml
|
182
182
|
- lib/mindee/http/endpoint.rb
|
183
183
|
- lib/mindee/http/error.rb
|
184
|
+
- lib/mindee/http/response_validation.rb
|
184
185
|
- lib/mindee/input.rb
|
185
186
|
- lib/mindee/input/sources.rb
|
186
187
|
- lib/mindee/parsing.rb
|