shutterstock-v2 0.0.1

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.
Files changed (136) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +27 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +6 -0
  5. data/.travis.yml +6 -0
  6. data/Dockerfile +17 -0
  7. data/Gemfile +3 -0
  8. data/Guardfile +9 -0
  9. data/README.md +377 -0
  10. data/Rakefile +19 -0
  11. data/lib/client/auth.rb +48 -0
  12. data/lib/client/categories.rb +11 -0
  13. data/lib/client/category.rb +16 -0
  14. data/lib/client/client.rb +72 -0
  15. data/lib/client/collection.rb +151 -0
  16. data/lib/client/collections.rb +16 -0
  17. data/lib/client/configuration.rb +20 -0
  18. data/lib/client/contributor.rb +15 -0
  19. data/lib/client/driver.rb +38 -0
  20. data/lib/client/error.rb +20 -0
  21. data/lib/client/image.rb +139 -0
  22. data/lib/client/image_assets.rb +56 -0
  23. data/lib/client/image_size_details.rb +26 -0
  24. data/lib/client/images.rb +27 -0
  25. data/lib/client/license.rb +67 -0
  26. data/lib/client/licenses.rb +23 -0
  27. data/lib/client/model.rb +15 -0
  28. data/lib/client/models.rb +11 -0
  29. data/lib/client/request.rb +41 -0
  30. data/lib/client/subscription.rb +35 -0
  31. data/lib/client/subscription_allotment.rb +19 -0
  32. data/lib/client/subscription_license_format.rb +16 -0
  33. data/lib/client/subscription_license_formats.rb +12 -0
  34. data/lib/client/subscription_price.rb +13 -0
  35. data/lib/client/subscriptions.rb +37 -0
  36. data/lib/client/thumbnail.rb +17 -0
  37. data/lib/client/user.rb +68 -0
  38. data/lib/client/version.rb +3 -0
  39. data/lib/shutterstock-v2.rb +31 -0
  40. data/shutterstock-v2.gemspec +30 -0
  41. data/spec/cassettes/Shutterstock_Auth_get_access_token/returns_hash_with_access_token.yml +86 -0
  42. data/spec/cassettes/Shutterstock_Auth_get_authorize_url/returns_URL_to_redirect_user_to_passing_redirect_url_an.yml +48 -0
  43. data/spec/cassettes/Shutterstock_Categories/parses_params_correctly.yml +53 -0
  44. data/spec/cassettes/Shutterstock_Categories/returns_all_cats_for_an_image.yml +53 -0
  45. data/spec/cassettes/Shutterstock_Collection/add_image_adds_image_using_Image_new.yml +48 -0
  46. data/spec/cassettes/Shutterstock_Collection/add_image_adds_image_using_id.yml +48 -0
  47. data/spec/cassettes/Shutterstock_Collection/add_image_error_raises_error_if_collection_does_not_exist.yml +52 -0
  48. data/spec/cassettes/Shutterstock_Collection/create_creates_a_collection.yml +52 -0
  49. data/spec/cassettes/Shutterstock_Collection/destroy_destroys_a_collection.yml +93 -0
  50. data/spec/cassettes/Shutterstock_Collection/find_adds_an_image.yml +97 -0
  51. data/spec/cassettes/Shutterstock_Collection/find_converts_list_to_images.yml +101 -0
  52. data/spec/cassettes/Shutterstock_Collection/find_finds_a_collection_given_an_id.yml +52 -0
  53. data/spec/cassettes/Shutterstock_Collection/find_raises_error_for_invalid_collection_id.yml +50 -0
  54. data/spec/cassettes/Shutterstock_Collection/find_removes_an_image.yml +95 -0
  55. data/spec/cassettes/Shutterstock_Collection/list_returns_all_collections_for_the_current_user.yml +53 -0
  56. data/spec/cassettes/Shutterstock_Collection/remove_image_removes_image_using_Image_new.yml +46 -0
  57. data/spec/cassettes/Shutterstock_Collection/remove_image_removes_image_using_id.yml +46 -0
  58. data/spec/cassettes/Shutterstock_Collection/update_changes_the_name_of_a_collection.yml +97 -0
  59. data/spec/cassettes/Shutterstock_Collections/returns_all_collections_for_current_user.yml +53 -0
  60. data/spec/cassettes/Shutterstock_Image/fill_fills_all_details_of_current_image.yml +109 -0
  61. data/spec/cassettes/Shutterstock_Image/fills_all_details_of_current_image.yml +109 -0
  62. data/spec/cassettes/Shutterstock_Image/find_places_image_data_into_correct_fields.yml +56 -0
  63. data/spec/cassettes/Shutterstock_Image/find_places_more_image_data_into_correct_fields.yml +53 -0
  64. data/spec/cassettes/Shutterstock_Image/find_returns_an_Image_object.yml +56 -0
  65. data/spec/cassettes/Shutterstock_Image/finds_similar_images_given_an_image.yml +125 -0
  66. data/spec/cassettes/Shutterstock_Image/returns_an_Image_object.yml +56 -0
  67. data/spec/cassettes/Shutterstock_Image/returns_similar_images.yml +72 -0
  68. data/spec/cassettes/Shutterstock_Image/search_searches_for_images_based_on_searchterm.yml +73 -0
  69. data/spec/cassettes/Shutterstock_Image/search_searches_using_more_than_one_parameter.yml +77 -0
  70. data/spec/cassettes/Shutterstock_Image/searches_for_images_based_on_searchterm.yml +73 -0
  71. data/spec/cassettes/Shutterstock_Image/searches_using_more_than_one_parameter.yml +77 -0
  72. data/spec/cassettes/Shutterstock_Image/similar_finds_similar_images_given_an_image.yml +125 -0
  73. data/spec/cassettes/Shutterstock_Image/similar_returns_similar_images.yml +72 -0
  74. data/spec/cassettes/Shutterstock_ImageAssets/find_calculates_fields_correctly.yml +53 -0
  75. data/spec/cassettes/Shutterstock_ImageAssets/find_places_image_data_into_correct_fields.yml +53 -0
  76. data/spec/cassettes/Shutterstock_Images/fill_fills_details_of_all_images_in_list_all_images_now_have_keywords.yml +1144 -0
  77. data/spec/cassettes/Shutterstock_Images/returns_similar_images.yml +126 -0
  78. data/spec/cassettes/Shutterstock_License/license_editorial_acknowledgement_returns_error_if_requesting_an_image.yml +53 -0
  79. data/spec/cassettes/Shutterstock_License/license_editorial_acknowledgement_returns_licenced_image_if_ed_ack_is_.yml +52 -0
  80. data/spec/cassettes/Shutterstock_License/license_license_from_image_object_sends_editorial_acknowledgement_when.yml +160 -0
  81. data/spec/cassettes/Shutterstock_License/license_license_from_image_object_using_found_subscription.yml +108 -0
  82. data/spec/cassettes/Shutterstock_License/license_license_from_image_object_vector_image.yml +108 -0
  83. data/spec/cassettes/Shutterstock_License/license_multiple_licenses_multiple_images.yml +52 -0
  84. data/spec/cassettes/Shutterstock_License/license_multiple_licenses_multiple_images_from_Image_new.yml +52 -0
  85. data/spec/cassettes/Shutterstock_License/license_multiple_returns_error_in_Licenses_when_incorrect_image_used.yml +53 -0
  86. data/spec/cassettes/Shutterstock_License/license_single_licencing_same_image_twice_does_not_give_error.yml +101 -0
  87. data/spec/cassettes/Shutterstock_License/license_single_license_fails_when_subscription_doesn_t_allow.yml +49 -0
  88. data/spec/cassettes/Shutterstock_License/license_single_licenses_single_image.yml +52 -0
  89. data/spec/cassettes/Shutterstock_License/license_single_licenses_single_image_from_Image_new.yml +52 -0
  90. data/spec/cassettes/Shutterstock_License/license_single_licenses_single_image_from_hash.yml +52 -0
  91. data/spec/cassettes/Shutterstock_License/license_single_licenses_single_image_with_smaller_size.yml +52 -0
  92. data/spec/cassettes/Shutterstock_License/license_single_licenses_vector_image.yml +52 -0
  93. data/spec/cassettes/Shutterstock_License/license_single_licensing_same_image_twice_does_not_give_error.yml +101 -0
  94. data/spec/cassettes/Shutterstock_License/license_single_returns_error_when_incorrect_image_used.yml +103 -0
  95. data/spec/cassettes/Shutterstock_License/license_single_returns_error_when_incorrect_subscription_used.yml +53 -0
  96. data/spec/cassettes/Shutterstock_Models/parses_params_correctly.yml +53 -0
  97. data/spec/cassettes/Shutterstock_Models/returns_all_models_for_an_image.yml +53 -0
  98. data/spec/cassettes/Shutterstock_Subscription/allows_image_size_download_correctly_finds_if_image_size_is_possi.yml +59 -0
  99. data/spec/cassettes/Shutterstock_Subscription/new_parses_info_on_user_correctly.yml +59 -0
  100. data/spec/cassettes/Shutterstock_Subscription/new_returns_a_subscription_for_current_user.yml +59 -0
  101. data/spec/cassettes/Shutterstock_SubscriptionLicenseFormat/new_parses_info_correctly.yml +59 -0
  102. data/spec/cassettes/Shutterstock_SubscriptionLicenseFormat/new_returns_a_subscription_license_format_for_curren.yml +59 -0
  103. data/spec/cassettes/Shutterstock_Subscriptions/subscriptions_active_expired_total_subscriptions.yml +59 -0
  104. data/spec/cassettes/Shutterstock_Subscriptions/subscriptions_active_returns_only_active_subscriptions.yml +59 -0
  105. data/spec/cassettes/Shutterstock_Subscriptions/subscriptions_downloads_left_only_subscriptions_with_downloads_l.yml +59 -0
  106. data/spec/cassettes/Shutterstock_Subscriptions/subscriptions_expired_returns_only_expired_subscriptions.yml +59 -0
  107. data/spec/cassettes/Shutterstock_Subscriptions/subscriptions_find_subscription_for_image_size_finds_subs_to_use.yml +59 -0
  108. data/spec/cassettes/Shutterstock_Subscriptions/subscriptions_returns_all_subscriptions_for_current_user.yml +59 -0
  109. data/spec/cassettes/Shutterstock_User/find_parses_info_on_user_correctly.yml +52 -0
  110. data/spec/cassettes/Shutterstock_User/find_returns_object_for_current_user.yml +52 -0
  111. data/spec/client/auth_spec.rb +36 -0
  112. data/spec/client/categories_spec.rb +26 -0
  113. data/spec/client/category_spec.rb +16 -0
  114. data/spec/client/client_spec.rb +32 -0
  115. data/spec/client/collection_spec.rb +159 -0
  116. data/spec/client/collections_spec.rb +18 -0
  117. data/spec/client/configuration_spec.rb +10 -0
  118. data/spec/client/contributor_spec.rb +14 -0
  119. data/spec/client/driver_spec.rb +20 -0
  120. data/spec/client/image_assets_spec.rb +51 -0
  121. data/spec/client/image_size_details_spec.rb +33 -0
  122. data/spec/client/image_spec.rb +102 -0
  123. data/spec/client/images_spec.rb +31 -0
  124. data/spec/client/license_spec.rb +234 -0
  125. data/spec/client/model_spec.rb +14 -0
  126. data/spec/client/models_spec.rb +23 -0
  127. data/spec/client/request_spec.rb +79 -0
  128. data/spec/client/subscription_allotment_spec.rb +25 -0
  129. data/spec/client/subscription_license_format_spec.rb +29 -0
  130. data/spec/client/subscription_price_spec.rb +17 -0
  131. data/spec/client/subscription_spec.rb +60 -0
  132. data/spec/client/subscriptions_spec.rb +54 -0
  133. data/spec/client/thumbnail_spec.rb +21 -0
  134. data/spec/client/user_spec.rb +37 -0
  135. data/spec/spec_helper.rb +88 -0
  136. metadata +467 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e4872bf6fbbe740553693206c9deed1348c5c7eb
