vk_music_loader 0.1.0 → 0.2.0
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/README.md +30 -6
- data/bin/vk_music_loader +1 -7
- data/lib/vk_music_loader.rb +20 -3
- data/lib/vk_music_loader/authorizer.rb +27 -4
- data/lib/vk_music_loader/songs_downloader.rb +68 -14
- data/lib/vk_music_loader/trash.rb +18 -8
- data/lib/vk_music_loader/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9487bed8735df5dec33b4295a2d70b28cec9d7f1
|
4
|
+
data.tar.gz: 3320b8a52fcf60e408c0aa412ab5f9508d87d8f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8da45f9d965ef76e98dc6e088354389d76c9bf47de021e3c740ecd16a4ac8aadc2810ff58d79775dff019c3d2ae87856e34acdef9a0b5107bac21f219b2af160
|
7
|
+
data.tar.gz: c852c6fc59de8494da3d92917d3be15f15d1b447e97a4de9d80ceae21ef2e76e5c10611d40dfa53c0a43ec2d0756bf82d5ac58694127520378ac0c94299c23e7
|
data/README.md
CHANGED
@@ -1,22 +1,46 @@
|
|
1
|
-
#
|
1
|
+
# VK Music Loader
|
2
2
|
|
3
|
+
<a href="https://vk.com"><img src="https://cdn2.iconfinder.com/data/icons/vkontakte-3/154/api-vk-vkontakte-programming-128.png" align="left" hspace="10" vspace="6" width="50" height="50"></a>
|
4
|
+
|
5
|
+
**VK Music Loader** is a simple CLI Ruby gem to download music from VK (ВКонта́кте) using easy and convenient way of authorization - [Implicit Flow](https://new.vk.com/dev/implicit_flow_user)
|
6
|
+
This gem aimed at Ruby 2.0 or later.
|
3
7
|
|
4
8
|
## Installation
|
5
9
|
|
6
|
-
```
|
7
|
-
gem install vk_music_loader
|
10
|
+
```sh
|
11
|
+
$ gem install vk_music_loader
|
8
12
|
```
|
9
13
|
|
10
14
|
## Usage
|
11
15
|
|
12
|
-
|
13
|
-
|
16
|
+
To login you will need [create Standalone Application](https://new.vk.com/editapp?act=create) or use the author's application (default APP ID: `5377636`)
|
17
|
+
|
18
|
+
```sh
|
19
|
+
$ vk_music_loader -id USER_OR_GROUP_ID
|
20
|
+
$ vk_music_loader -q QUERY_SEARCH
|
21
|
+
[ -app (or -app, --app, -application, --application) your_standalone_app_id (default: 5377636) ]
|
22
|
+
[ -count (or count, -count, --count, c, -c, --c) count_of_songs ]
|
23
|
+
[ -folder (or -folder, --folder, path, -path, --path, -p) folder_path_to_download_music (default: 'music') ]
|
24
|
+
[ -random (or --random, shuffle, -shuffle, --shuffle, -r) shuffle_download_flag (default: false) ]
|
14
25
|
```
|
15
26
|
|
27
|
+
If the song is already in the folder, it will not be downloaded.
|
28
|
+
## Usage examples
|
29
|
+
```sh
|
30
|
+
# Download all music from VK Public:
|
31
|
+
$ vk_music_loader -id -45172096
|
32
|
+
|
33
|
+
# Download 20 first songs from user in specified folder:
|
34
|
+
$ vk_music_loader -id 243556640 -с 20 -p '/Volumes/FLASHKA/music_in_da_bass_car'
|
35
|
+
|
36
|
+
# Download 4 random Eminem Song:
|
37
|
+
$ vk_music_loader -q 'Eminem' -c 4 -r
|
38
|
+
```
|
39
|
+

|
16
40
|
|
17
41
|
## Contributing
|
18
42
|
|
19
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
43
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/m1neral/vk_music_loader.
|
20
44
|
|
21
45
|
|
22
46
|
## License
|
data/bin/vk_music_loader
CHANGED
@@ -2,10 +2,4 @@
|
|
2
2
|
|
3
3
|
require 'vk_music_loader'
|
4
4
|
|
5
|
-
|
6
|
-
o.integer 'app', '-app', '--app', '-application', '-application', default: 5377636 # author's application (you can use it)
|
7
|
-
o.integer 'id', '-id', '--id', '-user-id', '--user-id', '-group-id', '--group-id'
|
8
|
-
o.string 'folder', '-folder', '--folder', 'path', '-path', '--path', default: 'audio'
|
9
|
-
end
|
10
|
-
|
11
|
-
VkMusicLoader.call(opts)
|
5
|
+
VkMusicLoader.call
|
data/lib/vk_music_loader.rb
CHANGED
@@ -14,8 +14,25 @@ require 'vk_music_loader/authorizer'
|
|
14
14
|
require 'vk_music_loader/songs_downloader'
|
15
15
|
|
16
16
|
module VkMusicLoader
|
17
|
-
def self.call
|
18
|
-
|
19
|
-
|
17
|
+
def self.call
|
18
|
+
begin
|
19
|
+
opts = Slop.parse uppress_errors: true do |o|
|
20
|
+
o.integer 'app', '-app', '--app', '-application', '-application', default: 5377636 # author's application (you can use it)
|
21
|
+
o.integer 'id', '-id', '--id', '-user-id', '--user-id', '-group-id', '--group-id'
|
22
|
+
o.string 'query', '-query', '--query', '-q', 'search', '-search', '--search'
|
23
|
+
o.integer 'count', '-count', '--count', 'c', '-c', '--c'
|
24
|
+
o.string 'folder', '-folder', '--folder', 'path', '-path', '--path', '-p', default: 'audio'
|
25
|
+
o.bool 'random', '-random', '--random', 'shuffle', '-shuffle', '--shuffle', '-r'
|
26
|
+
end
|
27
|
+
|
28
|
+
if opts[:id] || opts[:query]
|
29
|
+
auth_token = VkMusicLoader::Authorizer.new(opts[:app]).perform
|
30
|
+
VkMusicLoader::SongsDownloader.new(auth_token, opts).perform
|
31
|
+
else
|
32
|
+
puts 'No user id or group id or query'
|
33
|
+
end
|
34
|
+
rescue Slop::Error => e
|
35
|
+
puts e.message
|
36
|
+
end
|
20
37
|
end
|
21
38
|
end
|
@@ -1,6 +1,14 @@
|
|
1
1
|
module VkMusicLoader
|
2
2
|
class Authorizer
|
3
|
-
AUTH_FILE_PATH = File.expand_path('~') + '/.
|
3
|
+
AUTH_FILE_PATH = File.expand_path('~') + '/.vk_music_loader/auth_data'
|
4
|
+
|
5
|
+
AUTHORIZE_API_PATH = 'https://oauth.vk.com/authorize'
|
6
|
+
QUERY_PARAMS = {
|
7
|
+
scope: 'audio',
|
8
|
+
redirect_uri: 'http://oauth.vk.com/blank.html',
|
9
|
+
display: 'page',
|
10
|
+
response_type: 'token'
|
11
|
+
}
|
4
12
|
|
5
13
|
def initialize(app_id)
|
6
14
|
@app_id = app_id
|
@@ -14,15 +22,30 @@ module VkMusicLoader
|
|
14
22
|
|
15
23
|
attr_reader :app_id
|
16
24
|
|
17
|
-
def
|
18
|
-
|
25
|
+
def query_params
|
26
|
+
QUERY_PARAMS.merge(client_id: app_id)
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_uri
|
30
|
+
uri = URI(AUTHORIZE_API_PATH)
|
31
|
+
uri.query = URI.encode_www_form(query_params)
|
32
|
+
uri
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_auth_params_from_browser_bar(uri)
|
19
36
|
ARGV.clear
|
37
|
+
|
38
|
+
Launchy.open(uri)
|
20
39
|
puts 'Paste full URL from browser bar and press ENTER: '
|
21
40
|
CGI.parse(URI(gets.chomp.strip).fragment)
|
22
41
|
end
|
23
42
|
|
24
43
|
def save_auth_params_to_file
|
25
|
-
auth_params = get_auth_params_from_browser_bar
|
44
|
+
auth_params = get_auth_params_from_browser_bar(build_uri)
|
45
|
+
|
46
|
+
dir_path = File.dirname(AUTH_FILE_PATH)
|
47
|
+
Dir.mkdir(dir_path) unless File.exists?(dir_path)
|
48
|
+
|
26
49
|
auth_file = File.open(AUTH_FILE_PATH, 'w')
|
27
50
|
auth_file.puts(Time.new + auth_params['expires_in'].first.to_i)
|
28
51
|
auth_file.puts(auth_params['access_token'].first)
|
@@ -1,49 +1,103 @@
|
|
1
1
|
module VkMusicLoader
|
2
2
|
class SongsDownloader
|
3
|
-
|
3
|
+
API_AUDIO_METHOD_PATHS = {
|
4
|
+
get: 'https://api.vk.com/method/audio.get',
|
5
|
+
search: 'https://api.vk.com/method/audio.search'
|
6
|
+
}
|
7
|
+
|
8
|
+
QUERY_PARAMS = {
|
9
|
+
v: '5.53'
|
10
|
+
}
|
11
|
+
|
12
|
+
def initialize(auth_token, opts)
|
4
13
|
@auth_token = auth_token
|
5
|
-
@
|
6
|
-
@audio_folder_path = audio_folder_path
|
14
|
+
@opts = opts
|
7
15
|
end
|
8
16
|
|
9
17
|
def perform
|
10
|
-
|
18
|
+
raw_playlist = get_raw_playlist
|
19
|
+
|
20
|
+
if raw_playlist['error']
|
21
|
+
puts raw_playlist['error']['error_msg']
|
22
|
+
else
|
23
|
+
download_songs(get_milled_playlist(raw_playlist))
|
24
|
+
end
|
11
25
|
end
|
12
26
|
|
13
27
|
private
|
14
28
|
|
15
|
-
attr_reader :auth_token, :
|
29
|
+
attr_reader :auth_token, :opts
|
30
|
+
|
31
|
+
def query_params
|
32
|
+
merged_query_params = QUERY_PARAMS.merge(access_token: auth_token)
|
33
|
+
merged_query_params[:owner_id] = opts[:id] unless opts[:query]
|
34
|
+
merged_query_params[:q] = opts[:query] unless opts[:id]
|
35
|
+
merged_query_params[:count] = 300 if opts[:query]
|
36
|
+
# In other cases, do not set the number of audios, because bug: https://new.vk.com/bugs?act=show&id=5502832_1
|
16
37
|
|
17
|
-
|
18
|
-
|
38
|
+
merged_query_params
|
39
|
+
end
|
40
|
+
|
41
|
+
def audio_method_path
|
42
|
+
if opts[:id]
|
43
|
+
API_AUDIO_METHOD_PATHS[:get]
|
44
|
+
elsif opts[:query]
|
45
|
+
API_AUDIO_METHOD_PATHS[:search]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def build_uri
|
50
|
+
uri = URI(audio_method_path)
|
51
|
+
uri.query = URI.encode_www_form(query_params)
|
52
|
+
uri
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_http(uri)
|
56
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
19
57
|
http.use_ssl = true
|
20
58
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
59
|
+
http
|
60
|
+
end
|
21
61
|
|
22
|
-
|
23
|
-
|
62
|
+
def get_raw_playlist
|
63
|
+
uri = build_uri
|
64
|
+
req = Net::HTTP::Get.new(uri)
|
65
|
+
res = build_http(uri).request(req)
|
24
66
|
|
25
67
|
JSON.parse(res.body)
|
26
68
|
end
|
27
69
|
|
70
|
+
def get_milled_playlist(raw_playlist)
|
71
|
+
songs = raw_playlist['response']['items']
|
72
|
+
songs_count = opts[:count] || songs.count
|
73
|
+
|
74
|
+
opts[:random] ? songs.sample(songs_count) : songs.take(songs_count)
|
75
|
+
end
|
76
|
+
|
28
77
|
def download_songs(playlist)
|
29
|
-
Dir.mkdir(
|
78
|
+
Dir.mkdir(opts[:folder]) unless File.exists?(opts[:folder])
|
30
79
|
|
31
|
-
|
80
|
+
downloads_count = 0
|
32
81
|
|
33
|
-
|
82
|
+
playlist.each do |song|
|
34
83
|
song_url = URI.parse(song['url'])
|
35
|
-
file_name = "#{song['artist']} - #{song['title']}.mp3
|
36
|
-
file_path = "#{
|
84
|
+
file_name = "#{song['artist']} - #{song['title']}".slice(0, 100).gsub(/[\x00\/\\:\*\?\"<>\|]/, '_') + '.mp3'
|
85
|
+
file_path = "#{opts[:folder]}/#{file_name}"
|
37
86
|
|
38
87
|
unless File.file?(file_path)
|
39
88
|
File.open(file_path, 'w') do |f|
|
40
89
|
f.write Net::HTTP.get(song_url)
|
41
90
|
f.close
|
42
91
|
|
92
|
+
downloads_count += 1
|
43
93
|
puts "Downloaded: #{file_name}"
|
44
94
|
end
|
45
95
|
end
|
46
96
|
end
|
97
|
+
|
98
|
+
puts "-----> Downloaded #{downloads_count} songs in #{opts[:folder]}"
|
99
|
+
puts "-----> The other #{playlist.count - downloads_count} songs have been already downloaded" if
|
100
|
+
playlist.count - downloads_count > 0
|
47
101
|
end
|
48
102
|
end
|
49
103
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
require 'rubygems'
|
3
2
|
require 'time'
|
4
3
|
require 'cgi'
|
@@ -12,11 +11,22 @@ require 'launchy'
|
|
12
11
|
require '../vk_music_loader/authorizer'
|
13
12
|
require '../vk_music_loader/songs_downloader'
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
begin
|
15
|
+
opts = Slop.parse uppress_errors: true do |o|
|
16
|
+
o.integer 'app', '-app', '--app', '-application', '-application', default: 5377636 # author's application (you can use it)
|
17
|
+
o.integer 'id', '-id', '--id', '-user-id', '--user-id', '-group-id', '--group-id'
|
18
|
+
o.string 'query', '-query', '--query', '-q', 'search', '-search', '--search'
|
19
|
+
o.integer 'count', '-count', '--count', 'c', '-c', '--c'
|
20
|
+
o.string 'folder', '-folder', '--folder', 'path', '-path', '--path', '-p', default: 'audio'
|
21
|
+
o.bool 'random', '-random', '--random', 'shuffle', '-shuffle', '--shuffle', '-r'
|
22
|
+
end
|
20
23
|
|
21
|
-
|
22
|
-
VkMusicLoader::
|
24
|
+
if opts[:id] || opts[:query]
|
25
|
+
auth_token = VkMusicLoader::Authorizer.new(opts[:app]).perform
|
26
|
+
VkMusicLoader::SongsDownloader.new(auth_token, opts).perform
|
27
|
+
else
|
28
|
+
puts 'No user id or group id or query'
|
29
|
+
end
|
30
|
+
rescue Slop::Error => e
|
31
|
+
puts e.message
|
32
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vk_music_loader
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anatoly Ryabov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: launchy
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '4.
|
33
|
+
version: '4.4'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '4.
|
40
|
+
version: '4.4'
|
41
41
|
description: Download your VK playlist in one command
|
42
42
|
email:
|
43
43
|
- a.ryabov1993@gmail.com
|