lastfm-m3u 0.2.3 → 0.2.4
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.
- data/.gitignore +1 -1
- data/Rakefile +8 -6
- data/bin/lastfm-m3u +158 -0
- data/lastfm-m3u.gemspec +1 -0
- data/lib/lastfm-m3u.rb +1 -1
- data/lib/lastfm-m3u/base.rb +11 -0
- data/lib/lastfm-m3u/lastfm.rb +48 -0
- data/lib/lastfm-m3u/mp3_info_ext.rb +57 -0
- data/lib/lastfm-m3u/search/file_search.rb +101 -0
- data/lib/lastfm-m3u/util.rb +19 -0
- data/lib/lastfm-m3u/version.rb +3 -0
- metadata +21 -4
data/.gitignore
CHANGED
data/Rakefile
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env rake
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require "bundler/setup"
|
|
2
4
|
require "bundler/gem_tasks"
|
|
3
5
|
|
|
4
6
|
# RSpec
|
|
5
|
-
require 'rspec/core'
|
|
6
|
-
require 'rspec/core/rake_task'
|
|
7
|
-
RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
8
|
-
spec.pattern = FileList['spec/**/*_spec.rb']
|
|
9
|
-
end
|
|
10
|
-
task :default => :spec
|
|
7
|
+
require 'rspec/core'
|
|
8
|
+
require 'rspec/core/rake_task'
|
|
9
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
10
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
|
11
|
+
end
|
|
12
|
+
task :default => :spec
|
data/bin/lastfm-m3u
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require 'optparse'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
require 'highline/import'
|
|
6
|
+
require 'ruby-progressbar'
|
|
7
|
+
|
|
8
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
|
|
9
|
+
require 'lastfm-m3u'
|
|
10
|
+
require 'lastfm-m3u/util'
|
|
11
|
+
|
|
12
|
+
options = OpenStruct.new
|
|
13
|
+
OptionParser.new do |opts|
|
|
14
|
+
opts.banner = "LastfmM3u Playlist Creator".color(:blue)
|
|
15
|
+
opts.define_head "To get started: lastfm-m3u --init".color(:green)
|
|
16
|
+
opts.separator ""
|
|
17
|
+
opts.separator "Usage: lastfm-m3u [options]".color(:yellow)
|
|
18
|
+
opts.separator "Note: defaults to filename-only search. id3/both search is more thorough, but much slower"
|
|
19
|
+
opts.separator ""
|
|
20
|
+
opts.separator "Examples:"
|
|
21
|
+
#opts.separator " lastfm-m3u # auto-search config-music_dir mp3 id3 tags for all unique artists, query last.fm for top tracks and create m3us for each artist from available track files"
|
|
22
|
+
opts.separator ' lastfm-m3u -a "Biosphere,Brian Eno"'
|
|
23
|
+
opts.separator " lastfm-m3u -a Biosphere"
|
|
24
|
+
opts.separator " lastfm-m3u -a Biosphere -t both"
|
|
25
|
+
opts.separator " lastfm-m3u -a Biosphere -d ~/music/Biosphere"
|
|
26
|
+
#opts.separator " lastfm-m3u -a Biosphere -o biosphere.m3u"
|
|
27
|
+
opts.separator ""
|
|
28
|
+
opts.separator ""
|
|
29
|
+
opts.separator "Options:"
|
|
30
|
+
|
|
31
|
+
# Type of search
|
|
32
|
+
types = %w[file id3 both]
|
|
33
|
+
type_aliases = { "f" => "file", "i" => "id3", "b" => "both" }
|
|
34
|
+
type_list = (type_aliases.keys + types).join(',')
|
|
35
|
+
opts.on("--type TYPE", "-t TYPE", types, type_aliases, "Select search type", " (#{type_list})") do |type|
|
|
36
|
+
options.type = type.to_sym
|
|
37
|
+
end
|
|
38
|
+
options.type = :file if options.type.blank? or options.type.nil?
|
|
39
|
+
|
|
40
|
+
# init config
|
|
41
|
+
opts.on('-i', '--init', "init lastfm API access config") do |opt|
|
|
42
|
+
options.init = true
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# List of artists
|
|
46
|
+
opts.on('-a "x,y,z"', Array, "one or more artists separated by commas (enclose with quotes if any spaces)") do |artists|
|
|
47
|
+
options.artists = artists
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# directory
|
|
51
|
+
options.directory = Dir.pwd
|
|
52
|
+
opts.on("-d DIR", "--directory DIR", "music directory") do |directory|
|
|
53
|
+
options.directory = directory
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
#opts.on('-o', '--output FILENAME', 'Write m3u to FILENAME') do |fn| # writes single m3u when multiple artists
|
|
57
|
+
#options.out_file = fn
|
|
58
|
+
#end
|
|
59
|
+
|
|
60
|
+
opts.on('-p', '--path PATH', 'Specify path to use for m3u file entries (e.g. MPD requires a path relative to its music directory - i.e. -d /home/user/music/Biosphere -p /home/user/music where the second one is MPD\'s root)') do |path|
|
|
61
|
+
options.path = Pathname path
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
opts.on('-l', '--limit NUM', 'Specify limit of tracks to fetch from Last.fm (defaults to all)') do |limit|
|
|
65
|
+
options.limit = limit.to_i
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
opts.on('-f', '--not-found', 'Show not found') do
|
|
69
|
+
options.not_found = true
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
#opts.on('-f', '--force', 'Overwrite existing output file(s)') do
|
|
73
|
+
#options.force = true
|
|
74
|
+
#end
|
|
75
|
+
|
|
76
|
+
opts.on('--debug [LEVEL]', 'Enable debugging output (Optional Level :: 0=all, 1=info,warn,error, 2=warn,error, 3=error)') do |level|
|
|
77
|
+
if level
|
|
78
|
+
options.debug = level.to_i
|
|
79
|
+
else
|
|
80
|
+
options.debug = 0
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
opts.on_tail('-v', '--version', 'Show LastfmM3u version') do
|
|
85
|
+
puts "LastfmM3u v#{LastfmM3u::VERSION}"
|
|
86
|
+
exit
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
opts.on_tail('-h', '--help', 'Show this help message') do
|
|
90
|
+
puts opts
|
|
91
|
+
exit
|
|
92
|
+
end
|
|
93
|
+
end.parse!
|
|
94
|
+
|
|
95
|
+
if options.init
|
|
96
|
+
lastfm = LastfmM3u::Lastfm.new('')
|
|
97
|
+
exit
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
unless options.artists
|
|
101
|
+
puts "Please provide at least one artist (-a Elvis).".color(:red) + " See".color(:green) + " --help".color(:yellow) + " for usage or".color(:green) + " --init".color(:yellow) + " to get started".color(:green)
|
|
102
|
+
exit
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
if options.debug
|
|
106
|
+
$logger.level = options.debug
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
options.artists.each do |artist|
|
|
110
|
+
not_found = []
|
|
111
|
+
lastfm = LastfmM3u::Lastfm.new(artist)
|
|
112
|
+
lastfm.root_dir = options.directory if options.directory
|
|
113
|
+
lastfm.limit = options.limit if options.limit
|
|
114
|
+
tracks = lastfm.artist.top_tracks
|
|
115
|
+
|
|
116
|
+
puts
|
|
117
|
+
puts "Searching filesystem with method: ".color(:green) + options.type.to_s.capitalize.color(:yellow)
|
|
118
|
+
puts
|
|
119
|
+
num_tracks = (options.limit.nil? ? tracks.size : options.limit)
|
|
120
|
+
progressbar = ProgressBar.create(starting_at: 0, total: num_tracks, format: "%a".color(:cyan) + "|".color(:magenta) + "%B".color(:green) + "|".color(:magenta) + "%p%%".color(:cyan))
|
|
121
|
+
lastfm.find_tracks(tracks, options.type, progressbar).each do |track, track_set|
|
|
122
|
+
if track_set.empty?
|
|
123
|
+
not_found << track
|
|
124
|
+
next
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
if track_set.size > 1
|
|
128
|
+
unless found_track = LastfmM3u::Util.choose_track(track, track_set)
|
|
129
|
+
not_found << track
|
|
130
|
+
next
|
|
131
|
+
end
|
|
132
|
+
puts
|
|
133
|
+
else
|
|
134
|
+
found_track = track_set.first
|
|
135
|
+
end
|
|
136
|
+
if options.path
|
|
137
|
+
lastfm.m3u.add_file(found_track.relative_path_from options.path)
|
|
138
|
+
else
|
|
139
|
+
lastfm.m3u.add_file(found_track)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
puts
|
|
143
|
+
margin = 10
|
|
144
|
+
output_size = artist.length+10
|
|
145
|
+
puts " "*margin + ("="*output_size).color(:blue)
|
|
146
|
+
puts artist.center(output_size+margin*2).color(:green)
|
|
147
|
+
puts " "*margin + "#{num_tracks - not_found.size} of #{num_tracks} tracks found".center(output_size).color(:green)
|
|
148
|
+
puts " "*margin + ("="*output_size).color(:blue)
|
|
149
|
+
|
|
150
|
+
lastfm.m3u.write(File.join(lastfm.m3u_path, "#{artist}.m3u"))
|
|
151
|
+
|
|
152
|
+
unless not_found.empty? or options.not_found.nil?
|
|
153
|
+
puts
|
|
154
|
+
puts "Not Found:".color(:red)
|
|
155
|
+
not_found.each {|track| puts "#{track}".color(:yellow) }
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
end
|
data/lastfm-m3u.gemspec
CHANGED
|
@@ -21,6 +21,7 @@ Gem::Specification.new do |gem|
|
|
|
21
21
|
gem.add_development_dependency 'terminal-notifier-guard', '~> 1.5.3'
|
|
22
22
|
gem.add_development_dependency 'rb-fsevent', '~> 0.9'
|
|
23
23
|
gem.add_development_dependency 'debugger', '~> 1.5.0'
|
|
24
|
+
gem.add_development_dependency 'pry-debugger', '~> 0.2'
|
|
24
25
|
gem.add_development_dependency 'simplecov', '~> 0.7.1'
|
|
25
26
|
|
|
26
27
|
gem.add_dependency 'rockstar', '~> 0.7.1'
|
data/lib/lastfm-m3u.rb
CHANGED
|
@@ -4,7 +4,6 @@ require 'pathname'
|
|
|
4
4
|
require 'lastfm-m3u/version'
|
|
5
5
|
|
|
6
6
|
require 'rockstar'
|
|
7
|
-
require 'mp3info'
|
|
8
7
|
require 'm3uzi'
|
|
9
8
|
require 'rainbow'
|
|
10
9
|
require 'ansi/logger'
|
|
@@ -12,6 +11,7 @@ require 'ansi/logger'
|
|
|
12
11
|
require 'lastfm-m3u/base'
|
|
13
12
|
require 'lastfm-m3u/lastfm'
|
|
14
13
|
require 'lastfm-m3u/search/file_search'
|
|
14
|
+
require 'lastfm-m3u/mp3_info_ext'
|
|
15
15
|
|
|
16
16
|
module LastfmM3u
|
|
17
17
|
$logger = ANSI::Logger.new(STDOUT)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
3
|
+
module LastfmM3u
|
|
4
|
+
class Lastfm < Base
|
|
5
|
+
attr_accessor :artist, :root_dir, :limit, :tracks
|
|
6
|
+
|
|
7
|
+
def initialize(artist, root_dir='/home/jon/music/trance')
|
|
8
|
+
FileUtils.mkdir_p "#{ENV['HOME']}/.config"
|
|
9
|
+
config_path = "#{ENV['HOME']}/.config/lastfm-m3u.yml"
|
|
10
|
+
unless File.exists? config_path
|
|
11
|
+
puts "Copying empty config file to #{config_path}...".color(:green)
|
|
12
|
+
FileUtils.cp File.join(File.dirname(__FILE__), '../../config/lastfm.yml.dist'), config_path
|
|
13
|
+
end
|
|
14
|
+
config_hash = YAML.load_file(config_path)
|
|
15
|
+
Rockstar.lastfm = config_hash
|
|
16
|
+
unless config_hash.values.any? {|v| v==''}
|
|
17
|
+
@artist = Rockstar::Artist.new artist
|
|
18
|
+
@root_dir = root_dir
|
|
19
|
+
@limit = nil
|
|
20
|
+
super()
|
|
21
|
+
else
|
|
22
|
+
puts "Please add your api_key and api_secret to:\n #{config_path}\nGet your keys at http://www.last.fm/api/account".color(:yellow)
|
|
23
|
+
exit
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def find_tracks(tracks, search_type = :file, progressbar = nil)
|
|
28
|
+
begin
|
|
29
|
+
raise InvalidSearchType unless SEARCH_TYPES.include?(search_type)
|
|
30
|
+
rescue InvalidSearchType
|
|
31
|
+
$logger.error("Invalid Search Type '#{search_type}', use one of #{SEARCH_TYPES.join(',')}")
|
|
32
|
+
exit
|
|
33
|
+
end
|
|
34
|
+
found_tracks = {}
|
|
35
|
+
search = LastfmM3u::FileSearch.new(root_dir)
|
|
36
|
+
self.limit ||= tracks.size
|
|
37
|
+
tracks[0..limit-1].each do |track|
|
|
38
|
+
track.name = CGI.unescapeHTML(track.name)
|
|
39
|
+
found_tracks[track.name] = search.find(track.name, {search_type: search_type})
|
|
40
|
+
progressbar.increment if progressbar
|
|
41
|
+
end
|
|
42
|
+
found_tracks
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class InvalidSearchType < Exception; end
|
|
48
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'mp3info'
|
|
2
|
+
|
|
3
|
+
class Mp3InfoExt < Mp3Info
|
|
4
|
+
attr_reader :query, :query_type
|
|
5
|
+
|
|
6
|
+
def initialize(query, query_type, entry)
|
|
7
|
+
@query = query
|
|
8
|
+
@query_type = query_type
|
|
9
|
+
super(entry)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def found?
|
|
13
|
+
return true if @query_type == :track && title_found?
|
|
14
|
+
return true if @query_type == :album && album_found?
|
|
15
|
+
return true if @query_type == :artist && artist_found?
|
|
16
|
+
return false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# ARTIST
|
|
20
|
+
def artist_found?
|
|
21
|
+
tag2_artist_found? || tag1_artist_found?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def tag2_artist_found?
|
|
25
|
+
hastag2? && tag2.TPE1.downcase == query.downcase
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def tag1_artist_found?
|
|
29
|
+
hastag1? && tag1.artist.downcase == query.downcase
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# ALBUM
|
|
33
|
+
def album_found?
|
|
34
|
+
tag2_album_found? || tag1_album_found?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def tag2_album_found?
|
|
38
|
+
hastag2? && tag2.TALB.downcase == query.downcase
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def tag1_album_found?
|
|
42
|
+
hastag1? && tag1.album.downcase == query.downcase
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# TITLE
|
|
46
|
+
def title_found?
|
|
47
|
+
tag2_title_found? || tag1_title_found?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def tag2_title_found?
|
|
51
|
+
hastag2? && tag2.TIT2.downcase == query.downcase
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def tag1_title_found?
|
|
55
|
+
hastag1? and tag1.title.downcase == query.downcase
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
module LastfmM3u
|
|
2
|
+
require 'lastfm-m3u'
|
|
3
|
+
require 'pathname'
|
|
4
|
+
|
|
5
|
+
class Search < Base
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class FileSearch < Search
|
|
9
|
+
attr_accessor :root_dir
|
|
10
|
+
|
|
11
|
+
def initialize(root_dir)
|
|
12
|
+
@root_dir = Pathname root_dir
|
|
13
|
+
super()
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def find(query, options={})
|
|
17
|
+
query_type = options[:query_type] || :track
|
|
18
|
+
file_or_id3 = options[:search_type] || :both
|
|
19
|
+
prefer_flac = options[:prefer_flac] || true
|
|
20
|
+
|
|
21
|
+
files = find_unique_files(query, query_type, file_or_id3)
|
|
22
|
+
if prefer_flac && !(flac_files=trim_non_flac(files)).empty?
|
|
23
|
+
files = flac_files
|
|
24
|
+
end
|
|
25
|
+
$logger.debug "#{query} => #{files}"
|
|
26
|
+
files
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def find_unique_files(query, query_type, file_or_id3)
|
|
33
|
+
files = id3_files = []
|
|
34
|
+
files = find_in_filesystem(query, query_type) if [:both, :file].include? file_or_id3
|
|
35
|
+
id3_files = find_by_id3(query, query_type) if [:both, :id3].include? file_or_id3
|
|
36
|
+
(files + id3_files).sort.uniq
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def find_in_filesystem(name, query_type)
|
|
40
|
+
if query_type == :artist or query_type == :album
|
|
41
|
+
find_by_dir(name)
|
|
42
|
+
else
|
|
43
|
+
find_by_filename(name)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def find_by_dir(name)
|
|
48
|
+
found_entries = []
|
|
49
|
+
Dir.glob("#{root_dir}/**/*").each do |entry|
|
|
50
|
+
entry = Pathname.new entry
|
|
51
|
+
found_entries << entry.to_s if entry.directory? and normalize(entry).to_s =~ /.*#{Regexp.escape name}.*/i
|
|
52
|
+
end
|
|
53
|
+
found_entries
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def find_by_filename(name)
|
|
57
|
+
found_entries = []
|
|
58
|
+
Dir.glob("#{root_dir}/**/*.{mp3,flac}").each do |entry|
|
|
59
|
+
begin
|
|
60
|
+
entry = Pathname.new entry
|
|
61
|
+
if normalize(entry) =~ /.*#{Regexp.escape name}.*/i
|
|
62
|
+
$logger.debug "#{name} => #{entry}"
|
|
63
|
+
found_entries << entry.to_s
|
|
64
|
+
end
|
|
65
|
+
rescue ArgumentError => e
|
|
66
|
+
# for some reason it gets 'invalid byte sequence in UTF-8
|
|
67
|
+
# even though replacing ascii below with utf-8 causes nothing to be replaced.
|
|
68
|
+
entry = Pathname entry.to_s.encode('ascii', invalid: :replace, undef: :replace, replace: '??')
|
|
69
|
+
$logger.warn "#{e.message} => #{entry.relative_path_from(root_dir)}"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
found_entries
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def find_by_id3(query, query_type)
|
|
76
|
+
query = CGI.unescapeHTML(query)
|
|
77
|
+
found_entries = []
|
|
78
|
+
$logger.debug query
|
|
79
|
+
Dir.glob("#{root_dir}/**/*.mp3").each do |entry|
|
|
80
|
+
begin
|
|
81
|
+
id3 = Mp3InfoExt.new(query, query_type, entry)
|
|
82
|
+
found_entries << id3.filename if id3.found?
|
|
83
|
+
rescue Mp3InfoError => e
|
|
84
|
+
$logger.warn "#{e.message} => #{(Pathname.new entry).relative_path_from(root_dir)}"
|
|
85
|
+
rescue NoMethodError => e
|
|
86
|
+
$logger.warn "No tags found => #{(Pathname.new entry).relative_path_from(root_dir)}"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
found_entries
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def normalize(pathname)
|
|
93
|
+
pathname.basename.to_s.gsub('-', ' ').gsub('_', ' ').sub(/#{pathname.extname}$/, '')
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def trim_non_flac(pathnames)
|
|
97
|
+
pathnames.select{|pn| pn.to_s =~ /\.flac$/}
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module LastfmM3u
|
|
2
|
+
module Util
|
|
3
|
+
def self.choose_track(track, track_set)
|
|
4
|
+
choose do |menu|
|
|
5
|
+
menu.index = :letter
|
|
6
|
+
menu.index_suffix = ") "
|
|
7
|
+
|
|
8
|
+
menu.prompt = "For #{track}, which file would you like to use? ".color(:green)
|
|
9
|
+
|
|
10
|
+
track_set.each do |track|
|
|
11
|
+
menu.choice track do
|
|
12
|
+
return track
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
menu.choice "none" do return nil end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lastfm-m3u
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.4
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2013-
|
|
12
|
+
date: 2013-05-04 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: rspec
|
|
@@ -107,6 +107,22 @@ dependencies:
|
|
|
107
107
|
- - ~>
|
|
108
108
|
- !ruby/object:Gem::Version
|
|
109
109
|
version: 1.5.0
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: pry-debugger
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
none: false
|
|
114
|
+
requirements:
|
|
115
|
+
- - ~>
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0.2'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
none: false
|
|
122
|
+
requirements:
|
|
123
|
+
- - ~>
|
|
124
|
+
- !ruby/object:Gem::Version
|
|
125
|
+
version: '0.2'
|
|
110
126
|
- !ruby/object:Gem::Dependency
|
|
111
127
|
name: simplecov
|
|
112
128
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -258,6 +274,7 @@ files:
|
|
|
258
274
|
- lib/lastfm-m3u.rb
|
|
259
275
|
- lib/lastfm-m3u/base.rb
|
|
260
276
|
- lib/lastfm-m3u/lastfm.rb
|
|
277
|
+
- lib/lastfm-m3u/mp3_info_ext.rb
|
|
261
278
|
- lib/lastfm-m3u/search/file_search.rb
|
|
262
279
|
- lib/lastfm-m3u/util.rb
|
|
263
280
|
- lib/lastfm-m3u/version.rb
|
|
@@ -284,7 +301,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
284
301
|
version: '0'
|
|
285
302
|
segments:
|
|
286
303
|
- 0
|
|
287
|
-
hash:
|
|
304
|
+
hash: 3207334904113421642
|
|
288
305
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
289
306
|
none: false
|
|
290
307
|
requirements:
|
|
@@ -293,7 +310,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
293
310
|
version: '0'
|
|
294
311
|
segments:
|
|
295
312
|
- 0
|
|
296
|
-
hash:
|
|
313
|
+
hash: 3207334904113421642
|
|
297
314
|
requirements: []
|
|
298
315
|
rubyforge_project:
|
|
299
316
|
rubygems_version: 1.8.25
|