etsy 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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