17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
# File 'lib/exportify/cli.rb', line 17
def run(argv)
return run_init(argv[1]) if argv[0] == 'init'
retag = false
sync = false
parser = OptionParser.new do |opts|
opts.banner = "Usage:\n " \
"exportify init\n " \
'exportify <spotify_playlist_url> [--retag] [--sync]'
opts.on('--retag', 'Regravar tags ID3 nos arquivos existentes') { retag = true }
opts.on('--sync', 'Remover arquivos locais que não estão mais na playlist') { sync = true }
end
parser.parse!(argv)
playlist_url = argv[0]&.split('?', 2)&.first
abort parser.banner unless playlist_url
abort 'Credenciais não configuradas. Execute: exportify init' unless Auth.client_id && Auth.client_secret
playlist_id = playlist_url.match(%r{playlist/([A-Za-z0-9]+)})&.captures&.first
abort 'Invalid playlist URL' unless playlist_id
puts 'Authenticating with Spotify...'
token = Auth.access_token
puts 'Fetching playlist...'
name = Spotify.playlist_name(playlist_id, token)
tracks = Spotify.playlist_tracks(playlist_id, token)
tracks = Spotify.enrich_with_genres(tracks, token)
output_dir = File.expand_path(File.join(Config.output_dir, Downloader.sanitize(name)))
FileUtils.mkdir_p(output_dir)
puts "#{tracks.size} tracks found"
puts "Output: #{output_dir}\n\n"
ok = skip = failed = 0
tracks.each_with_index do |track, i|
artist = Downloader.sanitize(track[:artist])
name = Downloader.sanitize(track[:name])
filename = "#{artist} - #{name}.mp3"
filepath = File.join(output_dir, filename)
print "[#{i + 1}/#{tracks.size}] #{filename} "
if retag
if File.exist?(filepath)
Tagger.tag(filepath, track)
puts '(retagged)'
ok += 1
else
puts '(not found, skipping)'
skip += 1
end
next
end
if File.exist?(filepath)
puts '(already exists, skipping)'
skip += 1
next
end
puts '(downloading...)'
success = Downloader.download(track, output_dir)
if success && File.exist?(filepath)
Tagger.tag(filepath, track)
ok += 1
else
failed += 1
end
end
removed = 0
if sync
expected = tracks.to_set do |track|
"#{Downloader.sanitize(track[:artist])} - #{Downloader.sanitize(track[:name])}.mp3"
end
Dir.glob(File.join(output_dir, '*.mp3')).each do |file|
next if expected.include?(File.basename(file))
puts "Removing #{File.basename(file)}"
File.delete(file)
removed += 1
end
end
if retag
puts "\nDone: #{ok} retagged, #{skip} not found."
else
removed_msg = sync ? ", #{removed} removed" : ''
puts "\nDone: #{ok} downloaded, #{skip} skipped, #{failed} failed#{removed_msg}."
end
end
|