uploadcare-ruby 3.0.5 → 3.1.0.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -0
  3. data/CHANGELOG.md +12 -0
  4. data/README.md +248 -11
  5. data/lib/uploadcare/client/conversion/base_conversion_client.rb +54 -0
  6. data/lib/uploadcare/client/conversion/document_conversion_client.rb +38 -0
  7. data/lib/uploadcare/client/conversion/video_conversion_client.rb +42 -0
  8. data/lib/uploadcare/client/file_list_client.rb +4 -4
  9. data/lib/uploadcare/client/multipart_upload/chunks_client.rb +3 -1
  10. data/lib/uploadcare/client/multipart_upload_client.rb +8 -3
  11. data/lib/uploadcare/client/rest_client.rb +4 -3
  12. data/lib/uploadcare/client/rest_group_client.rb +2 -2
  13. data/lib/uploadcare/client/upload_client.rb +1 -0
  14. data/lib/uploadcare/client/uploader_client.rb +22 -6
  15. data/lib/uploadcare/client/webhook_client.rb +9 -5
  16. data/lib/uploadcare/concern/error_handler.rb +2 -2
  17. data/lib/uploadcare/entity/decorator/paginator.rb +4 -6
  18. data/lib/uploadcare/entity/document_converter.rb +26 -0
  19. data/lib/uploadcare/entity/file.rb +3 -3
  20. data/lib/uploadcare/entity/file_list.rb +1 -0
  21. data/lib/uploadcare/entity/group.rb +1 -2
  22. data/lib/uploadcare/entity/uploader.rb +2 -0
  23. data/lib/uploadcare/entity/video_converter.rb +26 -0
  24. data/lib/uploadcare/exception/conversion_error.rb +8 -0
  25. data/lib/uploadcare/exception/throttle_error.rb +2 -0
  26. data/lib/uploadcare/param/conversion/document/processing_job_url_builder.rb +39 -0
  27. data/lib/uploadcare/param/conversion/video/processing_job_url_builder.rb +64 -0
  28. data/lib/uploadcare/param/user_agent.rb +1 -1
  29. data/lib/uploadcare/ruby/version.rb +1 -1
  30. data/uploadcare-ruby.gemspec +2 -2
  31. metadata +15 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e78e5ae5b01f3ca9834186dbd80f7498a1ebec2491740e4b4d5a0aa2845e34e5
4
- data.tar.gz: 84a34cf0fdc9cda596cc54b1b60df014d4d4b3f3882e8f3dad7344ae230c7c2f
3
+ metadata.gz: b37d6357bdceca37eb0175201e52847b253c701771e3bed959e7e945e4b384b7
4
+ data.tar.gz: c70b33bed6660c649df6e93a5bb7e8b3cb5a4c79884a7c146086f0658da690a3
5
5
  SHA512:
6
- metadata.gz: 1efbec0c9e65cf94a769c206490090244628dd16952db2218e7dae5f004ed8b29c9b02855e48d7048006f125c4f019c17c03f40df1dc0db1d2fbd3cdfebf5e75
7
- data.tar.gz: aa3ac3a9e392c105d8be4d405323e645fe07406fe14bf9cc579b4dc3852a2853f15c2dc18d492831284f8cb6343a84f3ffb34f028b3d822d9cd5f738ecb67f17
6
+ metadata.gz: 47b8ead48824c45759a89a62e170374afe3cc0e8a39690ba4851c04785ee52096769a4415fea2e7ecffb62a864a5fae5f6fb1e95bf450442141973b0412990e7
7
+ data.tar.gz: a7aa262e0982825592487187f99018f5276582dffbfa3ef412abc06a3c9d723906d64d2443c79c20eb0dce137ae1cec4384c40b54e692170915289c8191032b0
data/.rubocop.yml CHANGED
@@ -7,6 +7,15 @@ Metrics/LineLength:
7
7
  IneffectiveAccessModifier:
8
8
  Enabled: false
9
9
 
10
+ Style/HashTransformKeys:
11
+ Exclude:
12
+ - 'lib/uploadcare/entity/decorator/paginator.rb'
13
+ - 'lib/uploadcare/client/conversion/video_conversion_client.rb'
14
+
15
+ Gemspec/RequiredRubyVersion:
16
+ Exclude:
17
+ - 'uploadcare-ruby.gemspec'
18
+
10
19
  Metrics/BlockLength:
11
20
  Exclude:
12
21
  - 'bin/'
@@ -18,3 +27,6 @@ Metrics/MethodLength:
18
27
 
19
28
  Style/Documentation:
20
29
  Enabled: false
30
+
31
+ Style/OptionalBooleanParameter:
32
+ AllowedMethods: ['create']
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.1.0-rc1 2021-08-11
4
+
5
+ ### Added
6
+ - Add video conversion
7
+ - Add document conversion
8
+ - Add new attributes to Uploadcare::File (variations, video_info, source, rekognition_info)
9
+
10
+ ### Fixed
11
+
12
+ - Fix the `uninitialized constant Uploadcare::Client::ApiStruct (NameError)` error
13
+
3
14
  ## 3.0.5 2021-04-15
4
15
 
5
16
  - Replace Travis-CI with Github Actions
@@ -12,6 +23,7 @@
12
23
  - Added CI
13
24
 
14
25
  ## 3.0.3-dev 2020-03-13
26
+
15
27
  - Added better pagination and iterators for GroupList & FileList
16
28
 
17
29
  ## 3.0.2-dev 2020-03-11
data/README.md CHANGED
@@ -12,12 +12,24 @@
12
12
  [stack-img]: https://img.shields.io/badge/tech-stack-0690fa.svg?style=flat
13
13
  [stack]: https://stackshare.io/uploadcare/stacks/
14
14
 
15
-
16
15
  Uploadcare Ruby integration handles uploads and further operations with files by
17
16
  wrapping Upload and REST APIs.
18
17
 
