discogs-wrapper 1.0.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.
Files changed (41) hide show
  1. data/README.markdown +81 -0
  2. data/Rakefile +27 -0
  3. data/discogs.gemspec +19 -0
  4. data/lib/discogs.rb +20 -0
  5. data/lib/wrapper/resource.rb +79 -0
  6. data/lib/wrapper/resource_mappings.rb +84 -0
  7. data/lib/wrapper/resources/artist.rb +37 -0
  8. data/lib/wrapper/resources/artist_release.rb +17 -0
  9. data/lib/wrapper/resources/format.rb +11 -0
  10. data/lib/wrapper/resources/generic_list.rb +29 -0
  11. data/lib/wrapper/resources/image.rb +11 -0
  12. data/lib/wrapper/resources/label.rb +16 -0
  13. data/lib/wrapper/resources/label_release.rb +17 -0
  14. data/lib/wrapper/resources/release.rb +22 -0
  15. data/lib/wrapper/resources/release_artist.rb +18 -0
  16. data/lib/wrapper/resources/release_label.rb +10 -0
  17. data/lib/wrapper/resources/search.rb +61 -0
  18. data/lib/wrapper/resources/search_result.rb +16 -0
  19. data/lib/wrapper/resources/track.rb +15 -0
  20. data/lib/wrapper/wrapper.rb +105 -0
  21. data/spec/resource_spec.rb +27 -0
  22. data/spec/resources/artist_release_spec.rb +59 -0
  23. data/spec/resources/artist_spec.rb +15 -0
  24. data/spec/resources/format_spec.rb +41 -0
  25. data/spec/resources/generic_list_spec.rb +66 -0
  26. data/spec/resources/image_spec.rb +43 -0
  27. data/spec/resources/label_release_spec.rb +55 -0
  28. data/spec/resources/label_spec.rb +15 -0
  29. data/spec/resources/release_artist_spec.rb +43 -0
  30. data/spec/resources/release_label_spec.rb +31 -0
  31. data/spec/resources/release_spec.rb +15 -0
  32. data/spec/resources/search_result_spec.rb +47 -0
  33. data/spec/resources/search_spec.rb +15 -0
  34. data/spec/resources/track_spec.rb +56 -0
  35. data/spec/spec_helper.rb +36 -0
  36. data/spec/wrapper_methods/get_artist_spec.rb +109 -0
  37. data/spec/wrapper_methods/get_label_spec.rb +89 -0
  38. data/spec/wrapper_methods/get_release_spec.rb +123 -0
  39. data/spec/wrapper_methods/search_spec.rb +330 -0
  40. data/spec/wrapper_spec.rb +162 -0
  41. metadata +126 -0
