diff --git a/.gitignore b/.gitignore index 3e5b7b3..261cb46 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ coverage tmp Gemfile.lock .gem +*.swp diff --git a/Contributors b/Contributors index f9986dc..ef23ba5 100644 --- a/Contributors +++ b/Contributors @@ -4,3 +4,4 @@ Applicat (https://github.com/Applicat) Jens Fahnenbruck (https://github.com/jigfox) Sander Nieuwenhuizen (https://github.com/munkius) Savater Sebastien (https://github.com/blakink) +Thomas Wolfe (https://github.com/tomwolfe) diff --git a/Gemfile b/Gemfile index e45e65f..851fabc 100644 --- a/Gemfile +++ b/Gemfile @@ -1,2 +1,2 @@ -source :rubygems +source 'https://rubygems.org' gemspec diff --git a/README.md b/README.md index c4ebef1..7e554b4 100644 --- a/README.md +++ b/README.md @@ -80,9 +80,9 @@ MusicBrainz::ReleaseGroup ```ruby # Class Methods MusicBrainz::ReleaseGroup.find(id) -MusicBrainz::ReleaseGroup.find_by_artist_and_title(artist_name, title, type: 'Album') +MusicBrainz::ReleaseGroup.find_by_artist_and_title(artist_name, title, 'Album') # 3rd arg optional MusicBrainz::ReleaseGroup.search(artist_name, title) -MusicBrainz::ReleaseGroup.search(artist_name, title, type: 'Album') +MusicBrainz::ReleaseGroup.search(artist_name, title, 'Album') # 3rd arg optional # Instance Methods @release_group.releases @@ -125,6 +125,7 @@ MusicBrainz::Track ```ruby # Class Methods MusicBrainz::Track.find(id) +MusicBrainz::ReleaseGroup.search(artist_name, track_name) # Fields { diff --git a/lib/musicbrainz.rb b/lib/musicbrainz.rb index 16390ec..c67e719 100644 --- a/lib/musicbrainz.rb +++ b/lib/musicbrainz.rb @@ -29,6 +29,7 @@ require "musicbrainz/bindings/release_group_releases" require "musicbrainz/bindings/release" require "musicbrainz/bindings/release_tracks" require "musicbrainz/bindings/track" +require "musicbrainz/bindings/track_search" module MusicBrainz GH_PAGE_URL = "http://git.io/brainz" diff --git a/lib/musicbrainz/bindings/track_search.rb b/lib/musicbrainz/bindings/track_search.rb new file mode 100644 index 0000000..512a9a8 --- /dev/null +++ b/lib/musicbrainz/bindings/track_search.rb @@ -0,0 +1,21 @@ +# encoding: UTF-8 +module MusicBrainz + module Bindings + module TrackSearch + def parse(xml) + xml.xpath('./recording-list/recording').map do |xml| + { + id: (xml.attribute('id').value rescue nil), + mbid: (xml.attribute('id').value rescue nil), # Old shit + title: (xml.xpath('./title').text.gsub(/[`’]/, "'") rescue nil), + artist: (xml.xpath('./artist-credit/name-credit/artist/name').text rescue nil), + releases: (xml.xpath('./release-list/release/title').map{ |xml| xml.text } rescue []), + score: (xml.attribute('score').value.to_i rescue nil) + } rescue nil + end.delete_if{ |item| item.nil? } + end + + extend self + end + end +end diff --git a/lib/musicbrainz/models/artist.rb b/lib/musicbrainz/models/artist.rb index 6ada1f4..c16335c 100644 --- a/lib/musicbrainz/models/artist.rb +++ b/lib/musicbrainz/models/artist.rb @@ -25,11 +25,7 @@ module MusicBrainz end def search(name) - name = CGI.escape(name).gsub(/\!/, '\!') - - client.load(:artist, { query: "artist:#{name}", limit: 10 }, { - binding: :artist_search - }) + super({artist: name}) end def discography(mbid) diff --git a/lib/musicbrainz/models/base_model.rb b/lib/musicbrainz/models/base_model.rb index cca3302..d11841e 100644 --- a/lib/musicbrainz/models/base_model.rb +++ b/lib/musicbrainz/models/base_model.rb @@ -23,6 +23,38 @@ module MusicBrainz def client MusicBrainz.client end + + def search(hash) + hash = escape_strings(hash) + query_val = build_query(hash) + underscore_name = self.name[13..-1].underscore + client.load(underscore_name.to_sym, { query: query_val, limit: 10 }, { binding: underscore_name.insert(-1,"_search").to_sym }) + end + + class ::String + def underscore + self.gsub(/::/, '/'). + gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). + gsub(/([a-z\d])([A-Z])/,'\1_\2'). + tr("-", "_"). + downcase + end + end + + def build_query(hash) + return ["#{hash.first[0].to_s}:\"#{hash.first[1]}\""] if hash.size ==1 + arr ||= [] + hash.each { |k, v| arr << "#{k.to_s}:\"#{hash[k]}\"" } + arr.join(' AND ') + end + + def escape_strings(hash) + hash.each { |k, v| hash[k] = CGI.escape(v).gsub(/\!/, '\!') } + hash + end + + # these probably should be private... but I'm not sure how to get it to work in a module... + # private_class_method :build_query, :escape_strings end module InstanceMethods diff --git a/lib/musicbrainz/models/release_group.rb b/lib/musicbrainz/models/release_group.rb index c3a7f8a..2129830 100644 --- a/lib/musicbrainz/models/release_group.rb +++ b/lib/musicbrainz/models/release_group.rb @@ -25,20 +25,16 @@ module MusicBrainz }) end - def search(artist_name, title, options = {}) - artist_name = CGI.escape(artist_name).gsub(/\!/, '\!') - title = CGI.escape(title).gsub(/\!/, '\!') - query = ["artist:\"#{artist_name}\"", "releasegroup:\"#{title}\""] - query << "type: #{options[:type]}" if options[:type] - - client.load( - :release_group, { query: query.join(' AND '), limit: 10 }, - { binding: :release_group_search } - ) + def search(artist_name, title, type = nil) + if type + super({artist: artist_name, releasegroup: title, type: type}) + else + super({artist: artist_name, releasegroup: title}) + end end - def find_by_artist_and_title(artist_name, title, options = {}) - matches = search(artist_name, title, options) + def find_by_artist_and_title(artist_name, title, type = nil ) + matches = search(artist_name, title, type) matches.empty? ? nil : find(matches.first[:id]) end end diff --git a/lib/musicbrainz/models/track.rb b/lib/musicbrainz/models/track.rb index 4895e2c..4e9203c 100644 --- a/lib/musicbrainz/models/track.rb +++ b/lib/musicbrainz/models/track.rb @@ -12,6 +12,10 @@ module MusicBrainz create_model: :track }) end + + def search(artist_name, track_name) + super({artist: artist_name, recording: track_name}) + end end end end diff --git a/spec/bindings/release_group_search_spec.rb b/spec/bindings/release_group_search_spec.rb index d1ff347..f093d74 100644 --- a/spec/bindings/release_group_search_spec.rb +++ b/spec/bindings/release_group_search_spec.rb @@ -5,8 +5,8 @@ require "spec_helper" describe MusicBrainz::Bindings::ReleaseGroupSearch do describe '.parse' do it "gets correct release group data" do - response = 'Empire' - described_class.parse(Nokogiri::XML.parse(response)).should == [ + response = 'Empire' + described_class.parse(Nokogiri::XML.parse(response).remove_namespaces!.xpath('/metadata')).should == [ { id: '246bc928-2dc8-35ba-80ee-7a0079de1632', mbid: '246bc928-2dc8-35ba-80ee-7a0079de1632', title: 'Empire', type: 'Single', score: 100 @@ -14,4 +14,4 @@ describe MusicBrainz::Bindings::ReleaseGroupSearch do ] end end -end \ No newline at end of file +end diff --git a/spec/bindings/track_search_spec.rb b/spec/bindings/track_search_spec.rb new file mode 100644 index 0000000..bff767b --- /dev/null +++ b/spec/bindings/track_search_spec.rb @@ -0,0 +1,17 @@ +# -*- encoding: utf-8 -*- + +require "spec_helper" + +describe MusicBrainz::Bindings::TrackSearch do + describe '.parse' do + it "gets correct Track (really recording) data" do + response = 'King FredToo Much JoyGreen Eggs and Crack' + described_class.parse(Nokogiri::XML.parse(response).remove_namespaces!.xpath('/metadata')).should == [ + { + id: '0b382a13-32f0-4743-9248-ba5536a6115e', mbid: '0b382a13-32f0-4743-9248-ba5536a6115e', + title: 'King Fred', artist: 'Too Much Joy', releases: ['Green Eggs and Crack'], score: 100 + } + ] + end + end +end diff --git a/spec/models/release_group_spec.rb b/spec/models/release_group_spec.rb index fccd221..545bc39 100644 --- a/spec/models/release_group_spec.rb +++ b/spec/models/release_group_spec.rb @@ -31,13 +31,13 @@ describe MusicBrainz::ReleaseGroup do matches = MusicBrainz::ReleaseGroup.search('Kasabian', 'Empire') matches.length.should be > 0 matches.first[:title].should == 'Empire' - matches.first[:type].should == 'Single' + matches.first[:type].should == 'Album' end end context 'with type filter' do it "searches release group by artist name and title" do - matches = MusicBrainz::ReleaseGroup.search('Kasabian', 'Empire', type: 'Album') + matches = MusicBrainz::ReleaseGroup.search('Kasabian', 'Empire', 'Album') matches.length.should be > 0 matches.first[:title].should == 'Empire' matches.first[:type].should == 'Album' @@ -48,7 +48,7 @@ describe MusicBrainz::ReleaseGroup do describe '.find_by_artist_and_title' do it "gets first release group by artist name and title" do release_group = MusicBrainz::ReleaseGroup.find_by_artist_and_title('Kasabian', 'Empire') - release_group.id.should == '246bc928-2dc8-35ba-80ee-7a0079de1632' + release_group.id.should == '6f33e0f0-cde2-38f9-9aee-2c60af8d1a61' end end