nehm 1.5.6.2 → 1.6.1
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGELOG.md +8 -0
- data/README.md +6 -7
- data/bin/nehm +6 -1
- data/lib/nehm.rb +31 -48
- data/lib/nehm/applescript.rb +7 -2
- data/lib/nehm/artwork.rb +6 -6
- data/lib/nehm/cfg.rb +5 -1
- data/lib/nehm/client.rb +78 -6
- data/lib/nehm/command.rb +123 -0
- data/lib/nehm/command_manager.rb +66 -0
- data/lib/nehm/commands/configure_command.rb +44 -0
- data/lib/nehm/commands/dl_command.rb +41 -0
- data/lib/nehm/commands/get_command.rb +44 -0
- data/lib/nehm/commands/help_command.rb +85 -0
- data/lib/nehm/commands/version_command.rb +23 -0
- data/lib/nehm/option_parser.rb +31 -0
- data/lib/nehm/os.rb +5 -0
- data/lib/nehm/path_manager.rb +28 -31
- data/lib/nehm/playlist.rb +7 -1
- data/lib/nehm/playlist_manager.rb +31 -14
- data/lib/nehm/track.rb +23 -21
- data/lib/nehm/tracks.rb +153 -0
- data/lib/nehm/ui.rb +35 -0
- data/lib/nehm/user_manager.rb +19 -42
- data/lib/nehm/version.rb +1 -1
- data/nehm.gemspec +2 -2
- metadata +24 -18
- data/lib/nehm/configure.rb +0 -24
- data/lib/nehm/get.rb +0 -100
- data/lib/nehm/help.rb +0 -93
- data/lib/nehm/user.rb +0 -81
@@ -1,38 +1,51 @@
|
|
1
|
+
require 'nehm/playlist'
|
2
|
+
|
1
3
|
module Nehm
|
4
|
+
|
5
|
+
##
|
6
|
+
# Playlist manager works with iTunes playlists
|
7
|
+
|
2
8
|
module PlaylistManager
|
3
|
-
|
4
|
-
|
9
|
+
|
10
|
+
##
|
11
|
+
# Returns default iTunes playlist (contains in ~/.nehmconfig)
|
12
|
+
|
13
|
+
def self.default_playlist
|
14
|
+
default_user_playlist || music_master_library unless OS.linux?
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Checks path for existence and returns it if exists
|
19
|
+
|
20
|
+
def self.get_playlist(playlist_name)
|
21
|
+
if AppleScript.list_of_playlists.include? playlist_name
|
22
|
+
Playlist.new(playlist_name)
|
23
|
+
else
|
24
|
+
UI.term 'Invalid playlist name. Please enter correct name'
|
25
|
+
end
|
5
26
|
end
|
6
27
|
|
7
28
|
def self.set_playlist
|
8
29
|
loop do
|
9
|
-
playlist = HighLine.new.ask('Enter name of default iTunes playlist to
|
30
|
+
playlist = HighLine.new.ask('Enter name of default iTunes playlist to that you want add tracks (press Enter to set it to default iTunes Music library):')
|
10
31
|
|
11
32
|
# If entered nothing, unset iTunes playlist
|
12
33
|
if playlist == ''
|
13
34
|
Cfg[:playlist] = nil
|
14
|
-
|
35
|
+
UI.success 'Default iTunes playlist unset'
|
15
36
|
break
|
16
37
|
end
|
17
38
|
|
18
39
|
if AppleScript.list_of_playlists.include? playlist
|
19
40
|
Cfg[:playlist] = playlist
|
20
|
-
|
41
|
+
UI.say "#{'Default iTunes playlist set up to'.green} #{playlist.magenta}"
|
21
42
|
break
|
22
43
|
else
|
23
|
-
|
44
|
+
UI.error 'Invalid playlist name. Please enter correct name'
|
24
45
|
end
|
25
46
|
end
|
26
47
|
end
|
27
48
|
|
28
|
-
def self.temp_playlist=(playlist)
|
29
|
-
if AppleScript.list_of_playlists.include? playlist
|
30
|
-
@temp_playlist = Playlist.new(playlist)
|
31
|
-
else
|
32
|
-
puts Paint['Invalid playlist name. Please enter correct name', :red]
|
33
|
-
exit
|
34
|
-
end
|
35
|
-
end
|
36
49
|
|
37
50
|
module_function
|
38
51
|
|
@@ -40,8 +53,12 @@ module Nehm
|
|
40
53
|
Playlist.new(Cfg[:playlist]) unless Cfg[:playlist].nil?
|
41
54
|
end
|
42
55
|
|
56
|
+
##
|
57
|
+
# Music master library is main iTunes music library
|
58
|
+
|
43
59
|
def music_master_library
|
44
60
|
Playlist.new(AppleScript.music_master_library)
|
45
61
|
end
|
62
|
+
|
46
63
|
end
|
47
64
|
end
|
data/lib/nehm/track.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
|
+
require 'nehm/artwork'
|
2
|
+
|
1
3
|
module Nehm
|
4
|
+
|
5
|
+
# Primitive for SoundCloud track
|
6
|
+
|
2
7
|
class Track
|
8
|
+
|
3
9
|
attr_reader :hash
|
4
10
|
|
5
11
|
def initialize(hash)
|
@@ -7,13 +13,7 @@ module Nehm
|
|
7
13
|
end
|
8
14
|
|
9
15
|
def artist
|
10
|
-
|
11
|
-
|
12
|
-
if title.include? ' - '
|
13
|
-
title.split(' - ')[0]
|
14
|
-
else
|
15
|
-
@hash['user']['username']
|
16
|
-
end
|
16
|
+
name[0]
|
17
17
|
end
|
18
18
|
|
19
19
|
def artwork
|
@@ -21,34 +21,35 @@ module Nehm
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def file_name
|
24
|
-
"#{
|
24
|
+
"#{full_name.tr(',./\\\'$%"', '')}.mp3"
|
25
25
|
end
|
26
26
|
|
27
27
|
def file_path
|
28
|
-
File.join(
|
28
|
+
File.join(ENV['dl_path'], file_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def full_name
|
32
|
+
"#{artist} - #{title}"
|
29
33
|
end
|
30
34
|
|
31
35
|
def id
|
32
36
|
@hash['id']
|
33
37
|
end
|
34
38
|
|
35
|
-
#
|
39
|
+
# Returns artist and title in array
|
36
40
|
def name
|
37
|
-
|
38
|
-
|
41
|
+
title = @hash['title']
|
42
|
+
|
43
|
+
separators = [' - ', ' ~ ']
|
44
|
+
separators.each do |sep|
|
45
|
+
return title.split(sep) if title.include? sep
|
46
|
+
end
|
39
47
|
|
40
|
-
|
41
|
-
@hash['streamable']
|
48
|
+
[@hash['user']['username'], title]
|
42
49
|
end
|
43
50
|
|
44
51
|
def title
|
45
|
-
|
46
|
-
|
47
|
-
if title.include? ' - '
|
48
|
-
title.split(' - ')[1]
|
49
|
-
else
|
50
|
-
title
|
51
|
-
end
|
52
|
+
name[1]
|
52
53
|
end
|
53
54
|
|
54
55
|
def url
|
@@ -58,5 +59,6 @@ module Nehm
|
|
58
59
|
def year
|
59
60
|
@hash['created_at'][0..3].to_i
|
60
61
|
end
|
62
|
+
|
61
63
|
end
|
62
64
|
end
|
data/lib/nehm/tracks.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'taglib'
|
2
|
+
|
3
|
+
require 'nehm/applescript'
|
4
|
+
require 'nehm/os'
|
5
|
+
require 'nehm/track'
|
6
|
+
|
7
|
+
module Nehm
|
8
|
+
|
9
|
+
##
|
10
|
+
# Tracks contains logic, that need to 'nehm get/dl ...' commands.
|
11
|
+
#
|
12
|
+
# It used in 'get_command.rb' and 'dl_command.rb'.
|
13
|
+
|
14
|
+
module Tracks
|
15
|
+
|
16
|
+
##
|
17
|
+
# Main method.
|
18
|
+
|
19
|
+
def self.[](type, options)
|
20
|
+
# Setting up user id
|
21
|
+
permalink = options[:from]
|
22
|
+
uid = permalink ? UserManager.get_uid(permalink) : UserManager.default_uid
|
23
|
+
unless uid
|
24
|
+
UI.error "You didn't logged in"
|
25
|
+
UI.say "Login from #{'nehm configure'.yellow} or use #{'[from PERMALINK]'.yellow} option"
|
26
|
+
UI.term
|
27
|
+
end
|
28
|
+
|
29
|
+
# Setting up iTunes playlist
|
30
|
+
if type == :get && !OS.linux?
|
31
|
+
playlist_name = options[:playlist]
|
32
|
+
playlist = playlist_name ? PlaylistManager.get_playlist(playlist_name) : PlaylistManager.default_playlist
|
33
|
+
itunes_playlist_ready = true if playlist
|
34
|
+
else
|
35
|
+
itunes_playlist_ready = false
|
36
|
+
end
|
37
|
+
|
38
|
+
# Setting up download path
|
39
|
+
temp_path = options[:to]
|
40
|
+
dl_path = temp_path ? PathManager.get_path(temp_path) : PathManager.default_dl_path
|
41
|
+
if dl_path
|
42
|
+
ENV['dl_path'] = dl_path
|
43
|
+
else
|
44
|
+
UI.error "You don't set up download path!"
|
45
|
+
UI.say "Set it up from #{'nehm configure'.yellow} or use #{'[to PATH_TO_DIRECTORY]'.yellow} option"
|
46
|
+
UI.term
|
47
|
+
end
|
48
|
+
|
49
|
+
UI.say 'Getting information about track(s)'
|
50
|
+
arg = options[:args].pop
|
51
|
+
tracks = []
|
52
|
+
tracks +=
|
53
|
+
case arg
|
54
|
+
when 'like'
|
55
|
+
likes(1, uid)
|
56
|
+
when 'post'
|
57
|
+
posts(1, uid)
|
58
|
+
when 'likes'
|
59
|
+
count = options[:args].pop.to_i
|
60
|
+
likes(count, uid)
|
61
|
+
when 'posts'
|
62
|
+
count = options[:args].pop.to_i
|
63
|
+
posts(count, uid)
|
64
|
+
when %r{https:\/\/soundcloud.com\/}
|
65
|
+
track(arg)
|
66
|
+
when nil
|
67
|
+
UI.error 'You must provide argument'
|
68
|
+
UI.say "Use #{'nehm help'.yellow} for help"
|
69
|
+
UI.term
|
70
|
+
else
|
71
|
+
UI.error "Invalid argument/option #{arg}"
|
72
|
+
UI.say "Use #{'nehm help'.yellow} for help"
|
73
|
+
UI.term
|
74
|
+
end
|
75
|
+
|
76
|
+
tracks.each do |track|
|
77
|
+
UI.newline
|
78
|
+
dl(track)
|
79
|
+
tag(track)
|
80
|
+
track.artwork.suicide
|
81
|
+
playlist.add_track(track.file_path) if itunes_playlist_ready
|
82
|
+
UI.newline
|
83
|
+
end
|
84
|
+
UI.success 'Done!'
|
85
|
+
end
|
86
|
+
|
87
|
+
module_function
|
88
|
+
|
89
|
+
def dl(track)
|
90
|
+
# Downloading track
|
91
|
+
UI.say 'Downloading ' + track.full_name
|
92
|
+
`curl -# -o \"#{track.file_path}\" -L #{track.url}`
|
93
|
+
|
94
|
+
# Downloading artwork
|
95
|
+
UI.say 'Downloading artwork'
|
96
|
+
artwork = track.artwork
|
97
|
+
`curl -# -o \"#{artwork.file_path}\" -L #{artwork.url}`
|
98
|
+
end
|
99
|
+
|
100
|
+
def tag(track)
|
101
|
+
UI.say 'Setting tags'
|
102
|
+
path = track.file_path
|
103
|
+
TagLib::MPEG::File.open(path) do |file|
|
104
|
+
tag = file.id3v2_tag
|
105
|
+
tag.artist = track.artist
|
106
|
+
tag.title = track.title
|
107
|
+
tag.year = track.year
|
108
|
+
|
109
|
+
# Adding artwork
|
110
|
+
apic = TagLib::ID3v2::AttachedPictureFrame.new
|
111
|
+
apic.mime_type = 'image/jpeg'
|
112
|
+
apic.description = 'Cover'
|
113
|
+
apic.type = TagLib::ID3v2::AttachedPictureFrame::FrontCover
|
114
|
+
apic.picture = File.open(track.artwork.file_path, 'rb') { |f| f.read }
|
115
|
+
tag.add_frame(apic)
|
116
|
+
|
117
|
+
file.save
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def likes(count, uid)
|
122
|
+
likes = Client.tracks(count, :likes, uid)
|
123
|
+
UI.term 'There are no likes yet' if likes.empty?
|
124
|
+
|
125
|
+
# Removing playlists and unstreamable tracks
|
126
|
+
unstreamable_tracks = likes.reject! { |hash| hash['streamable'] == false }
|
127
|
+
UI.warning "Was skipped #{unstreamable_tracks.length} undownloadable track(s)" if unstreamable_tracks
|
128
|
+
|
129
|
+
likes.map! { |hash| Track.new(hash) }
|
130
|
+
end
|
131
|
+
|
132
|
+
def posts(count, uid)
|
133
|
+
posts = Client.tracks(count, :posts, uid)
|
134
|
+
UI.term 'There are no posts yet' if posts.empty?
|
135
|
+
|
136
|
+
# Removing playlists and unstreamable tracks
|
137
|
+
first_count = posts.length
|
138
|
+
playlists = posts.reject! { |hash| hash['type'] == 'playlist' }
|
139
|
+
unstreamable_tracks = posts.reject! { |hash| hash['track']['streamable'] == false }
|
140
|
+
if playlists || unstreamable_tracks
|
141
|
+
UI.warning "Was skipped #{first_count - posts.length} undownloadable track(s) or playlist(s)"
|
142
|
+
end
|
143
|
+
|
144
|
+
posts.map! { |hash| Track.new(hash['track']) }
|
145
|
+
end
|
146
|
+
|
147
|
+
def track(url)
|
148
|
+
hash = Client.track(url)
|
149
|
+
[*Track.new(hash)]
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
end
|
data/lib/nehm/ui.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Nehm
|
2
|
+
module UI
|
3
|
+
|
4
|
+
# TODO: add Highline features to UI module
|
5
|
+
|
6
|
+
def self.error(msg)
|
7
|
+
puts "#{msg}\n".red
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.newline
|
11
|
+
puts "\n"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.say(msg)
|
15
|
+
puts msg
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.success(msg)
|
19
|
+
puts msg.green
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.term(msg = nil)
|
23
|
+
if msg
|
24
|
+
abort msg.red
|
25
|
+
else
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.warning(msg)
|
31
|
+
puts "#{msg}".yellow
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
data/lib/nehm/user_manager.rb
CHANGED
@@ -1,61 +1,38 @@
|
|
1
1
|
module Nehm
|
2
|
+
|
3
|
+
##
|
4
|
+
# User manager works with SoundCloud users' id
|
5
|
+
|
2
6
|
module UserManager
|
3
|
-
|
4
|
-
|
7
|
+
|
8
|
+
##
|
9
|
+
# Returns default user id (contains in ~/.nehmconfig)
|
10
|
+
|
11
|
+
def self.default_uid
|
12
|
+
Cfg[:default_id]
|
5
13
|
end
|
6
14
|
|
7
|
-
def self.
|
8
|
-
|
15
|
+
def self.get_uid(permalink)
|
16
|
+
user = Client.user(permalink)
|
17
|
+
UI.term 'Invalid permalink. Please enter correct permalink' if user.nil?
|
18
|
+
|
19
|
+
user['id']
|
9
20
|
end
|
10
21
|
|
11
|
-
def self.
|
22
|
+
def self.set_uid
|
12
23
|
loop do
|
13
24
|
permalink = HighLine.new.ask('Please enter your permalink (last word in your profile url): ')
|
14
|
-
user =
|
25
|
+
user = Client.user(permalink)
|
15
26
|
if user
|
16
27
|
Cfg[:default_id] = user.id
|
17
28
|
Cfg[:permalink] = permalink
|
18
|
-
|
29
|
+
UI.success 'Successfully logged in!'
|
19
30
|
break
|
20
31
|
else
|
21
|
-
|
32
|
+
UI.error 'Invalid permalink. Please enter correct permalink'
|
22
33
|
end
|
23
34
|
end
|
24
35
|
end
|
25
36
|
|
26
|
-
def self.temp_user=(permalink)
|
27
|
-
user = get_user(permalink)
|
28
|
-
if user
|
29
|
-
@temp_user = User.new(user.id)
|
30
|
-
else
|
31
|
-
puts Paint['Invalid permalink. Please enter correct permalink', :red]
|
32
|
-
exit
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
module_function
|
37
|
-
|
38
|
-
def default_user
|
39
|
-
if UserManager.logged_in?
|
40
|
-
User.new(Cfg[:default_id])
|
41
|
-
else
|
42
|
-
puts Paint["You didn't logged in", :red]
|
43
|
-
puts "Login from #{Paint['nehm configure', :yellow]} or use #{Paint['[from PERMALINK]', :yellow]} option"
|
44
|
-
exit
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def get_user(permalink)
|
49
|
-
begin
|
50
|
-
user = Client.get('/resolve', url: "https://soundcloud.com/#{permalink}")
|
51
|
-
rescue SoundCloud::ResponseError => e
|
52
|
-
if e.message =~ /404/
|
53
|
-
user = nil
|
54
|
-
else
|
55
|
-
raise e
|
56
|
-
end
|
57
|
-
end
|
58
|
-
user
|
59
|
-
end
|
60
37
|
end
|
61
38
|
end
|
data/lib/nehm/version.rb
CHANGED
data/nehm.gemspec
CHANGED
@@ -20,11 +20,11 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.require_paths = ['lib']
|
21
21
|
spec.required_ruby_version = '>= 1.9.3'
|
22
22
|
|
23
|
-
spec.add_dependency 'bogy'
|
23
|
+
spec.add_dependency 'bogy'
|
24
24
|
spec.add_dependency 'certifi'
|
25
|
+
spec.add_dependency 'colored'
|
25
26
|
spec.add_dependency 'faraday', '>= 0.9.1'
|
26
27
|
spec.add_dependency 'highline', '>= 1.7.2'
|
27
|
-
spec.add_dependency 'paint'
|
28
28
|
spec.add_dependency 'soundcloud', '>= 0.3.2'
|
29
29
|
spec.add_dependency 'taglib-ruby', '>= 0.7.0'
|
30
30
|
end
|