uploadcare-ruby 2.1.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/gem-push.yml +20 -0
- data/.github/workflows/ruby.yml +52 -0
- data/.gitignore +13 -6
- data/.rspec +2 -0
- data/.rubocop.yml +33 -0
- data/.yardopts +4 -0
- data/CHANGELOG.md +29 -47
- data/DEVELOPMENT.md +18 -0
- data/Gemfile +2 -0
- data/LICENSE +1 -1
- data/README.md +433 -527
- data/Rakefile +5 -5
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/uploadcare/api/api.rb +25 -0
- data/lib/uploadcare/client/conversion/base_conversion_client.rb +59 -0
- data/lib/uploadcare/client/conversion/document_conversion_client.rb +41 -0
- data/lib/uploadcare/client/conversion/video_conversion_client.rb +46 -0
- data/lib/uploadcare/client/file_client.rb +44 -0
- data/lib/uploadcare/client/file_list_client.rb +46 -0
- data/lib/uploadcare/client/group_client.rb +45 -0
- data/lib/uploadcare/client/multipart_upload/chunks_client.rb +57 -0
- data/lib/uploadcare/client/multipart_upload_client.rb +64 -0
- data/lib/uploadcare/client/project_client.rb +18 -0
- data/lib/uploadcare/client/rest_client.rb +74 -0
- data/lib/uploadcare/client/rest_group_client.rb +23 -0
- data/lib/uploadcare/client/upload_client.rb +43 -0
- data/lib/uploadcare/client/uploader_client.rb +101 -0
- data/lib/uploadcare/client/webhook_client.rb +47 -0
- data/lib/uploadcare/concern/error_handler.rb +54 -0
- data/lib/uploadcare/concern/throttle_handler.rb +25 -0
- data/lib/uploadcare/concern/upload_error_handler.rb +32 -0
- data/lib/uploadcare/entity/conversion/base_converter.rb +36 -0
- data/lib/uploadcare/entity/conversion/document_converter.rb +15 -0
- data/lib/uploadcare/entity/conversion/video_converter.rb +15 -0
- data/lib/uploadcare/entity/decorator/paginator.rb +79 -0
- data/lib/uploadcare/entity/entity.rb +18 -0
- data/lib/uploadcare/entity/file.rb +106 -0
- data/lib/uploadcare/entity/file_list.rb +31 -0
- data/lib/uploadcare/entity/group.rb +40 -0
- data/lib/uploadcare/entity/group_list.rb +24 -0
- data/lib/uploadcare/entity/project.rb +13 -0
- data/lib/uploadcare/entity/uploader.rb +81 -0
- data/lib/uploadcare/entity/webhook.rb +14 -0
- data/lib/uploadcare/exception/conversion_error.rb +8 -0
- data/lib/uploadcare/exception/request_error.rb +9 -0
- data/lib/uploadcare/exception/throttle_error.rb +16 -0
- data/lib/uploadcare/param/authentication_header.rb +25 -0
- data/lib/uploadcare/param/conversion/document/processing_job_url_builder.rb +39 -0
- data/lib/uploadcare/param/conversion/video/processing_job_url_builder.rb +64 -0
- data/lib/uploadcare/param/param.rb +10 -0
- data/lib/uploadcare/param/secure_auth_header.rb +37 -0
- data/lib/uploadcare/param/simple_auth_header.rb +14 -0
- data/lib/uploadcare/param/upload/signature_generator.rb +24 -0
- data/lib/uploadcare/param/upload/upload_params_generator.rb +23 -0
- data/lib/uploadcare/param/user_agent.rb +21 -0
- data/lib/uploadcare/ruby/version.rb +5 -0
- data/lib/uploadcare.rb +36 -32
- data/uploadcare-ruby.gemspec +50 -37
- metadata +107 -113
- data/.travis.yml +0 -26
- data/UPGRADE_NOTES.md +0 -36
- data/lib/uploadcare/api/file_api.rb +0 -7
- data/lib/uploadcare/api/file_list_api.rb +0 -19
- data/lib/uploadcare/api/file_storage_api.rb +0 -34
- data/lib/uploadcare/api/group_api.rb +0 -38
- data/lib/uploadcare/api/group_list_api.rb +0 -17
- data/lib/uploadcare/api/project_api.rb +0 -9
- data/lib/uploadcare/api/raw_api.rb +0 -38
- data/lib/uploadcare/api/uploading_api/upload_params.rb +0 -72
- data/lib/uploadcare/api/uploading_api.rb +0 -71
- data/lib/uploadcare/api/validators/file_list_options_validator.rb +0 -73
- data/lib/uploadcare/api/validators/group_list_options_validator.rb +0 -49
- data/lib/uploadcare/api.rb +0 -26
- data/lib/uploadcare/errors/errors.rb +0 -64
- data/lib/uploadcare/resources/file.rb +0 -164
- data/lib/uploadcare/resources/file_list.rb +0 -14
- data/lib/uploadcare/resources/group.rb +0 -115
- data/lib/uploadcare/resources/group_list.rb +0 -14
- data/lib/uploadcare/resources/project.rb +0 -13
- data/lib/uploadcare/resources/resource_list.rb +0 -83
- data/lib/uploadcare/rest/auth/auth.rb +0 -31
- data/lib/uploadcare/rest/auth/secure.rb +0 -43
- data/lib/uploadcare/rest/auth/simple.rb +0 -16
- data/lib/uploadcare/rest/connections/api_connection.rb +0 -53
- data/lib/uploadcare/rest/connections/upload_connection.rb +0 -22
- data/lib/uploadcare/rest/middlewares/auth_middleware.rb +0 -24
- data/lib/uploadcare/rest/middlewares/parse_json_middleware.rb +0 -33
- data/lib/uploadcare/rest/middlewares/raise_error_middleware.rb +0 -21
- data/lib/uploadcare/utils/parser.rb +0 -71
- data/lib/uploadcare/utils/user_agent.rb +0 -44
- data/lib/uploadcare/version.rb +0 -3
- data/spec/api/file_list_api_spec.rb +0 -95
- data/spec/api/file_storage_api_spec.rb +0 -88
- data/spec/api/group_list_api_spec.rb +0 -59
- data/spec/api/raw_api_spec.rb +0 -25
- data/spec/api/uploading_api/upload_params_spec.rb +0 -99
- data/spec/api/uploading_api_spec.rb +0 -59
- data/spec/resources/file_list_spec.rb +0 -25
- data/spec/resources/file_spec.rb +0 -223
- data/spec/resources/group_list_spec.rb +0 -25
- data/spec/resources/group_spec.rb +0 -101
- data/spec/resources/operations_spec.rb +0 -59
- data/spec/resources/project_spec.rb +0 -21
- data/spec/rest/api_connection_spec.rb +0 -68
- data/spec/rest/auth/secure_spec.rb +0 -66
- data/spec/rest/auth/simple_spec.rb +0 -31
- data/spec/rest/errors_spec.rb +0 -75
- data/spec/rest/upload_connection_spec.rb +0 -19
- data/spec/shared/resource_list.rb +0 -188
- data/spec/spec_helper.rb +0 -54
- data/spec/uploadcare_spec.rb +0 -43
- data/spec/utils/parser_spec.rb +0 -85
- data/spec/utils/user_agent_spec.rb +0 -46
- data/spec/view.png +0 -0
- data/spec/view2.jpg +0 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'upload_client'
|
|
4
|
+
require 'retries'
|
|
5
|
+
require 'param/upload/upload_params_generator'
|
|
6
|
+
|
|
7
|
+
module Uploadcare
|
|
8
|
+
module Client
|
|
9
|
+
# This is client for general uploads
|
|
10
|
+
#
|
|
11
|
+
# @see https://uploadcare.com/api-refs/upload-api/#tag/Upload
|
|
12
|
+
class UploaderClient < UploadClient
|
|
13
|
+
# @see https://uploadcare.com/api-refs/upload-api/#operation/baseUpload
|
|
14
|
+
|
|
15
|
+
def upload_many(arr, **options)
|
|
16
|
+
body = upload_many_body(arr, **options)
|
|
17
|
+
post(path: 'base/',
|
|
18
|
+
headers: { 'Content-Type': body.content_type },
|
|
19
|
+
body: body)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# syntactic sugar for upload_many
|
|
23
|
+
# There is actual upload method for one file, but it is redundant
|
|
24
|
+
|
|
25
|
+
def upload(file, **options)
|
|
26
|
+
upload_many([file], **options)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Upload files from url
|
|
30
|
+
# @see https://uploadcare.com/api-refs/upload-api/#operation/fromURLUpload
|
|
31
|
+
# options:
|
|
32
|
+
# - check_URL_duplicates
|
|
33
|
+
# - filename
|
|
34
|
+
# - save_URL_duplicates
|
|
35
|
+
# - async - returns upload token instead of upload data
|
|
36
|
+
def upload_from_url(url, **options)
|
|
37
|
+
body = upload_from_url_body(url, **options)
|
|
38
|
+
token_response = post(path: 'from_url/', headers: { 'Content-Type': body.content_type }, body: body)
|
|
39
|
+
return token_response if options[:async]
|
|
40
|
+
|
|
41
|
+
uploaded_response = poll_upload_response(token_response.success[:token])
|
|
42
|
+
return uploaded_response if uploaded_response.success[:status] == 'error'
|
|
43
|
+
|
|
44
|
+
Dry::Monads::Success(files: [uploaded_response.success])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Check upload status
|
|
48
|
+
#
|
|
49
|
+
# @see https://uploadcare.com/api-refs/upload-api/#operation/fromURLUploadStatus
|
|
50
|
+
def get_upload_from_url_status(token)
|
|
51
|
+
query_params = { token: token }
|
|
52
|
+
get(path: 'from_url/status/', params: query_params)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
alias api_struct_post post
|
|
58
|
+
def post(**args)
|
|
59
|
+
handle_throttling { api_struct_post(**args) }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def poll_upload_response(token)
|
|
63
|
+
with_retries(max_tries: Uploadcare.config.max_request_tries,
|
|
64
|
+
base_sleep_seconds: Uploadcare.config.base_request_sleep,
|
|
65
|
+
max_sleep_seconds: Uploadcare.config.max_request_sleep) do
|
|
66
|
+
response = get_upload_from_url_status(token)
|
|
67
|
+
raise RequestError if %w[progress waiting unknown].include?(response.success[:status])
|
|
68
|
+
|
|
69
|
+
response
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Prepares body for upload_many method
|
|
74
|
+
def upload_many_body(arr, **options)
|
|
75
|
+
files_formdata = arr.map do |file|
|
|
76
|
+
[HTTP::FormData::File.new(file).filename,
|
|
77
|
+
form_data_for(file)]
|
|
78
|
+
end.to_h
|
|
79
|
+
HTTP::FormData::Multipart.new(
|
|
80
|
+
Param::Upload::UploadParamsGenerator.call(options[:store]).merge(files_formdata)
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
STORE_VALUES_MAP = {
|
|
85
|
+
true => '1',
|
|
86
|
+
false => '0'
|
|
87
|
+
}.freeze
|
|
88
|
+
|
|
89
|
+
# Prepare upload_from_url initial request body
|
|
90
|
+
def upload_from_url_body(url, **options)
|
|
91
|
+
HTTP::FormData::Multipart.new(
|
|
92
|
+
options.merge(
|
|
93
|
+
'pub_key' => Uploadcare.config.public_key,
|
|
94
|
+
'source_url' => url,
|
|
95
|
+
'store' => STORE_VALUES_MAP[options[:store]]
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'rest_client'
|
|
4
|
+
|
|
5
|
+
module Uploadcare
|
|
6
|
+
module Client
|
|
7
|
+
# client for webhook management
|
|
8
|
+
# @see https://uploadcare.com/api-refs/rest-api/v0.5.0/#tag/Webhook
|
|
9
|
+
class WebhookClient < RestClient
|
|
10
|
+
# Create webhook
|
|
11
|
+
# @see https://uploadcare.com/docs/api_reference/rest/webhooks/#subscribe
|
|
12
|
+
def create(options = {})
|
|
13
|
+
body = {
|
|
14
|
+
'target_url': options[:target_url],
|
|
15
|
+
'event': options[:event] || 'file.uploaded',
|
|
16
|
+
'is_active': options[:is_active].nil? ? true : options[:is_active]
|
|
17
|
+
}.to_json
|
|
18
|
+
post(uri: '/webhooks/', content: body)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Returns array (not paginated list) of webhooks
|
|
22
|
+
# @see https://uploadcare.com/docs/api_reference/rest/webhooks/#get-list
|
|
23
|
+
def list
|
|
24
|
+
get(uri: '/webhooks/')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Permanently deletes subscription
|
|
28
|
+
# @see https://uploadcare.com/docs/api_reference/rest/webhooks/#unsubscribe
|
|
29
|
+
def delete(target_url)
|
|
30
|
+
body = { 'target_url': target_url }.to_json
|
|
31
|
+
post(uri: '/webhooks/unsubscribe/', content: body)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Updates webhook
|
|
35
|
+
# @see https://uploadcare.com/docs/api_reference/rest/webhooks/#subscribe-update
|
|
36
|
+
def update(id, options = {})
|
|
37
|
+
body = options.to_json
|
|
38
|
+
post(uri: "/webhooks/#{id}/", content: body)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
alias create_webhook create
|
|
42
|
+
alias list_webhooks list
|
|
43
|
+
alias delete_webhook delete
|
|
44
|
+
alias update_webhook update
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uploadcare
|
|
4
|
+
module Concerns
|
|
5
|
+
# Wrapper for responses
|
|
6
|
+
# raises errors instead of returning monads
|
|
7
|
+
module ErrorHandler
|
|
8
|
+
include Exception
|
|
9
|
+
|
|
10
|
+
# Extension of ApiStruct's failure method
|
|
11
|
+
#
|
|
12
|
+
# Raises errors instead of returning falsey objects
|
|
13
|
+
# @see https://github.com/rubygarage/api_struct/blob/master/lib/api_struct/client.rb#L55
|
|
14
|
+
def failure(response)
|
|
15
|
+
catch_upload_errors(response)
|
|
16
|
+
parsed_response = JSON.parse(response.body.to_s)
|
|
17
|
+
raise RequestError, parsed_response['detail'] || parsed_response.map { |k, v| "#{k}: #{v}" }.join('; ')
|
|
18
|
+
rescue JSON::ParserError
|
|
19
|
+
raise RequestError, response.body.to_s
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Extension of ApiStruct's wrap method
|
|
23
|
+
#
|
|
24
|
+
# Catches throttling errors and Upload API errors
|
|
25
|
+
#
|
|
26
|
+
# @see https://github.com/rubygarage/api_struct/blob/master/lib/api_struct/client.rb#L45
|
|
27
|
+
def wrap(response)
|
|
28
|
+
raise_throttling_error(response) if response.status == 429
|
|
29
|
+
return failure(response) if response.status >= 300
|
|
30
|
+
|
|
31
|
+
catch_upload_errors(response)
|
|
32
|
+
success(response)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
# Raise ThrottleError. Also, tells in error when server will be ready for next request
|
|
38
|
+
def raise_throttling_error(response)
|
|
39
|
+
retry_after = response.headers['Retry-After'].to_i + 1 || 11
|
|
40
|
+
raise ThrottleError.new(retry_after), "Response throttled, retry #{retry_after} seconds later"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Upload API returns its errors with code 200, and stores its actual code and details within response message
|
|
44
|
+
# This methods detects that and raises apropriate error
|
|
45
|
+
def catch_upload_errors(response)
|
|
46
|
+
return unless response.code == 200
|
|
47
|
+
|
|
48
|
+
parsed_response = JSON.parse(response.body.to_s)
|
|
49
|
+
error = parsed_response['error'] if parsed_response.is_a?(Hash)
|
|
50
|
+
raise RequestError, error if error
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uploadcare
|
|
4
|
+
module Concerns
|
|
5
|
+
# This module lets clients send request multiple times if request is throttled
|
|
6
|
+
module ThrottleHandler
|
|
7
|
+
# call given block. If ThrottleError is returned, it will wait and attempt again 4 more times
|
|
8
|
+
# @yield executable block (HTTP request that may be throttled)
|
|
9
|
+
def handle_throttling
|
|
10
|
+
(Uploadcare.config.max_throttle_attempts - 1).times do
|
|
11
|
+
# rubocop:disable Style/RedundantBegin
|
|
12
|
+
begin
|
|
13
|
+
return yield
|
|
14
|
+
rescue(Exception::ThrottleError) => e
|
|
15
|
+
wait_time = e.timeout
|
|
16
|
+
sleep(wait_time)
|
|
17
|
+
next
|
|
18
|
+
end
|
|
19
|
+
# rubocop:enable Style/RedundantBegin
|
|
20
|
+
end
|
|
21
|
+
yield
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uploadcare
|
|
4
|
+
module Concerns
|
|
5
|
+
# Wrapper for responses
|
|
6
|
+
# raises errors instead of returning monads
|
|
7
|
+
module UploadErrorHandler
|
|
8
|
+
include Exception
|
|
9
|
+
|
|
10
|
+
# Extension of ApiStruct's failure method
|
|
11
|
+
#
|
|
12
|
+
# Raises errors instead of returning falsey objects
|
|
13
|
+
# @see https://github.com/rubygarage/api_struct/blob/master/lib/api_struct/client.rb#L55
|
|
14
|
+
def failure(response)
|
|
15
|
+
catch_throttling_error(response)
|
|
16
|
+
parsed_response = JSON.parse(response.body.to_s)
|
|
17
|
+
raise RequestError, parsed_response['detail']
|
|
18
|
+
rescue JSON::ParserError
|
|
19
|
+
raise RequestError, response.status
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def catch_throttling_error(response)
|
|
25
|
+
return unless response.code == 429
|
|
26
|
+
|
|
27
|
+
retry_after = response.headers['Retry-After'].to_i + 1 || 11
|
|
28
|
+
raise ThrottleError.new(retry_after), "Response throttled, retry #{retry_after} seconds later"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uploadcare
|
|
4
|
+
module Entity
|
|
5
|
+
module Conversion
|
|
6
|
+
# This serializer lets a user convert uploaded documents
|
|
7
|
+
# @see https://uploadcare.com/api-refs/rest-api/v0.6.0/#operation/documentConvert
|
|
8
|
+
class BaseConverter < Entity
|
|
9
|
+
class << self
|
|
10
|
+
# Converts files
|
|
11
|
+
#
|
|
12
|
+
# @param doc_params [Array] of hashes with params or [Hash]
|
|
13
|
+
# @option options [Boolean] :store (false) whether to store file on servers.
|
|
14
|
+
def convert(params, options = {})
|
|
15
|
+
files_params = params.is_a?(Hash) ? [params] : params
|
|
16
|
+
conversion_client.new.convert_many(files_params, options)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Returns a status of a conversion job
|
|
20
|
+
#
|
|
21
|
+
# @param token [Integer, String] token obtained from a server in convert method
|
|
22
|
+
def status(token)
|
|
23
|
+
conversion_client.new.get_conversion_status(token)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def conversion_client
|
|
29
|
+
clients[:base]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
include Conversion
|
|
36
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_converter'
|
|
4
|
+
|
|
5
|
+
module Uploadcare
|
|
6
|
+
module Entity
|
|
7
|
+
module Conversion
|
|
8
|
+
# This serializer lets a user convert uploaded documents
|
|
9
|
+
# @see https://uploadcare.com/api-refs/rest-api/v0.5.0/#operation/documentConvert
|
|
10
|
+
class DocumentConverter < BaseConverter
|
|
11
|
+
client_service Client::Conversion::DocumentConversionClient
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_converter'
|
|
4
|
+
|
|
5
|
+
module Uploadcare
|
|
6
|
+
module Entity
|
|
7
|
+
module Conversion
|
|
8
|
+
# This serializer lets a user convert uploaded videos, and usually returns an array of results
|
|
9
|
+
# @see https://uploadcare.com/api-refs/rest-api/v0.5.0/#operation/videoConvert
|
|
10
|
+
class VideoConverter < BaseConverter
|
|
11
|
+
client_service Client::Conversion::VideoConversionClient
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uploadcare
|
|
4
|
+
module Entity
|
|
5
|
+
# @abstract
|
|
6
|
+
module Decorator
|
|
7
|
+
# provides pagination methods for things in Uploadcare that paginate,
|
|
8
|
+
# namely [FileList] and [Group]
|
|
9
|
+
#
|
|
10
|
+
# Requirements:
|
|
11
|
+
# - Should be Entity with Client
|
|
12
|
+
# - Associated Client should have `list` method that returns objects with pagination
|
|
13
|
+
# - Response should have :next, :previous, :total, :per_page params and :results fields
|
|
14
|
+
module Paginator
|
|
15
|
+
@entity ||= Hashie::Mash.new
|
|
16
|
+
|
|
17
|
+
# meta data of a pagination object
|
|
18
|
+
def meta
|
|
19
|
+
Hashie::Mash.new(next: @entity[:next], previous: @entity[:previous],
|
|
20
|
+
total: @entity[:total], per_page: @entity[:per_page])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Returns new instance of current object on next page
|
|
24
|
+
def next_page
|
|
25
|
+
url = @entity[:next]
|
|
26
|
+
return unless url
|
|
27
|
+
|
|
28
|
+
query = URI.decode_www_form(URI(url).query).to_h
|
|
29
|
+
query = query.map { |k, v| [k.to_sym, v] }.to_h
|
|
30
|
+
self.class.list(**query)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Returns new instance of current object on previous page
|
|
34
|
+
def previous_page
|
|
35
|
+
url = @entity[:previous]
|
|
36
|
+
return unless url
|
|
37
|
+
|
|
38
|
+
query = URI.decode_www_form(URI(url).query).to_h
|
|
39
|
+
query = query.map { |k, v| [k.to_sym, v] }.to_h
|
|
40
|
+
self.class.list(**query)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Attempts to load the entire list after offset into results of current object
|
|
44
|
+
#
|
|
45
|
+
# It's possible to avoid loading objects on previous pages by offsetting them first
|
|
46
|
+
def load
|
|
47
|
+
return if @entity[:next].nil? || @entity[:results].length == @entity[:total]
|
|
48
|
+
|
|
49
|
+
np = self
|
|
50
|
+
until np.next.nil?
|
|
51
|
+
np = np.next_page
|
|
52
|
+
@entity[:results].concat(np.results.map(&:to_h))
|
|
53
|
+
end
|
|
54
|
+
@entity[:next] = nil
|
|
55
|
+
@entity[:per_page] = @entity[:total]
|
|
56
|
+
self
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# iterate through pages, starting with current one
|
|
60
|
+
#
|
|
61
|
+
# @yield [Block]
|
|
62
|
+
def each(&block)
|
|
63
|
+
current_page = self
|
|
64
|
+
while current_page
|
|
65
|
+
current_page.results.each(&block)
|
|
66
|
+
current_page = current_page.next_page
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Load and return all objects in list
|
|
71
|
+
#
|
|
72
|
+
# @return [Array]
|
|
73
|
+
def all
|
|
74
|
+
load[:results]
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Gem.find_files('client/**/*.rb').each { |path| require path }
|
|
4
|
+
|
|
5
|
+
module Uploadcare
|
|
6
|
+
# Entities represent objects existing in Uploadcare cloud
|
|
7
|
+
#
|
|
8
|
+
# Typically, Entities inherit class methods from {Client} instance methods
|
|
9
|
+
# @see Client
|
|
10
|
+
module Entity
|
|
11
|
+
# @abstract
|
|
12
|
+
class Entity < ApiStruct::Entity
|
|
13
|
+
include Client
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
include Entity
|
|
18
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uploadcare
|
|
4
|
+
module Entity
|
|
5
|
+
# This serializer returns a single file
|
|
6
|
+
#
|
|
7
|
+
# @see https://uploadcare.com/docs/api_reference/rest/handling_projects/
|
|
8
|
+
class File < Entity
|
|
9
|
+
client_service FileClient
|
|
10
|
+
|
|
11
|
+
attr_entity :datetime_removed, :datetime_stored, :datetime_uploaded, :image_info, :is_image, :is_ready,
|
|
12
|
+
:mime_type, :original_file_url, :original_filename, :size, :url, :uuid, :variations, :video_info,
|
|
13
|
+
:source, :rekognition_info
|
|
14
|
+
|
|
15
|
+
# gets file's uuid - even if it's only initialized with url
|
|
16
|
+
# @returns [String]
|
|
17
|
+
def uuid
|
|
18
|
+
return @entity.uuid if @entity.uuid
|
|
19
|
+
|
|
20
|
+
uuid = @entity.url.gsub('https://ucarecdn.com/', '')
|
|
21
|
+
uuid.gsub(%r{/.*}, '')
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# loads file metadata, if it's initialized with url or uuid
|
|
25
|
+
def load
|
|
26
|
+
initialize(File.info(uuid).entity)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# The method to convert a document file to another file
|
|
30
|
+
# gets (conversion) params [Hash], options (store: Boolean) [Hash], converter [Class]
|
|
31
|
+
# @returns [File]
|
|
32
|
+
def convert_document(params = {}, options = {}, converter = Conversion::DocumentConverter)
|
|
33
|
+
convert_file(params, converter, options)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# The method to convert a video file to another file
|
|
37
|
+
# gets (conversion) params [Hash], options (store: Boolean) [Hash], converter [Class]
|
|
38
|
+
# @returns [File]
|
|
39
|
+
def convert_video(params = {}, options = {}, converter = Conversion::VideoConverter)
|
|
40
|
+
convert_file(params, converter, options)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# 'copy' method is used to copy original files or their modified versions to default storage.
|
|
44
|
+
#
|
|
45
|
+
# Source files MAY either be stored or just uploaded and MUST NOT be deleted.
|
|
46
|
+
#
|
|
47
|
+
# @param [String] source uuid or uploadcare link to file.
|
|
48
|
+
# @param [Hash] args
|
|
49
|
+
# @option args [Boolean] :store Whether to store the file
|
|
50
|
+
# @option args [Boolean] :strip_operations Copies file without transformations (if source has them)
|
|
51
|
+
# @option args [String] :target points to a target custom storage.
|
|
52
|
+
# @option args [Boolean] :make_public make files on custom storage available via public links.
|
|
53
|
+
# @option args [String] :pattern define file naming pattern for the custom storage scenario.
|
|
54
|
+
#
|
|
55
|
+
# @see https://uploadcare.com/api-refs/rest-api/v0.5.0/#operation/copyFile
|
|
56
|
+
def self.copy(source, **args)
|
|
57
|
+
response = FileClient.new.copy(source: source, **args).success[:result]
|
|
58
|
+
File.new(response)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Copies file to current project
|
|
62
|
+
#
|
|
63
|
+
# source can be UID or full CDN link
|
|
64
|
+
#
|
|
65
|
+
# @see .copy
|
|
66
|
+
def self.local_copy(source, **args)
|
|
67
|
+
File.copy(source, **args)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# copy file to different project
|
|
71
|
+
#
|
|
72
|
+
# source can be UID or full CDN link
|
|
73
|
+
#
|
|
74
|
+
# @see .copy
|
|
75
|
+
def self.remote_copy(source, target, **args)
|
|
76
|
+
File.copy(source: source, target: target, **args)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Instance version of #{copy}. Copies current file.
|
|
80
|
+
def copy(**args)
|
|
81
|
+
File.copy(uuid, **args)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Instance version of {internal_copy}
|
|
85
|
+
def local_copy(**args)
|
|
86
|
+
File.local_copy(uuid, **args)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Instance version of {external_copy}
|
|
90
|
+
def remote_copy(target, **args)
|
|
91
|
+
File.copy(uuid, target: target, **args)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def convert_file(params, converter, options = {})
|
|
97
|
+
raise Uploadcare::Exception::ConversionError, 'The first argument must be a Hash' unless params.is_a?(Hash)
|
|
98
|
+
|
|
99
|
+
params_with_symbolized_keys = params.map { |k, v| [k.to_sym, v] }.to_h
|
|
100
|
+
params_with_symbolized_keys[:uuid] = uuid
|
|
101
|
+
result = converter.convert(params_with_symbolized_keys, options)
|
|
102
|
+
result.success? ? File.info(result.value![:result].first[:uuid]) : result
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'uploadcare/entity/file'
|
|
4
|
+
require 'uploadcare/entity/decorator/paginator'
|
|
5
|
+
require 'api_struct'
|
|
6
|
+
|
|
7
|
+
module Uploadcare
|
|
8
|
+
module Entity
|
|
9
|
+
# This serializer returns lists of files
|
|
10
|
+
#
|
|
11
|
+
# This is a paginated list, so all pagination methods apply
|
|
12
|
+
# @see Uploadcare::Entity::Decorator::Paginator
|
|
13
|
+
class FileList < ApiStruct::Entity
|
|
14
|
+
include Uploadcare::Entity::Decorator::Paginator
|
|
15
|
+
client_service Client::FileListClient
|
|
16
|
+
|
|
17
|
+
attr_entity :next, :previous, :total, :per_page
|
|
18
|
+
|
|
19
|
+
has_entities :results, as: Uploadcare::Entity::File
|
|
20
|
+
has_entities :result, as: Uploadcare::Entity::File
|
|
21
|
+
|
|
22
|
+
# alias for result/results, depending on which API this FileList was initialized from
|
|
23
|
+
# @return [Array] of [Uploadcare::Entity::File]
|
|
24
|
+
def files
|
|
25
|
+
results
|
|
26
|
+
rescue ApiStruct::EntityError
|
|
27
|
+
result
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'uploadcare/entity/file'
|
|
4
|
+
|
|
5
|
+
module Uploadcare
|
|
6
|
+
module Entity
|
|
7
|
+
# Groups serve a purpose of better organizing files in your Uploadcare projects.
|
|
8
|
+
#
|
|
9
|
+
# You can create one from a set of files by using their UUIDs.
|
|
10
|
+
#
|
|
11
|
+
# @see https://uploadcare.com/docs/api_reference/upload/groups/
|
|
12
|
+
class Group < Entity
|
|
13
|
+
client_service RestGroupClient, prefix: 'rest', only: :store
|
|
14
|
+
client_service GroupClient
|
|
15
|
+
|
|
16
|
+
attr_entity :id, :datetime_created, :datetime_stored, :files_count, :cdn_url, :url
|
|
17
|
+
has_entities :files, as: Uploadcare::Entity::File
|
|
18
|
+
|
|
19
|
+
# Remove these lines and bump api_struct version when this PR is accepted:
|
|
20
|
+
# @see https://github.com/rubygarage/api_struct/pull/15
|
|
21
|
+
def self.store(uuid)
|
|
22
|
+
rest_store(uuid)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# gets groups's id - even if it's only initialized with cdn_url
|
|
26
|
+
# @return [String]
|
|
27
|
+
def id
|
|
28
|
+
return @entity.id if @entity.id
|
|
29
|
+
|
|
30
|
+
id = @entity.cdn_url.gsub('https://ucarecdn.com/', '')
|
|
31
|
+
id.gsub(%r{/.*}, '')
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# loads group metadata, if it's initialized with url or id
|
|
35
|
+
def load
|
|
36
|
+
initialize(Group.info(id).entity)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'uploadcare/entity/group'
|
|
4
|
+
require 'uploadcare/entity/decorator/paginator'
|
|
5
|
+
|
|
6
|
+
module Uploadcare
|
|
7
|
+
module Entity
|
|
8
|
+
# List of groups
|
|
9
|
+
#
|
|
10
|
+
# @see https://uploadcare.com/docs/api_reference/upload/groups/
|
|
11
|
+
#
|
|
12
|
+
# This is a paginated list, so all pagination methods apply
|
|
13
|
+
# @see Uploadcare::Entity::Decorator::Paginator
|
|
14
|
+
class GroupList < Entity
|
|
15
|
+
include Uploadcare::Entity::Decorator::Paginator
|
|
16
|
+
client_service RestGroupClient, only: :list
|
|
17
|
+
|
|
18
|
+
attr_entity :next, :previous, :total, :per_page, :results
|
|
19
|
+
has_entities :results, as: Group
|
|
20
|
+
|
|
21
|
+
alias groups results
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uploadcare
|
|
4
|
+
module Entity
|
|
5
|
+
# This serializer returns info about a project and its data
|
|
6
|
+
# @see https://uploadcare.com/docs/api_reference/rest/handling_projects/
|
|
7
|
+
class Project < Entity
|
|
8
|
+
client_service ProjectClient
|
|
9
|
+
|
|
10
|
+
attr_entity :collaborators, :pub_key, :name, :autostore_enabled
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|