cardmagic-etsy 0.3.2

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 (93) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.travis.yml +13 -0
  4. data/Gemfile +11 -0
  5. data/LICENSE +9 -0
  6. data/README.md +348 -0
  7. data/Rakefile +12 -0
  8. data/etsy.gemspec +34 -0
  9. data/lib/etsy.rb +223 -0
  10. data/lib/etsy/about.rb +15 -0
  11. data/lib/etsy/address.rb +47 -0
  12. data/lib/etsy/attribute_value.rb +46 -0
  13. data/lib/etsy/basic_client.rb +32 -0
  14. data/lib/etsy/category.rb +84 -0
  15. data/lib/etsy/country.rb +27 -0
  16. data/lib/etsy/favorite_listing.rb +26 -0
  17. data/lib/etsy/image.rb +44 -0
  18. data/lib/etsy/listing.rb +296 -0
  19. data/lib/etsy/model.rb +127 -0
  20. data/lib/etsy/payment_template.rb +33 -0
  21. data/lib/etsy/profile.rb +49 -0
  22. data/lib/etsy/receipt.rb +37 -0
  23. data/lib/etsy/request.rb +150 -0
  24. data/lib/etsy/response.rb +128 -0
  25. data/lib/etsy/section.rb +16 -0
  26. data/lib/etsy/secure_client.rb +131 -0
  27. data/lib/etsy/shipping_info.rb +27 -0
  28. data/lib/etsy/shipping_template.rb +41 -0
  29. data/lib/etsy/shop.rb +88 -0
  30. data/lib/etsy/transaction.rb +29 -0
  31. data/lib/etsy/user.rb +109 -0
  32. data/lib/etsy/variation/property_set.rb +71 -0
  33. data/lib/etsy/verification_request.rb +17 -0
  34. data/lib/etsy/version.rb +3 -0
  35. data/test/fixtures/about/getAbout.json +16 -0
  36. data/test/fixtures/address/getUserAddresses.json +12 -0
  37. data/test/fixtures/attribute_value/findAllListingPropertyValues.json +44 -0
  38. data/test/fixtures/category/findAllSubCategoryChildren.json +78 -0
  39. data/test/fixtures/category/findAllTopCategory.json +347 -0
  40. data/test/fixtures/category/findAllTopCategory.single.json +18 -0
  41. data/test/fixtures/category/findAllTopCategoryChildren.json +308 -0
  42. data/test/fixtures/category/getCategory.multiple.json +28 -0
  43. data/test/fixtures/category/getCategory.single.json +18 -0
  44. data/test/fixtures/country/getCountry.json +1 -0
  45. data/test/fixtures/favorite_listing/findAllFavoriteListings.json +1 -0
  46. data/test/fixtures/image/findAllListingImages.json +102 -0
  47. data/test/fixtures/listing/findAllListingActive.category.json +827 -0
  48. data/test/fixtures/listing/findAllShopListings.json +69 -0
  49. data/test/fixtures/listing/getListing.multiple.json +1 -0
  50. data/test/fixtures/listing/getListing.single.includeImages.json +1 -0
  51. data/test/fixtures/listing/getListing.single.json +1 -0
  52. data/test/fixtures/payment_template/getPaymentTemplate.json +1 -0
  53. data/test/fixtures/profile/new.json +28 -0
  54. data/test/fixtures/receipt/findAllShopReceipts.json +28 -0
  55. data/test/fixtures/section/getShopSection.json +18 -0
  56. data/test/fixtures/shipping_info/getShippingInfo.json +1 -0
  57. data/test/fixtures/shipping_template/getShippingTemplate.json +1 -0
  58. data/test/fixtures/shop/findAllShop.json +1 -0
  59. data/test/fixtures/shop/findAllShop.single.json +1 -0
  60. data/test/fixtures/shop/getShop.multiple.json +1 -0
  61. data/test/fixtures/shop/getShop.single.json +34 -0
  62. data/test/fixtures/transaction/findAllShopTransactions.json +1 -0
  63. data/test/fixtures/user/getUser.multiple.json +29 -0
  64. data/test/fixtures/user/getUser.single.json +13 -0
  65. data/test/fixtures/user/getUser.single.private.json +18 -0
  66. data/test/fixtures/user/getUser.single.withProfile.json +38 -0
  67. data/test/fixtures/user/getUser.single.withShops.json +41 -0
  68. data/test/test_helper.rb +45 -0
  69. data/test/unit/etsy/address_test.rb +61 -0
  70. data/test/unit/etsy/attribute_value_test.rb +67 -0
  71. data/test/unit/etsy/basic_client_test.rb +30 -0
  72. data/test/unit/etsy/category_test.rb +106 -0
  73. data/test/unit/etsy/country_test.rb +64 -0
  74. data/test/unit/etsy/favorite_listing_test.rb +44 -0
  75. data/test/unit/etsy/image_test.rb +51 -0
  76. data/test/unit/etsy/listing_test.rb +268 -0
  77. data/test/unit/etsy/model_test.rb +64 -0
  78. data/test/unit/etsy/payment_template_test.rb +68 -0
  79. data/test/unit/etsy/profile_test.rb +111 -0
  80. data/test/unit/etsy/receipt_test.rb +107 -0
  81. data/test/unit/etsy/request_test.rb +190 -0
  82. data/test/unit/etsy/response_test.rb +175 -0
  83. data/test/unit/etsy/section_test.rb +28 -0
  84. data/test/unit/etsy/secure_client_test.rb +132 -0
  85. data/test/unit/etsy/shipping_info_test.rb +24 -0
  86. data/test/unit/etsy/shipping_template_test.rb +24 -0
  87. data/test/unit/etsy/shop_about_test.rb +43 -0
  88. data/test/unit/etsy/shop_test.rb +116 -0
  89. data/test/unit/etsy/transaction_test.rb +61 -0
  90. data/test/unit/etsy/user_test.rb +250 -0
  91. data/test/unit/etsy/verification_request_test.rb +26 -0
  92. data/test/unit/etsy_test.rb +173 -0
  93. metadata +293 -0
