etsy 0.3.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 63b1728090ce087c6421fdb354545b5031206bdd
4
- data.tar.gz: 720fd11d6f39fe99e5f414e54155db73c2bedce3
3
+ metadata.gz: dd7112229ce87257b5ea66ca6eddafe82d07bacc
4
+ data.tar.gz: e8f34ab7f54ee0675a26d387c77b337ca10ec2db
5
5
  SHA512:
6
- metadata.gz: 2c7a7b67c5bb186cecfe0a61000dd6b2a6258d5e4bd915c67672e40d949af76d7c083bfd54ec7e96c7d0396665562c389deafd3a1422ca21e6a4553a47a1f5aa
7
- data.tar.gz: 60c5ad5ef28a7f5104ffcbb9e6df25f292ab31292725e9a45dddfe8fe62a93ac22ce1d0ea22d18c98db91e37b7d66e4bbc676ad6d7f422a339b86b878edc7eb7
6
+ metadata.gz: ad057b670ae67786f6c4093218dfb615ede31d5c005b8e19c753f3a776fcb1b77e0cf3e1dbf5f7227ad303ab6320ae7d5c4d014be48684d2c8490279e1992a73
7
+ data.tar.gz: 50108ef28fcd663125db0787a1127d6a5ee8587f5b1c35cf7aee4776f6f503fb2995af90a595d8f1577b8a4e228c02c06adce626e45fa468629f49c395423f1c
@@ -1,7 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
4
3
  - 1.9.3
5
- - jruby-18mode
6
4
  - jruby-19mode
7
5
  - rbx-2
6
+ - 2.1.5
data/README.md CHANGED
@@ -26,6 +26,32 @@ It will likely work with higher versions, but this is unproven.
26
26
 
27
27
  ## Usage
28
28
 
29
+ In order to try this out you'll need to create an app on [etsy.com/your/apps](https://www.etsy.com/your/apps).
30
+
31
+ This will give you an api key and secret.
32
+
33
+ Paste the following into IRB, replacing the api key and secret with the ones you got on Etsy:
34
+
35
+ ```ruby
36
+ require 'etsy'
37
+ Etsy.protocol = "https"
38
+ Etsy.api_key = 'YOUR API KEY'
39
+ Etsy.api_secret = 'YOUR SECRET'
40
+ request = Etsy.request_token
41
+ Etsy.verification_url
42
+ ```
43
+
44
+ Paste the verification URL into your browser, and authorize the application. That will give you a page
45
+ with a code on it. Paste the following into IRB, replacing the code:
46
+
47
+ ```ruby
48
+ access = Etsy.access_token(request.token, request.secret, 'CODE')
49
+ Etsy.myself(access.token, access.secret)
50
+ ```
51
+
52
+ If you've received a 401 unauthorized error, then you likely don't have a valid api key and secret, or
53
+ perhaps the verification url timed out.
54
+
29
55
  ### Public Mode
30
56
 
31
57
  The Etsy API has two modes: public, and authenticated. Public mode only requires an
@@ -67,6 +93,11 @@ Authenticated calls can now be made by passing an access token and secret:
67
93
 
68
94
  Etsy.myself(access.token, access.secret)
69
95
 
96
+ The key and secret have to be passed in for the authenticated calls.
97
+
98
+ auth = {:access_token=>access.token, :access_secret=>access.secret}
99
+ Etsy::Transaction.find_all_by_shop_id(shop_id, auth.merge(options))
100
+
70
101
  ### Web Application
71
102
 
72
103
  The process for authenticating via a web application is similar, but requires the configuration of a callback URL:
@@ -278,16 +309,28 @@ I ask that you not submit patches that include changes to the version or gemspec
278
309
  These people have helped make the Etsy gem what it is today:
279
310
 