19
18
  * [Installation](#installation)
20
19
  * [Usage](#usage)
20
+ * [Uploading files](#uploading-files)
21
+ * [Uploading and storing a single file](#uploading-and-storing-a-single-file)
22
+ * [Multiple ways to upload files](#multiple-ways-to-upload-files)
23
+ * [Uploading options](#uploading-options)
24
+ * [File management](#file-management)
25
+ * [File](#file)
26
+ * [FileList](#filelist)
27
+ * [Pagination](#pagination)
28
+ * [Group](#group)
29
+ * [GroupList](#grouplist)
30
+ * [Webhook](#webhook)
31
+ * [Project](#project)
32
+ * [Conversion](#conversion)
21
33
  * [Useful links](#useful-links)
22
34
 
23
35
  ## Requirements
@@ -25,7 +37,7 @@ wrapping Upload and REST APIs.
25
37
 
26
38
  ## Compatibility
27
39
 
28
- Note that `uploadcare-ruby` **3.x** is not backward compativble with
40
+ Note that `uploadcare-ruby` **3.x** is not backward compatible with
29
41
  **[2.x](https://github.com/uploadcare/uploadcare-ruby/tree/v2.x)**.
30
42
 
31
43
  ## Installation
@@ -65,7 +77,8 @@ This section contains practical usage examples. Please note, everything that
65
77
  follows gets way more clear once you've looked through our
66
78
  [docs](https://uploadcare.com/docs/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby).
67
79
 
68
- ### Uploading and storing a single file
80
+ ### Uploading files
81
+ #### Uploading and storing a single file
69
82
 
70
83
  Using Uploadcare is simple, and here are the basics of handling files.
71
84
 
@@ -97,7 +110,7 @@ within a 24-hour period.
97
110
  # => #<Uploadcare::Api::File ...
98
111
  ```
99
112
 
100
- ### Uploads
113
+ #### Multiple ways to upload files
101
114
 
102
115
  Uploadcare supports multiple ways to upload files:
103
116
 
@@ -118,7 +131,7 @@ Uploadcare::Uploader.upload_from_url('https://placekitten.com/96/139')
118
131
  Uploadcare::Uploader.multipart_upload(File.open('big_file.bin'))
119
132
  ```
120
133
 
121
- ### Upload options
134
+ #### Uploading options
122
135
 
123
136
  You can override global [`:autostore`](#initialization) option for each upload request:
124
137
 
@@ -127,15 +140,13 @@ You can override global [`:autostore`](#initialization) option for each upload r
127
140
  @api.upload_from_url(url, store: :auto)
128
141
  ```
129
142
 
130
- ### Api
143
+ ### File management
131
144
  Most methods are also available through `Uploadcare::Api` object:
132
145
  ```ruby
133
146
  # Same as Uploadcare::Uploader.upload
134
147
  Uploadcare::Api.upload('https://placekitten.com/96/139')
135
148
  ```
136
149
 
137
- ### Entity object
138
-
139
150
  Entities are representations of objects in Uploadcare cloud.
140
151
 
141
152
  #### File
@@ -168,6 +179,8 @@ File entity contains its metadata.
168
179
  "https://api.uploadcare.com/files/FILE_ID_IN_YOUR_PROJECT/",
169
180
  "uuid"=>"8f64f313-e6b1-4731-96c0-6751f1e7a50a"}
170
181
 
182
+ @file.store # copies file, returns a new (copied) file metadata
183
+
171
184
  @file.store # stores file, returns updated metadata
172
185
 
173
186
  @file.delete #deletes file. Returns updated metadata
@@ -226,7 +239,7 @@ To simply get all associated objects:
226
239
  @list.all # => returns Array of Files
227
240
  ```
228
241
 
229
- ##### Pagination
242
+ #### Pagination
230
243
 
231
244
  Initially, `FileList` is a paginated collection. It can be navigated using following methods:
232
245
  ```ruby
@@ -251,10 +264,15 @@ assigned UUID. Note, group UUIDs include a `~#{files_count}` part at the end.
251
264
  That's a requirement of our API.
252
265
 
253
266
  ```ruby
254
- # group can be created from an array of Uploadcare files
267
+ # group can be created from an array of Uploadcare files (UUIDs)
268
+ @file = '134dc30c-093e-4f48-a5b9-966fe9cb1d01'
269
+ @file2 = '134dc30c-093e-4f48-a5b9-966fe9cb1d02'
255
270
  @files_ary = [@file, @file2]
256
271
  @files = Uploadcare::Uploader.upload @files_ary
257
272
  @group = Uploadcare::Group.create @files
273
+
274
+ # group can be stored by group ID. It means that all files of a group will be stored on Uploadcare servers permanently
275
+ Uploadcare::Group.store(group.id)
258
276
  ```
259
277
 
260
278
  #### GroupList
@@ -275,7 +293,10 @@ You can use webhooks to provide notifications about your uploads to target urls.
275
293
  This gem lets you create and manage webhooks.
276
294
 
277
295
  ```ruby
278
- Uploadcare::Webhook.create('example.com/listen', event: 'file.uploaded')
296
+ Uploadcare::Webhook.create(target_url: 'https://example.com/listen', event: 'file.uploaded', is_active: true)
297
+ Uploadcare::Webhook.update(<webhook_id>, target_url: 'https://newexample.com/listen/new', event: 'file.uploaded', is_active: true)
298
+ Uploadcare::Webhook.delete('https://example.com/listen')
299
+ Uploadcare::Webhook.list
279
300
  ```
280
301
 
281
302
  #### Project
@@ -297,6 +318,222 @@ object is also an Hashie::Mash, so every methods out of
297
318
  # [{"email": collaborator@gmail.com, "name": "Collaborator"}, {"email": collaborator@gmail.com, "name": "Collaborator"}]
298
319
  ```
299
320
 
321
+ #### Conversion
322
+
323
+ ##### Video
324
+
325
+ Uploadcare can encode video files from all popular formats, adjust their quality, format and dimensions, cut out a video fragment, and generate thumbnails via [REST API](https://uploadcare.com/api-refs/rest-api/v0.6.0/).
326
+
327
+ After each video file upload you obtain a file identifier in UUID format.
328
+ Then you can use this file identifier to convert your video in multiple ways:
329
+
330
+ ```ruby
331
+ Uploadcare::VideoConverter.convert(
332
+ [
333
+ {
334
+ uuid: "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40",
335
+ size: { resize_mode: 'change_ratio', width: '600', height: '400' },
336
+ quality: 'best',
337
+ format: 'ogg',
338
+ cut: { start_time: '0:0:0.0', length: '0:0:1.0' },
339
+ thumbs: { N: 2, number: 1 }
340
+ }
341
+ ], store: false
342
+ )
343
+ ```
344
+ This method accepts options to set properties of an output file:
345
+
346
+ - **uuid** — the file UUID-identifier.
347
+ - **size**:
348
+ - **resize_mode** - size operation to apply to a video file. Can be `preserve_ratio (default)`, `change_ratio`, `scale_crop` or `add_padding`.
349
+ - **width** - width for a converted video.
350
+ - **height** - height for a converted video.
351
+
352
+ ```
353
+ NOTE: you can choose to provide a single dimension (width OR height).
354
+ The value you specify for any of the dimensions should be a non-zero integer divisible by 4
355
+ ```
356
+
357
+ - **quality** - sets the level of video quality that affects file sizes and hence loading times and volumes of generated traffic. Can be `normal (default)`, `better`, `best`, `lighter`, `lightest`.
358
+ - **format** - format for a converted video. Can be `mp4 (default)`, `webm`, `ogg`.
359
+ - **cut**:
360
+ - **start_time** - defines the starting point of a fragment to cut based on your input file timeline.
361
+ - **length** - defines the duration of that fragment.
362
+ - **thumbs**:
363
+ - **N** - quantity of thumbnails for your video - non-zero integer ranging from 1 to 50; defaults to 1.
364
+ - **number** - zero-based index of a particular thumbnail in a created set, ranging from 1 to (N - 1).
365
+ - **store** - a flag indicating if Uploadcare should store your transformed outputs.
366
+
367
+ ```ruby
368
+ # Response
369
+ {
370
+ :result => [
371
+ {
372
+ :original_source=>"dc99200d-9bd6-4b43-bfa9-aa7bfaefca40/video/-/size/600x400/change_ratio/-/quality/best/-/format/ogg/-/cut/0:0:0.0/0:0:1.0/-/thumbs~2/1/",
373
+ :token=>911933811,
374
+ :uuid=>"6f9b88bd-625c-4d60-bfde-145fa3813d95",
375
+ :thumbnails_group_uuid=>"cf34c5a1-8fcc-4db2-9ec5-62c389e84468~2"
376
+ }
377
+ ],
378
+ :problems=>{}
379
+ }
380
+ ```
381
+ Params in the response:
382
+ - **result** - info related to your transformed output(-s):
383
+ - **original_source** - built path for a particular video with all the conversion operations and parameters.
384
+ - **token** - a processing job token that can be used to get a [job status](https://uploadcare.com/docs/transformations/video-encoding/#status) (see below).
385
+ - **uuid** - UUID of your processed video file.
386
+ - **thumbnails_group_uuid** - holds :uuid-thumb-group, a UUID of a [file group](https://uploadcare.com/api-refs/rest-api/v0.5.0/#operation/groupsList) with thumbnails for an output video, based on the thumbs [operation](https://uploadcare.com/docs/transformations/video-encoding/#operation-thumbs) parameters.
387
+ - **problems** - problems related to your processing job, if any.
388
+
389
+ To convert multiple videos just add params as a hash for each video to the first argument of the `Uploadcare::VideoConverter#convert` method:
390
+
391
+ ```ruby
392
+ Uploadcare::VideoConverter.convert(
393
+ [
394
+ { video_one_params }, { video_two_params }, ...
395
+ ], store: false
396
+ )
397
+ ```
398
+
399
+
400
+ To check a status of a video processing job you can simply use appropriate method of `Uploadcare::VideoConverter`:
401
+
402
+ ```ruby
403
+ token = 911933811
404
+ Uploadcare::VideoConverter.status(token)
405
+ ```
406
+ `token` here is a processing job token, obtained in a response of a convert video request.
407
+
408
+ ```ruby
409
+ # Response
410
+ {
411
+ :status => "finished",
412
+ :error => nil,
413
+ :result => {
414
+ :uuid => "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40",
415
+ :thumbnails_group_uuid => "0f181f24-7551-42e5-bebc-14b15d9d3838~2"
416
+ }
417
+ }
418
+ ```
419
+
420
+ Params in the response:
421
+ - **status** - processing job status, can have one of the following values:
422
+ - *pending* — video file is being prepared for conversion.
423
+ - *processing* — video file processing is in progress.
424
+ - *finished* — the processing is finished.
425
+ - *failed* — we failed to process the video, see error for details.
426
+ - *canceled* — video processing was canceled.
427
+ - **error** - holds a processing error if we failed to handle your video.
428
+ - **result** - repeats the contents of your processing output.
429
+ - **thumbnails_group_uuid** - holds :uuid-thumb-group, a UUID of a file group with thumbnails for an output video, based on the thumbs operation parameters.
430
+ - **uuid** - a UUID of your processed video file.
431
+
432
+ More examples and options can be found [here](https://uploadcare.com/docs/transformations/video-encoding/#video-encoding)
433
+
434
+ ##### Document
435
+
436
+ Uploadcare allows converting documents to the following target formats: DOC, DOCX, XLS, XLSX, ODT, ODS, RTF, TXT, PDF, JPG, ENHANCED JPG, PNG. Document Conversion works via our [REST API](https://uploadcare.com/api-refs/rest-api/v0.6.0/).
437
+
438
+ After each document file upload you obtain a file identifier in UUID format.
439
+ Then you can use this file identifier to convert your document to a new format:
440
+
441
+ ```ruby
442
+ Uploadcare::DocumentConverter.convert(
443
+ [
444
+ {
445
+ uuid: "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40",
446
+ format: 'pdf'
447
+ }
448
+ ], store: false
449
+ )
450
+ ```
451
+ or create an image of a particular page (if using image format):
452
+ ```ruby
453
+ Uploadcare::DocumentConverter.convert(
454
+ [
455
+ {
456
+ uuid: "a4b9db2f-1591-4f4c-8f68-94018924525d",
457
+ format: 'png',
458
+ page: 1
459
+ }
460
+ ], store: false
461
+ )
462
+ ```
463
+
464
+ This method accepts options to set properties of an output file:
465
+
466
+ - **uuid** — the file UUID-identifier.
467
+ - **format** - defines the target format you want a source file converted to. The supported values are: `pdf (default)`, `doc`, `docx`, `xls`, `xlsx`, `odt`, `ods`, `rtf`, `txt`, `jpg`, `enhanced.jpg`, `png`. In case the format operation was not found, your input document will be converted to `pdf`.
468
+ - **page** - a page number of a multi-paged document to either `jpg` or `png`. The method will not work for any other target formats.
469
+
470
+ ```
471
+ NOTE: Use an enhanced.jpg output format for PDF documents with inline fonts.
472
+ When converting multi-page documents to an image format (jpg or png), the output will be a zip archive with one image per page.
473
+ ```
474
+
475
+ ```ruby
476
+ # Response
477
+ {
478
+ :result => [
479
+ {
480
+ :original_source=>"a4b9db2f-1591-4f4c-8f68-94018924525d/document/-/format/png/-/page/1/",
481
+ :token=>21120220
482
+ :uuid=>"88fe5ada-90f1-422a-a233-3a0f3a7cf23c"
483
+ }
484
+ ],
485
+ :problems=>{}
486
+ }
487
+ ```
488
+ Params in the response:
489
+ - **result** - info related to your transformed output(-s):
490
+ - **original_source** - source file identifier including a target format, if present.
491
+ - **token** - a processing job token that can be used to get a [job status](https://uploadcare.com/docs/transformations/document-conversion/#status) (see below).
492
+ - **uuid** - UUID of your processed document file.
493
+ - **problems** - problems related to your processing job, if any.
494
+
495
+ To convert multiple documents just add params as a hash for each document to the first argument of the `Uploadcare::DocumentConverter#convert` method:
496
+
497
+ ```ruby
498
+ Uploadcare::DocumentConverter.convert(
499
+ [
500
+ { doc_one_params }, { doc_two_params }, ...
501
+ ], store: false
502
+ )
503
+ ```
504
+
505
+ To check a status of a document processing job you can simply use appropriate method of `Uploadcare::DocumentConverter`:
506
+
507
+ ```ruby
508
+ token = 21120220
509
+ Uploadcare::DocumentConverter.status(token)
510
+ ```
511
+ `token` here is a processing job token, obtained in a response of a convert document request.
512
+
513
+ ```ruby
514
+ # Response
515
+ {
516
+ :status => "finished",
517
+ :error => nil,
518
+ :result => {
519
+ :uuid => "a4b9db2f-1591-4f4c-8f68-94018924525d"
520
+ }
521
+ }
522
+ ```
523
+
524
+ Params in the response:
525
+ - **status** - processing job status, can have one of the following values:
526
+ - *pending* — document file is being prepared for conversion.
527
+ - *processing* — document file processing is in progress.
528
+ - *finished* — the processing is finished.
529
+ - *failed* — we failed to process the document, see error for details.
530
+ - *canceled* — document processing was canceled.
531
+ - **error** - holds a processing error if we failed to handle your document.
532
+ - **result** - repeats the contents of your processing output.
533
+ - **uuid** - a UUID of your processed document file.
534
+
535
+ More examples and options can be found [here](https://uploadcare.com/docs/transformations/document-conversion/#document-conversion)
536
+
300
537
  ## Useful links
301
538
 
302
539
  * [Development](https://github.com/uploadcare/uploadcare-ruby/blob/main/DEVELOPMENT.md)
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../rest_client'
4
+ require 'exception/conversion_error'
5
+
6
+ module Uploadcare
7
+ module Client
8
+ module Conversion
9
+ # This is a base client for conversion operations
10
+ #
11
+ # @see https://uploadcare.com/api-refs/rest-api/v0.6.0/#tag/Conversion
12
+ class BaseConversionClient < RestClient
13
+ def headers
14
+ {
15
+ 'Content-type': 'application/json',
16
+ 'Accept': 'application/vnd.uploadcare-v0.6+json',
17
+ 'User-Agent': Uploadcare::Param::UserAgent.call
18
+ }
19
+ end
20
+
21
+ private
22
+
23
+ def success(response)
24
+ body = response.body.to_s
25
+ result = extract_result(body)
26
+
27
+ Dry::Monads::Success(result)
28
+ end
29
+
30
+ def extract_result(response_body)
31
+ return nil if response_body.nil? || response_body.empty?
32
+
33
+ parsed_body = JSON.parse(response_body, symbolize_names: true)
34
+ errors = parsed_body[:error] || parsed_body[:problems]
35
+ raise ConversionError, errors unless errors.nil? || errors.empty?
36
+
37
+ parsed_body
38
+ end
39
+
40
+ # Prepares body for convert_many method
41
+ def build_body_for_many(arr, options, url_builder_class)
42
+ {
43
+ "paths": arr.map do |params|
44
+ url_builder_class.call(
45
+ **build_paths_body(params)
46
+ )
47
+ end,
48
+ "store": options[:store]
49
+ }.compact.to_json
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'client/conversion/base_conversion_client'
4
+ require 'param/conversion/document/processing_job_url_builder'
5
+
6
+ module Uploadcare
7
+ module Client
8
+ module Conversion
9
+ # This is client for document conversion
10
+ #
11
+ # @see https://uploadcare.com/api-refs/rest-api/v0.6.0/#operation/documentConvert
12
+ class DocumentConversionClient < BaseConversionClient
13
+ def convert_many(
14
+ arr,
15
+ options = {},
16
+ url_builder_class = Uploadcare::Param::Conversion::Document::ProcessingJobUrlBuilder
17
+ )
18
+ body = build_body_for_many(arr, options, url_builder_class)
19
+ post(uri: '/convert/document/', content: body)
20
+ end
21
+
22
+ def get_conversion_status(token)
23
+ get(uri: "/convert/document/status/#{token}/")
24
+ end
25
+
26
+ private
27
+
28
+ def build_paths_body(params)
29
+ {
30
+ uuid: params[:uuid],
31
+ format: params[:format],
32
+ page: params[:page]
33
+ }.compact
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'client/conversion/base_conversion_client'
4
+ require 'param/conversion/video/processing_job_url_builder'
5
+ require 'exception/conversion_error'
6
+
7
+ module Uploadcare
8
+ module Client
9
+ module Conversion
10
+ # This is client for video conversion
11
+ #
12
+ # @see https://uploadcare.com/api-refs/rest-api/v0.6.0/#operation/videoConvert
13
+ class VideoConversionClient < BaseConversionClient
14
+ def convert_many(
15
+ arr,
16
+ options = {},
17
+ url_builder_class = Uploadcare::Param::Conversion::Video::ProcessingJobUrlBuilder
18
+ )
19
+ body = build_body_for_many(arr, options, url_builder_class)
20
+ post(uri: '/convert/video/', content: body)
21
+ end
22
+
23
+ def get_conversion_status(token)
24
+ get(uri: "/convert/video/status/#{token}/")
25
+ end
26
+
27
+ private
28
+
29
+ def build_paths_body(params)
30
+ {
31
+ uuid: params[:uuid],
32
+ quality: params[:quality],
33
+ format: params[:format],
34
+ size: params[:size],
35
+ cut: params[:cut],
36
+ thumbs: params[:thumbs]
37
+ }.compact
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -15,8 +15,8 @@ module Uploadcare
15
15
  # limit: (1..1000)
16
16
  # ordering: ["datetime_uploaded"|"-datetime_uploaded"|"size"|"-size"]
17
17
  # from: number of files skipped
18
- def file_list(**options)
19
- query = options.empty? ? '' : '?' + URI.encode_www_form(options)
18
+ def file_list(options = {})
19
+ query = options.empty? ? '' : "?#{URI.encode_www_form(options)}"
20
20
  get(uri: "/files/#{query}")
21
21
  end
22
22
 
@@ -25,7 +25,7 @@ module Uploadcare
25
25
  # uuids: Array
26
26
  def batch_store(uuids)
27
27
  body = uuids.to_json
28
- put(uri: '/files/storage/', body: body)
28
+ put(uri: '/files/storage/', content: body)
29
29
  end
30
30
 
31
31
  alias request_delete delete
@@ -35,7 +35,7 @@ module Uploadcare
35
35
  # uuids: Array
36
36
  def batch_delete(uuids)
37
37
  body = uuids.to_json
38
- request_delete(uri: '/files/storage/', body: body)
38
+ request_delete(uri: '/files/storage/', content: body)
39
39
  end
40
40
 
41
41
  alias store_files batch_store
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'parallel'
4
+ require 'api_struct'
4
5
 
5
6
  module Uploadcare
6
7
  module Client
@@ -17,9 +18,10 @@ module Uploadcare
17
18
  # @param links [Array] of strings; by default list of Amazon storage urls
18
19
  def upload_chunks(object, links)
19
20
  Parallel.each(0...links.count, in_threads: Uploadcare.config.upload_threads) do |link_id|
21
+ client = self.class.new
20
22
  offset = link_id * CHUNK_SIZE
21
23
  chunk = IO.read(object, CHUNK_SIZE, offset)
22
- upload_chunk(chunk, links[link_id])
24
+ client.send(:upload_chunk, chunk, links[link_id])
23
25
  end
24
26
  end
25
27
 
@@ -36,8 +36,10 @@ module Uploadcare
36
36
  # When every chunk is uploaded, ask Uploadcare server to finish the upload
37
37
  def upload_complete(uuid)
38
38
  body = HTTP::FormData::Multipart.new(
39
- 'UPLOADCARE_PUB_KEY': Uploadcare.config.public_key,
40
- 'uuid': uuid
39
+ {
40
+ 'UPLOADCARE_PUB_KEY': Uploadcare.config.public_key,
41
+ 'uuid': uuid
42
+ }
41
43
  )
42
44
  post(path: 'multipart/complete/', body: body, headers: { 'Content-type': body.content_type })
43
45
  end
@@ -45,7 +47,10 @@ module Uploadcare
45
47
  private
46
48
 
47
49
  def multiupload_metadata(file)
48
- file = HTTP::FormData::File.new(file)
50
+ filename = file.original_filename if file.respond_to?(:original_filename)
51
+ mime_type = file.content_type if file.respond_to?(:content_type)
52
+ options = { filename: filename, content_type: mime_type }.compact
53
+ file = HTTP::FormData::File.new(file, options)
49
54
  {
50
55
  filename: file.filename,
51
56
  size: file.size,
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'rest_client'
4
+ require 'api_struct'
4
5
  require 'uploadcare/concern/error_handler'
5
6
  require 'uploadcare/concern/throttle_handler'
6
7
  require 'param/authentication_header'
@@ -22,11 +23,11 @@ module Uploadcare
22
23
  # Send request with authentication header
23
24
  #
24
25
  # Handle throttling as well
25
- def request(method: 'GET', uri:, **options)
26
+ def request(uri:, method: 'GET', **options)
26
27
  request_headers = Param::AuthenticationHeader.call(method: method.upcase, uri: uri,
27
28
  content_type: headers[:'Content-type'], **options)
28
29
  handle_throttling do
29
- send('api_struct_' + method.downcase, path: remove_trailing_slash(uri),
30
+ send("api_struct_#{method.downcase}", path: remove_trailing_slash(uri),
30
31
  headers: request_headers, body: options[:content])
31
32
  end
32
33
  end
@@ -62,7 +63,7 @@ module Uploadcare
62
63
  private
63
64
 
64
65
  def remove_trailing_slash(str)
65
- str.gsub(%r{^\/}, '')
66
+ str.gsub(%r{^/}, '')
66
67
  end
67
68
 
68
69
  def default_params
@@ -14,8 +14,8 @@ module Uploadcare
14
14
 
15
15
  # return paginated list of groups
16
16
  # @see https://uploadcare.com/api-refs/rest-api/v0.5.0/#operation/groupsList
17
- def list(**options)
18
- query = options.empty? ? '' : '?' + URI.encode_www_form(options)
17
+ def list(options = {})
18
+ query = options.empty? ? '' : "?#{URI.encode_www_form(options)}"
19
19
  get(uri: "/groups/#{query}")
20
20
  end
21
21
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'api_struct'
3
4
  require 'param/user_agent'
4
5
  require 'uploadcare/concern/error_handler'
5
6
  require 'uploadcare/concern/throttle_handler'
@@ -74,19 +74,35 @@ module Uploadcare
74
74
  def upload_many_body(arr, **options)
75
75
  files_formdata = arr.map do |file|
76
76
  [HTTP::FormData::File.new(file).filename,
77
- HTTP::FormData::File.new(file)]
78
- end .to_h
77
+ form_data_for(file)]
78
+ end.to_h
79
+ p Param::Upload::UploadParamsGenerator.call(options[:store]).merge(files_formdata)
79
80
  HTTP::FormData::Multipart.new(
80
81
  Param::Upload::UploadParamsGenerator.call(options[:store]).merge(files_formdata)
81
82
  )
82
83
  end
83
84
 
85
+ def form_data_for(file)
86
+ filename = file.original_filename if file.respond_to?(:original_filename)
87
+ mime_type = file.content_type if file.respond_to?(:content_type)
88
+ options = { filename: filename, content_type: mime_type }.compact
89
+ HTTP::FormData::File.new(file, options)
90
+ end
91
+
92
+ STORE_VALUES = {
93
+ true => '1',
94
+ false => '0'
95
+ }.freeze
96
+
84
97
  # Prepare upload_from_url initial request body
85
98
  def upload_from_url_body(url, **options)
86
- HTTP::FormData::Multipart.new({
87
- 'pub_key': Uploadcare.config.public_key,
88
- 'source_url': url
89
- }.merge(**options))
99
+ HTTP::FormData::Multipart.new(
100
+ options.merge(
101
+ 'pub_key' => Uploadcare.config.public_key,
102
+ 'source_url' => url,
103
+ 'store' => STORE_VALUES[options[:store]]
104
+ )
105
+ )
90
106
  end
91
107
  end
92
108
  end
@@ -9,8 +9,12 @@ module Uploadcare
9
9
  class WebhookClient < RestClient
10
10
  # Create webhook
11
11
  # @see https://uploadcare.com/docs/api_reference/rest/webhooks/#subscribe
12
- def create(target_url, event: 'file.uploaded', is_active: true)
13
- body = { 'target_url': target_url, 'event': event, 'is_active': is_active }.to_json
12
+ def create(options = {})
13
+ body = {
14
+ 'target_url': options[:target_url],
15
+ 'event': options[:event] || 'file.uploaded',
16
+ 'is_active': options[:is_active] || true
17
+ }.to_json
14
18
  post(uri: '/webhooks/', content: body)
15
19
  end
16
20
 
@@ -22,14 +26,14 @@ module Uploadcare
22
26
 
23
27
  # Permanently deletes subscription
24
28
  # @see https://uploadcare.com/docs/api_reference/rest/webhooks/#unsubscribe
25
- def delete(name)
26
- body = { 'name': name }.to_json
29
+ def delete(target_url)
30
+ body = { 'target_url': target_url }.to_json
27
31
  post(uri: '/webhooks/unsubscribe/', content: body)
28
32
  end
29
33
 
30
34
  # Updates webhook
31
35
  # @see https://uploadcare.com/docs/api_reference/rest/webhooks/#subscribe-update
32
- def update(id, **options)
36
+ def update(id, options = {})
33
37
  body = options.to_json
34
38
  post(uri: "/webhooks/#{id}/", content: body)
35
39
  end
@@ -14,9 +14,9 @@ module Uploadcare
14
14
  def failure(response)
15
15
  catch_upload_errors(response)
16
16
  parsed_response = JSON.parse(response.body.to_s)
17
- raise RequestError, parsed_response['detail']
17
+ raise RequestError, parsed_response['detail'] || parsed_response.map { |k, v| "#{k}: #{v}" }.join('; ')
18
18
  rescue JSON::ParserError
19
- raise RequestError, response.status
19
+ raise RequestError, response.body.to_s
20
20
  end
21
21
 
22
22
  # Extension of ApiStruct's wrap method
@@ -26,7 +26,7 @@ module Uploadcare
26
26
  return unless url
27
27
 
28
28
  query = URI.decode_www_form(URI(url).query).to_h
29
- query = Hash[query.map { |k, v| [k.to_sym, v] }]
29
+ query = query.map { |k, v| [k.to_sym, v] }.to_h
30
30
  self.class.list(**query)
31
31
  end
32
32
 
@@ -36,7 +36,7 @@ module Uploadcare
36
36
  return unless url
37
37
 
38
38
  query = URI.decode_www_form(URI(url).query).to_h
39
- query = Hash[query.map { |k, v| [k.to_sym, v] }]
39
+ query = query.map { |k, v| [k.to_sym, v] }.to_h
40
40
  self.class.list(**query)
41
41
  end
42
42
 
@@ -59,12 +59,10 @@ module Uploadcare
59
59
  # iterate through pages, starting with current one
60
60
  #
61
61
  # @yield [Block]
62
- def each
62
+ def each(&block)
63
63
  current_page = self
64
64
  while current_page
65
- current_page.results.each do |obj|
66
- yield obj
67
- end
65
+ current_page.results.each(&block)
68
66
  current_page = current_page.next_page
69
67
  end
70
68
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Uploadcare
4
+ module Entity
5
+ # This serializer lets a user convert uploaded documents
6
+ # @see https://uploadcare.com/api-refs/rest-api/v0.6.0/#operation/documentConvert
7
+ class DocumentConverter < Entity
8
+ client_service Conversion::DocumentConversionClient
9
+ # Converts documents
10
+ #
11
+ # @param doc_params [Array] of hashes with params or [Hash]
12
+ # @option options [Boolean] :store (false) whether to store file on servers.
13
+ def self.convert(doc_params, **options)
14
+ params = doc_params.is_a?(Hash) ? [doc_params] : doc_params
15
+ Conversion::DocumentConversionClient.new.convert_many(params, **options)
16
+ end
17
+
18
+ # Returns a status of document conversion job
19
+ #
20
+ # @param token [Integer, String] token obtained from a server in convert method
21
+ def self.status(token)
22
+ Conversion::DocumentConversionClient.new.get_conversion_status(token)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -9,7 +9,8 @@ module Uploadcare
9
9
  client_service FileClient
10
10
 
11
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
12
+ :mime_type, :original_file_url, :original_filename, :size, :url, :uuid, :variations, :video_info,
13
+ :source, :rekognition_info
13
14
 
14
15
  # gets file's uuid - even if it's only initialized with url
15
16
  # @return [String]
@@ -17,8 +18,7 @@ module Uploadcare
17
18
  return @entity.uuid if @entity.uuid
18
19
 
19
20
  uuid = @entity.url.gsub('https://ucarecdn.com/', '')
20
- uuid = uuid.gsub(%r{\/.*}, '')
21
- uuid
21
+ uuid.gsub(%r{/.*}, '')
22
22
  end
23
23
 
24
24
  # loads file metadata, if it's initialized with url or uuid
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'uploadcare/entity/file'
4
4
  require 'uploadcare/entity/decorator/paginator'
5
+ require 'api_struct'
5
6
 
6
7
  module Uploadcare
7
8
  module Entity
@@ -28,8 +28,7 @@ module Uploadcare
28
28
  return @entity.id if @entity.id
29
29
 
30
30
  id = @entity.cdn_url.gsub('https://ucarecdn.com/', '')
31
- id = id.gsub(%r{\/.*}, '')
32
- id
31
+ id.gsub(%r{/.*}, '')
33
32
  end
34
33
 
35
34
  # loads group metadata, if it's initialized with url or id
@@ -52,6 +52,8 @@ module Uploadcare
52
52
  # @param url [String]
53
53
  def self.upload_from_url(url, **options)
54
54
  response = UploaderClient.new.upload_from_url(url, **options)
55
+ return response.success[:token] unless response.success[:files]
56
+
55
57
  response.success[:files].map { |file_data| Uploadcare::Entity::File.new(file_data) }
56
58
  end
57
59
 
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Uploadcare
4
+ module Entity
5
+ # This serializer lets a user convert uploaded videos, and usually returns an array of results
6
+ # @see https://uploadcare.com/api-refs/rest-api/v0.6.0/#operation/videoConvert
7
+ class VideoConverter < Entity
8
+ client_service Conversion::VideoConversionClient
9
+ # Converts video files
10
+ #
11
+ # @param doc_params [Array] of hashes with params or [Hash]
12
+ # @option options [Boolean] :store (false) whether to store file on servers.
13
+ def self.convert(video_params, **options)
14
+ params = video_params.is_a?(Hash) ? [video_params] : video_params
15
+ Conversion::VideoConversionClient.new.convert_many(params, **options)
16
+ end
17
+
18
+ # Returns a status of video conversion job
19
+ #
20
+ # @param token [Integer, String] token obtained from a server in convert method
21
+ def self.status(token)
22
+ Conversion::VideoConversionClient.new.get_conversion_status(token)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Uploadcare
4
+ module Exception
5
+ # Standard error for invalid API conversion responses
6
+ class ConversionError < StandardError; end
7
+ end
8
+ end
@@ -5,8 +5,10 @@ module Uploadcare
5
5
  # Exception for throttled requests
6
6
  class ThrottleError < StandardError
7
7
  attr_reader :timeout
8
+
8
9
  # @param timeout [Float] Amount of seconds the request have been throttled for
9
10
  def initialize(timeout = 10.0)
11
+ super
10
12
  @timeout = timeout
11
13
  end
12
14
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Uploadcare
4
+ module Param
5
+ module Conversion
6
+ module Document
7
+ class ProcessingJobUrlBuilder
8
+ class << self
9
+ def call(uuid:, format: nil, page: nil)
10
+ [
11
+ uuid_part(uuid),
12
+ format_part(format),
13
+ page_part(page)
14
+ ].compact.join('-')
15
+ end
16
+
17
+ private
18
+
19
+ def uuid_part(uuid)
20
+ "#{uuid}/document/"
21
+ end
22
+
23
+ def format_part(format)
24
+ return if format.nil?
25
+
26
+ "/format/#{format}/"
27
+ end
28
+
29
+ def page_part(page)
30
+ return if page.nil?
31
+
32
+ "/page/#{page}/"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Uploadcare
4
+ module Param
5
+ module Conversion
6
+ module Video
7
+ class ProcessingJobUrlBuilder
8
+ class << self
9
+ # rubocop:disable Metrics/ParameterLists
10
+ def call(uuid:, size: {}, quality: nil, format: nil, cut: {}, thumbs: {})
11
+ [
12
+ uuid_part(uuid),
13
+ size_part(size),
14
+ quality_part(quality),
15
+ format_part(format),
16
+ cut_part(cut),
17
+ thumbs_part(thumbs)
18
+ ].compact.join('-')
19
+ end
20
+ # rubocop:enable Metrics/ParameterLists
21
+
22
+ private
23
+
24
+ def uuid_part(uuid)
25
+ "#{uuid}/video/"
26
+ end
27
+
28
+ def size_part(size)
29
+ return if size.empty?
30
+
31
+ dimensions = "#{size[:width]}x#{size[:height]}" if size[:width] || size[:height]
32
+ resize_mode = (size[:resize_mode]).to_s
33
+ "/size/#{dimensions}/#{resize_mode}/".squeeze('/')
34
+ end
35
+
36
+ def quality_part(quality)
37
+ return if quality.nil?
38
+
39
+ "/quality/#{quality}/"
40
+ end
41
+
42
+ def format_part(format)
43
+ return if format.nil?
44
+
45
+ "/format/#{format}/"
46
+ end
47
+
48
+ def cut_part(cut)
49
+ return if cut.empty?
50
+
51
+ "/cut/#{cut[:start_time]}/#{cut[:length]}/"
52
+ end
53
+
54
+ def thumbs_part(thumbs)
55
+ return if thumbs.empty?
56
+
57
+ "/thumbs~#{thumbs[:N]}/#{thumbs[:number]}/".squeeze('/')
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -12,7 +12,7 @@ module Uploadcare
12
12
  # UploadcareRuby/3.0.0-dev/Pubkey_(Ruby/2.6.3;UploadcareRuby)
13
13
  def self.call
14
14
  framework_data = Uploadcare.config.framework_data || ''
15
- framework_data_string = '; ' + Uploadcare.config.framework_data unless framework_data.empty?
15
+ framework_data_string = "; #{Uploadcare.config.framework_data}" unless framework_data.empty?
16
16
  public_key = Uploadcare.config.public_key
17
17
  "UploadcareRuby/#{VERSION}/#{public_key} (Ruby/#{RUBY_VERSION}#{framework_data_string})"
18
18
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Uploadcare
4
- VERSION = '3.0.5'
4
+ VERSION = '3.1.0-rc1'
5
5
  end
@@ -7,8 +7,8 @@ require 'uploadcare/ruby/version'
7
7
  Gem::Specification.new do |spec|
8
8
  spec.name = 'uploadcare-ruby'
9
9
  spec.version = Uploadcare::VERSION
10
- spec.authors = ['Stepan Redka']
11
- spec.email = ['stepan.redka@railsmuffin.com']
10
+ spec.authors = ['Stepan Redka, Dmitrij Ivanchenko']
11
+ spec.email = ['stepan.redka@railsmuffin.com', 'dmitrij.ivanchenko@gmail.com']
12
12
 
13
13
  spec.summary = 'Ruby wrapper for uploadcare API'
14
14
  spec.description = spec.summary
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uploadcare-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.5
4
+ version: 3.1.0.pre.rc1
5
5
  platform: ruby
6
6
  authors:
7
- - Stepan Redka
7
+ - Stepan Redka, Dmitrij Ivanchenko
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-04-15 00:00:00.000000000 Z
11
+ date: 2021-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: api_struct
@@ -153,6 +153,7 @@ dependencies:
153
153
  description: Ruby wrapper for uploadcare API
154
154
  email:
155
155
  - stepan.redka@railsmuffin.com
156
+ - dmitrij.ivanchenko@gmail.com
156
157
  executables: []
157
158
  extensions: []
158
159
  extra_rdoc_files: []
@@ -173,6 +174,9 @@ files:
173
174
  - bin/setup
174
175
  - lib/uploadcare.rb
175
176
  - lib/uploadcare/api/api.rb
177
+ - lib/uploadcare/client/conversion/base_conversion_client.rb
178
+ - lib/uploadcare/client/conversion/document_conversion_client.rb
179
+ - lib/uploadcare/client/conversion/video_conversion_client.rb
176
180
  - lib/uploadcare/client/file_client.rb
177
181
  - lib/uploadcare/client/file_list_client.rb
178
182
  - lib/uploadcare/client/group_client.rb
@@ -188,6 +192,7 @@ files:
188
192
  - lib/uploadcare/concern/throttle_handler.rb
189
193
  - lib/uploadcare/concern/upload_error_handler.rb
190
194
  - lib/uploadcare/entity/decorator/paginator.rb
195
+ - lib/uploadcare/entity/document_converter.rb
191
196
  - lib/uploadcare/entity/entity.rb
192
197
  - lib/uploadcare/entity/file.rb
193
198
  - lib/uploadcare/entity/file_list.rb
@@ -195,10 +200,14 @@ files:
195
200
  - lib/uploadcare/entity/group_list.rb
196
201
  - lib/uploadcare/entity/project.rb
197
202
  - lib/uploadcare/entity/uploader.rb
203
+ - lib/uploadcare/entity/video_converter.rb
198
204
  - lib/uploadcare/entity/webhook.rb
205
+ - lib/uploadcare/exception/conversion_error.rb
199
206
  - lib/uploadcare/exception/request_error.rb
200
207
  - lib/uploadcare/exception/throttle_error.rb
201
208
  - lib/uploadcare/param/authentication_header.rb
209
+ - lib/uploadcare/param/conversion/document/processing_job_url_builder.rb
210
+ - lib/uploadcare/param/conversion/video/processing_job_url_builder.rb
202
211
  - lib/uploadcare/param/param.rb
203
212
  - lib/uploadcare/param/secure_auth_header.rb
204
213
  - lib/uploadcare/param/simple_auth_header.rb
@@ -228,11 +237,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
228
237
  version: '0'
229
238
  required_rubygems_version: !ruby/object:Gem::Requirement
230
239
  requirements:
231
- - - ">="
240
+ - - ">"
232
241
  - !ruby/object:Gem::Version
233
- version: '0'
242
+ version: 1.3.1
234
243
  requirements: []
235
- rubygems_version: 3.0.1
244
+ rubygems_version: 3.2.22
236
245
  signing_key:
237
246
  specification_version: 4
238
247
  summary: Ruby wrapper for uploadcare API