musicbrainz 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.gitignore +1 -4
  2. data/.travis.yml +2 -2
  3. data/Contributors +1 -0
  4. data/README.md +91 -40
  5. data/lib/mb.rb +2 -0
  6. data/lib/musicbrainz.rb +27 -22
  7. data/lib/musicbrainz/bindings/artist.rb +23 -0
  8. data/lib/musicbrainz/bindings/artist_release_groups.rb +13 -0
  9. data/lib/musicbrainz/bindings/artist_search.rb +23 -0
  10. data/lib/musicbrainz/bindings/release.rb +28 -0
  11. data/lib/musicbrainz/bindings/release_group.rb +18 -0
  12. data/lib/musicbrainz/bindings/release_group_releases.rb +13 -0
  13. data/lib/musicbrainz/bindings/release_tracks.rb +13 -0
  14. data/lib/musicbrainz/bindings/track.rb +16 -0
  15. data/lib/musicbrainz/client.rb +72 -0
  16. data/lib/musicbrainz/client_modules/caching_proxy.rb +46 -0
  17. data/lib/musicbrainz/client_modules/failsafe_proxy.rb +38 -0
  18. data/lib/musicbrainz/client_modules/transparent_proxy.rb +12 -0
  19. data/lib/musicbrainz/configuration.rb +60 -0
  20. data/lib/musicbrainz/deprecated.rb +36 -0
  21. data/lib/musicbrainz/middleware.rb +23 -0
  22. data/lib/musicbrainz/models/artist.rb +47 -0
  23. data/lib/musicbrainz/models/base_model.rb +63 -0
  24. data/lib/musicbrainz/models/release.rb +27 -0
  25. data/lib/musicbrainz/models/release_group.rb +28 -0
  26. data/lib/musicbrainz/models/track.rb +17 -0
  27. data/lib/musicbrainz/version.rb +3 -0
  28. data/musicbrainz.gemspec +10 -12
  29. data/spec/bindings/release_spec.rb +43 -0
  30. data/spec/client_modules/cache_spec.rb +62 -0
  31. data/spec/deprecated/cache_config_spec.rb +32 -0
  32. data/spec/deprecated/proxy_config_spec.rb +32 -0
  33. data/spec/{requests → models}/artist_spec.rb +3 -9
  34. data/spec/{requests → models}/release_group_spec.rb +2 -2
  35. data/spec/{requests → models}/release_spec.rb +1 -1
  36. data/spec/{requests → models}/track_spec.rb +0 -0
  37. data/spec/spec_helper.rb +13 -7
  38. metadata +63 -58
  39. data/Rakefile +0 -13
  40. data/lib/deprecated.rb +0 -25
  41. data/lib/musicbrainz/artist.rb +0 -63
  42. data/lib/musicbrainz/base.rb +0 -71
  43. data/lib/musicbrainz/release.rb +0 -43
  44. data/lib/musicbrainz/release_group.rb +0 -41
  45. data/lib/musicbrainz/track.rb +0 -23
  46. data/lib/parsers/artist.rb +0 -47
  47. data/lib/parsers/base.rb +0 -41
  48. data/lib/parsers/release.rb +0 -28
  49. data/lib/parsers/release_group.rb +0 -27
  50. data/lib/parsers/track.rb +0 -18
  51. data/lib/tools/cache.rb +0 -48
  52. data/lib/tools/proxy.rb +0 -62
  53. data/lib/version.rb +0 -5
  54. data/spec/misc/deprecated_spec.rb +0 -38
  55. data/spec/tools/cache_spec.rb +0 -59
