nehm 1.5.4 → 1.5.5.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/CHANGELOG.md +9 -25
- data/bin/nehm +1 -1
- data/lib/nehm.rb +42 -37
- data/lib/nehm/applescript.rb +18 -15
- data/lib/nehm/artwork.rb +26 -24
- data/lib/nehm/cfg.rb +21 -18
- data/lib/nehm/client.rb +14 -12
- data/lib/nehm/configure.rb +18 -16
- data/lib/nehm/get.rb +82 -83
- data/lib/nehm/help.rb +75 -72
- data/lib/nehm/os.rb +5 -3
- data/lib/nehm/path_manager.rb +52 -50
- data/lib/nehm/playlist.rb +13 -11
- data/lib/nehm/playlist_manager.rb +34 -30
- data/lib/nehm/track.rb +45 -43
- data/lib/nehm/user.rb +58 -55
- data/lib/nehm/user_manager.rb +45 -43
- data/lib/nehm/version.rb +1 -1
- metadata +3 -3
data/lib/nehm/playlist.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Nehm
|
2
|
+
class Playlist
|
3
|
+
attr_reader :name
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def initialize(name)
|
6
|
+
@name = name
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
def add_track(track_path)
|
10
|
+
puts 'Adding to iTunes'
|
11
|
+
AppleScript.add_track_to_playlist(track_path, @name)
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
def to_s
|
15
|
+
@name
|
16
|
+
end
|
15
17
|
end
|
16
18
|
end
|
@@ -1,43 +1,47 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module Nehm
|
2
|
+
module PlaylistManager
|
3
|
+
def self.playlist
|
4
|
+
@temp_playlist || default_user_playlist || music_master_library unless OS.linux?
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.set_playlist
|
8
|
+
loop do
|
9
|
+
playlist = HighLine.new.ask('Enter name of default iTunes playlist to which you want add tracks (press Enter to set it to default iTunes Music library)')
|
5
10
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
# If entered nothing, unset iTunes playlist
|
12
|
+
if playlist == ''
|
13
|
+
Cfg[:playlist] = nil
|
14
|
+
puts Paint['Default iTunes playlist unset', :green]
|
15
|
+
break
|
16
|
+
end
|
17
|
+
|
18
|
+
if AppleScript.list_of_playlists.include? playlist
|
19
|
+
Cfg[:playlist] = playlist
|
20
|
+
puts Paint["Default iTunes playlist set up to #{playlist}", :green]
|
21
|
+
break
|
22
|
+
else
|
23
|
+
puts Paint['Invalid playlist name. Please enter correct name', :red]
|
24
|
+
end
|
13
25
|
end
|
26
|
+
end
|
14
27
|
|
28
|
+
def self.temp_playlist=(playlist)
|
15
29
|
if AppleScript.list_of_playlists.include? playlist
|
16
|
-
|
17
|
-
puts Paint["Default iTunes playlist set up to #{playlist}", :green]
|
18
|
-
break
|
30
|
+
@temp_playlist = Playlist.new(playlist)
|
19
31
|
else
|
20
32
|
puts Paint['Invalid playlist name. Please enter correct name', :red]
|
33
|
+
exit
|
21
34
|
end
|
22
35
|
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.temp_playlist=(playlist)
|
26
|
-
if AppleScript.list_of_playlists.include? playlist
|
27
|
-
@temp_playlist = Playlist.new(playlist)
|
28
|
-
else
|
29
|
-
puts Paint['Invalid playlist name. Please enter correct name', :red]
|
30
|
-
exit
|
31
|
-
end
|
32
|
-
end
|
33
36
|
|
34
|
-
|
37
|
+
module_function
|
35
38
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
+
def default_user_playlist
|
40
|
+
Playlist.new(Cfg[:playlist]) unless Cfg[:playlist].nil?
|
41
|
+
end
|
39
42
|
|
40
|
-
|
41
|
-
|
43
|
+
def music_master_library
|
44
|
+
Playlist.new(AppleScript.music_master_library)
|
45
|
+
end
|
42
46
|
end
|
43
47
|
end
|
data/lib/nehm/track.rb
CHANGED
@@ -1,58 +1,60 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Nehm
|
2
|
+
class Track
|
3
|
+
attr_reader :hash
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def initialize(hash)
|
6
|
+
@hash = hash
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
def artist
|
10
|
+
if @hash['title'].include?('-')
|
11
|
+
title = @hash['title'].split('-')
|
12
|
+
title[0].rstrip
|
13
|
+
else
|
14
|
+
@hash['user']['username']
|
15
|
+
end
|
14
16
|
end
|
15
|
-
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
def artwork
|
19
|
+
Artwork.new(self)
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
def file_name
|
23
|
+
"#{name}.mp3".tr("/'\"", '')
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
def file_path
|
27
|
+
File.join(PathManager.dl_path, file_name)
|
28
|
+
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
def id
|
31
|
+
@hash['id']
|
32
|
+
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
# Used in Get#dl and in Track#file_name
|
35
|
+
def name
|
36
|
+
artist + ' - ' + title
|
37
|
+
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
def streamable?
|
40
|
+
@hash['streamable']
|
41
|
+
end
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
43
|
+
def title
|
44
|
+
if @hash['title'].include?('-')
|
45
|
+
title = @hash['title'].split('-')
|
46
|
+
title[1].lstrip
|
47
|
+
else
|
48
|
+
@hash['title']
|
49
|
+
end
|
48
50
|
end
|
49
|
-
end
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
52
|
+
def url
|
53
|
+
"#{@hash['stream_url']}?client_id=#{Client::CLIENT_ID}"
|
54
|
+
end
|
54
55
|
|
55
|
-
|
56
|
-
|
56
|
+
def year
|
57
|
+
@hash['created_at'][0..3].to_i
|
58
|
+
end
|
57
59
|
end
|
58
60
|
end
|
data/lib/nehm/user.rb
CHANGED
@@ -1,78 +1,81 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'faraday'
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
module Nehm
|
5
|
+
class User
|
6
|
+
# Max limit of tracks for correct SoundCloud requests
|
7
|
+
SOUNDCLOUD_MAX_LIMIT = 180
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
end
|
10
|
-
|
11
|
-
def likes(count)
|
12
|
-
# Method to_i return 0, if there aren't any numbers in string
|
13
|
-
if count == 0
|
14
|
-
puts Paint['Invalid number of likes!', :red]
|
15
|
-
exit
|
9
|
+
def initialize(id)
|
10
|
+
@id = id
|
16
11
|
end
|
17
12
|
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
def likes(count)
|
14
|
+
# Method to_i return 0, if there aren't any numbers in string
|
15
|
+
if count == 0
|
16
|
+
puts Paint['Invalid number of likes!', :red]
|
17
|
+
exit
|
18
|
+
end
|
21
19
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
count -= SOUNDCLOUD_MAX_LIMIT
|
20
|
+
d = count / SOUNDCLOUD_MAX_LIMIT
|
21
|
+
m = count % SOUNDCLOUD_MAX_LIMIT
|
22
|
+
d = m == 0 ? d : d + 1
|
26
23
|
|
27
|
-
likes
|
28
|
-
|
24
|
+
likes = []
|
25
|
+
d.times do |i|
|
26
|
+
limit = count > SOUNDCLOUD_MAX_LIMIT ? SOUNDCLOUD_MAX_LIMIT : count
|
27
|
+
count -= SOUNDCLOUD_MAX_LIMIT
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
exit
|
33
|
-
end
|
29
|
+
likes += Client.get("/users/#{@id}/favorites?limit=#{limit}&offset=#{(i)*SOUNDCLOUD_MAX_LIMIT}")
|
30
|
+
end
|
34
31
|
|
35
|
-
|
36
|
-
|
32
|
+
if likes.empty?
|
33
|
+
puts Paint['There are no likes yet :(', :red]
|
34
|
+
exit
|
35
|
+
end
|
37
36
|
|
38
|
-
|
39
|
-
def posts(count)
|
40
|
-
# Method to_i return 0, if there aren't any numbers in string
|
41
|
-
if count == 0
|
42
|
-
puts Paint['Invalid number of posts!', :red]
|
43
|
-
exit
|
37
|
+
likes.map! { |hash| Track.new(hash) }
|
44
38
|
end
|
45
39
|
|
46
|
-
|
47
|
-
|
48
|
-
|
40
|
+
# Post is last track/repost in profile
|
41
|
+
def posts(count)
|
42
|
+
# Method to_i return 0, if there aren't any numbers in string
|
43
|
+
if count == 0
|
44
|
+
puts Paint['Invalid number of posts!', :red]
|
45
|
+
exit
|
46
|
+
end
|
49
47
|
|
50
|
-
|
51
|
-
|
52
|
-
|
48
|
+
d = count / SOUNDCLOUD_MAX_LIMIT
|
49
|
+
m = count % SOUNDCLOUD_MAX_LIMIT
|
50
|
+
d = m == 0 ? d : d + 1
|
53
51
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
count -= SOUNDCLOUD_MAX_LIMIT
|
52
|
+
# Official SC API wrapper doesn't support posts
|
53
|
+
# So I should get posts by HTTP requests
|
54
|
+
conn = Faraday.new(url: 'https://api-v2.soundcloud.com/')
|
58
55
|
|
59
|
-
|
60
|
-
|
61
|
-
|
56
|
+
posts = []
|
57
|
+
d.times do |i|
|
58
|
+
limit = count > SOUNDCLOUD_MAX_LIMIT ? SOUNDCLOUD_MAX_LIMIT : count
|
59
|
+
count -= SOUNDCLOUD_MAX_LIMIT
|
62
60
|
|
63
|
-
|
61
|
+
response = conn.get("/profile/soundcloud:users:#{@id}?limit=#{limit}&offset=#{i*SOUNDCLOUD_MAX_LIMIT}")
|
62
|
+
parsed = JSON.parse(response.body)
|
63
|
+
collection = parsed['collection']
|
64
64
|
|
65
|
-
|
66
|
-
end
|
65
|
+
break if collection.nil?
|
67
66
|
|
68
|
-
|
69
|
-
|
70
|
-
exit
|
71
|
-
end
|
67
|
+
posts += collection
|
68
|
+
end
|
72
69
|
|
73
|
-
|
74
|
-
|
70
|
+
if posts.empty?
|
71
|
+
puts Paint['There are no posts yet :(', :red]
|
72
|
+
exit
|
73
|
+
end
|
75
74
|
|
76
|
-
|
75
|
+
rejected = posts.reject! { |hash| hash['type'] == 'playlist' }
|
76
|
+
puts Paint["Was skipped #{rejected.length} playlist(s) (nehm doesn't download playlists)", :yellow] if rejected
|
77
|
+
|
78
|
+
posts.map! { |hash| Track.new(hash['track']) }
|
79
|
+
end
|
77
80
|
end
|
78
81
|
end
|
data/lib/nehm/user_manager.rb
CHANGED
@@ -1,59 +1,61 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module Nehm
|
2
|
+
module UserManager
|
3
|
+
def self.user
|
4
|
+
@temp_user || default_user
|
5
|
+
end
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def self.logged_in?
|
8
|
+
Cfg.key?(:default_id)
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def self.log_in
|
12
|
+
loop do
|
13
|
+
permalink = HighLine.new.ask('Please enter your permalink (last word in your profile url): ')
|
14
|
+
user = get_user(permalink)
|
15
|
+
if user
|
16
|
+
Cfg[:default_id] = user.id
|
17
|
+
Cfg[:permalink] = permalink
|
18
|
+
puts Paint['Successfully logged in!', :green]
|
19
|
+
break
|
20
|
+
else
|
21
|
+
puts Paint['Invalid permalink. Please enter correct permalink', :red]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.temp_user=(permalink)
|
13
27
|
user = get_user(permalink)
|
14
28
|
if user
|
15
|
-
|
16
|
-
Cfg[:permalink] = permalink
|
17
|
-
puts Paint['Successfully logged in!', :green]
|
18
|
-
break
|
29
|
+
@temp_user = User.new(user.id)
|
19
30
|
else
|
20
31
|
puts Paint['Invalid permalink. Please enter correct permalink', :red]
|
32
|
+
exit
|
21
33
|
end
|
22
34
|
end
|
23
|
-
end
|
24
35
|
|
25
|
-
|
26
|
-
user = get_user(permalink)
|
27
|
-
if user
|
28
|
-
@temp_user = User.new(user.id)
|
29
|
-
else
|
30
|
-
puts Paint['Invalid permalink. Please enter correct permalink', :red]
|
31
|
-
exit
|
32
|
-
end
|
33
|
-
end
|
36
|
+
module_function
|
34
37
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
exit
|
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
|
44
46
|
end
|
45
|
-
end
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
55
57
|
end
|
58
|
+
user
|
56
59
|
end
|
57
|
-
user
|
58
60
|
end
|
59
61
|
end
|