etsy 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +125 -0
- data/Rakefile +40 -0
- data/lib/etsy.rb +65 -0
- data/lib/etsy/image.rb +27 -0
- data/lib/etsy/listing.rb +76 -0
- data/lib/etsy/model.rb +64 -0
- data/lib/etsy/request.rb +48 -0
- data/lib/etsy/response.rb +30 -0
- data/lib/etsy/shop.rb +50 -0
- data/lib/etsy/user.rb +54 -0
- data/lib/etsy/version.rb +13 -0
- data/test/fixtures/getShopDetails.json +70 -0
- data/test/fixtures/getShopListings.json +135 -0
- data/test/fixtures/getUserDetails.json +34 -0
- data/test/test_helper.rb +54 -0
- data/test/unit/etsy/image_test.rb +22 -0
- data/test/unit/etsy/listing_test.rb +92 -0
- data/test/unit/etsy/request_test.rb +74 -0
- data/test/unit/etsy/response_test.rb +49 -0
- data/test/unit/etsy/shop_test.rb +63 -0
- data/test/unit/etsy/user_test.rb +75 -0
- data/test/unit/etsy_test.rb +21 -0
- metadata +88 -0
data/README.rdoc
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
= Etsy
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
The Etsy gem provides a friendly Ruby interface to the Etsy API
|
6
|
+
|
7
|
+
== Installation
|
8
|
+
|
9
|
+
Installing the latest stable version is simple:
|
10
|
+
|
11
|
+
sudo gem install etsy
|
12
|
+
|
13
|
+
If you want to be on the bleeding edge, install from GitHub:
|
14
|
+
|
15
|
+
sudo gem install reagent-etsy --source=http://gems.github.com
|
16
|
+
|
17
|
+
== Usage
|
18
|
+
|
19
|
+
The Etsy API is read-only - all you need to gain access is an API Key (available
|
20
|
+
from http://developer.etsy.com). Once you have your API key, set it in your script:
|
21
|
+
|
22
|
+
require 'rubygems'
|
23
|
+
require 'etsy'
|
24
|
+
Etsy.api_key = 'foobar'
|
25
|
+
|
26
|
+
From there, you can make any calls to the API that you need.
|
27
|
+
|
28
|
+
=== Users
|
29
|
+
|
30
|
+
If you're starting with a user, the easiest way is to use the Etsy.user method:
|
31
|
+
|
32
|
+
>> user = Etsy.user('littletjane')
|
33
|
+
=> #<Etsy::User:0x107f82c @result=[{"city"=>"Washington, DC", ... >
|
34
|
+
>> user.username
|
35
|
+
=> "littletjane"
|
36
|
+
>> user.id
|
37
|
+
=> 5327518
|
38
|
+
>> user.url
|
39
|
+
=> "http://www.etsy.com/shop.php?user_id=5327518"
|
40
|
+
|
41
|
+
For more information about what is available for a user, check out the documentation
|
42
|
+
for Etsy::User.
|
43
|
+
|
44
|
+
== Shops
|
45
|
+
|
46
|
+
Each user may optionally have a shop. If a user is a seller, he / she also has an
|
47
|
+
associated shop object:
|
48
|
+
|
49
|
+
>> user.seller?
|
50
|
+
=> true
|
51
|
+
>> shop = user.shop
|
52
|
+
=> #<Etsy::Shop:0x102578c @result={"is_vacation"=>"", "announcement"=> ... >
|
53
|
+
>> shop.name
|
54
|
+
=> "littletjane"
|
55
|
+
>> shop.title
|
56
|
+
=> "a cute and crafty mix of handmade goods."
|
57
|
+
|
58
|
+
More information about shops can be found in the documentation for Etsy::Shop.
|
59
|
+
|
60
|
+
== Listings
|
61
|
+
|
62
|
+
Shops contain multiple listings:
|
63
|
+
|
64
|
+
>> shop.listings
|
65
|
+
=> [#<Etsy::Listing:0x119acac @result={} ...>, ... ]
|
66
|
+
>> listing = shop.listings.first
|
67
|
+
=> #<Etsy::Listing:0x19a981c @result={} ... >
|
68
|
+
>> listing.title
|
69
|
+
=> "hanging with the bad boys matchbox"
|
70
|
+
>> listing.description
|
71
|
+
=> "standard size matchbox, approx. 1.5 x 2 inches ..."
|
72
|
+
>> listing.url
|
73
|
+
=> "http://www.etsy.com/view_listing.php?listing_id=24165902"
|
74
|
+
>> listing.view_count
|
75
|
+
=> 19
|
76
|
+
>> listing.created_at
|
77
|
+
=> Sat Apr 25 11:31:34 -0400 2009
|
78
|
+
|
79
|
+
See the documentation for Etsy::Listing for more information.
|
80
|
+
|
81
|
+
== Images
|
82
|
+
|
83
|
+
Each listing has one or more images available:
|
84
|
+
|
85
|
+
>> listing.images
|
86
|
+
=> [#<Etsy::Image:0x18f85e4 @result={} ... >,
|
87
|
+
#<Etsy::Image:0x18f85d0 @result={} ... >]
|
88
|
+
>> listing.images.first.small_square
|
89
|
+
=> "http://ny-image2.etsy.com/il_25x25.67765346.jpg"
|
90
|
+
>> listing.images.first.large
|
91
|
+
=> "http://ny-image2.etsy.com/il_430xN.67765346.jpg"
|
92
|
+
|
93
|
+
Listings also have a primary image:
|
94
|
+
|
95
|
+
>> listing.image
|
96
|
+
=> #<Etsy::Image:0x18c3060 @result={} ... >
|
97
|
+
>> listing.image.large
|
98
|
+
=> "http://ny-image2.etsy.com/il_430xN.67765346.jpg"
|
99
|
+
|
100
|
+
More information is available in the documentation for Etsy::Image.
|
101
|
+
|
102
|
+
== License
|
103
|
+
|
104
|
+
Copyright (c) 2009 Patrick Reagan (reaganpr@gmail.com)
|
105
|
+
|
106
|
+
Permission is hereby granted, free of charge, to any person
|
107
|
+
obtaining a copy of this software and associated documentation
|
108
|
+
files (the "Software"), to deal in the Software without
|
109
|
+
restriction, including without limitation the rights to use,
|
110
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
111
|
+
copies of the Software, and to permit persons to whom the
|
112
|
+
Software is furnished to do so, subject to the following
|
113
|
+
conditions:
|
114
|
+
|
115
|
+
The above copyright notice and this permission notice shall be
|
116
|
+
included in all copies or substantial portions of the Software.
|
117
|
+
|
118
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
119
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
120
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
121
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
122
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
123
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
124
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
125
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
require 'lib/etsy/version'
|
6
|
+
|
7
|
+
task :default => :test
|
8
|
+
|
9
|
+
spec = Gem::Specification.new do |s|
|
10
|
+
s.name = 'etsy'
|
11
|
+
s.version = Etsy::Version.to_s
|
12
|
+
s.has_rdoc = true
|
13
|
+
s.extra_rdoc_files = %w(README.rdoc)
|
14
|
+
s.rdoc_options = %w(--main README.rdoc)
|
15
|
+
s.summary = "Provides a friendly ruby-like interface to the Etsy API"
|
16
|
+
s.author = 'Patrick Reagan'
|
17
|
+
s.email = 'reaganpr@gmail.com'
|
18
|
+
s.homepage = 'http://sneaq.net'
|
19
|
+
s.files = %w(README.rdoc Rakefile) + Dir.glob("{lib,test}/**/*")
|
20
|
+
# s.executables = ['etsy']
|
21
|
+
|
22
|
+
s.add_dependency('json', '~> 1.1.0')
|
23
|
+
end
|
24
|
+
|
25
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
26
|
+
pkg.gem_spec = spec
|
27
|
+
end
|
28
|
+
|
29
|
+
Rake::TestTask.new do |t|
|
30
|
+
t.libs << 'test'
|
31
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
32
|
+
t.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'Generate the gemspec to serve this Gem from Github'
|
36
|
+
task :github do
|
37
|
+
file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
|
38
|
+
File.open(file, 'w') {|f| f << spec.to_ruby }
|
39
|
+
puts "Created gemspec: #{file}"
|
40
|
+
end
|
data/lib/etsy.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
require 'etsy/request'
|
7
|
+
require 'etsy/response'
|
8
|
+
|
9
|
+
require 'etsy/model'
|
10
|
+
require 'etsy/user'
|
11
|
+
require 'etsy/shop'
|
12
|
+
require 'etsy/listing'
|
13
|
+
require 'etsy/image'
|
14
|
+
|
15
|
+
# = Etsy: A friendly Ruby interface to the Etsy API
|
16
|
+
#
|
17
|
+
# == Quick Start
|
18
|
+
#
|
19
|
+
# Getting started is easy. First, you will need a valid API key from the Etsy
|
20
|
+
# developer site (http://developer.etsy.com/). Since the API is read-only at
|
21
|
+
# the moment, that's all you need to do.
|
22
|
+
#
|
23
|
+
# To start using the API, require the etsy gem and set it up to use your API key:
|
24
|
+
#
|
25
|
+
# require 'rubygems'
|
26
|
+
# require 'etsy'
|
27
|
+
#
|
28
|
+
# Etsy.api_key = 'itsasecret'
|
29
|
+
#
|
30
|
+
# Now you can make API calls that originate from an Etsy user:
|
31
|
+
#
|
32
|
+
# # Find a user by username
|
33
|
+
# user = Etsy.user('littletjane')
|
34
|
+
#
|
35
|
+
# # Grab that user's shop information
|
36
|
+
# user.seller?
|
37
|
+
# user.shop
|
38
|
+
# user.shop.title
|
39
|
+
#
|
40
|
+
# # ... and the listings in the shop
|
41
|
+
# listing = user.shop.listings.first
|
42
|
+
# listing.title
|
43
|
+
# listing.description
|
44
|
+
#
|
45
|
+
# To see what else is available for a user, check out the full documentation for
|
46
|
+
# the Etsy::User class.
|
47
|
+
#
|
48
|
+
module Etsy
|
49
|
+
|
50
|
+
# Set the API key for all requests
|
51
|
+
def self.api_key=(api_key)
|
52
|
+
@api_key = api_key
|
53
|
+
end
|
54
|
+
|
55
|
+
# Retrieve the API key
|
56
|
+
def self.api_key
|
57
|
+
@api_key
|
58
|
+
end
|
59
|
+
|
60
|
+
# Find a user by username. See Etsy::User for more information.
|
61
|
+
def self.user(username)
|
62
|
+
User.find_by_username(username)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
data/lib/etsy/image.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Etsy
|
2
|
+
|
3
|
+
# = Image
|
4
|
+
#
|
5
|
+
# Represents an image resource of an Etsy listing and contains multiple sizes.
|
6
|
+
# Sizes available are:
|
7
|
+
#
|
8
|
+
# [small_square] The smallest square image (25x25 pixels)
|
9
|
+
# [medium_square] The medium square image (50x50 pixels)
|
10
|
+
# [large_square] The largest square image (75x75 pixels)
|
11
|
+
# [small] The small image for this listing (155x125 pixels)
|
12
|
+
# [medium] The medium image for this listing (200x200 pixels)
|
13
|
+
# [large] The largest image available for this listing (430x? pixels)
|
14
|
+
#
|
15
|
+
class Image
|
16
|
+
|
17
|
+
include Etsy::Model
|
18
|
+
|
19
|
+
attribute :small_square, :from => :image_url_25x25
|
20
|
+
attribute :medium_square, :from => :image_url_50x50
|
21
|
+
attribute :large_square, :from => :image_url_75x75
|
22
|
+
attribute :small, :from => :image_url_155x125
|
23
|
+
attribute :medium, :from => :image_url_200x200
|
24
|
+
attribute :large, :from => :image_url_430xN
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/lib/etsy/listing.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
module Etsy
|
2
|
+
|
3
|
+
# = Listing
|
4
|
+
#
|
5
|
+
# Represents a single Etsy listing. Has the following attributes:
|
6
|
+
#
|
7
|
+
# [id] The unique identifier for this listing
|
8
|
+
# [title] The title of this listing
|
9
|
+
# [description] This listing's full description
|
10
|
+
# [view_count] The number of times this listing has been viewed
|
11
|
+
# [url] The full URL to this listing's detail page
|
12
|
+
# [price] The price of this listing item
|
13
|
+
# [currency] The currency that the seller is using for this listing item
|
14
|
+
# [quantity] The number of items available for sale
|
15
|
+
# [tags] An array of tags that the seller has used for this listing
|
16
|
+
# [materials] Any array of materials that was used in the production of this item
|
17
|
+
#
|
18
|
+
# Additionally, the following queries on this item are available:
|
19
|
+
#
|
20
|
+
# [active?] Is this listing active?
|
21
|
+
# [removed?] Has this listing been removed?
|
22
|
+
# [sold_out?] Is this listing sold out?
|
23
|
+
# [expired?] Has this listing expired?
|
24
|
+
# [alchemy?] Is this listing an Alchemy item? (i.e. requested by an Etsy user)
|
25
|
+
#
|
26
|
+
class Listing
|
27
|
+
|
28
|
+
include Etsy::Model
|
29
|
+
|
30
|
+
STATES = %w(active removed sold_out expired alchemy)
|
31
|
+
|
32
|
+
finder :all, '/shops/:user_id/listings'
|
33
|
+
|
34
|
+
attribute :id, :from => :listing_id
|
35
|
+
attribute :view_count, :from => :views
|
36
|
+
attribute :created, :from => :creation_epoch
|
37
|
+
attribute :currency, :from => :currency_code
|
38
|
+
attribute :ending, :from => :ending_epoch
|
39
|
+
|
40
|
+
attributes :title, :description, :state, :url, :price, :quantity,
|
41
|
+
:tags, :materials
|
42
|
+
|
43
|
+
STATES.each do |state|
|
44
|
+
define_method "#{state}?" do
|
45
|
+
self.state == state.sub('_', '')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Time that this listing was created
|
50
|
+
#
|
51
|
+
def created_at
|
52
|
+
Time.at(created)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Time that this listing is ending (will be removed from store)
|
56
|
+
#
|
57
|
+
def ending_at
|
58
|
+
Time.at(ending)
|
59
|
+
end
|
60
|
+
|
61
|
+
# The list of images associated with this listing. See Etsy::Image
|
62
|
+
# for more information
|
63
|
+
#
|
64
|
+
def images
|
65
|
+
@result['all_images'].map {|image_data| Image.new(image_data) }
|
66
|
+
end
|
67
|
+
|
68
|
+
# The primary image for this listing. See Etsy::Image for more
|
69
|
+
# information
|
70
|
+
#
|
71
|
+
def image
|
72
|
+
images.first
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
data/lib/etsy/model.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
module Etsy
|
2
|
+
module Model # :nodoc:all
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
|
6
|
+
def attribute(name, options = {})
|
7
|
+
from = options.fetch(:from, name)
|
8
|
+
|
9
|
+
class_eval <<-CODE
|
10
|
+
def #{name}
|
11
|
+
@result['#{from}']
|
12
|
+
end
|
13
|
+
CODE
|
14
|
+
end
|
15
|
+
|
16
|
+
def attributes(*names)
|
17
|
+
names.each {|name| attribute(name) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def finder(type, endpoint)
|
21
|
+
parameter = endpoint.scan(/:\w+/).first
|
22
|
+
parameter.sub!(/^:/, '')
|
23
|
+
|
24
|
+
endpoint.sub!(":#{parameter}", '#{' + parameter + '}')
|
25
|
+
|
26
|
+
send("find_#{type}", parameter, endpoint)
|
27
|
+
end
|
28
|
+
|
29
|
+
def find_all(parameter, endpoint)
|
30
|
+
class_eval <<-CODE
|
31
|
+
def self.find_all_by_#{parameter}(#{parameter})
|
32
|
+
response = Request.get("#{endpoint}")
|
33
|
+
response.result.map {|listing| new(listing) }
|
34
|
+
end
|
35
|
+
CODE
|
36
|
+
end
|
37
|
+
|
38
|
+
def find_one(parameter, endpoint)
|
39
|
+
class_eval <<-CODE
|
40
|
+
def self.find_by_#{parameter}(#{parameter})
|
41
|
+
response = Request.get("#{endpoint}")
|
42
|
+
new response.result
|
43
|
+
end
|
44
|
+
CODE
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
module InstanceMethods
|
50
|
+
|
51
|
+
def initialize(result = nil)
|
52
|
+
@result = result
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.included(other)
|
58
|
+
other.send(:extend, Etsy::Model::ClassMethods)
|
59
|
+
other.send(:include, Etsy::Model::InstanceMethods)
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
data/lib/etsy/request.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Etsy
|
2
|
+
|
3
|
+
# = Request
|
4
|
+
#
|
5
|
+
# A basic wrapper around GET requests to the Etsy JSON API
|
6
|
+
#
|
7
|
+
class Request
|
8
|
+
|
9
|
+
# The base URL for API requests
|
10
|
+
def self.base_url
|
11
|
+
"http://beta-api.etsy.com/v1"
|
12
|
+
end
|
13
|
+
|
14
|
+
# Perform a GET request for the resource with optional parameters - returns
|
15
|
+
# A Response object with the payload data
|
16
|
+
def self.get(resource_path, parameters = {})
|
17
|
+
request = Request.new(resource_path, parameters)
|
18
|
+
Response.new(request.get)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Create a new request for the resource with optional parameters
|
22
|
+
def initialize(resource_path, parameters = {})
|
23
|
+
@resource_path = resource_path
|
24
|
+
@parameters = parameters
|
25
|
+
end
|
26
|
+
|
27
|
+
# Perform a GET request against the API endpoint and return the raw
|
28
|
+
# response data
|
29
|
+
def get
|
30
|
+
Net::HTTP.get(endpoint_uri)
|
31
|
+
end
|
32
|
+
|
33
|
+
def parameters # :nodoc:
|
34
|
+
@parameters.merge(:api_key => Etsy.api_key, :detail_level => 'high')
|
35
|
+
end
|
36
|
+
|
37
|
+
def query # :nodoc:
|
38
|
+
parameters.map {|k,v| "#{k}=#{v}"}.join('&')
|
39
|
+
end
|
40
|
+
|
41
|
+
def endpoint_uri # :nodoc:
|
42
|
+
uri = URI.parse("#{self.class.base_url}#{@resource_path}")
|
43
|
+
uri.query = query
|
44
|
+
uri
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|