@@ -0,0 +1,46 @@
1
+ module MusicBrainz
2
+ module ClientModules
3
+ module CachingProxy
4
+ def cache_path
5
+ MusicBrainz.config.cache_path
6
+ end
7
+
8
+ def clear_cache
9
+ FileUtils.rm_r(cache_path) if cache_path && File.exist?(cache_path)
10
+ end
11
+
12
+ def get_contents(url)
13
+ return super unless caching?
14
+
15
+ hash = Digest::SHA256.hexdigest(url)
16
+ dir_path = [cache_path, *(0..2).map{ |i| hash.slice(2*i, 2) }].join(?/)
17
+ file_path = [dir_path, '/', hash.slice(6, 58), '.xml'].join
18
+
19
+ response = { body: nil, status: 500 }
20
+
21
+ if File.exist?(file_path)
22
+ response = {
23
+ body: File.open(file_path, 'rb').gets,
24
+ status: 200
25
+ }
26
+ else
27
+ response = super
28
+ if response[:status] == 200
29
+ FileUtils.mkpath(dir_path)
30
+ File.open(file_path, 'wb') do |f|
31
+ f.puts(response[:body])
32
+ f.chmod(0755)
33
+ f.close
34
+ end
35
+ end
36
+ end
37
+
38
+ response
39
+ end
40
+
41
+ def caching?
42
+ MusicBrainz.config.perform_caching
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,38 @@
1
+ module MusicBrainz
2
+ module ClientModules
3
+ module FailsafeProxy
4
+ def get_contents(url)
5
+ return super unless failsafe?
6
+
7
+ response = { body: nil, status: 500 }
8
+ MusicBrainz.config.tries_limit.times do
9
+ response = super
10
+ break if response[:status] == 200
11
+ end
12
+
13
+ response
14
+ end
15
+
16
+ def time_passed
17
+ Time.now.to_f - @last_query_time ||= 0.0
18
+ end
19
+
20
+ def time_to_wait
21
+ MusicBrainz.config.query_interval - time_passed
22
+ end
23
+
24
+ def ready?
25
+ time_passed > MusicBrainz.config.query_interval
26
+ end
27
+
28
+ def wait_util_ready!
29
+ sleep(time_to_wait) unless ready?
30
+ @last_query_time = Time.now.to_f
31
+ end
32
+
33
+ def failsafe?
34
+ MusicBrainz.config.tries_limit > 1 && MusicBrainz.config.query_interval.to_f > 0
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,12 @@
1
+ module MusicBrainz
2
+ module ClientModules
3
+ module TransparentProxy
4
+ def get_contents(url)
5
+ response = http.get(url)
6
+ { body: response.body, status: response.status }
7
+ rescue
8
+ { body: nil, status: 500 }
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,60 @@
1
+ module MusicBrainz
2
+ class Configuration
3
+ attr_accessor :app_name, :app_version, :contact,
4
+ :web_service_url,
5
+ :query_interval, :tries_limit,
6
+ :cache_path, :perform_caching
7
+
8
+ DEFAULT_WEB_SERVICE_URL = "http://musicbrainz.org/ws/2/"
9
+ DEFAULT_QUERY_INTERVAL = 1.5
10
+ DEFAULT_TRIES_LIMIT = 5
11
+ DEFAULT_CACHE_PATH = File.join(File.dirname(__FILE__), "..", "tmp", "cache")
12
+ DEFAULT_PERFORM_CACHING = false
13
+
14
+ def initialize
15
+ @web_service_url = DEFAULT_WEB_SERVICE_URL
16
+ @query_interval = DEFAULT_QUERY_INTERVAL
17
+ @tries_limit = DEFAULT_TRIES_LIMIT
18
+ @cache_path = DEFAULT_CACHE_PATH
19
+ @perform_caching = DEFAULT_PERFORM_CACHING
20
+ end
21
+
22
+ def valid?
23
+ %w[ app_name app_version contact ].each do |param|
24
+ unless instance_variable_defined?(:"@#{param}")
25
+ raise Exception.new("Application identity parameter '#{param}' missing")
26
+ end
27
+ end
28
+ unless tries_limit.nil? && query_interval.nil?
29
+ raise Exception.new("'tries_limit' parameter must be 1 or greater") if tries_limit.to_i < 1
30
+ raise Exception.new("'query_interval' parameter must be greater than zero") if query_interval.to_f < 0
31
+ end
32
+ if perform_caching
33
+ raise Exception.new("'cache_path' parameter must be set") if cache_path.nil?
34
+ end
35
+ true
36
+ end
37
+ end
38
+
39
+ module Configurable
40
+ def configure
41
+ raise Exception.new("Configuration block missing") unless block_given?
42
+ yield @config ||= MusicBrainz::Configuration.new
43
+ config.valid?
44
+ end
45
+
46
+ def config
47
+ raise Exception.new("Configuration missing") unless instance_variable_defined?(:@config)
48
+ @config
49
+ end
50
+
51
+ def apply_test_configuration!
52
+ configure do |c|
53
+ c.app_name = "gem musicbrainz (development mode)"
54
+ c.app_version = MusicBrainz::VERSION
55
+ c.contact = `git config user.email`.chomp
56
+ end
57
+ end
58
+ end
59
+ extend Configurable
60
+ end
@@ -0,0 +1,36 @@
1
+ module MusicBrainz
2
+ module Deprecated
3
+ module ProxyConfig
4
+ def query_interval
5
+ MusicBrainz.config.query_interval
6
+ end
7
+
8
+ def query_interval=(value)
9
+ MusicBrainz.config.query_interval = value
10
+ end
11
+ end
12
+
13
+ module CacheConfig
14
+ def cache_path
15
+ MusicBrainz.config.cache_path
16
+ end
17
+
18
+ def cache_path=(value)
19
+ MusicBrainz.config.cache_path = value
20
+ end
21
+ end
22
+ end
23
+
24
+ module Tools
25
+ module Proxy
26
+ extend Deprecated::ProxyConfig
27
+ end
28
+
29
+ module Cache
30
+ extend Deprecated::CacheConfig
31
+ end
32
+ end
33
+
34
+ extend Deprecated::ProxyConfig
35
+ extend Deprecated::CacheConfig
36
+ end
@@ -0,0 +1,23 @@
1
+ module MusicBrainz
2
+ class Middleware < Faraday::Middleware
3
+ def call(env)
4
+ env[:request_headers].merge!(
5
+ "User-Agent" => user_agent_string,
6
+ "Via" => via_string
7
+ )
8
+ @app.call(env)
9
+ end
10
+
11
+ def user_agent_string
12
+ "#{config.app_name}/#{config.app_version} ( #{config.contact} )"
13
+ end
14
+
15
+ def via_string
16
+ "gem musicbrainz/#{VERSION} (#{GH_PAGE_URL})"
17
+ end
18
+
19
+ def config
20
+ MusicBrainz.config
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,47 @@
1
+ module MusicBrainz
2
+ class Artist < BaseModel
3
+ field :id, String
4
+ field :type, String
5
+ field :name, String
6
+ field :country, String
7
+ field :date_begin, Date
8
+ field :date_end, Date
9
+ field :urls, Hash
10
+
11
+ def release_groups
12
+ @release_groups ||= client.load(:release_group, { artist: id }, {
13
+ binding: :artist_release_groups,
14
+ create_models: :release_group,
15
+ sort: :first_release_date
16
+ }) unless @id.nil?
17
+ end
18
+
19
+ class << self
20
+ def find(id)
21
+ client.load(:artist, { id: id, inc: [:url_rels] }, {
22
+ binding: :artist,
23
+ create_model: :artist
24
+ })
25
+ end
26
+
27
+ def search(name)
28
+ name = CGI.escape(name).gsub(/\!/, '\!')
29
+
30
+ client.load(:artist, { query: "artist:#{name}", limit: 10 }, {
31
+ binding: :artist_search
32
+ })
33
+ end
34
+
35
+ def discography(mbid)
36
+ artist = find(mbid)
37
+ artist.release_groups.each { |rg| rg.releases.each { |r| r.tracks } }
38
+ artist
39
+ end
40
+
41
+ def find_by_name(name)
42
+ matches = search(name)
43
+ matches.empty? ? nil : find(matches.first[:id])
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,63 @@
1
+ module MusicBrainz
2
+ class BaseModel
3
+ def self.inherited(klass)
4
+ klass.send(:include, InstanceMethods)
5
+ klass.send(:extend, ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def field(name, type)
10
+ fields[name] = type
11
+ attr_reader name
12
+
13
+ define_method("#{name}=") do |val|
14
+ instance_variable_set("@#{name}", validate_type(val, type))
15
+ end
16
+ end
17
+
18
+ def fields
19
+ instance_variable_set(:@fields, {}) unless instance_variable_defined?(:@fields)
20
+ instance_variable_get(:@fields)
21
+ end
22
+
23
+ def client
24
+ MusicBrainz.client
25
+ end
26
+ end
27
+
28
+ module InstanceMethods
29
+ def initialize(params = {})
30
+ params.each do |field, value|
31
+ self.send(:"#{field}=", value)
32
+ end
33
+ end
34
+
35
+ def client
36
+ MusicBrainz.client
37
+ end
38
+
39
+ private
40
+
41
+ def validate_type(val, type)
42
+ if type == Integer
43
+ val.to_i
44
+ elsif type == Float
45
+ val.to_f
46
+ elsif type == String
47
+ val.to_s
48
+ elsif type == Date
49
+ if val.nil? or val == ""
50
+ val = "2030-12-31"
51
+ elsif val.split("-").length == 1
52
+ val << "-12-31"
53
+ elsif val.split("-").length == 2
54
+ val << "-31"
55
+ end
56
+ Date.new(*val.split(?-).map(&:to_i))
57
+ else
58
+ val
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,27 @@
1
+ module MusicBrainz
2
+ class Release < BaseModel
3
+ field :id, String
4
+ field :title, String
5
+ field :status, String
6
+ field :format, String
7
+ field :date, Date
8
+ field :country, String
9
+
10
+ def tracks
11
+ @tracks ||= client.load(:release, { id: id, inc: [:recordings, :media], limit: 100 }, {
12
+ binding: :release_tracks,
13
+ create_models: :track,
14
+ sort: :position
15
+ }) unless @id.nil?
16
+ end
17
+
18
+ class << self
19
+ def find(id)
20
+ client.load(:release, { id: id, inc: [:media] }, {
21
+ binding: :release,
22
+ create_model: :release
23
+ })
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ module MusicBrainz
2
+ class ReleaseGroup < BaseModel
3
+ field :id, String
4
+ field :type, String
5
+ field :title, String
6
+ field :desc, String
7
+ field :first_release_date, Date
8
+
9
+ alias_method :disambiguation, :desc
10
+
11
+ def releases
12
+ @releases ||= client.load(:release, { release_group: id, inc: [:media], limit: 100 }, {
13
+ binding: :release_group_releases,
14
+ create_models: :release,
15
+ sort: :date
16
+ }) unless @id.nil?
17
+ end
18
+
19
+ class << self
20
+ def find(id)
21
+ client.load(:release_group, { id: id }, {
22
+ binding: :release_group,
23
+ create_model: :release_group
24
+ })
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ module MusicBrainz
2
+ class Track < BaseModel
3
+ field :position, Integer
4
+ field :recording_id, String
5
+ field :title, String
6
+ field :length, Integer
7
+
8
+ class << self
9
+ def find(id)
10
+ client.load(:recording, { id: id }, {
11
+ binding: :track,
12
+ create_model: :track
13
+ })
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module MusicBrainz
2
+ VERSION = "0.7.2"
3
+ end
data/musicbrainz.gemspec CHANGED
@@ -1,23 +1,21 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- require File.expand_path('../lib/version', __FILE__)
1
+ require File.expand_path('../lib/musicbrainz/version', __FILE__)
4
2
 
5
3
  Gem::Specification.new do |gem|
6
4
  gem.authors = ["Gregory Eremin"]
7
5
  gem.email = ["magnolia_fan@me.com"]
8
- gem.summary = %q{MusicBrainz Web Service wrapper with ActiveRecord-style models}
6
+ gem.summary = %q{ MusicBrainz Web Service wrapper with ActiveRecord-style models }
9
7
  gem.homepage = "http://github.com/magnolia-fan/musicbrainz"
10
8
 
11
- gem.files = `git ls-files`.split($\)
12
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
9
+ gem.files = %x{ git ls-files }.split($\)
10
+ gem.executables = []
11
+ gem.test_files = gem.files.grep(%r{^spec/})
14
12
  gem.name = "musicbrainz"
15
- gem.require_paths = ["lib"]
13
+ gem.require_paths = %w[ lib ]
16
14
  gem.version = MusicBrainz::VERSION
17
15
  gem.license = "MIT"
18
16
 
19
- gem.add_dependency("nokogiri")
20
- gem.add_development_dependency("rake")
21
- gem.add_development_dependency("awesome_print")
22
- gem.add_development_dependency("rspec")
17
+ gem.add_dependency('faraday')
18
+ gem.add_dependency('nokogiri')
19
+ gem.add_development_dependency('rspec')
20
+ gem.add_development_dependency('awesome_print')
23
21
  end