discogs-wrapper 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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