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
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nehm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Albert Nigmatzianov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bogy
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: certifi
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,47 +39,47 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: colored
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0
|
47
|
+
version: '0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: faraday
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 0.9.1
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 0.9.1
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: highline
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 1.7.2
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 1.7.2
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: soundcloud
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -133,15 +133,21 @@ files:
|
|
133
133
|
- lib/nehm/artwork.rb
|
134
134
|
- lib/nehm/cfg.rb
|
135
135
|
- lib/nehm/client.rb
|
136
|
-
- lib/nehm/
|
137
|
-
- lib/nehm/
|
138
|
-
- lib/nehm/
|
136
|
+
- lib/nehm/command.rb
|
137
|
+
- lib/nehm/command_manager.rb
|
138
|
+
- lib/nehm/commands/configure_command.rb
|
139
|
+
- lib/nehm/commands/dl_command.rb
|
140
|
+
- lib/nehm/commands/get_command.rb
|
141
|
+
- lib/nehm/commands/help_command.rb
|
142
|
+
- lib/nehm/commands/version_command.rb
|
143
|
+
- lib/nehm/option_parser.rb
|
139
144
|
- lib/nehm/os.rb
|
140
145
|
- lib/nehm/path_manager.rb
|
141
146
|
- lib/nehm/playlist.rb
|
142
147
|
- lib/nehm/playlist_manager.rb
|
143
148
|
- lib/nehm/track.rb
|
144
|
-
- lib/nehm/
|
149
|
+
- lib/nehm/tracks.rb
|
150
|
+
- lib/nehm/ui.rb
|
145
151
|
- lib/nehm/user_manager.rb
|
146
152
|
- lib/nehm/version.rb
|
147
153
|
- nehm.gemspec
|
@@ -165,7 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
171
|
version: '0'
|
166
172
|
requirements: []
|
167
173
|
rubyforge_project:
|
168
|
-
rubygems_version: 2.4.
|
174
|
+
rubygems_version: 2.4.8
|
169
175
|
signing_key:
|
170
176
|
specification_version: 4
|
171
177
|
summary: Convenient way to download tracks from SoundCloud via terminal
|
data/lib/nehm/configure.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
module Nehm
|
2
|
-
# Configure module responds to 'nehm configure' command
|
3
|
-
module Configure
|
4
|
-
def self.menu
|
5
|
-
loop do
|
6
|
-
puts "Download path: #{Paint[Cfg[:dl_path], :magenta]}" if Cfg[:dl_path]
|
7
|
-
puts "Permalink: #{Paint[Cfg[:permalink], :cyan]}" if Cfg[:permalink]
|
8
|
-
puts "iTunes playlist: #{Paint[PlaylistManager.playlist, :cyan]}" if !OS.linux? && PlaylistManager.playlist
|
9
|
-
puts "\n"
|
10
|
-
|
11
|
-
HighLine.new.choose do |menu|
|
12
|
-
menu.prompt = Paint['Choose setting', :yellow]
|
13
|
-
|
14
|
-
menu.choice('Edit download path'.freeze) { PathManager.set_dl_path }
|
15
|
-
menu.choice('Edit permalink'.freeze) { UserManager.log_in }
|
16
|
-
menu.choice('Edit iTunes playlist'.freeze) { PlaylistManager.set_playlist } unless OS.linux?
|
17
|
-
menu.choice('Exit'.freeze) { puts 'Goodbye!'; exit }
|
18
|
-
end
|
19
|
-
sleep(1)
|
20
|
-
puts "\n"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/lib/nehm/get.rb
DELETED
@@ -1,100 +0,0 @@
|
|
1
|
-
require 'taglib'
|
2
|
-
|
3
|
-
module Nehm
|
4
|
-
# Get module responds to 'nehm get/dl ...' commands
|
5
|
-
module Get
|
6
|
-
def self.[](get_or_dl, args)
|
7
|
-
# Processing arguments
|
8
|
-
options = [{ name: 'to', method: PathManager.method(:temp_dl_path=) },
|
9
|
-
{ name: 'from', method: UserManager.method(:temp_user=) },
|
10
|
-
{ name: 'playlist', method: PlaylistManager.method(:temp_playlist=) }]
|
11
|
-
|
12
|
-
options.each do |option|
|
13
|
-
if args.include? option[:name]
|
14
|
-
index = args.index(option[:name])
|
15
|
-
value = args[index + 1]
|
16
|
-
args.delete_at(index + 1)
|
17
|
-
args.delete_at(index)
|
18
|
-
|
19
|
-
option[:method].call(value)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
puts 'Getting information about track(s)'
|
24
|
-
user = UserManager.user
|
25
|
-
tracks = []
|
26
|
-
tracks +=
|
27
|
-
case args.last
|
28
|
-
when 'like'
|
29
|
-
user.likes(1)
|
30
|
-
when 'post'
|
31
|
-
user.posts(1)
|
32
|
-
when 'likes'
|
33
|
-
count = args[-2].to_i
|
34
|
-
user.likes(count)
|
35
|
-
when 'posts'
|
36
|
-
count = args[-2].to_i
|
37
|
-
user.posts(count)
|
38
|
-
when %r{https:\/\/soundcloud.com\/}
|
39
|
-
track_from_url(args.last)
|
40
|
-
when nil
|
41
|
-
puts Paint['You must provide option', :red]
|
42
|
-
puts "Input #{Paint['nehm help', :yellow]} for help"
|
43
|
-
exit
|
44
|
-
else
|
45
|
-
puts Paint["Invalid argument(s) '#{args.last}'", :red]
|
46
|
-
puts "Input #{Paint['nehm help', :yellow]} for help"
|
47
|
-
exit
|
48
|
-
end
|
49
|
-
|
50
|
-
tracks.each do |track|
|
51
|
-
if track.streamable?
|
52
|
-
dl(track)
|
53
|
-
dl(track.artwork)
|
54
|
-
tag(track)
|
55
|
-
track.artwork.suicide
|
56
|
-
PlaylistManager.playlist.add_track(track.file_path) if PlaylistManager.playlist && get_or_dl == :get && !OS.linux?
|
57
|
-
else
|
58
|
-
puts "#{Paint['Track', :yellow]} #{Paint[track.name, :cyan]} #{Paint['undownloadable', :yellow]}"
|
59
|
-
end
|
60
|
-
end
|
61
|
-
puts Paint['Done!', :green]
|
62
|
-
end
|
63
|
-
|
64
|
-
module_function
|
65
|
-
|
66
|
-
def track_from_url(url)
|
67
|
-
hash = Client.get('/resolve', url: url)
|
68
|
-
[*Track.new(hash)]
|
69
|
-
end
|
70
|
-
|
71
|
-
def dl(arg)
|
72
|
-
puts 'Downloading ' + arg.name
|
73
|
-
path = arg.file_path
|
74
|
-
url = arg.url
|
75
|
-
command = "curl -# -o \"#{path}\" -L #{url}"
|
76
|
-
`#{command}`
|
77
|
-
end
|
78
|
-
|
79
|
-
def tag(track)
|
80
|
-
path = track.file_path
|
81
|
-
TagLib::MPEG::File.open(path) do |file|
|
82
|
-
puts 'Setting tags'
|
83
|
-
tag = file.id3v2_tag
|
84
|
-
tag.artist = track.artist
|
85
|
-
tag.title = track.title
|
86
|
-
tag.year = track.year
|
87
|
-
|
88
|
-
# Adding artwork
|
89
|
-
apic = TagLib::ID3v2::AttachedPictureFrame.new
|
90
|
-
apic.mime_type = 'image/jpeg'
|
91
|
-
apic.description = 'Cover'
|
92
|
-
apic.type = TagLib::ID3v2::AttachedPictureFrame::FrontCover
|
93
|
-
apic.picture = File.open(track.artwork.file_path, 'rb') { |f| f.read }
|
94
|
-
tag.add_frame(apic)
|
95
|
-
|
96
|
-
file.save
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
data/lib/nehm/help.rb
DELETED
@@ -1,93 +0,0 @@
|
|
1
|
-
module Nehm
|
2
|
-
# Help module responds to 'nehm help ...' command
|
3
|
-
module Help
|
4
|
-
def self.available_commands
|
5
|
-
puts <<-HELP.gsub(/^ {8}/, '')
|
6
|
-
#{Paint['nehm', :green]} is a console tool, which downloads, sets IDv3 tags and adds to your iTunes library your SoundCloud posts or likes in convenient way
|
7
|
-
|
8
|
-
#{Paint['Avalaible nehm commands:', :yellow]}
|
9
|
-
#{Paint['get', :green]} Download, set tags and add to your iTunes library last post or like from your profile
|
10
|
-
#{Paint['dl', :green]} Download and set tags last post or like from your profile
|
11
|
-
#{Paint['configure', :green]} Configure application
|
12
|
-
#{Paint['version', :green]} Show version of installed nehm
|
13
|
-
|
14
|
-
See #{Paint['nehm help [command]', :yellow]} to read about a specific subcommand
|
15
|
-
HELP
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.show(command)
|
19
|
-
case command
|
20
|
-
when 'get', 'dl', 'configure', 'permalink'
|
21
|
-
Help.send(command)
|
22
|
-
when nil
|
23
|
-
Help.available_commands
|
24
|
-
else
|
25
|
-
puts Paint["Command '#{command}' doesn't exist", :red]
|
26
|
-
puts "\n"
|
27
|
-
Help.available_commands
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
module_function
|
32
|
-
|
33
|
-
def configure
|
34
|
-
puts <<-CONFIGURE.gsub(/^ {8}/, '')
|
35
|
-
#{Paint['Input:', :yellow]} nehm configure
|
36
|
-
|
37
|
-
#{Paint['Summary:', :yellow]}
|
38
|
-
Configuring nehm app
|
39
|
-
CONFIGURE
|
40
|
-
end
|
41
|
-
|
42
|
-
def dl
|
43
|
-
puts <<-DL.gsub(/^ {8}/, '')
|
44
|
-
#{Paint['Input:', :yellow]} nehm dl OPTIONS [from PERMALINK] [to PATH_TO_DIRECTORY] [playlist ITUNES_PLAYLIST]
|
45
|
-
|
46
|
-
#{Paint['Summary:', :yellow]}
|
47
|
-
Download tracks from SoundCloud and setting tags
|
48
|
-
|
49
|
-
#{Paint['OPTIONS:', :yellow]}
|
50
|
-
#{Paint['post', :green]} Do same with last post (track or repost) from your profile
|
51
|
-
#{Paint['<number> posts', :green]} Do same with last <number> posts from your profile
|
52
|
-
#{Paint['like', :green]} Do same with your last like
|
53
|
-
#{Paint['<number> likes', :green]} Do same with your last <number> likes
|
54
|
-
#{Paint['url', :magenta]} Do same with track from entered url
|
55
|
-
|
56
|
-
#{Paint['Extra options:', :yellow]}
|
57
|
-
#{Paint['from PERMALINK', :green]} Do aforecited operations from custom user profile
|
58
|
-
#{Paint['to PATH_TO_DIRECTORY', :green]} Do aforecited operations to custom directory
|
59
|
-
#{Paint['to current', :green]} Do aforecited operations to current working directory
|
60
|
-
#{Paint['playlist ITUNES_PLAYLIST', :green]} Do aforecited operations to custom iTunes playlist
|
61
|
-
DL
|
62
|
-
end
|
63
|
-
|
64
|
-
def get
|
65
|
-
puts <<-GET.gsub(/^ {8}/, '')
|
66
|
-
#{Paint['Input:', :yellow]} nehm get OPTIONS [from PERMALINK] [to PATH_TO_DIRECTORY] [playlist ITUNES_PLAYLIST]
|
67
|
-
|
68
|
-
#{Paint['Summary:', :yellow]}
|
69
|
-
Download tracks, set tags and add to your iTunes library tracks from Soundcloud
|
70
|
-
|
71
|
-
#{Paint['OPTIONS:', :yellow]}
|
72
|
-
#{Paint['post', :green]} Do same with last post (track or repost) from your profile
|
73
|
-
#{Paint['<number> posts', :green]} Do same with last <number> posts from your profile
|
74
|
-
#{Paint['like', :green]} Do same with your last like
|
75
|
-
#{Paint['<number> likes', :green]} Do same with your last <number> likes
|
76
|
-
#{Paint['url', :magenta]} Do same with track from entered url
|
77
|
-
|
78
|
-
#{Paint['Extra options:', :yellow]}
|
79
|
-
#{Paint['from PERMALINK', :green]} Do aforecited operations from profile with PERMALINK
|
80
|
-
#{Paint['to PATH_TO_DIRECTORY', :green]} Do aforecited operations to custom directory
|
81
|
-
#{Paint['to current', :green]} Do aforecited operations to current working directory
|
82
|
-
#{Paint['playlist ITUNES_PLAYLIST', :green]} Do aforecited operations to custom iTunes playlist
|
83
|
-
GET
|
84
|
-
end
|
85
|
-
|
86
|
-
def permalink
|
87
|
-
puts <<-PERM.gsub(/^ {8}/, '')
|
88
|
-
Permalink is the last word in your profile url
|
89
|
-
Example: for profile url #{Paint['soundcloud.com/qwerty', :magenta]} permalink is #{Paint['qwerty', :magenta]}
|
90
|
-
PERM
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
data/lib/nehm/user.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'faraday'
|
3
|
-
|
4
|
-
module Nehm
|
5
|
-
class User
|
6
|
-
# Max limit of tracks for correct SoundCloud requests
|
7
|
-
SOUNDCLOUD_MAX_LIMIT = 180
|
8
|
-
|
9
|
-
def initialize(id)
|
10
|
-
@id = id
|
11
|
-
end
|
12
|
-
|
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
|
19
|
-
|
20
|
-
d = count / SOUNDCLOUD_MAX_LIMIT
|
21
|
-
m = count % SOUNDCLOUD_MAX_LIMIT
|
22
|
-
d = m == 0 ? d : d + 1
|
23
|
-
|
24
|
-
likes = []
|
25
|
-
d.times do |i|
|
26
|
-
limit = count > SOUNDCLOUD_MAX_LIMIT ? SOUNDCLOUD_MAX_LIMIT : count
|
27
|
-
count -= SOUNDCLOUD_MAX_LIMIT
|
28
|
-
|
29
|
-
likes += Client.get("/users/#{@id}/favorites?limit=#{limit}&offset=#{(i)*SOUNDCLOUD_MAX_LIMIT}")
|
30
|
-
end
|
31
|
-
|
32
|
-
if likes.empty?
|
33
|
-
puts Paint['There are no likes yet :(', :red]
|
34
|
-
exit
|
35
|
-
end
|
36
|
-
|
37
|
-
likes.map! { |hash| Track.new(hash) }
|
38
|
-
end
|
39
|
-
|
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
|
47
|
-
|
48
|
-
d = count / SOUNDCLOUD_MAX_LIMIT
|
49
|
-
m = count % SOUNDCLOUD_MAX_LIMIT
|
50
|
-
d = m == 0 ? d : d + 1
|
51
|
-
|
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/')
|
55
|
-
|
56
|
-
posts = []
|
57
|
-
d.times do |i|
|
58
|
-
limit = count > SOUNDCLOUD_MAX_LIMIT ? SOUNDCLOUD_MAX_LIMIT : count
|
59
|
-
count -= SOUNDCLOUD_MAX_LIMIT
|
60
|
-
|
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
|
-
|
65
|
-
break if collection.nil?
|
66
|
-
|
67
|
-
posts += collection
|
68
|
-
end
|
69
|
-
|
70
|
-
if posts.empty?
|
71
|
-
puts Paint['There are no posts yet :(', :red]
|
72
|
-
exit
|
73
|
-
end
|
74
|
-
|
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
|
80
|
-
end
|
81
|
-
end
|