etsy 0.3.0 → 0.3.4

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 (52) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +14 -5
  3. data/CHANGELOG.md +16 -0
  4. data/Gemfile +0 -4
  5. data/README.md +50 -8
  6. data/etsy.gemspec +5 -5
  7. data/lib/etsy/about.rb +15 -0
  8. data/lib/etsy/attribute_value.rb +46 -0
  9. data/lib/etsy/bill_charge.rb +31 -0
  10. data/lib/etsy/bill_payment.rb +28 -0
  11. data/lib/etsy/billing_overview.rb +18 -0
  12. data/lib/etsy/image.rb +5 -2
  13. data/lib/etsy/listing.rb +108 -7
  14. data/lib/etsy/model.rb +2 -2
  15. data/lib/etsy/receipt.rb +23 -3
  16. data/lib/etsy/request.rb +5 -5
  17. data/lib/etsy/secure_client.rb +1 -1
  18. data/lib/etsy/shipping_info.rb +27 -0
  19. data/lib/etsy/shipping_template.rb +10 -1
  20. data/lib/etsy/shop.rb +5 -0
  21. data/lib/etsy/transaction.rb +51 -1
  22. data/lib/etsy/user.rb +30 -0
  23. data/lib/etsy/variation/property_set.rb +71 -0
  24. data/lib/etsy/version.rb +1 -1
  25. data/lib/etsy.rb +10 -3
  26. data/test/fixtures/about/getAbout.json +16 -0
  27. data/test/fixtures/attribute_value/findAllListingPropertyValues.json +44 -0
  28. data/test/fixtures/bill_charge/getBillCharge.json +1 -0
  29. data/test/fixtures/bill_payment/getBillPayment.json +1 -0
  30. data/test/fixtures/billing_overview/getBillingOverview.json +1 -0
  31. data/test/fixtures/listing/findAllShopListings.json +5 -3
  32. data/test/fixtures/listing/getListing.single.includeImages.json +1 -0
  33. data/test/fixtures/receipt/findAllShopReceipts.json +4 -4
  34. data/test/fixtures/shipping_info/getShippingInfo.json +1 -0
  35. data/test/fixtures/shop/findAllShop.json +1 -1
  36. data/test/fixtures/shop/findAllShop.single.json +1 -1
  37. data/test/fixtures/shop/getShop.multiple.json +1 -1
  38. data/test/fixtures/shop/getShop.single.json +2 -1
  39. data/test/test_helper.rb +0 -2
  40. data/test/unit/etsy/attribute_value_test.rb +67 -0
  41. data/test/unit/etsy/bill_charge_test.rb +24 -0
  42. data/test/unit/etsy/bill_payment_test.rb +24 -0
  43. data/test/unit/etsy/billing_overview_test.rb +20 -0
  44. data/test/unit/etsy/image_test.rb +15 -3
  45. data/test/unit/etsy/listing_test.rb +45 -7
  46. data/test/unit/etsy/model_test.rb +4 -4
  47. data/test/unit/etsy/receipt_test.rb +15 -0
  48. data/test/unit/etsy/shipping_info_test.rb +24 -0
  49. data/test/unit/etsy/shop_about_test.rb +43 -0
  50. data/test/unit/etsy/shop_test.rb +12 -0
  51. data/test/unit/etsy/transaction_test.rb +5 -1
  52. metadata +50 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 63b1728090ce087c6421fdb354545b5031206bdd
4
- data.tar.gz: 720fd11d6f39fe99e5f414e54155db73c2bedce3
2
+ SHA256:
3
+ metadata.gz: 52e5bcc56a9eb4df1e1b2e732f296d82034b8b8fee77e17a7d4c567d70e8741e
4
+ data.tar.gz: bde90f57588f337c92a0a97b4c4f1c98757e6e3eff4d0372dcb9bbcd4d7b8103
5
5
  SHA512:
6
- metadata.gz: 2c7a7b67c5bb186cecfe0a61000dd6b2a6258d5e4bd915c67672e40d949af76d7c083bfd54ec7e96c7d0396665562c389deafd3a1422ca21e6a4553a47a1f5aa
7
- data.tar.gz: 60c5ad5ef28a7f5104ffcbb9e6df25f292ab31292725e9a45dddfe8fe62a93ac22ce1d0ea22d18c98db91e37b7d66e4bbc676ad6d7f422a339b86b878edc7eb7
6
+ metadata.gz: c974d38d7df6ee9be0df31072dc0cbadc59c762610b12039ad8132febea31273817c281dcd257e9b3334a3855677b8eb770df091caa58e77a5fb080214c0442b
7
+ data.tar.gz: 409997c87e75203d40037069af7deda3814954d33f88e3cc610c8976e7593fa9cad932fbe72025f79a82e1b4ea1a18b5c461ca1f782227d3479218c2e3ad9b1e
data/.travis.yml CHANGED
@@ -1,7 +1,16 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
4
- - 1.9.3
5
- - jruby-18mode
6
- - jruby-19mode
7
- - rbx-2
3
+ - jruby
4
+ - 2.6.8
5
+ - 2.7.4
6
+ - 3.0.2
7
+
8
+ dist: bionic
9
+
10
+ before_install:
11
+ - gem install bundler
12
+ - sudo apt-get update && sudo apt-get install apt-transport-https ca-certificates -y && sudo update-ca-certificates
13
+
14
+ matrix:
15
+ allow_failures:
16
+ - rvm: 3.0.2
data/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ All changes to the Etsy gem are documented here.
4
+
5
+ ## [0.3.4] - November 3, 2021
6
+
7
+ Getting the gem back to life and ready to migrate to Etsy API v3.
8
+
9
+ ### Added:
10
+ - States for listings as per current documentation (Etsy API v2)
11
+ - id attribute for Image class
12
+ - Change log file is here!
13
+
14
+ ### Changed:
15
+ - Cleaned up the dependencies and updated old gems
16
+ - Updated ruby versions in Travis config
data/Gemfile CHANGED
@@ -1,7 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
-
5
- if RUBY_VERSION < '1.9'
6
- gem 'activesupport', '< 4.0'
7
- end
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # Etsy
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/kytrinyx/etsy.png)](http://travis-ci.org/kytrinyx/etsy)
4
- [![Dependency Status](https://gemnasium.com/kytrinyx/etsy.png)](https://gemnasium.com/kytrinyx/etsy)
5
4
 
6
5
  ## Description
7
6
 
@@ -15,7 +14,7 @@ Installing the latest stable version is simple:
15
14
 
16
15
  If you want to be on the bleeding edge, install from GitHub:
17
16
 
18
- $ git clone git://github.com/kytrinyx/etsy.git
17
+ $ git clone git://github.com/iamfmjk/etsy.git
19
18
  $ cd etsy
20
19
  $ rake install
21
20
 
@@ -26,6 +25,32 @@ It will likely work with higher versions, but this is unproven.
26
25
 
27
26
  ## Usage
28
27
 
28
+ In order to try this out you'll need to create an app on [etsy.com/your/apps](https://www.etsy.com/your/apps).
29
+
30
+ This will give you an api key and secret.
31
+
32
+ Paste the following into IRB, replacing the api key and secret with the ones you got on Etsy:
33
+
34
+ ```ruby
35
+ require 'etsy'
36
+ Etsy.protocol = "https"
37
+ Etsy.api_key = 'YOUR API KEY'
38
+ Etsy.api_secret = 'YOUR SECRET'
39
+ request = Etsy.request_token
40
+ Etsy.verification_url
41
+ ```
42
+
43
+ Paste the verification URL into your browser, and authorize the application. That will give you a page
44
+ with a code on it. Paste the following into IRB, replacing the code:
45
+
46
+ ```ruby
47
+ access = Etsy.access_token(request.token, request.secret, 'CODE')
48
+ Etsy.myself(access.token, access.secret)
49
+ ```
50
+
51
+ If you've received a 401 unauthorized error, then you likely don't have a valid api key and secret, or
52
+ perhaps the verification url timed out.
53
+
29
54
  ### Public Mode
30
55
 
31
56
  The Etsy API has two modes: public, and authenticated. Public mode only requires an
@@ -67,6 +92,11 @@ Authenticated calls can now be made by passing an access token and secret:
67
92
 
68
93
  Etsy.myself(access.token, access.secret)
69
94
 
95
+ The key and secret have to be passed in for the authenticated calls.
96
+
97
+ auth = {:access_token=>access.token, :access_secret=>access.secret}
98
+ Etsy::Transaction.find_all_by_shop_id(shop_id, auth.merge(options))
99
+
70
100
  ### Web Application
71
101
 
72
102
  The process for authenticating via a web application is similar, but requires the configuration of a callback URL:
@@ -278,16 +308,28 @@ I ask that you not submit patches that include changes to the version or gemspec
278
308
  These people have helped make the Etsy gem what it is today:
279
309
 
280
310
  * [Patrick Reagan](https://github.com/reagent)
281
- * [Katrina Owen](http://github.com/kytrinyx)
311
+ * [Katrina Owen](https://github.com/kytrinyx)
312
+ * [Trae Robrock](https://github.com/trobrock)
313
+ * [Roger Smith](https://github.com/rogsmith)
314
+ * [Jimmy Tang](https://github.com/jimmytang)
282
315
  * [Mak Nazečić-Andrlon](https://github.com/Muon)
316
+ * [Daniel Szmulewicz](https://github.com/danielsz)
283
317
  * [Patrick Schless](https://github.com/plainlystated)
318
+ * [Martin Popelak](https://github.com/pupca)
319
+ * [Julio Santos](https://github.com/julio)
284
320
  * [Matt Fields](https://github.com/mfields106)
321
+ * [Mike Taylor](https://github.com/sealabcore)
322
+ * [Mason Stewart](https://github.com/masondesu)
323
+ * [Sasha Gerrand](https://github.com/sgerrand)
285
324
  * [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)
325
+ * [Sunwoo Yang](https://github.com/sunwooz)
326
+ * [Isaac Rosenberg](https://github.com/irosenb)
327
+ * [Carson Gross](https://github.com/carsongross)
328
+ * [John Amicangelo](https://github.com/JohnAmican)
329
+ * [Max Gulyaev](https://github.com/maxilev)
330
+ * [fbehrens](https://github.com/fbehrens)
331
+ * [William Jeffries](https://github.com/williamcodes)
332
+ * [Jack Guoyuan Zhao](https://github.com/zhaoguoyuan)
291
333
 
292
334
  ### Github Flow
293
335
 
data/etsy.gemspec CHANGED
@@ -2,8 +2,8 @@
2
2
  require File.expand_path('../lib/etsy/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
- gem.authors = ["Patrick Reagan", "Katrina Owen"]
6
- gem.email = ["reaganpr@gmail.com", "katrina.owen@gmail.com"]
5
+ gem.authors = ["Iuliia Kolomiiets", "Patrick Reagan", "Katrina Owen"]
6
+ gem.email = ["etsygeminfo@gmail.com, reaganpr@gmail.com", "katrina.owen@gmail.com" ]
7
7
  gem.description = %q{A friendly Ruby interface to the Etsy API}
8
8
  gem.summary = %q{Provides a friendly ruby-like wrapper for the Etsy API}
9
9
  gem.homepage = "http://github.com/kytrinyx/etsy"
@@ -20,9 +20,9 @@ Gem::Specification.new do |gem|
20
20
  gem.rubygems_version = "1.8.10"
21
21
 
22
22
  gem.add_dependency "json", ">= 1.5.0"
23
- gem.add_dependency "oauth", "~> 0.4.0"
23
+ gem.add_dependency "oauth", ">= 0.5.5"
24
24
 
25
- gem.add_development_dependency "rake", "~> 10.0.4"
25
+ gem.add_development_dependency "rake", "~> 12.3.3"
26
26
  gem.add_development_dependency "jnunemaker-matchy", "~> 0.4.0"
27
27
  gem.add_development_dependency 'shoulda', "~> 3.4.0"
28
28
  gem.add_development_dependency 'mocha', "~> 0.13.3"
@@ -30,5 +30,5 @@ Gem::Specification.new do |gem|
30
30
  # on shoulda/context.rb:7
31
31
  # But then when you load active_support, shoulda-context decides
32
32
  # to load MiniTest
33
- gem.add_development_dependency 'minitest', "=4.7.4"
33
+ gem.add_development_dependency 'test-unit', "~>3.5.0"
34
34
  end
data/lib/etsy/about.rb ADDED
@@ -0,0 +1,15 @@
1
+ module Etsy
2
+ class About
3
+ include Etsy::Model
4
+
5
+ attributes :status, :story_headline, :story_leading_paragraph,
6
+ :story, :related_links, :url
7
+ attribute :id, :from => :shop_id
8
+ attribute :shop_id, :from => :shop_id
9
+
10
+ def self.find_by_shop(shop)
11
+ get("/shops/#{shop.id}/about")
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,46 @@
1
+ module Etsy
2
+
3
+ # = AttributeValue
4
+ #
5
+ # An attribute of a listing according to its taxonomy.
6
+ #
7
+ # An attribute has the following attributes:
8
+ #
9
+ # [property_id] (INT) The numeric ID of this property.
10
+ # [property_name] (STRING) The name of the property, in the requested locale language.
11
+ # [scale_id] (INT) The numeric ID of the scale (if any).
12
+ # [scale_name] (STRING) The label used to describe the chosen scale (if any).
13
+ # [value_ids] (Array(INT)) The numeric IDs of the values.
14
+ # [values] (Array(STRING)) The literal values of the value
15
+ class AttributeValue
16
+
17
+ include Etsy::Model
18
+
19
+ attribute :id, :from => :property_id
20
+ attributes :property_name, :scale_id, :scale_name, :value_ids,
21
+ :values
22
+
23
+ # Fetch all property_values for a given listing.
24
+ #
25
+ def self.find_all_by_listing_id(listing_id, options = {})
26
+ get_all("/listings/#{listing_id}/attributes", options)
27
+ end
28
+
29
+ # Adds a new attribute_value to the listing given
30
+ #
31
+ def self.create(listing, property_hash, options = {})
32
+ property_id = property_hash[:property_id]
33
+ options.merge!(:require_secure => true)
34
+ options.merge!(property_hash)
35
+ put("/listings/#{listing.id}/attributes/#{property_id}", options)
36
+ end
37
+
38
+ # Delete attribute_value from listing
39
+ #
40
+ def self.destroy(listing, property_value, options = {})
41
+ options.merge!(:require_secure => true)
42
+ delete("/listings/#{listing.id}/attributes/#{property_value.id}", options)
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,31 @@
1
+ module Etsy
2
+
3
+ # = BillCharge
4
+ #
5
+ # Represents a charge to an Etsy member's account.
6
+ #
7
+ #
8
+ class BillCharge
9
+
10
+ include Etsy::Model
11
+
12
+ attribute :id, :from => :bill_charge_id
13
+ attribute :created, :from => :creation_tsz
14
+ attribute :last_modified, :from => :last_modified_tsz
15
+
16
+ attributes :type, :type_id, :user_id, :amount, :currency_code, :creation_month,
17
+ :creation_year
18
+
19
+ def self.find_all_by_user_id(user_id, options = {})
20
+ get_all("/users/#{user_id}/charges", options)
21
+ end
22
+
23
+ def created_at
24
+ Time.at(created)
25
+ end
26
+
27
+ def last_modified_at
28
+ Time.at(last_modified)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ module Etsy
2
+
3
+ # = BillPayment
4
+ #
5
+ # Represents a user's Billing Payment.
6
+ #
7
+ #
8
+ class BillPayment
9
+
10
+ include Etsy::Model
11
+
12
+ attribute :id, :from => :bill_payment_id
13
+ attribute :created, :from => :creation_tsz
14
+
15
+ attributes :type, :type_id, :user_id, :amount, :currency_code, :creation_month,
16
+ :creation_year
17
+
18
+ def self.find_all_by_user_id(user_id, options = {})
19
+ get_all("/users/#{user_id}/payments", options)
20
+ end
21
+
22
+ # Time that this listing was created
23
+ #
24
+ def created_at
25
+ Time.at(created)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+ module Etsy
2
+
3
+ # = BillingOverview
4
+ #
5
+ # A user's account balance on Etsy.
6
+ #
7
+ class BillingOverview
8
+
9
+ include Etsy::Model
10
+
11
+ attributes :is_overdue, :overdue_balance, :balance_due, :total_balance, :currency_code, :date_due,
12
+ :creation_year
13
+
14
+ def self.find_all_by_user_id(user_id, options = {})
15
+ get_all("/users/#{user_id}/billing/overview", options)
16
+ end
17
+ end
18
+ end
data/lib/etsy/image.rb CHANGED
@@ -14,15 +14,18 @@ module Etsy
14
14
 
15
15
  include Etsy::Model
16
16
 
17
+ attribute :id, :from => :listing_image_id
17
18
  attribute :square, :from => :url_75x75
18
19
  attribute :small, :from => :url_170x135
19
20
  attribute :thumbnail, :from => :url_570xN
21
+ attribute :height, :from => :full_height
22
+ attribute :width, :from => :full_width
20
23
  attribute :full, :from => :url_fullxfull
21
24
 
22
25
  # Fetch all images for a given listing.
23
26
  #
24
- def self.find_all_by_listing_id(listing_id)
25
- get_all("/listings/#{listing_id}/images")
27
+ def self.find_all_by_listing_id(listing_id, options = {})
28
+ get_all("/listings/#{listing_id}/images", options)
26
29
  end
27
30
 
28
31
  def self.create(listing, image_path, options = {})
data/lib/etsy/listing.rb CHANGED
@@ -26,28 +26,45 @@ module Etsy
26
26
  # [removed?] Has this listing been removed?
27
27
  # [sold_out?] Is this listing sold out?
28
28
  # [expired?] Has this listing expired?
29
- # [alchemy?] Is this listing an Alchemy item? (i.e. requested by an Etsy user)
29
+ # [edit?] Is this listing inactive?
30
+ # [draft?] Is this listing in draft mode / not yet published?
31
+ # [private?] Is this a private listing?
32
+ # [unavailable?] Has this listing been removed by Etsy admins?
33
+
30
34
  #
31
35
  class Listing
32
36
 
33
37
  include Etsy::Model
34
38
 
35
- STATES = %w(active removed sold_out expired alchemy)
36
- VALID_STATES = [:active, :expired, :inactive, :sold, :featured]
39
+ STATES = %w(active removed sold_out expired edit draft private unavailable)
40
+ #TODO: re-check valid states
41
+ VALID_STATES = [:active, :draft, :expired, :featured, :inactive, :sold, :sold_out]
37
42
 
38
43
  attribute :id, :from => :listing_id
39
44
  attribute :view_count, :from => :views
40
45
  attribute :created, :from => :creation_tsz
46
+ attribute :original_created, :from => :original_creation_tsz
41
47
  attribute :modified, :from => :last_modified_tsz
42
48
  attribute :currency, :from => :currency_code
43
49
  attribute :ending, :from => :ending_tsz
50
+ attribute :shop_section, :from => :shop_section_id
44
51
 
45
52
  attributes :title, :description, :state, :url, :price, :quantity,
46
53
  :tags, :materials, :hue, :saturation, :brightness, :is_black_and_white,
47
- :featured_rank, :occasion, :num_favorers, :user_id
54
+ :featured_rank, :occasion, :num_favorers, :user_id,
55
+ :shipping_template_id, :who_made, :when_made,
56
+ :style, :category_path, :taxonomy_id, :taxonomy_attributes
48
57
 
49
58
  association :image, :from => 'Images'
50
59
 
60
+ def transactions
61
+ @transactions ||= Transaction.find_all_by_listing_id(id, oauth)
62
+ end
63
+
64
+ def receipts
65
+ transactions.map{|t|t.receipt}
66
+ end
67
+
51
68
  def self.create(options = {})
52
69
  options.merge!(:require_secure => true)
53
70
  post("/listings", options)
@@ -57,7 +74,7 @@ module Etsy
57
74
  options.merge!(:require_secure => true)
58
75
  put("/listings/#{listing.id}", options)
59
76
  end
60
-
77
+
61
78
  def self.destroy(listing, options = {})
62
79
  options.merge!(:require_secure => true)
63
80
  delete("/listings/#{listing.id}", options)
@@ -79,7 +96,7 @@ module Etsy
79
96
  # By default, pulls back the first 25 active listings.
80
97
  # Defaults can be overridden using :limit, :offset, and :state
81
98
  #
82
- # Available states are :active, :expired, :inactive, :sold, and :featured
99
+ # Available states are :active, :expired, :inactive, :sold, and :featured, :draft, :sold_out
83
100
  # where :featured is a subset of the others.
84
101
  #
85
102
  # options = {
@@ -123,7 +140,7 @@ module Etsy
123
140
  # The collection of images associated with this listing.
124
141
  #
125
142
  def images
126
- @images ||= Image.find_all_by_listing_id(id)
143
+ @images ||= listing_images
127
144
  end
128
145
 
129
146
  # The primary image for this listing.
@@ -132,6 +149,68 @@ module Etsy
132
149
  images.first
133
150
  end
134
151
 
152
+ # Listing category name
153
+ #
154
+ def category
155
+ path = category_path.join('/')
156
+ @category ||= Category.find(path)
157
+ end
158
+
159
+ # Returns the taxonomy defined attributes for the listing
160
+ #
161
+ def taxonomy_attributes(options={})
162
+ options.merge!(:require_secure => true)
163
+ self.class.get_all("/listings/#{id}/attributes", oauth.merge(options))
164
+ end
165
+
166
+ def variations(options={})
167
+ options.merge!(:require_secure => true)
168
+ self.class.get_all("/listings/#{id}/variations", oauth.merge(options))
169
+ end
170
+
171
+ # If these are your desired variations:
172
+ # - Dimensions: 1 x 2 inches
173
+ # - Dimensions: 2 x 4 inches
174
+ #
175
+ # Then you first have to find the property ID of the property you want to vary. Eg:
176
+ # Etsy::Variation::PropertySet.find_property_by_name("Dimensions").fetch("property_id")
177
+ #
178
+ # Then you can decide which options you want to set for this property.
179
+ # Eg:
180
+ # Etsy::Variation::PropertySet.qualifying_properties_for_property("Dimension")
181
+ # => [{
182
+ # "param"=>"dimensions_scale",
183
+ # "description"=>"Sizing Scale",
184
+ # "options"=>{
185
+ # "Inches" => 344,
186
+ # "Centimeters" => 345,
187
+ # "Other" => 346
188
+ # }
189
+ # }]
190
+ #
191
+ # Put it all together for a call to add_variations:
192
+
193
+ # property_id = Etsy::Variation::PropertySet.find_property_by_name("Dimensions").fetch("property_id")
194
+ # scale = Etsy::Variation::PropertySet.qualifying_properties_for_property("Dimensions").detect {|qp| qp.fetch("description") == "Sizing Scale"}
195
+ # my_listing.add_variations(
196
+ # :variations => [
197
+ # {"property_id" => property_id, "value" => "1 x 2", "is_available" => true, "price" => 1.23},
198
+ # {"property_id" => property_id, "value" => "2 x 4", "is_available" => true, "price" => 2.34}
199
+ # ],
200
+ # scale.fetch("param") => scale.fetch("options").fetch("Inches")
201
+ # )
202
+ def add_variations(options)
203
+ options[:variations] = JSON.dump(options.delete(:variations))
204
+ options[:require_secure] = true
205
+ self.class.post("/listings/#{id}/variations", options)
206
+ end
207
+
208
+ def update_variations(options)
209
+ options[:variations] = JSON.dump(options.delete(:variations))
210
+ options[:require_secure] = true
211
+ self.class.put("/listings/#{id}/variations", options)
212
+ end
213
+
135
214
  def black_and_white?
136
215
  is_black_and_white
137
216
  end
@@ -148,6 +227,11 @@ module Etsy
148
227
  Time.at(created)
149
228
  end
150
229
 
230
+ # Time that this listing was originally created
231
+ def original_created_at
232
+ Time.at(original_created)
233
+ end
234
+
151
235
  # Time that this listing was last modified
152
236
  #
153
237
  def modified_at
@@ -169,6 +253,10 @@ module Etsy
169
253
  (user_ids.size > 0) ? Array(Etsy::User.find(user_ids, options)) : []
170
254
  end
171
255
 
256
+ def is_supply
257
+ @result.fetch('is_supply') == 'true'
258
+ end
259
+
172
260
  private
173
261
 
174
262
  def self.valid?(state)
@@ -209,5 +297,18 @@ module Etsy
209
297
  (listing_ids.size > 0) ? Array(find(listing_ids, options)) : []
210
298
  end
211
299
 
300
+ private
301
+
302
+ def oauth
303
+ oauth = (token && secret) ? {:access_token => token, :access_secret => secret} : {}
304
+ end
305
+
306
+ def listing_images
307
+ if result && result["Images"]
308
+ result["Images"].map { |hash| Image.new(hash) }
309
+ else
310
+ Image.find_all_by_listing_id(id, oauth)
311
+ end
312
+ end
212
313
  end
213
314
  end
data/lib/etsy/model.rb CHANGED
@@ -43,7 +43,7 @@ module Etsy
43
43
  if limit == :all
44
44
  response = Request.get(endpoint, options.merge(:limit => batch_size, :offset => initial_offset))
45
45
  result << response.result
46
- limit = [response.count - batch_size - initial_offset, 0].max
46
+ limit = [response.total - batch_size - initial_offset, 0].max
47
47
  initial_offset += batch_size
48
48
  end
49
49
 
@@ -83,7 +83,7 @@ module Etsy
83
83
  def put(endpoint, options={})
84
84
  Request.put(endpoint, options)
85
85
  end
86
-
86
+
87
87
  def delete(endpoint, options={})
88
88
  Request.delete(endpoint, options)
89
89
  end
data/lib/etsy/receipt.rb CHANGED
@@ -5,20 +5,40 @@ module Etsy
5
5
  attribute :id, :from => :receipt_id
6
6
  attribute :buyer_id, :from => :buyer_user_id
7
7
 
8
+ attribute :created, :from => :creation_tsz
9
+ attribute :last_modified, :from => :last_modified_tsz
10
+
8
11
  attributes :quantity, :listing_id, :name, :first_line, :second_line, :city, :state, :zip, :country_id,
9
- :payment_email, :buyer_email, :created_tsz
12
+ :payment_email, :buyer_email
13
+
14
+ def self.find(*identifiers_and_options)
15
+ find_one_or_more('receipts', identifiers_and_options)
16
+ end
10
17
 
11
18
  def self.find_all_by_shop_id(shop_id, options = {})
12
19
  get_all("/shops/#{shop_id}/receipts", options)
13
20
  end
14
21
 
22
+ def self.find_all_by_shop_id_and_status(shop_id, status, options = {})
23
+ get_all("/shops/#{shop_id}/receipts/#{status}", options)
24
+ end
25
+
15
26
  def created_at
16
- Time.at(created_tsz)
27
+ Time.at(created)
17
28
  end
18
29
 
19
30
  def buyer
20
31
  @buyer ||= User.find(buyer_id)
21
32
  end
22
33
 
34
+ def transactions
35
+ unless @transactions
36
+ options = {}
37
+ options = options.merge(:access_token => token, :access_secret => secret) if (token && secret)
38
+ @transactions = Transaction.find_all_by_receipt_id(id, options)
39
+ end
40
+ @transactions
41
+ end
42
+
23
43
  end
24
- end
44
+ end
data/lib/etsy/request.rb CHANGED
@@ -22,13 +22,13 @@ module Etsy
22
22
  request = Request.new(resource_path, parameters)
23
23
  Response.new(request.put)
24
24
  end
25
-
25
+
26
26
  def self.delete(resource_path, parameters = {})
27
27
  request = Request.new(resource_path, parameters)
28
28
  Response.new(request.delete)
29
29
  end
30
-
31
-
30
+
31
+
32
32
 
33
33
  # Create a new request for the resource with optional parameters
34
34
  def initialize(resource_path, parameters = {})
@@ -75,7 +75,7 @@ module Etsy
75
75
  def put
76
76
  client.put(endpoint_url)
77
77
  end
78
-
78
+
79
79
  def delete
80
80
  client.delete(endpoint_url)
81
81
  end
@@ -104,7 +104,7 @@ module Etsy
104
104
  k.nil? || v.nil? || (k.respond_to?(:empty?) && k.empty?) || (v.respond_to?(:empty?) && v.empty?)
105
105
  }.map { |k, v| "#{to_url(k.to_s)}=#{to_url(v)}" }.join('&')
106
106
  else
107
- URI.escape(val.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
107
+ URI.encode_www_form_component(val.to_s)
108
108
  end
109
109
  end
110
110
 
@@ -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,27 @@
1
+ module Etsy
2
+ class ShippingInfo
3
+ include Etsy::Model
4
+
5
+ attribute :id, :from => :shipping_info_id
6
+
7
+ attributes :origin_country_id, :destination_country_id, :currency_code, :primary_cost, :secondary_cost, :listing_id, :region_id, :origin_country_name, :destination_country_name
8
+
9
+ def self.find(id, credentials = {})
10
+ options = {
11
+ :access_token => credentials[:access_token],
12
+ :access_secret => credentials[:access_secret],
13
+ :require_secure => true
14
+ }
15
+ get("/shipping/info/#{id}", options)
16
+ end
17
+
18
+ def self.find_all_by_listing_id(listing_id, credentials = {})
19
+ options = {
20
+ :access_token => credentials[:access_token],
21
+ :access_secret => credentials[:access_secret],
22
+ :require_secure => true
23
+ }
24
+ get_all("/listings/#{listing_id}/shipping/info", options)
25
+ end
26
+ end
27
+ end