280
311
  * [Patrick Reagan](https://github.com/reagent)
281
- * [Katrina Owen](http://github.com/kytrinyx)
312
+ * [Katrina Owen](https://github.com/kytrinyx)
313
+ * [Trae Robrock](https://github.com/trobrock)
314
+ * [Roger Smith](https://github.com/rogsmith)
315
+ * [Jimmy Tang](https://github.com/jimmytang)
282
316
  * [Mak Nazečić-Andrlon](https://github.com/Muon)
317
+ * [Daniel Szmulewicz](https://github.com/danielsz)
283
318
  * [Patrick Schless](https://github.com/plainlystated)
319
+ * [Martin Popelak](https://github.com/pupca)
320
+ * [Julio Santos](https://github.com/julio)
284
321
  * [Matt Fields](https://github.com/mfields106)
322
+ * [Mike Taylor](https://github.com/sealabcore)
323
+ * [Mason Stewart](https://github.com/masondesu)
324
+ * [Sasha Gerrand](https://github.com/sgerrand)
285
325
  * [Jake Boxer](https://github.com/jakeboxer)
286
- * [Trae Robrock](https://github.com/trobrock)
287
- * [Jimmy Tang](https://github.com/jimmytang)
288
- * [Julio Santos](https://github.com/julio)
289
- * [Roger Smith](https://github.com/rogsmith)
290
- * [Daniel Szmulewicz](https://github.com/danielsz)
326
+ * [Sunwoo Yang](https://github.com/sunwooz)
327
+ * [Isaac Rosenberg](https://github.com/irosenb)
328
+ * [Carson Gross](https://github.com/carsongross)
329
+ * [John Amicangelo](https://github.com/JohnAmican)
330
+ * [Max Gulyaev](https://github.com/maxilev)
331
+ * [fbehrens](https://github.com/fbehrens)
332
+ * [William Jeffries](https://github.com/williamcodes)
333
+ * [Jack Guoyuan Zhao](https://github.com/zhaoguoyuan)
291
334
 
292
335
  ### Github Flow
293
336
 
@@ -27,6 +27,7 @@ require 'etsy/shipping_template'
27
27
  require 'etsy/section'
28
28
  require 'etsy/favorite_listing'
29
29
  require 'etsy/receipt'
30
+ require 'etsy/variation/property_set'
30
31
 
31
32
  # = Etsy: A friendly Ruby interface to the Etsy API
32
33
  #
@@ -21,8 +21,8 @@ module Etsy
21
21
 
22
22
  # Fetch all images for a given listing.
23
23
  #
24
- def self.find_all_by_listing_id(listing_id)
25
- get_all("/listings/#{listing_id}/images")
24
+ def self.find_all_by_listing_id(listing_id, options = {})
25
+ get_all("/listings/#{listing_id}/images", options)
26
26
  end
27
27
 
28
28
  def self.create(listing, image_path, options = {})
@@ -33,7 +33,7 @@ module Etsy
33
33
  include Etsy::Model
34
34
 
35
35
  STATES = %w(active removed sold_out expired alchemy)
36
- VALID_STATES = [:active, :expired, :inactive, :sold, :featured]
36
+ VALID_STATES = [:active, :expired, :inactive, :sold, :featured, :draft, :sold_out]
37
37
 
38
38
  attribute :id, :from => :listing_id
39
39
  attribute :view_count, :from => :views
@@ -44,7 +44,8 @@ module Etsy
44
44
 
45
45
  attributes :title, :description, :state, :url, :price, :quantity,
46
46
  :tags, :materials, :hue, :saturation, :brightness, :is_black_and_white,
47
- :featured_rank, :occasion, :num_favorers, :user_id
47
+ :featured_rank, :occasion, :num_favorers, :user_id,
48
+ :shipping_template_id, :who_made, :when_made
48
49
 
49
50
  association :image, :from => 'Images'
50
51
 
@@ -79,7 +80,7 @@ module Etsy
79
80
  # By default, pulls back the first 25 active listings.
80
81
  # Defaults can be overridden using :limit, :offset, and :state
81
82
  #
82
- # Available states are :active, :expired, :inactive, :sold, and :featured
83
+ # Available states are :active, :expired, :inactive, :sold, and :featured, :draft, :sold_out
83
84
  # where :featured is a subset of the others.
84
85
  #
85
86
  # options = {
@@ -123,7 +124,7 @@ module Etsy
123
124
  # The collection of images associated with this listing.
124
125
  #
125
126
  def images
126
- @images ||= Image.find_all_by_listing_id(id)
127
+ @images ||= Image.find_all_by_listing_id(id, oauth)
127
128
  end
128
129
 
129
130
  # The primary image for this listing.
@@ -132,6 +133,53 @@ module Etsy
132
133
  images.first
133
134
  end
134
135
 
136
+ def variations
137
+ self.class.get_all("/listings/#{id}/variations")
138
+ end
139
+
140
+ # If these are your desired variations:
141
+ # - Dimensions: 1 x 2 inches
142
+ # - Dimensions: 2 x 4 inches
143
+ #
144
+ # Then you first have to find the property ID of the property you want to vary. Eg:
145
+ # Etsy::Variation::PropertySet.find_property_by_name("Dimensions").fetch("property_id")
146
+ #
147
+ # Then you can decide which options you want to set for this property.
148
+ # Eg:
149
+ # Etsy::Variation::PropertySet.qualifying_properties_for_property("Dimension")
150
+ # => [{
151
+ # "param"=>"dimensions_scale",
152
+ # "description"=>"Sizing Scale",
153
+ # "options"=>{
154
+ # "Inches" => 344,
155
+ # "Centimeters" => 345,
156
+ # "Other" => 346
157
+ # }
158
+ # }]
159
+ #
160
+ # Put it all together for a call to add_variations:
161
+
162
+ # property_id = Etsy::Variation::PropertySet.find_property_by_name("Dimensions").fetch("property_id")
163
+ # scale = Etsy::Variation::PropertySet.qualifying_properties_for_property("Dimensions").detect {|qp| qp.fetch("description") == "Sizing Scale"}
164
+ # my_listing.add_variations(
165
+ # :variations => [
166
+ # {"property_id" => property_id, "value" => "1 x 2", "is_available" => true, "price" => 1.23},
167
+ # {"property_id" => property_id, "value" => "2 x 4", "is_available" => true, "price" => 2.34}
168
+ # ],
169
+ # scale.fetch("param") => scale.fetch("options").fetch("Inches")
170
+ # )
171
+ def add_variations(options)
172
+ options[:variations] = JSON.dump(options.delete(:variations))
173
+ options[:require_secure] = true
174
+ self.class.post("/listings/#{id}/variations", options)
175
+ end
176
+
177
+ def update_variations(options)
178
+ options[:variations] = JSON.dump(options.delete(:variations))
179
+ options[:require_secure] = true
180
+ self.class.put("/listings/#{id}/variations", options)
181
+ end
182
+
135
183
  def black_and_white?
136
184
  is_black_and_white
137
185
  end
@@ -169,6 +217,10 @@ module Etsy
169
217
  (user_ids.size > 0) ? Array(Etsy::User.find(user_ids, options)) : []
170
218
  end
171
219
 
220
+ def is_supply
221
+ !!@result.fetch("is_supply")
222
+ end
223
+
172
224
  private
173
225
 
174
226
  def self.valid?(state)
@@ -209,5 +261,10 @@ module Etsy
209
261
  (listing_ids.size > 0) ? Array(find(listing_ids, options)) : []
210
262
  end
211
263
 
264
+ private
265
+
266
+ def oauth
267
+ oauth = (token && secret) ? {:access_token => token, :access_secret => secret} : {}
268
+ end
212
269
  end
213
270
  end
@@ -6,14 +6,14 @@ module Etsy
6
6
  attribute :buyer_id, :from => :buyer_user_id
7
7
 
8
8
  attributes :quantity, :listing_id, :name, :first_line, :second_line, :city, :state, :zip, :country_id,
9
- :payment_email, :buyer_email, :created_tsz
9
+ :payment_email, :buyer_email, :creation_tsz
10
10
 
11
11
  def self.find_all_by_shop_id(shop_id, options = {})
12
12
  get_all("/shops/#{shop_id}/receipts", options)
13
13
  end
14
14
 
15
15
  def created_at
16
- Time.at(created_tsz)
16
+ Time.at(creation_tsz)
17
17
  end
18
18
 
19
19
  def buyer
@@ -21,4 +21,4 @@ module Etsy
21
21
  end
22
22
 
23
23
  end
24
- end
24
+ end
@@ -107,7 +107,7 @@ module Etsy
107
107
  if value.respond_to?(:read)
108
108
  body << "Content-Disposition: form-data; name=\"#{esc_key}\"; filename=\"#{File.basename(value.path)}\"#{crlf}"
109
109
  body << "Content-Type: image/jpeg#{crlf*2}"
110
- body << value.read
110
+ body << open(value.path, "rb") {|io| io.read}
111
111
  else
112
112
  body << "Content-Disposition: form-data; name=\"#{esc_key}\"#{crlf*2}#{value}"
113
113
  end
@@ -0,0 +1,71 @@
1
+ module Etsy
2
+ module Variation
3
+ class PropertySet
4
+ # Used to find properties which the seller can vary (eg Size, Color, etc), and options associated with those properties (eg Inches)
5
+ #
6
+ # The variations stuff is complex. See https://www.etsy.com/developers/documentation/getting_started/variations for more info.
7
+ #
8
+ # Probably the most useful method here is qualifying_properties_for_property. This method pulls in data from a few sources to get
9
+ # you everything you need to set up your variation options.
10
+ #
11
+ # Eg: I want to have a few Length options on my listings, and I want to use the unit Inches, then:
12
+ # Etsy::Variation::PropertySet.qualifying_properties_for_property("Length")
13
+ # => [{
14
+ # "param"=>"sizing_scale",
15
+ # "description"=>"Sizing Scale",
16
+ # "options"=>{
17
+ # "Alpha" => 301,
18
+ # "Inches" => 327,
19
+ # "Centimeters" => 328,
20
+ # "Fluid Ounces" => 335,
21
+ # "Millilitres" => 336,
22
+ # "Litres" => 337,
23
+ # "Other => 329
24
+ # }
25
+ # }]
26
+ #
27
+ # This tells me I want to set the parameter sizing_scale to 327 when calling Etsy::Listing.add_variations.
28
+
29
+ include Etsy::Model
30
+
31
+
32
+ attributes :properties, :category_id, :options, :qualifiers,
33
+ :qualifying_properties
34
+
35
+ def self.all
36
+ @all ||= get("/property_sets")
37
+ end
38
+
39
+ def self.find_property_by_name(name)
40
+ property = all.properties.detect {|prop_id, prop| prop["name"] == name}
41
+ if property
42
+ property_id, property_data = property
43
+ property_data
44
+ end
45
+ end
46
+
47
+ def self.qualifying_properties_for_property(name)
48
+ property = find_property_by_name(name)
49
+ return nil unless property
50
+ property_id = property["property_id"]
51
+
52
+ qualifiers = all.qualifiers[property_id.to_s]
53
+ return [] unless qualifiers
54
+
55
+ qualifiers.map do |qualifier|
56
+ qualifying_properties = all.qualifying_properties[qualifier.fetch("property_id").to_s]
57
+ options = qualifier.fetch("options").inject({}) do |acc, opt_id|
58
+ acc.merge({
59
+ all.options.fetch(opt_id.to_s) => opt_id
60
+ })
61
+ end
62
+ {
63
+ "param" => qualifying_properties.fetch("param"),
64
+ "description" => qualifying_properties.fetch("description"),
65
+ "options" => options
66
+ }
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,3 +1,3 @@
1
1
  module Etsy
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -1,11 +1,11 @@
1
- {
1
+ {
2
2
  "count":1,
3
3
  "results":
4
4
  [
5
5
  {
6
6
  "receipt_id":27230877,
7
7
  "buyer_user_id":12345,
8
- "created_tsz":1412206858,
8
+ "creation_tsz":1412206858,
9
9
  "quantity":5,
10
10
  "listing_id":123456,
11
11
  "name":"Mike Taylor",
@@ -19,10 +19,10 @@
19
19
  "buyer_email":"bar@example.com"
20
20
  }
21
21
  ],
22
- "params": {
22
+ "params": {
23
23
  "shop_id":"5818087",
24
24
  "limit":25,
25
25
  "offset":0
26
26
  },
27
27
  "type":"Receipt"
28
- }
28
+ }
@@ -5,11 +5,19 @@ module Etsy
5
5
 
6
6
  context "The Image class" do
7
7
 
8
- should "be able to find all images for a listing" do
9
- images = mock_request('/listings/1/images', {}, 'Image', 'findAllListingImages.json')
10
- Image.find_all_by_listing_id(1).should == images
8
+ context "without oauth" do
9
+ should "be able to find all images for a listing" do
10
+ images = mock_request('/listings/1/images', {}, 'Image', 'findAllListingImages.json')
11
+ Image.find_all_by_listing_id(1, {}).should == images
12
+ end
11
13
  end
12
14
 
15
+ context "with options" do
16
+ should "be able to find all images for a listing with options in request" do
17
+ images = mock_request('/listings/1/images', {foo: "bar"}, 'Image', 'findAllListingImages.json')
18
+ Image.find_all_by_listing_id(1, {foo: "bar"}).should == images
19
+ end
20
+ end
13
21
  end
14
22
 
15
23
  context "An instance of the Image class" do
@@ -32,6 +32,16 @@ module Etsy
32
32
  Listing.find_all_by_shop_id(1, :state => :inactive).should == listings
33
33
  end
34
34
 
35
+ should "be able to find draft listings" do
36
+ listings = mock_request('/shops/1/listings/draft', {}, 'Listing', 'findAllShopListings.json')
37
+ Listing.find_all_by_shop_id(1, :state => :draft).should == listings
38
+ end
39
+
40
+ should "be able to find sold_out listings" do
41
+ listings = mock_request('/shops/1/listings/sold_out', {}, 'Listing', 'findAllShopListings.json')
42
+ Listing.find_all_by_shop_id(1, :state => :sold_out).should == listings
43
+ end
44
+
35
45
  should "be able to find featured listings" do
36
46
  listings = mock_request('/shops/1/listings/featured', {}, 'Listing', 'findAllShopListings.json')
37
47
  Listing.find_all_by_shop_id(1, :state => :featured).should == listings
@@ -196,15 +206,31 @@ module Etsy
196
206
  end
197
207
  end
198
208
 
199
- should "have a collection of images" do
200
- listing = Listing.new
201
- listing.stubs(:id).with().returns(1)
209
+ context "with oauth" do
210
+ should "have a collection of images" do
211
+ listing = Listing.new
212
+ listing.stubs(:id).with().returns(1)
213
+ listing.stubs(:token).with().returns("token")
214
+ listing.stubs(:secret).with().returns("secret")
215
+
216
+ Image.stubs(:find_all_by_listing_id).with(1, {access_token: "token", access_secret: "secret"}).returns('images')
202
217
 
203
- Image.stubs(:find_all_by_listing_id).with(1).returns('images')
218
+ listing.images.should == 'images'
219
+ end
220
+ end
221
+
222
+ context "without oauth" do
223
+ should "have a collection of images" do
224
+ listing = Listing.new
225
+ listing.stubs(:id).with().returns(1)
204
226
 
205
- listing.images.should == 'images'
227
+ Image.stubs(:find_all_by_listing_id).with(1, {}).returns('images')
228
+
229
+ listing.images.should == 'images'
230
+ end
206
231
  end
207
232
 
233
+
208
234
  should "have a default image" do
209
235
  listing = Listing.new
210
236
  listing.stubs(:images).with().returns(%w(image_1 image_2))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: etsy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick Reagan
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-10-02 00:00:00.000000000 Z
12
+ date: 2015-09-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
@@ -144,6 +144,7 @@ files:
144
144
  - lib/etsy/shop.rb
145
145
  - lib/etsy/transaction.rb
146
146
  - lib/etsy/user.rb
147
+ - lib/etsy/variation/property_set.rb
147
148
  - lib/etsy/verification_request.rb
148
149
  - lib/etsy/version.rb
149
150
  - test/fixtures/address/getUserAddresses.json