4
+ data.tar.gz: c8f43a8f5a5c1bb05fe20c6f724be8ad81a7428f
5
+ SHA512:
6
+ metadata.gz: ba33e6cc67b0b3929c6e57d527be97d485a965d7a7617162e7099431066719d3fad7dbad736ae18f411845eb4669a5d28467a80c3c1329469da7919281e13ae8
7
+ data.tar.gz: d38bc5675ca6223227f98685efe12cfb17366f26037e1aceecb5d2ed78c4a74563d4a20b72666127ac9c91ec5e8bc7f198228cd29ffccb4799d9d91d66029b7c
@@ -0,0 +1,27 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ Gemfile.lock
16
+
17
+ # YARD artifacts
18
+ .yardoc
19
+ _yardoc
20
+ doc/
21
+ vendor
22
+ *.swp
23
+ *.swo
24
+
25
+ .env
26
+ auth_sequence.txt
27
+ run-docker.sh
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format progress
3
+ -I.
@@ -0,0 +1,6 @@
1
+ Documentation:
2
+ Enabled: false
3
+
4
+ MethodLength:
5
+ Max: 20
6
+
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1
4
+ - 2.2
5
+ - 2.3
6
+ - 2.4
@@ -0,0 +1,17 @@
1
+ FROM ruby:2.4
2
+ MAINTAINER dp@vivitec.com.au
3
+
4
+ RUN apt-get update && apt-get install -y \
5
+ build-essential
6
+
7
+ RUN mkdir -p /app
8
+ WORKDIR /app
9
+
10
+ RUN mkdir -p /app/lib/client
11
+ COPY Gemfile Gemfile.lock shutterstock.gemspec ./
12
+ COPY lib/client/version.rb ./lib/client
13
+ RUN gem install bundler && bundle install --jobs 20 --retry 5
14
+
15
+ ENV RAKE_ENV development
16
+
17
+ CMD ["bundle", "exec", "rake", "test"]
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec, cmd: 'bundle exec rspec' do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
@@ -0,0 +1,377 @@
1
+ ## Description
2
+
3
+ This client provides an easy way to interact with [version 2 of the Shutterstock, Inc. API](http://api.shutterstock.com) which gives you access to millions of photos, illustrations and footage clips. You will need a [Client ID and Client Secret from Shutterstock](https://developers.shutterstock.com/applications) to use this client.
4
+
5
+ The API operations are done within the context of a specific user/account. Below are some examples of how to use the API client.
6
+
7
+ **Currently, this API only supports Images, not videos or music.**
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'shutterstock-v2'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install shutterstock-v2
22
+
23
+ ## Quick Start
24
+
25
+ First, see the Authentication section to generate a client_id, client_secret and access_token
26
+
27
+ ```ruby
28
+ require 'shutterstock-v2'
29
+
30
+ Shutterstock::Client.instance.configure do |config|
31
+ config.client_id = "xxx"
32
+ config.client_secret = "xxx"
33
+ config.access_token = "xxx"
34
+ end
35
+
36
+ images = Shutterstock::Image.search("blue rose")
37
+ images.total_count
38
+ # => 170416
39
+ images.count # Only returns first page of results
40
+ # => 20
41
+
42
+ image = images.first
43
+ image.id
44
+ # => 353732165
45
+ image.description
46
+ # => "close-up blue rose isolated on white background macro"
47
+
48
+ # License image for download, finding appropriate license from user's subscriptions
49
+ license = image.license
50
+
51
+ if !license.error
52
+ `wget #{license.url}`
53
+ end
54
+
55
+ # Create a collection
56
+ collection = Shutterstock::Collection.create("blue rose")
57
+ # Add first page of results from our search to the collection
58
+ collection.add_image(images)
59
+ # Delete the collection
60
+ collection.destroy
61
+
62
+ ```
63
+
64
+
65
+ ## Configuration
66
+
67
+ Configuration is through a call to the `Shutterstock::Client` singleton. All subsequent calls will use these configuration options.
68
+
69
+ You can receive a [Client ID and Client Secret from Shutterstock](https://developers.shutterstock.com/applications). A non-expiring access_token can be generated through API calls. See the Authentication section below.
70
+
71
+ ```ruby
72
+ require 'shutterstock-v2'
73
+
74
+ Shutterstock::Client.instance.configure do |config|
75
+ config.client_id = "xxx"
76
+ config.client_secret = "xxx"
77
+ config.access_token = "xxx"
78
+ end
79
+ ```
80
+
81
+
82
+ # Image
83
+
84
+ ```ruby
85
+ image = Shutterstock::Image.find(118139110)
86
+ # => #<Shutterstock::Image>
87
+ image.assets
88
+ # => #<Shutterstock::ImageAssets>
89
+ image.assets.preview.url
90
+ # => "https://image.shutterstock.com/display_pic_with_logo/1306729/118139110/stock-photo-adorable-labrador-puppy-playing-with-a-chew-toy-on-white-backdrop-118139110.jpg
91
+ image.assets.huge.height
92
+ # => 3090
93
+
94
+ image.keywords
95
+ # => ["animal", "animal themes", "backgrounds", "cute", "dog", ...]
96
+
97
+ image.description
98
+ # => "Adorable Labrador Puppy Playing with a Chew Toy on White Backdrop"
99
+
100
+ image.adult?
101
+ # => false
102
+
103
+ # Requires editorial consent before licenseing
104
+ image.editorial?
105
+ # => false
106
+
107
+ image.similar
108
+ # => #<Shutterstock::Images>, an array of #<Shutterstock::Image>
109
+ # Currently only returns first page of results
110
+
111
+ image.similar.total_count # total count of similar images
112
+ ```
113
+
114
+ ### Retrieving all image data
115
+
116
+ Some queries don't return full image data. Use `fill` to retrieve all data for a `Shutterstock::Image`
117
+
118
+ ```ruby
119
+ # collection.items only returns image id's
120
+ first_collection_of_user = Shutterstock::Collection.list.first
121
+ image = first_collection_of_user.items.first
122
+
123
+ # Description isn't downloaded by default
124
+ image.description
125
+ # => nil
126
+
127
+ image.fill
128
+
129
+ image.description
130
+ # => "Rose Garden"
131
+ image.assets.preview.url
132
+ # => "http://...."
133
+
134
+ # .fill returns self, to help with chaining
135
+ image.fill.description
136
+
137
+ # .fill can also be used on a image list
138
+ images = Shutterstock::Collection.list.fill
139
+ images.first.description
140
+ ```
141
+
142
+ ## Searching for Images
143
+
144
+ ```ruby
145
+ purple_cats = Shutterstock::Image.search("purple cat")
146
+ purple_cats.first.id
147
+ # => 431931730
148
+ ```
149
+
150
+ Shutterstock has a strong searching capability. Pass a hash to utilize [all search parameters available](https://developers.shutterstock.com/api/v2/images/search).
151
+
152
+ ```ruby
153
+ # one older japanese male teenager with a garden with a model release in landscape format
154
+ images = Shutterstock::Image.search({
155
+ query: 'garden',
156
+ people_number: 1,
157
+ people_ethnicity: 'japanese',
158
+ people_gender: 'male',
159
+ people_age: 'teenagers',
160
+ people_model_released: true,
161
+ orientation: 'horizontal'})
162
+
163
+ images.first.assets.preview.url
164
+ ```
165
+
166
+ ![Image 529426645](https://image.shutterstock.com/display_pic_with_logo/692713/529426645/stock-photo-man-who-plant-a-garden-529426645.jpg)
167
+
168
+ ## Image Licencing
169
+
170
+ To license an image for use, call `license` on a `Shutterstock::Image`. You'll receive a `Shutterstock::License` object back with any errors, the allotment from your plan, and the download url. `license` will find a valid subscription for the image size, and use that to purchase the image. Optionally specify the size (small, medium, huge, vector) and format (jpg, eps).
171
+
172
+ If an image requires editorial approval, `license` requests it.
173
+
174
+ ```ruby
175
+ licensed = Image.find(553180399).license
176
+ licensed.allotment_charge # 1 if not previously licensed, otherwise 0
177
+ licensed.url
178
+ # => "https://download.shutterstock.com/gatekeeper/abc/original.jpg"
179
+
180
+ # License the smallest asset of the image. Supports: small, medium, huge, vector. Default: huge.
181
+ licensed = Image.find(553180399).license(size: 'small')
182
+
183
+ # License the vector image
184
+ licensed = Image.find(553956103).license(size: 'vector', format: 'eps')
185
+ ```
186
+
187
+ You can choose a specific subscription, or license multiple images through `Shutterstock::License`. See Subscriptions below.
188
+
189
+
190
+ # Collections
191
+
192
+ ```ruby
193
+ collection = Shutterstock::Collection.find(21722255) # get a collection
194
+ collection.items # array of Shutterstock::Images
195
+
196
+ # metadata
197
+ collection.name # name of collection
198
+ collection.cover_item # Shutterstock::Image of cover image
199
+
200
+ ## Create Collection
201
+ new_collection = Shutterstock::Collection.create("mynewcollection")
202
+
203
+ ## Update Collection
204
+ new_collection.update(name: "updatename")
205
+
206
+ ## Destroy Collection
207
+ new_collection.destroy
208
+
209
+ ## Add Image to Collection
210
+ collection.add_image(987654321)
211
+ # or use any Shutterstock::Image object
212
+ collection.add_image(Image.find(12345))
213
+ # Can add multiple images
214
+ collection.add_image([1234, 2345, 3456])
215
+
216
+ ## Remove image from Collection
217
+ collection.remove_image(987654321)
218
+
219
+ ## Show all collections for current user (linked to access_token)
220
+ result = Shutterstock::Collection.list
221
+
222
+ ```
223
+
224
+ If you don't have a `Shutterstock::Collection` object handy, call the class with a collection ID
225
+
226
+ ```ruby
227
+ new_collection = Shutterstock::Collection.create("mynewcollection")
228
+ collection_id = new_collection.id
229
+ Shutterstock::Collection.update(id: collection_id, name: "updatename")
230
+ Shutterstock::Collection.destroy(id: collection_id)
231
+ Shutterstock::Collection.add_image(id: collection_id, image_id: 987654321)
232
+ Shutterstock::Collection.remove_image({id: collection_id, image_id: 987654321})
233
+ ```
234
+
235
+ # Subscriptions
236
+
237
+ ```ruby
238
+ # Find active (not expired) subscriptions for current user
239
+ subscriptions = Shutterstock::User.subscriptions.active
240
+ sub = subscriptions.first
241
+
242
+ sub.description
243
+ # => "Monthly Subscription"
244
+ sub.allotment.downloads_limit
245
+ # => 350
246
+ sub.allotment.downloads_left
247
+ # => 314
248
+ sub.has_downloads_left?
249
+ # => true
250
+
251
+ # Find a subscription for a specific image size
252
+ # Searches active subscriptions with downloads left
253
+ sub_id = Shutterstock::User.subscriptions.find_subscription_for_image_size('small').id
254
+ # => "s9999999"
255
+
256
+ # Images can be licensed using a subscription id
257
+ Shutterstock::License.license(subscription_id: sub_id, image_id: 1234)
258
+ Shutterstock::License.license(subscription_id: sub_id, image_id: Shutterstock::Image.find(1234))
259
+
260
+ # Optionally choose the size, format, or acknowledge the image will be used for editorial purposes
261
+ Shutterstock::License.license(subscription_id: sub_id, image_id: 1234, format: 'jpg', size: 'huge', editorial_acknowledgement: true)
262
+
263
+ # To specify metadata with the license request, use a hash
264
+ license_request = { image_id: 1234, metadata: { job: "job1", purchase_order: 'purchase order 1'}}
265
+ Shutterstock::License.license(subscription_id: sub_id, image_id: license_request)
266
+
267
+ # License multiple images by sending an array of image_ids, Shutterstock::Image objects, or hashes to license_multiple
268
+ licenses = Shutterstock::License.license_multiple(subscription_id: sub_id, image_id: [1234, 2345, 3456])
269
+ if !licenses.errors
270
+ `wget #{licenses.first.url}`
271
+ end
272
+ ```
273
+
274
+
275
+ # Authentication
276
+
277
+ To use this library, first [register an application at Shutterstock](https://developers.shutterstock.com/applications).
278
+
279
+ An access_token is needed. If your integration uses only one user account, you can follow the [single user integration](https://developers.shutterstock.com/guides/authentication#single-user-integration) directions to find the access_token.
280
+
281
+ Specify a `scope` to limit the queries that can be run by this token.
282
+
283
+ ## Manually retrieve an access_token
284
+
285
+ ```ruby
286
+ require 'shutterstock-v2'
287
+
288
+ puts "Retrieves access_token from Shutterstock API"
289
+ puts "First, create an application from this page:"
290
+ puts "https://developers.shutterstock.com/applications"
291
+ puts
292
+ puts "Enter Client ID"
293
+ client_id = gets.strip
294
+ puts
295
+ puts "Enter Client Secret"
296
+ client_secret = gets.strip
297
+
298
+ # Create configuration
299
+ Shutterstock::Client.instance.configure do |config|
300
+ config.client_id = client_id
301
+ config.client_secret = client_secret
302
+ end
303
+
304
+ puts "Requesting auth from Shutterstock..."
305
+ url = Shutterstock::Auth.get_authorize_url(redirect_uri: 'http://localhost',
306
+ state: 'my_state',
307
+ scope: 'licenses.create licenses.view purchases.view collections.view collections.edit')
308
+
309
+ puts
310
+ puts "Open this url in your process to complete the authication process :"
311
+ puts url
312
+ puts
313
+ puts "Authorize with your Shutterstock username/password."
314
+ puts
315
+ puts "You will be redirected to a localhost URL. Find the code= parameter in the URI"
316
+ puts "For example: http://localhost/?code=Dc4nSMazdKkFtk7AyBkSG3&state=my_state"
317
+ puts "Code is Dc4nSMazdKkFtk7AyBkSG3"
318
+ puts
319
+ puts "Enter the code= parameter here:"
320
+ code = gets.strip
321
+
322
+ begin
323
+ result = Shutterstock::Auth.get_access_token(code: code)
324
+ puts "You are now authenticated."
325
+ puts
326
+ puts "access_token is : #{result["access_token"]}"
327
+ puts "Use this in the config section:"
328
+
329
+ puts "Shutterstock::Client.instance.configure do |config|"
330
+ puts " config.client_id = '#{client_id}'"
331
+ puts " config.client_secret = '#{client_secret}'"
332
+ puts " config.access_token = '#{result["access_token"]}'"
333
+ puts "end"
334
+ puts
335
+ rescue Shutterstock::FailedResponse => e
336
+ puts "Authentication failed : #{e.msg}"
337
+ end
338
+
339
+ ```
340
+
341
+
342
+ # Tests
343
+
344
+ To run the tests using mocked responses, use
345
+ ```ruby
346
+ rspec
347
+ ```
348
+
349
+ To run the tests using making real API requests, use
350
+ ```ruby
351
+ VCR_OFF=1 SSTK_CLIENT_ID=<clientid> SSTK_CLIENT_SECRET=<secret> SSTK_ACCESS_TOKEN=<token> rspec
352
+ ```
353
+
354
+ Note: some tests will fail because they rely on new IDs supplied when the mocks were created.
355
+
356
+ When adding new test, uncomment options[:record] = :new_episodes line in `spec/spec-helper.rb`. And delete existing yml file
357
+
358
+ ## Automation
359
+
360
+ If you would like to automatically run tests when files are chaged, run `bundle exec guard`.
361
+ This will monitor `lib` and `spec` and will run the appropriate tests. After a test runs, hit `ENTER` to re-run all tests.
362
+
363
+
364
+ # Based on v1 code
365
+
366
+ The structure of this API code was based on the [Shutterstock API Version 1](https://github.com/shutterstock/ruby-shutterstock-api).
367
+
368
+ Major changes:
369
+ - Using version 2 of the Shutterstock API
370
+ - switched to Faraday for http requests
371
+ - used rspec 3 expect format
372
+ - added objects to support Image class
373
+ - added subscriptions and purchasing
374
+
375
+ Limitations:
376
+
377
+ - Currently limited to first page of results