vk_music 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/vk_music/client.rb +58 -21
- data/lib/vk_music/constants.rb +3 -2
- data/lib/vk_music/playlist.rb +13 -5
- data/lib/vk_music/utility.rb +2 -2
- data/test/test_find.rb +13 -1
- data/test/test_playlist.rb +6 -0
- data/vk_music.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c25c28560c85999aeffe7b23070762fe875600eb32fde5758c5d02041a9d079b
|
4
|
+
data.tar.gz: 64b80f5fe01c1e8bf19ef95c6660ccbb5043b5fb07257c8590bb93f08af2b7e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bb0b4d69ad1699d760ab30e3e6149b3440318ab7edf2c42e2e17172d18c564f4922fde227089e2dc828658c34689599f93759fa5ea954af350f35747ba32cd2
|
7
|
+
data.tar.gz: 4cb018f20a3cae069616cb1f339703b9f9975f7939a1924225d1840562f30c9f759a21386f00729a499193bd11a3af7339e9b9860ed148cb6f6f3bdae834c0ae
|
data/lib/vk_music/client.rb
CHANGED
@@ -50,28 +50,42 @@ module VkMusic
|
|
50
50
|
#@!group Loading audios
|
51
51
|
|
52
52
|
##
|
53
|
-
#
|
53
|
+
# @!macro [new] find__options
|
54
|
+
# @option options [Symbol] :type (:audio) what to search for (you can find available values for this option above).
|
54
55
|
#
|
55
|
-
#
|
56
|
+
# Search for audio or playlist.
|
57
|
+
#
|
58
|
+
# @note some audios and playlists might be removed from search.
|
56
59
|
#
|
57
60
|
# @todo search in group audios.
|
58
61
|
#
|
59
|
-
#
|
62
|
+
# Possible values of +type+ option:
|
63
|
+
# * +:audio+ - search for audios. Returns up to 50 audios.
|
64
|
+
# * +:playlist+ - search for playlists. Returns up to 6 playlists *without* audios (Loaded with +up_to: 0+ option).
|
65
|
+
# You can get all the audios of selected playlist calling {Client#playlist} method with gained info.
|
66
|
+
#
|
67
|
+
# @overload find(query, options)
|
60
68
|
# @param query [String] string to search for.
|
69
|
+
# @macro options_hash_param
|
70
|
+
# @macro find__options
|
61
71
|
#
|
62
72
|
# @overload find(options)
|
63
73
|
# @macro options_hash_param
|
64
74
|
# @option options [String] :query string to search for.
|
75
|
+
# @macro find__options
|
65
76
|
#
|
66
|
-
# @return [Array<Audio>] array with audios matching given string.
|
67
|
-
# Possibly contains audios without download URL.
|
68
|
-
def find(
|
77
|
+
# @return [Array<Audio>, Array<Playlist>] array with audios or playlists matching given string.
|
78
|
+
# Possibly empty. Possibly contains audios or playlists without download URL.
|
79
|
+
def find(*args)
|
69
80
|
begin
|
70
|
-
case
|
71
|
-
when String
|
72
|
-
|
73
|
-
|
74
|
-
query =
|
81
|
+
case
|
82
|
+
when (args.size == 1 && String === args[0]) ||
|
83
|
+
(args.size == 2 && String === args[0] && Hash === args[1])
|
84
|
+
options = args[1] || {}
|
85
|
+
query = args[0]
|
86
|
+
when args.size == 1 && Hash === args[0]
|
87
|
+
options = args[0]
|
88
|
+
query = options[:query].to_s
|
75
89
|
else
|
76
90
|
raise
|
77
91
|
end
|
@@ -79,10 +93,21 @@ module VkMusic
|
|
79
93
|
raise ArgumentError, "Bad arguments", caller
|
80
94
|
end
|
81
95
|
|
96
|
+
options[:type] ||= :audio
|
97
|
+
|
82
98
|
uri = URI(Constants::URL::VK[:audios])
|
83
|
-
uri.query = Utility.hash_to_params({ "act" => "search", "q" => query.to_s })
|
84
99
|
|
85
|
-
|
100
|
+
case options[:type]
|
101
|
+
when :audio
|
102
|
+
uri.query = Utility.hash_to_params({ "act" => "search", "q" => query })
|
103
|
+
audios__from_page(uri)
|
104
|
+
when :playlist
|
105
|
+
uri.query = Utility.hash_to_params({ "q" => query, "tab" => "global" })
|
106
|
+
urls = playlist_urls__from_page(uri)
|
107
|
+
urls.map { |url| playlist(url, up_to: 0, with_url: false) }
|
108
|
+
else
|
109
|
+
raise ArgumentError, "Bad :type option", caller
|
110
|
+
end
|
86
111
|
end
|
87
112
|
alias search find
|
88
113
|
|
@@ -130,7 +155,7 @@ module VkMusic
|
|
130
155
|
raise ArgumentError, "Bad arguments", caller
|
131
156
|
end
|
132
157
|
|
133
|
-
options[:up_to]
|
158
|
+
options[:up_to] ||= Constants::MAXIMUM_PLAYLIST_SIZE
|
134
159
|
options[:with_url] = true if options[:with_url].nil?
|
135
160
|
|
136
161
|
if options[:with_url]
|
@@ -350,8 +375,8 @@ module VkMusic
|
|
350
375
|
rescue Exception => error
|
351
376
|
raise Exceptions::ParseError, "Unable to get user or group ID. Custom ID: #{str}. Error: #{error.message}", caller
|
352
377
|
end
|
353
|
-
|
354
|
-
|
378
|
+
else
|
379
|
+
raise Exceptions::ParseError, "Unable to convert \"#{str}\" into ID", caller
|
355
380
|
end
|
356
381
|
id
|
357
382
|
end
|
@@ -565,9 +590,9 @@ module VkMusic
|
|
565
590
|
footer_node = first_page.at_css(".audioPlaylist__footer")
|
566
591
|
if footer_node
|
567
592
|
footer_match = footer_node.text.strip.match(/^\d+/)
|
568
|
-
|
593
|
+
real_size = footer_match ? footer_match[0].to_i : 0
|
569
594
|
else
|
570
|
-
|
595
|
+
real_size = 0
|
571
596
|
end
|
572
597
|
rescue Exception => error
|
573
598
|
raise Exceptions::ParseError, error.message, caller
|
@@ -577,7 +602,7 @@ module VkMusic
|
|
577
602
|
first_page_audios = audios__from_page(first_page)
|
578
603
|
|
579
604
|
# Check whether need to make additional requests
|
580
|
-
options[:up_to] =
|
605
|
+
options[:up_to] = real_size if (options[:up_to] < 0 || options[:up_to] > real_size)
|
581
606
|
list = first_page_audios[0, options[:up_to]]
|
582
607
|
while list.length < options[:up_to] do
|
583
608
|
playlist_page = load__page__playlist(owner_id, playlist_id, access_hash, offset: list.length)
|
@@ -590,6 +615,7 @@ module VkMusic
|
|
590
615
|
:access_hash => access_hash,
|
591
616
|
:title => title,
|
592
617
|
:subtitle => subtitle,
|
618
|
+
:real_size => real_size
|
593
619
|
})
|
594
620
|
end
|
595
621
|
|
@@ -608,8 +634,8 @@ module VkMusic
|
|
608
634
|
raise Exceptions::ParseError, error.message, caller
|
609
635
|
end
|
610
636
|
|
611
|
-
|
612
|
-
options[:up_to] =
|
637
|
+
real_size = first_data["totalCount"]
|
638
|
+
options[:up_to] = real_size if (options[:up_to] < 0 || options[:up_to] > real_size)
|
613
639
|
list = first_data_audios[0, options[:up_to]]
|
614
640
|
while list.length < options[:up_to] do
|
615
641
|
json = load__json__playlist_section(owner_id, playlist_id, access_hash,
|
@@ -625,9 +651,20 @@ module VkMusic
|
|
625
651
|
:access_hash => first_data["access_hash"],
|
626
652
|
:title => CGI.unescapeHTML(first_data["title"].to_s),
|
627
653
|
:subtitle => CGI.unescapeHTML(first_data["subtitle"].to_s),
|
654
|
+
:real_size => real_size
|
628
655
|
})
|
629
656
|
end
|
630
657
|
|
658
|
+
# Found playlist on *global* search page
|
659
|
+
def playlist_urls__from_page(obj)
|
660
|
+
page = obj.class == Mechanize::Page ? obj : load__page(obj)
|
661
|
+
begin
|
662
|
+
page.css(".AudioSerp__foundGlobal .AudioPlaylistSlider .al_playlist").map { |elem| elem.attribute("href").to_s }
|
663
|
+
rescue Exception => error
|
664
|
+
raise Exceptions::ParseError, error.message, caller
|
665
|
+
end
|
666
|
+
end
|
667
|
+
|
631
668
|
# Load audios from wall using JSON request.
|
632
669
|
def wall__json(owner_id, post_id, options)
|
633
670
|
if options[:up_to] < 0 || options[:up_to] > 91
|
data/lib/vk_music/constants.rb
CHANGED
@@ -24,7 +24,8 @@ module VkMusic
|
|
24
24
|
login: "https://m.vk.com/login",
|
25
25
|
login_action: "https://login.vk.com",
|
26
26
|
wall: "https://m.vk.com/wall",
|
27
|
-
audio_unavailable: "https://m.vk.com/mp3/audio_api_unavailable.mp3"
|
27
|
+
audio_unavailable: "https://m.vk.com/mp3/audio_api_unavailable.mp3",
|
28
|
+
profile_audios: "https://m.vk.com/audios",
|
28
29
|
}
|
29
30
|
|
30
31
|
end
|
@@ -63,7 +64,7 @@ module VkMusic
|
|
63
64
|
|
64
65
|
##
|
65
66
|
# Playlist URL regular expression.
|
66
|
-
VK_PLAYLIST_URL_POSTFIX = /.*audio_playlist(-?\d+)_(\d+)(?:(?:(
|
67
|
+
VK_PLAYLIST_URL_POSTFIX = /.*audio_playlist(-?\d+)_(\d+)(?:(?:(?:.*(?=&access_hash=)&access_hash=)|\/|%2F)([\da-z]+))?/
|
67
68
|
|
68
69
|
##
|
69
70
|
# Post URL regular expression #1.
|
data/lib/vk_music/playlist.rb
CHANGED
@@ -24,11 +24,17 @@ module VkMusic
|
|
24
24
|
##
|
25
25
|
# @return [String, nil] playlist subtitle. May be empty.
|
26
26
|
attr_reader :subtitle
|
27
|
+
|
28
|
+
##
|
29
|
+
# @return [Integer, nil] real size of playlist or +nil+ if unknown.
|
30
|
+
attr_reader :real_size
|
27
31
|
|
28
32
|
##
|
29
33
|
# @return [String] playlist description in Russian.
|
30
34
|
def to_s
|
31
|
-
(@subtitle ? "#{@subtitle} - " : "") +
|
35
|
+
(@subtitle && !@subtitle.empty? ? "#{@subtitle} - " : "") +
|
36
|
+
@title +
|
37
|
+
(@real_size ? "(#{self.length} из #{@real_size} аудиозаписей загружено)" : " (#{self.length} аудиозаписей)")
|
32
38
|
end
|
33
39
|
|
34
40
|
##
|
@@ -77,11 +83,12 @@ module VkMusic
|
|
77
83
|
#
|
78
84
|
# @param list [Array] list of audios in playlist.
|
79
85
|
#
|
80
|
-
# @option options [Integer] :id
|
81
|
-
# @option options [Integer] :owner_id
|
82
|
-
# @option options [String] :access_hash
|
86
|
+
# @option options [Integer, nil] :id
|
87
|
+
# @option options [Integer, nil] :owner_id
|
88
|
+
# @option options [String, nil] :access_hash
|
83
89
|
# @option options [String] :title
|
84
|
-
# @option options [String] :subtitle
|
90
|
+
# @option options [String, nil] :subtitle
|
91
|
+
# @option options [Integer, nil] :real_size
|
85
92
|
def initialize(list, options = {})
|
86
93
|
raise ArgumentError, "Bad arguments", caller unless list.class == Array
|
87
94
|
# Saving list
|
@@ -93,6 +100,7 @@ module VkMusic
|
|
93
100
|
@access_hash = Utility.unless_nil_to String, options[:access_hash]
|
94
101
|
@title = options[:title].to_s
|
95
102
|
@subtitle = Utility.unless_nil_to String, options[:subtitle]
|
103
|
+
@real_size = Utility.unless_nil_to Integer, options[:real_size]
|
96
104
|
end
|
97
105
|
|
98
106
|
end
|
data/lib/vk_music/utility.rb
CHANGED
data/test/test_find.rb
CHANGED
@@ -36,8 +36,20 @@ class TestVkMusic < MiniTest::Test
|
|
36
36
|
|
37
37
|
def test_find_bad_arg
|
38
38
|
assert_raises(ArgumentError) do
|
39
|
-
CLIENT.search("Good music",
|
39
|
+
CLIENT.search("Good music", "or not")
|
40
40
|
end
|
41
41
|
end
|
42
|
+
|
43
|
+
def test_find_playlist
|
44
|
+
results = CLIENT.find("OST", type: :playlist)
|
45
|
+
refute_empty(results, "There must be lot of playlists")
|
46
|
+
assert_empty(results[0], "Album must be empty")
|
47
|
+
refute_equal(0, results[0].real_size, "Album must actually have some audios")
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_find_unexisting_playlist
|
51
|
+
results = CLIENT.find("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", type: :playlist)
|
52
|
+
assert_empty(results, "There must be no results for such query")
|
53
|
+
end
|
42
54
|
|
43
55
|
end
|
data/test/test_playlist.rb
CHANGED
@@ -18,6 +18,12 @@ class TestVkMusic < MiniTest::Test
|
|
18
18
|
refute_empty(pl[-1].url, "Audio must have download url")
|
19
19
|
end
|
20
20
|
|
21
|
+
def test_big_url
|
22
|
+
pl = CLIENT.playlist("https://m.vk.com/audio?act=audio_playlist256492540_83617715&from=search_owned_playlist&access_hash=b8d408241bcfb60583&back_url=%2Faudios-39786657%3Fq%3Dmashup%26tab%3Downed&back_hash=76ef9186ac6f248a27")
|
23
|
+
refute_empty(pl, "This playlist must not be empty")
|
24
|
+
assert_instance_of(VkMusic::Audio, pl[0], "Playlist members must be of class Audio")
|
25
|
+
end
|
26
|
+
|
21
27
|
def test_playlist_small_with_options
|
22
28
|
pl = CLIENT.playlist(owner_id: -37661843, playlist_id: 1, access_hash: "0e420c32c8b69e6637", with_url: false)
|
23
29
|
refute_empty(pl, "This playlist must not be empty")
|
data/vk_music.gemspec
CHANGED
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
|
|
2
2
|
s.name = "vk_music"
|
3
3
|
s.summary = "Provides interface to work with VK music via HTTP requests"
|
4
4
|
s.description = "Library to work with audios on popular Russian social network vk.com. VK disabled their public API for audios, so it is now necessary to use parsers instead."
|
5
|
-
s.version = "2.
|
5
|
+
s.version = "2.1.0"
|
6
6
|
s.author = "Kuznetsov Vladislav"
|
7
7
|
s.email = "fizvlad@mail.ru"
|
8
8
|
s.homepage = "https://github.com/fizvlad/vk-music-rb"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vk_music
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kuznetsov Vladislav
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-08-
|
11
|
+
date: 2019-08-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mechanize
|