@@ -0,0 +1,223 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'net/http'
4
+ require 'json'
5
+ require 'oauth'
6
+ require 'uri'
7
+
8
+ require 'etsy/request'
9
+ require 'etsy/response'
10
+
11
+ require 'etsy/basic_client'
12
+ require 'etsy/secure_client'
13
+ require 'etsy/verification_request'
14
+
15
+ require 'etsy/model'
16
+ require 'etsy/user'
17
+ require 'etsy/profile'
18
+ require 'etsy/shop'
19
+ require 'etsy/listing'
20
+ require 'etsy/attribute_value'
21
+ require 'etsy/image'
22
+ require 'etsy/transaction'
23
+ require 'etsy/address'
24
+ require 'etsy/category'
25
+ require 'etsy/payment_template'
26
+ require 'etsy/country'
27
+ require 'etsy/shipping_template'
28
+ require 'etsy/shipping_info'
29
+ require 'etsy/section'
30
+ require 'etsy/favorite_listing'
31
+ require 'etsy/receipt'
32
+ require 'etsy/variation/property_set'
33
+ require 'etsy/about'
34
+
35
+ # = Etsy: A friendly Ruby interface to the Etsy API
36
+ #
37
+ # == Quick Start
38
+ #
39
+ # Getting started is easy. First, you will need a valid API key from the Etsy
40
+ # developer site (http://developer.etsy.com/).
41
+ #
42
+ # To start using the API, require the etsy gem and set it up to use your API key:
43
+ #
44
+ # require 'rubygems'
45
+ # require 'etsy'
46
+ #
47
+ # Etsy.api_key = 'itsasecret'
48
+ #
49
+ # Now you can make API calls that originate from an Etsy user:
50
+ #
51
+ # # Find a user by username
52
+ # user = Etsy.user('littletjane')
53
+ #
54
+ # # Grab that user's shop information
55
+ # user.shop
56
+ # user.shop.title
57
+ #
58
+ # # ... and the listings in the shop
59
+ # listing = user.shop.listings.first
60
+ # listing.title
61
+ # listing.description
62
+ #
63
+ # To see what else is available for a user, check out the full documentation for
64
+ # the Etsy::User class. Information about making authenticated calls is available
65
+ # in the README.
66
+ #
67
+ module Etsy
68
+ class Error < RuntimeError; end
69
+
70
+ class << self
71
+ attr_writer :callback_url
72
+ attr_writer :permission_scopes
73
+ end
74
+
75
+ # Make Etsy.api_key and Etsy.api_secret global but also local to threads
76
+ #
77
+ def self.api_key
78
+ Thread.current[:etsy_api_key] || @api_key
79
+ end
80
+
81
+ def self.api_key=(key)
82
+ @api_key ||= key
83
+ Thread.current[:etsy_api_key] = key
84
+ end
85
+
86
+ def self.api_secret
87
+ Thread.current[:etsy_api_secret] || @api_secret
88
+ end
89
+
90
+ def self.api_secret=(secret)
91
+ @api_secret ||= secret
92
+ Thread.current[:etsy_api_secret] = secret
93
+ end
94
+
95
+ SANDBOX_HOST = 'sandbox.openapi.etsy.com'
96
+ PRODUCTION_HOST = 'openapi.etsy.com'
97
+
98
+ # Set the environment, accepts either :sandbox or :production. Defaults to :sandbox
99
+ # and will raise an exception when set to an unrecognized environment.
100
+ #
101
+ def self.environment=(environment)
102
+ unless [:sandbox, :production].include?(environment)
103
+ raise(ArgumentError, "environment must be set to either :sandbox or :production")
104
+ end
105
+ @environment = environment
106
+ @host = (environment == :sandbox) ? SANDBOX_HOST : PRODUCTION_HOST
107
+ end
108
+
109
+ def self.protocol=(protocol)
110
+ unless ["http", "https"].include?(protocol.to_s)
111
+ raise(ArgumentError, "protocol must be set to either 'http' or 'https'")
112
+ end
113
+ @protocol = protocol.to_s
114
+ end
115
+
116
+ # Allow throwing API errors
117
+ #
118
+ def self.silent_errors=(bool)
119
+ unless [TrueClass, FalseClass].include?(bool.class)
120
+ raise(ArgumentError, "Silent errors must be set to either true or false'")
121
+ end
122
+ @silent_errors = bool
123
+ end
124
+
125
+ def self.protocol
126
+ @protocol || "https"
127
+ end
128
+
129
+ # The currently configured environment.
130
+ #
131
+ def self.environment
132
+ @environment || :production
133
+ end
134
+
135
+ # The default will change to false for a 1.0 release (breaking changes)
136
+ #
137
+ def self.silent_errors
138
+ @silent_errors.nil? ? true : @silent_errors
139
+ end
140
+
141
+ def self.host # :nodoc:
142
+ @host || PRODUCTION_HOST
143
+ end
144
+
145
+ # The configured callback URL or 'oob' if no callback URL is configured. This controls
146
+ # whether or not we need to pass the OAuth verifier by hand.
147
+ #
148
+ def self.callback_url
149
+ @callback_url || 'oob'
150
+ end
151
+
152
+ # OAuth permission scopes. Defines which private fields we can have access to.
153
+ #
154
+ def self.permission_scopes
155
+ @permission_scopes || []
156
+ end
157
+
158
+ # Find a user by username. See Etsy::User for more information.
159
+ #
160
+ def self.user(username)
161
+ User.find(username)
162
+ end
163
+
164
+ # Convenience method for accessing the authenticated user's own user information. Requires
165
+ # authentication.
166
+ #
167
+ def self.myself(token, secret, options = {})
168
+ User.myself(token, secret, options)
169
+ end
170
+
171
+ # Generate a request token for authorization.
172
+ #
173
+ def self.request_token
174
+ clear_for_new_authorization
175
+ verification_request.request_token
176
+ end
177
+
178
+ # Generate an access token from the request token, secret, and verifier. The verifier can
179
+ # either be passed manually or from the params in the callback URL.
180
+ #
181
+ def self.access_token(request_token, request_secret, verifier)
182
+ @access_token = begin
183
+ client = Etsy::SecureClient.new({
184
+ :request_token => request_token,
185
+ :request_secret => request_secret,
186
+ :verifier => verifier
187
+ })
188
+ client.client
189
+ end
190
+ end
191
+
192
+ # Generate the URL to begin the verification process for a user.
193
+ #
194
+ def self.verification_url
195
+ verification_request.url
196
+ end
197
+
198
+ def self.single_user(access_token, access_secret)
199
+ @credentials = {
200
+ :access_token => access_token,
201
+ :access_secret => access_secret
202
+ }
203
+ nil
204
+ end
205
+
206
+ def self.credentials
207
+ @credentials || {}
208
+ end
209
+
210
+ private
211
+
212
+ def self.verification_request
213
+ @verification_request ||= VerificationRequest.new
214
+ end
215
+
216
+ def self.clear_for_new_authorization
217
+ @verification_request = nil
218
+ end
219
+
220
+ def self.deprecate(message)
221
+ puts "DEPRECATED: #{message}."
222
+ end
223
+ end
@@ -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,47 @@
1
+ module Etsy
2
+
3
+ # = Address
4
+ #
5
+ # Represents a single Etsy Address. Users may or may not have associated addresses.
6
+ #
7
+ # An address has the following attributes:
8
+ #
9
+ # [first_line] Street address
10
+ # [second_line] Additional street information.
11
+ # [city]
12
+ # [state]
13
+ # [country]
14
+ # [country_id] The Etsy country id
15
+ #
16
+ class Address
17
+
18
+ include Etsy::Model
19
+
20
+ attributes :name, :first_line, :second_line, :city, :state, :zip, :country_id
21
+
22
+ attribute :id, :from => :user_address_id
23
+ attribute :country, :from => :country_name
24
+
25
+ # Retrieve all of a user's addresses by user name or ID:
26
+ #
27
+ # Etsy::Address.find('reagent')
28
+ #
29
+ def self.find(*identifiers_and_options)
30
+ self.append_to_endpoint('addresses', identifiers_and_options)
31
+ self.find_one_or_more('users', identifiers_and_options)
32
+ end
33
+
34
+ private
35
+ def oauth
36
+ oauth = (token && secret) ? {:access_token => token, :access_secret => secret} : {}
37
+ end
38
+
39
+ def self.append_to_endpoint(suffix, arguments)
40
+ if arguments.last.class == Hash
41
+ arguments.last[:append_to_endpoint] = suffix
42
+ else
43
+ arguments << {:append_to_endpoint => suffix}
44
+ end
45
+ end
46
+ end
47
+ 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,32 @@
1
+ module Etsy
2
+
3
+ # = BasicClient
4
+ #
5
+ # Used for calling public API methods.
6
+ #
7
+ class BasicClient
8
+
9
+ # Create a new client that will connect to the specified host
10
+ #
11
+ def initialize
12
+ @host = Etsy.host
13
+ end
14
+
15
+ def client # :nodoc:
16
+ if @client
17
+ return @client
18
+ else
19
+ @client = Net::HTTP.new(@host, Etsy.protocol == "http" ? 80 : 443)
20
+ @client.use_ssl = true if Etsy.protocol == "https"
21
+ return @client
22
+ end
23
+ end
24
+
25
+ # Fetch a raw response from the specified endpoint
26
+ #
27
+ def get(endpoint)
28
+ client.get(endpoint)
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,84 @@
1
+ module Etsy
2
+
3
+ # = Category
4
+ #
5
+ # A category of listings for sale, formed from 1 to 3 tags.
6
+ #
7
+ # A category has the following attributes:
8
+ #
9
+ # [page_description] A short description of the category from the category's landing page
10
+ # [page_title] The title of the category's landing page
11
+ # [category_name] The category's string ID
12
+ # [short_name] A short display name for the category
13
+ # [long_name] A longer display name for the category
14
+ # [children_count] The number of subcategories below this one
15
+ #
16
+ class Category
17
+
18
+ include Etsy::Model
19
+
20
+ attribute :id, :from => :category_id
21
+ attribute :children_count, :from => :num_children
22
+ attributes :page_description, :page_title, :category_name, :short_name,
23
+ :long_name
24
+
25
+ # Retrieve one or more top-level categories by name:
26
+ #
27
+ # Etsy::Category.find('accessories')
28
+ #
29
+ # You can find multiple top-level categories by passing an array of identifiers:
30
+ #
31
+ # Etsy::Category.find(['accessories', 'art'])
32
+ #
33
+ def self.find_top(*identifiers_and_options)
34
+ self.find_one_or_more('categories', identifiers_and_options)
35
+ end
36
+
37
+ # Retrieve a list of all subcategories of the specified category.
38
+ #
39
+ # Etsy::Category.find_all_subcategories('accessories')
40
+ #
41
+ # You can also find the subcategories of a subcategory.
42
+ #
43
+ # Etsy::Category.find_all_subcategories('accessories/apron')
44
+ #
45
+ # Etsy categories only go three levels deep, so this will return nil past the third level.
46
+ #
47
+ # Etsy::Category.find_all_subcategories('accessories/apron/women')
48
+ # => nil
49
+ #
50
+ def self.find_all_subcategories(category, options = {})
51
+ valid?(category) ? self.get_all("/taxonomy/categories/#{category}", options) : nil
52
+ end
53
+
54
+ def self.find(tag)
55
+ get("/categories/#{tag}")
56
+ end
57
+
58
+ # Retrieve a list of all top-level categories.
59
+ #
60
+ # Etsy::Category.all
61
+ #
62
+ def self.all_top(options = {})
63
+ self.get_all("/taxonomy/categories", options)
64
+ end
65
+
66
+ # The collection of active listings associated with this category.
67
+ #
68
+ def active_listings
69
+ @active_listings ||= Listing.find_all_active_by_category(category_name)
70
+ end
71
+
72
+ # The collection of subcategories associated with this category.
73
+ #
74
+ def subcategories
75
+ @subcategories ||= Category.find_all_subcategories(category_name)
76
+ end
77
+
78
+ private
79
+
80
+ def self.valid?(parent_category)
81
+ parent_category.count("/") < 2
82
+ end
83
+ end
84
+ end