vk_music 3.1.2 → 3.1.7
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/Gemfile.lock +13 -12
- data/lib/vk_music/audio.rb +1 -1
- data/lib/vk_music/client.rb +101 -39
- data/lib/vk_music/constants.rb +1 -1
- data/lib/vk_music/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 49d94fb81d001d5d050d274f14ab6a3931467097adb46aa84601444fba4ac312
|
|
4
|
+
data.tar.gz: b8b6433c2373a1229bf5e27e31d8bc5c7d4ae01840b0620f99e715707ddc665e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ee9d28c4ef87b6fc12865ec267aeca8ddb24a9275c6c231f42fc68c6390b8fb9bfa8759f3d0f3b6f17e1d8e4ba8880b32976f987c0bde5edb4c1c3856a0a2ab1
|
|
7
|
+
data.tar.gz: 48451ee22f080a93a0d8fea4fbb468f1c45b97bc089dc87675663d602092ba2fb255826ef3b127129b7d6fe8855751ee6bc3869e0c59ccc8e5e4c413eb9be45d
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
vk_music (3.1.
|
|
4
|
+
vk_music (3.1.7)
|
|
5
5
|
execjs (~> 2.7)
|
|
6
6
|
json (~> 2.0)
|
|
7
7
|
logger (~> 1.4)
|
|
@@ -11,14 +11,14 @@ PATH
|
|
|
11
11
|
GEM
|
|
12
12
|
remote: https://rubygems.org/
|
|
13
13
|
specs:
|
|
14
|
-
coderay (1.1.
|
|
14
|
+
coderay (1.1.3)
|
|
15
15
|
domain_name (0.5.20190701)
|
|
16
16
|
unf (>= 0.0.5, < 1.0.0)
|
|
17
17
|
execjs (2.7.0)
|
|
18
18
|
http-cookie (1.0.3)
|
|
19
19
|
domain_name (~> 0.5)
|
|
20
|
-
json (2.3.
|
|
21
|
-
logger (1.4.
|
|
20
|
+
json (2.3.1)
|
|
21
|
+
logger (1.4.2)
|
|
22
22
|
mechanize (2.7.6)
|
|
23
23
|
domain_name (~> 0.5, >= 0.5.1)
|
|
24
24
|
http-cookie (~> 1.0)
|
|
@@ -29,16 +29,16 @@ GEM
|
|
|
29
29
|
ntlm-http (~> 0.1, >= 0.1.1)
|
|
30
30
|
webrobots (>= 0.0.9, < 0.2)
|
|
31
31
|
method_source (0.9.2)
|
|
32
|
-
mime-types (3.3)
|
|
32
|
+
mime-types (3.3.1)
|
|
33
33
|
mime-types-data (~> 3.2015)
|
|
34
|
-
mime-types-data (3.
|
|
34
|
+
mime-types-data (3.2020.0512)
|
|
35
35
|
mini_portile2 (2.4.0)
|
|
36
|
-
minitest (5.
|
|
36
|
+
minitest (5.14.1)
|
|
37
37
|
net-http-digest_auth (1.4.1)
|
|
38
38
|
net-http-persistent (2.9.4)
|
|
39
|
-
nokogiri (1.10.
|
|
39
|
+
nokogiri (1.10.10)
|
|
40
40
|
mini_portile2 (~> 2.4.0)
|
|
41
|
-
nokogiri (1.10.
|
|
41
|
+
nokogiri (1.10.10-x64-mingw32)
|
|
42
42
|
mini_portile2 (~> 2.4.0)
|
|
43
43
|
ntlm-http (0.1.1)
|
|
44
44
|
pry (0.12.2)
|
|
@@ -47,9 +47,10 @@ GEM
|
|
|
47
47
|
rake (13.0.1)
|
|
48
48
|
unf (0.1.4)
|
|
49
49
|
unf_ext
|
|
50
|
-
unf_ext (0.0.7.
|
|
50
|
+
unf_ext (0.0.7.7)
|
|
51
|
+
unf_ext (0.0.7.7-x64-mingw32)
|
|
51
52
|
webrobots (0.1.2)
|
|
52
|
-
yard (0.9.
|
|
53
|
+
yard (0.9.25)
|
|
53
54
|
|
|
54
55
|
PLATFORMS
|
|
55
56
|
ruby
|
|
@@ -66,4 +67,4 @@ DEPENDENCIES
|
|
|
66
67
|
yard (~> 0.9)
|
|
67
68
|
|
|
68
69
|
BUNDLED WITH
|
|
69
|
-
2.
|
|
70
|
+
2.1.4
|
data/lib/vk_music/audio.rb
CHANGED
|
@@ -153,7 +153,7 @@ module VkMusic
|
|
|
153
153
|
else
|
|
154
154
|
# Probably audios from some post
|
|
155
155
|
new(
|
|
156
|
-
artist: node.at_css(".
|
|
156
|
+
artist: node.at_css(".medias_music_author").text.strip,
|
|
157
157
|
title: Utility.plain_text(node.at_css(".medias_audio_title")).strip,
|
|
158
158
|
duration: Utility.parse_duration(node.at_css(".medias_audio_dur").text)
|
|
159
159
|
)
|
data/lib/vk_music/client.rb
CHANGED
|
@@ -43,13 +43,12 @@ module VkMusic
|
|
|
43
43
|
def find(query = "", type: :audio)
|
|
44
44
|
raise ArgumentError if query.empty?
|
|
45
45
|
uri = URI(Constants::URL::VK[:audios])
|
|
46
|
+
search_page = load_ajax(uri, { "q" => query })
|
|
46
47
|
case type
|
|
47
48
|
when :audio
|
|
48
|
-
|
|
49
|
-
audios_from_page(uri)
|
|
49
|
+
audios_from_ajax(search_page)
|
|
50
50
|
when :playlist
|
|
51
|
-
|
|
52
|
-
urls = playlist_urls_from_page(uri)
|
|
51
|
+
urls = playlist_urls_from_page(search_page)
|
|
53
52
|
urls.map { |url| playlist(url: url, up_to: 0, use_web: false) }
|
|
54
53
|
else
|
|
55
54
|
raise ArgumentError
|
|
@@ -81,7 +80,7 @@ module VkMusic
|
|
|
81
80
|
raise Exceptions::ParseError
|
|
82
81
|
end
|
|
83
82
|
raise ArgumentError unless owner_id && playlist_id
|
|
84
|
-
use_web
|
|
83
|
+
use_web ||= (up_to <= 200)
|
|
85
84
|
if use_web
|
|
86
85
|
playlist_web(owner_id, playlist_id, access_hash, up_to: up_to)
|
|
87
86
|
else
|
|
@@ -363,6 +362,23 @@ module VkMusic
|
|
|
363
362
|
raise Exceptions::ParseError, error.message, caller
|
|
364
363
|
end
|
|
365
364
|
end
|
|
365
|
+
##
|
|
366
|
+
# Load response to AJAX post request.
|
|
367
|
+
# @param url [String, URI]
|
|
368
|
+
# @return [Nokogiri::XML::Document]
|
|
369
|
+
def load_ajax(url, query = {})
|
|
370
|
+
uri = URI(url) if url.class != URI
|
|
371
|
+
query["_ajax"] = 1
|
|
372
|
+
headers = { "Content-Type" => "application/x-www-form-urlencoded", "x-requested-with" => "XMLHttpRequest" }
|
|
373
|
+
VkMusic.debug("Loading #{uri} with query #{query}")
|
|
374
|
+
begin
|
|
375
|
+
page = @agent.post(uri, query, headers)
|
|
376
|
+
str = JSON.parse(page.body.strip)["data"][2]
|
|
377
|
+
Nokogiri::XML("<body>#{CGI.unescapeElement(str)}</body>")
|
|
378
|
+
rescue
|
|
379
|
+
raise Exceptions::RequestError
|
|
380
|
+
end
|
|
381
|
+
end
|
|
366
382
|
|
|
367
383
|
##
|
|
368
384
|
# Load playlist web page.
|
|
@@ -458,6 +474,20 @@ module VkMusic
|
|
|
458
474
|
raise Exceptions::ParseError
|
|
459
475
|
end
|
|
460
476
|
end
|
|
477
|
+
##
|
|
478
|
+
# Load audios from AJAX data.
|
|
479
|
+
# @param page [Nokogiri::XML::Document]
|
|
480
|
+
# @return [Array<Audio>]
|
|
481
|
+
def audios_from_ajax(page)
|
|
482
|
+
begin
|
|
483
|
+
page.css(".audio_item.ai_has_btn").map do |elem|
|
|
484
|
+
data = JSON.parse(elem.attribute("data-audio"))
|
|
485
|
+
Audio.from_data(data, @id)
|
|
486
|
+
end
|
|
487
|
+
rescue
|
|
488
|
+
raise Exceptions::ParseError
|
|
489
|
+
end
|
|
490
|
+
end
|
|
461
491
|
|
|
462
492
|
##
|
|
463
493
|
# Load playlist through web page requests.
|
|
@@ -467,26 +497,7 @@ module VkMusic
|
|
|
467
497
|
# @param up_to [Integer] if less than 0, all audios will be loaded.
|
|
468
498
|
# @return [Playlist]
|
|
469
499
|
def playlist_web(owner_id, playlist_id, access_hash = nil, up_to: -1)
|
|
470
|
-
|
|
471
|
-
first_page = load_page_playlist(owner_id, playlist_id, access_hash, offset: 0)
|
|
472
|
-
begin
|
|
473
|
-
# Parse out essential data
|
|
474
|
-
title = first_page.at_css(".audioPlaylist__title").text.strip
|
|
475
|
-
subtitle = first_page.at_css(".audioPlaylist__subtitle").text.strip
|
|
476
|
-
|
|
477
|
-
footer_node = first_page.at_css(".audioPlaylist__footer")
|
|
478
|
-
if footer_node
|
|
479
|
-
footer_match = footer_node.text.strip.match(/^\d+/)
|
|
480
|
-
real_size = footer_match ? footer_match[0].to_i : 0
|
|
481
|
-
else
|
|
482
|
-
real_size = 0
|
|
483
|
-
end
|
|
484
|
-
rescue
|
|
485
|
-
raise Exceptions::ParseError
|
|
486
|
-
end
|
|
487
|
-
# Now we can be sure we are on correct page and have essential data.
|
|
488
|
-
|
|
489
|
-
first_page_audios = audios_from_page(first_page)
|
|
500
|
+
first_page_audios, title, subtitle, real_size = playlist_first_page_web(owner_id, playlist_id, access_hash || "")
|
|
490
501
|
|
|
491
502
|
# Check whether need to make additional requests
|
|
492
503
|
up_to = real_size if (up_to < 0 || up_to > real_size)
|
|
@@ -514,18 +525,16 @@ module VkMusic
|
|
|
514
525
|
# @param up_to [Integer] if less than 0, all audios will be loaded.
|
|
515
526
|
# @return [Playlist]
|
|
516
527
|
def playlist_json(owner_id, playlist_id, access_hash, up_to: -1)
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
first_data_audios = audios_from_data(first_data["list"])
|
|
522
|
-
rescue
|
|
523
|
-
raise Exceptions::ParseError
|
|
528
|
+
if playlist_id == -1
|
|
529
|
+
first_audios, title, subtitle, real_size = playlist_first_page_json(owner_id, playlist_id, access_hash || "")
|
|
530
|
+
else
|
|
531
|
+
first_audios, title, subtitle, real_size = playlist_first_page_web(owner_id, playlist_id, access_hash || "")
|
|
524
532
|
end
|
|
533
|
+
# NOTE: We need to load first page from web to be able to unmask links in future
|
|
525
534
|
|
|
526
|
-
|
|
535
|
+
# Check whether need to make additional requests
|
|
527
536
|
up_to = real_size if (up_to < 0 || up_to > real_size)
|
|
528
|
-
list =
|
|
537
|
+
list = first_audios.first(up_to)
|
|
529
538
|
while list.length < up_to do
|
|
530
539
|
json = load_json_playlist_section(owner_id, playlist_id, access_hash, offset: list.length)
|
|
531
540
|
audios = begin
|
|
@@ -538,11 +547,11 @@ module VkMusic
|
|
|
538
547
|
|
|
539
548
|
begin
|
|
540
549
|
Playlist.new(list,
|
|
541
|
-
id:
|
|
542
|
-
owner_id:
|
|
543
|
-
access_hash:
|
|
544
|
-
title:
|
|
545
|
-
subtitle:
|
|
550
|
+
id: playlist_id,
|
|
551
|
+
owner_id: owner_id,
|
|
552
|
+
access_hash: access_hash,
|
|
553
|
+
title: title,
|
|
554
|
+
subtitle: subtitle,
|
|
546
555
|
real_size: real_size
|
|
547
556
|
)
|
|
548
557
|
rescue
|
|
@@ -550,6 +559,59 @@ module VkMusic
|
|
|
550
559
|
end
|
|
551
560
|
end
|
|
552
561
|
|
|
562
|
+
##
|
|
563
|
+
# Load playlist first page in web and return essential data.
|
|
564
|
+
# @note not suitable for user audios
|
|
565
|
+
# @param owner_id [Integer]
|
|
566
|
+
# @param playlist_id [Integer]
|
|
567
|
+
# @param access_hash [String, nil]
|
|
568
|
+
# @return [Array<Array, String, String, Integer>] array with audios from first page, title, subtitle and playlist real size.
|
|
569
|
+
def playlist_first_page_web(owner_id, playlist_id, access_hash)
|
|
570
|
+
first_page = load_page_playlist(owner_id, playlist_id, access_hash, offset: 0)
|
|
571
|
+
begin
|
|
572
|
+
# Parse out essential data
|
|
573
|
+
title = first_page.at_css(".audioPlaylist__title").text.strip
|
|
574
|
+
subtitle = first_page.at_css(".audioPlaylist__subtitle").text.strip
|
|
575
|
+
|
|
576
|
+
footer_node = first_page.at_css(".audioPlaylist__footer")
|
|
577
|
+
if footer_node
|
|
578
|
+
footer_text = footer_node.text.strip
|
|
579
|
+
footer_text.gsub!(/\s/, "") # Removing all whitespace to get rid of delimiters ('1 042 audios')
|
|
580
|
+
footer_match = footer_text.match(/^\d+/)
|
|
581
|
+
real_size = footer_match ? footer_match[0].to_i : 0
|
|
582
|
+
else
|
|
583
|
+
real_size = 0
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
first_audios = audios_from_page(first_page)
|
|
587
|
+
rescue
|
|
588
|
+
raise Exceptions::ParseError
|
|
589
|
+
end
|
|
590
|
+
[first_audios, title, subtitle, real_size]
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
##
|
|
594
|
+
# Load playlist first page in JSON and return essential data.
|
|
595
|
+
# @param owner_id [Integer]
|
|
596
|
+
# @param playlist_id [Integer]
|
|
597
|
+
# @param access_hash [String, nil]
|
|
598
|
+
# @return [Array<Array, String, String, Integer>] array with audios from first page, title, subtitle and playlist real size.
|
|
599
|
+
def playlist_first_page_json(owner_id, playlist_id, access_hash)
|
|
600
|
+
first_json = load_json_playlist_section(owner_id, playlist_id, access_hash, offset: 0)
|
|
601
|
+
begin
|
|
602
|
+
first_data = first_json["data"][0]
|
|
603
|
+
first_data_audios = audios_from_data(first_data["list"])
|
|
604
|
+
rescue
|
|
605
|
+
raise Exceptions::ParseError
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
real_size = first_data["totalCount"]
|
|
609
|
+
title = CGI.unescapeHTML(first_data["title"].to_s)
|
|
610
|
+
subtitle = CGI.unescapeHTML(first_data["subtitle"].to_s)
|
|
611
|
+
|
|
612
|
+
[first_data_audios, title, subtitle, real_size]
|
|
613
|
+
end
|
|
614
|
+
|
|
553
615
|
##
|
|
554
616
|
# Found playlist URLs on *global* search page.
|
|
555
617
|
# @param obj [Mechanize::Page, String, URI]
|
data/lib/vk_music/constants.rb
CHANGED
|
@@ -52,7 +52,7 @@ module VkMusic
|
|
|
52
52
|
VK_AUDIOS_URL_POSTFIX = /^audios(-?\d+)$/
|
|
53
53
|
##
|
|
54
54
|
# Playlist URL regular expression.
|
|
55
|
-
VK_PLAYLIST_URL_POSTFIX = /.*(?:audio_playlist|album\/)(-?\d+)_(\d+)(?:(?:(?:.*(?=&access_hash=)&access_hash=)|\/|%2F|_)([\da-z]+))?/
|
|
55
|
+
VK_PLAYLIST_URL_POSTFIX = /.*(?:audio_playlist|album\/|playlist\/)(-?\d+)_(\d+)(?:(?:(?:.*(?=&access_hash=)&access_hash=)|\/|%2F|_)([\da-z]+))?/
|
|
56
56
|
##
|
|
57
57
|
# Post URL regular expression #1.
|
|
58
58
|
VK_POST_URL_POSTFIX = /.*post(-?\d+)_(\d+)/
|
data/lib/vk_music/version.rb
CHANGED
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: 3.1.
|
|
4
|
+
version: 3.1.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Fizvlad
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-
|
|
11
|
+
date: 2020-11-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -186,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
186
186
|
- !ruby/object:Gem::Version
|
|
187
187
|
version: '0'
|
|
188
188
|
requirements: []
|
|
189
|
-
rubygems_version: 3.
|
|
189
|
+
rubygems_version: 3.1.4
|
|
190
190
|
signing_key:
|
|
191
191
|
specification_version: 4
|
|
192
192
|
summary: Provides interface to work with VK music via HTTP requests
|