etsy 0.1.0

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.
@@ -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.
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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