@@ -0,0 +1,17 @@
1
+ # Represents a labels release in the Discogs API.
2
+
3
+ require File.dirname(__FILE__) + "/label"
4
+
5
+ class Discogs::Label::Release < Discogs::Resource
6
+
7
+ attr_accessor :id,
8
+ :status,
9
+ :type,
10
+ :catno,
11
+ :artist,
12
+ :title,
13
+ :format,
14
+ :year,
15
+ :trackinfo
16
+
17
+ end
@@ -0,0 +1,22 @@
1
+ # Represents a release in the Discogs API.
2
+
3
+ class Discogs::Release < Discogs::Resource
4
+
5
+ no_mapping
6
+
7
+ attr_accessor :id,
8
+ :status,
9
+ :title,
10
+ :country,
11
+ :released,
12
+ :notes,
13
+ :images,
14
+ :artists,
15
+ :extraartists,
16
+ :labels,
17
+ :formats,
18
+ :styles,
19
+ :genres,
20
+ :tracklist
21
+
22
+ end
@@ -0,0 +1,18 @@
1
+ # Represents an release's artist in the Discogs API.
2
+
3
+ require File.dirname(__FILE__) + "/track"
4
+
5
+ class Discogs::Release::Artist < Discogs::Resource
6
+
7
+ map_to_plural :artists, :extraartists
8
+
9
+ attr_accessor :name,
10
+ :role,
11
+ :join,
12
+ :anv,
13
+ :tracks
14
+
15
+ end
16
+
17
+ # Define other classes that also replicate this structure.
18
+ class Discogs::Release::Track::Artist < Discogs::Release::Artist; end
@@ -0,0 +1,10 @@
1
+ # Represents a Releases Label in the Discogs API.
2
+
3
+ require File.dirname(__FILE__) + "/release"
4
+
5
+ class Discogs::Release::Label < Discogs::Resource
6
+
7
+ attr_accessor :catno,
8
+ :name
9
+
10
+ end
@@ -0,0 +1,61 @@
1
+ # Represents a search resultset in the Discogs API.
2
+
3
+ class Discogs::Search < Discogs::Resource
4
+
5
+ no_mapping
6
+
7
+ attr_accessor :exactresults,
8
+ :searchresults,
9
+ :start,
10
+ :end,
11
+ :numResults
12
+
13
+ def total_results
14
+ self.numResults.to_i
15
+ end
16
+
17
+ def current_page
18
+ (start.to_i / page_size) + 1
19
+ end
20
+
21
+ def total_pages
22
+ (total_results.to_f / page_size).ceil
23
+ end
24
+
25
+ def last_page?
26
+ current_page == total_pages
27
+ end
28
+
29
+ def exact(filter=nil)
30
+ filter_results(filter, self.exactresults)
31
+ end
32
+
33
+ def results(filter=nil)
34
+ filter_results(filter, self.searchresults)
35
+ end
36
+
37
+ # Returns the closest exact result for _filter_, or nil.
38
+ def closest(filter)
39
+ exact(filter)[0] rescue nil
40
+ end
41
+
42
+ private
43
+
44
+ # An easy way for filtering a particular "type" of result (Artist, Release, etc)
45
+ def filter_results(filter, results)
46
+ results ||= []
47
+
48
+ if filter.nil?
49
+ results
50
+ else
51
+ results.find_all do |result|
52
+ result.type == filter.to_s
53
+ end
54
+ end
55
+ end
56
+
57
+ def page_size
58
+ self.end.to_i - (self.start.to_i - 1)
59
+ end
60
+
61
+ end
@@ -0,0 +1,16 @@
1
+ # Represents a single search result in the Discogs API.
2
+
3
+ require File.dirname(__FILE__) + "/search"
4
+
5
+ class Discogs::Search::Result < Discogs::Resource
6
+
7
+ map_to_plural :exactresults, :searchresults
8
+
9
+ attr_accessor :num,
10
+ :type,
11
+ :title,
12
+ :uri,
13
+ :anv,
14
+ :summary
15
+
16
+ end
@@ -0,0 +1,15 @@
1
+ # Represents a track in the Discogs API.
2
+
3
+ require File.dirname(__FILE__) + "/release"
4
+
5
+ class Discogs::Release::Track < Discogs::Resource
6
+
7
+ map_to_plural :tracklist
8
+
9
+ attr_accessor :position,
10
+ :title,
11
+ :duration,
12
+ :artists,
13
+ :extraartists
14
+
15
+ end
@@ -0,0 +1,105 @@
1
+ # Core API wrapper class.
2
+
3
+ require 'uri'
4
+ require 'net/http'
5
+ require 'rexml/document'
6
+ require 'zlib'
7
+ require 'stringio'
8
+
9
+ require File.dirname(__FILE__) + "/resource"
10
+
11
+ class Discogs::Wrapper
12
+
13
+ @@root_host = "http://api.discogs.com"
14
+
15
+ attr_reader :user_agent
16
+
17
+ def initialize(user_agent=nil)
18
+ @user_agent = user_agent
19
+ end
20
+
21
+ def get_release(id)
22
+ query_and_build "release/#{id}", Discogs::Release
23
+ end
24
+
25
+ def get_artist(name)
26
+ query_and_build "artist/#{name}", Discogs::Artist
27
+ end
28
+
29
+ def get_label(name)
30
+ query_and_build "label/#{name}", Discogs::Label
31
+ end
32
+
33
+ def search(term, options={})
34
+ opts = { :type => :all, :page => 1 }.merge(options)
35
+ params = { :q => term, :type => opts[:type], :page => opts[:page] }
36
+
37
+ data = query_api("search", params)
38
+ resource = Discogs::Search.new(data)
39
+
40
+ resource.build_with_resp!
41
+ end
42
+
43
+ private
44
+
45
+ def query_and_build(path, klass)
46
+ data = query_api(path)
47
+ resource = klass.send(:new, data)
48
+ resource.build!
49
+ end
50
+
51
+ # Queries the API and handles the response.
52
+ def query_api(path, params={})
53
+ response = make_request(path, params)
54
+
55
+ raise_unknown_resource(path) if response.code == "404"
56
+ raise_internal_server_error if response.code == "500"
57
+
58
+ # Unzip the response data, or just read it in directly
59
+ # if the API responds without gzipping.
60
+ response_body = nil
61
+ begin
62
+ inflated_data = Zlib::GzipReader.new(StringIO.new(response.body))
63
+ response_body = inflated_data.read
64
+ rescue Zlib::GzipFile::Error
65
+ response_body = response.body
66
+ end
67
+
68
+ response_body
69
+ end
70
+
71
+ # Generates a HTTP request and returns the response.
72
+ def make_request(path, params={})
73
+ uri = build_uri(path, params)
74
+
75
+ request = Net::HTTP::Get.new(uri.path + "?" + uri.query)
76
+ request.add_field("Accept-Encoding", "gzip,deflate")
77
+ request.add_field("User-Agent", @user_agent)
78
+
79
+ Net::HTTP.new(uri.host).start do |http|
80
+ http.request(request)
81
+ end
82
+ end
83
+
84
+ def build_uri(path, params={})
85
+ parameters = { :f => "xml" }.merge(params)
86
+ querystring = "?" + parameters.map { |key, value| "#{key}=#{value}" }.sort.join("&")
87
+
88
+ URI.parse(File.join(@@root_host, sanitize_path(path, querystring)))
89
+ end
90
+
91
+ def sanitize_path(*path_parts)
92
+ clean_path = path_parts.map { |part| part.gsub(/\s/, '+') }
93
+
94
+ clean_path.join
95
+ end
96
+
97
+ def raise_unknown_resource(path='')
98
+ raise Discogs::UnknownResource, "Unknown Discogs resource: #{path}"
99
+ end
100
+
101
+ def raise_internal_server_error
102
+ raise Discogs::InternalServerError, "The remote server cannot complete the request"
103
+ end
104
+
105
+ end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ describe Discogs::Resource do
4
+
5
+ before do
6
+ @resource = Discogs::Resource.new(sample_valid_binary)
7
+ end
8
+
9
+ it "should have a default element name" do
10
+ Discogs::Resource.element_names.should == [ :resource ]
11
+ end
12
+
13
+ it "should have a default plural element name" do
14
+ Discogs::Resource.plural_element_names.should == [ :resources ]
15
+ end
16
+
17
+ it "should have an original_content method" do
18
+ @resource.original_content.should == sample_valid_binary
19
+ end
20
+
21
+ it "should be able to build the content"
22
+
23
+ it "should remove the <resp> element by default"
24
+
25
+ it "should leave the <resp> element if told to"
26
+
27
+ end
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe Discogs::Artist::Release do
4
+
5
+ it "should map to release" do
6
+ Discogs::Artist::Release.element_names.should == [ :release ]
7
+ end
8
+
9
+ it "should map to plural releases" do
10
+ Discogs::Artist::Release.plural_element_names.should == [ :releases ]
11
+ end
12
+
13
+ describe "when asking for artist-release information" do
14
+
15
+ before do
16
+ data = File.read(File.join(File.dirname(__FILE__), "..", "samples", "valid_artist_release.xml"))
17
+ @artist_release = Discogs::Artist::Release.new(data)
18
+ @artist_release.build!
19
+ end
20
+
21
+ it "should have a ID attribute" do
22
+ @artist_release.id.should == "999333"
23
+ end
24
+
25
+ it "should have a status attribute" do
26
+ @artist_release.status.should == "Accepted"
27
+ end
28
+
29
+ it "should have a type attribute" do
30
+ @artist_release.type.should == "Main"
31
+ end
32
+
33
+ it "should have a title attribute" do
34
+ @artist_release.title.should == "Temple of the Underworld"
35
+ end
36
+
37
+ it "should have a format attribute" do
38
+ @artist_release.format.should == "LP"
39
+ end
40
+
41
+ it "should have a label attribute" do
42
+ @artist_release.label.should == "Monitor Records"
43
+ end
44
+
45
+ it "should have a year attribute" do
46
+ @artist_release.year.should == "1992"
47
+ end
48
+
49
+ it "should have a trackinfo attribute" do
50
+ @artist_release.trackinfo.should be_nil
51
+ end
52
+
53
+ it "should have an artist attribute" do
54
+ @artist_release.artist.should == "ArtIst"
55
+ end
56
+
57
+ end
58
+
59
+ end
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe Discogs::Artist do
4
+
5
+ it "should map to empty array" do
6
+ Discogs::Artist.element_names.should == []
7
+ end
8
+
9
+ it "should map plural to empty array" do
10
+ Discogs::Artist.plural_element_names.should == []
11
+ end
12
+
13
+ ## See ./spec/wrapper_methods/get_artist_spec.rb for extensive tests of this class.
14
+
15
+ end
@@ -0,0 +1,41 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe Discogs::Release::Format do
4
+
5
+ it "should map to format" do
6
+ Discogs::Release::Format.element_names.should == [ :format ]
7
+ end
8
+
9
+ it "should map to plural formats" do
10
+ Discogs::Release::Format.plural_element_names.should == [ :formats ]
11
+ end
12
+
13
+ describe "when asking for format information" do
14
+
15
+ before do
16
+ data = File.read(File.join(File.dirname(__FILE__), "..", "samples", "valid_format.xml"))
17
+ @format = Discogs::Release::Format.new(data)
18
+ @format.build!
19
+ end
20
+
21
+ it "should have a name attribute" do
22
+ @format.name.should == "CD"
23
+ end
24
+
25
+ it "should have a quantity attribute" do
26
+ @format.qty.should == "1"
27
+ end
28
+
29
+ it "should have an array of descriptions" do
30
+ @format.descriptions.should be_instance_of(Array)
31
+ end
32
+
33
+ it "should have built each description" do
34
+ @format.descriptions[0].should == "Album"
35
+ @format.descriptions[1].should == "Digipak"
36
+ @format.descriptions[9].should be_nil
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,66 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe Discogs::GenericList do
4
+
5
+ it "should map to all generic lists" do
6
+ Discogs::GenericList.element_names.should be_instance_of(Array)
7
+
8
+ Discogs::GenericList.element_names.include?(:aliases).should be_true
9
+ Discogs::GenericList.element_names.include?(:urls).should be_true
10
+ end
11
+
12
+ it "should map to plural lists" do
13
+ Discogs::GenericList.plural_element_names.should == [ :lists ]
14
+ end
15
+
16
+ describe "when asking for description information" do
17
+
18
+ before do
19
+ data = File.read(File.join(File.dirname(__FILE__), "..", "samples", "valid_description_list.xml"))
20
+ @descriptions = Discogs::GenericList.new(data)
21
+ end
22
+
23
+ it "should return an array on build" do
24
+ @descriptions.build!.should be_instance_of(Array)
25
+ end
26
+
27
+ it "should have access to the items after build" do
28
+ @descriptions.build!
29
+
30
+ @descriptions[0].should == "Album"
31
+ @descriptions[1].should == "LP"
32
+ @descriptions[2].should == "33 rpm"
33
+ end
34
+
35
+ it "should return nil on unknown index" do
36
+ @descriptions[9].should be_nil
37
+ end
38
+
39
+ end
40
+
41
+ describe "when asking for genre information" do
42
+
43
+ before do
44
+ data = File.read(File.join(File.dirname(__FILE__), "..", "samples", "valid_genre_list.xml"))
45
+ @genres = Discogs::GenericList.new(data)
46
+ end
47
+
48
+ it "should return an array on build" do
49
+ @genres.build!.should be_instance_of(Array)
50
+ end
51
+
52
+ it "should have access to the items after build" do
53
+ @genres.build!
54
+
55
+ @genres[0].should == "Heavy Metal"
56
+ @genres[1].should == "Neofolk"
57
+ @genres[2].should == "Medieval folk"
58
+ end
59
+
60
+ it "should return nil on unknown index" do
61
+ @genres[9].should be_nil
62
+ end
63
+
64
+ end
65
+
66
+ end