vk_music 3.1.2 → 3.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f27b9cb93f819517475fdba4135daf7fde34e6bdb0e992a642308838f0e32bb
4
- data.tar.gz: 85445fdf8362b71fbe2dde767b9772e95b8e47ab887e5d584062f008a1899be3
3
+ metadata.gz: 49d94fb81d001d5d050d274f14ab6a3931467097adb46aa84601444fba4ac312
4
+ data.tar.gz: b8b6433c2373a1229bf5e27e31d8bc5c7d4ae01840b0620f99e715707ddc665e
5
5
  SHA512:
6
- metadata.gz: 2f5ed3c5cca385e291e8f9abab438adc557a87d4a5145dc6e9b47c1d46535474433ae10cf8eb40318717ba47722c8112ef44997741073783caddda6ba6b6c812
7
- data.tar.gz: 27317f2d5cc75756e8015cd9a95eb5bb71a66a55ffa2495044f7de75dcfa87f2e9f5769e8b8d9c56219aea211b2e728bcb77e0ae2763d39b180d28eaadec1f96
6
+ metadata.gz: ee9d28c4ef87b6fc12865ec267aeca8ddb24a9275c6c231f42fc68c6390b8fb9bfa8759f3d0f3b6f17e1d8e4ba8880b32976f987c0bde5edb4c1c3856a0a2ab1
7
+ data.tar.gz: 48451ee22f080a93a0d8fea4fbb468f1c45b97bc089dc87675663d602092ba2fb255826ef3b127129b7d6fe8855751ee6bc3869e0c59ccc8e5e4c413eb9be45d
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- vk_music (3.1.0)
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.2)
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.0)
21
- logger (1.4.1)
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.2019.1009)
34
+ mime-types-data (3.2020.0512)
35
35
  mini_portile2 (2.4.0)
36
- minitest (5.13.0)
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.8)
39
+ nokogiri (1.10.10)
40
40
  mini_portile2 (~> 2.4.0)
41
- nokogiri (1.10.8-x64-mingw32)
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.6)
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.20)
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.0.2
70
+ 2.1.4
@@ -153,7 +153,7 @@ module VkMusic
153
153
  else
154
154
  # Probably audios from some post
155
155
  new(
156
- artist: node.at_css(".medias_audio_artist").text.strip,
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
  )
@@ -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
- uri.query = Utility.hash_to_params({ "act" => "search", "q" => query })
49
- audios_from_page(uri)
49
+ audios_from_ajax(search_page)
50
50
  when :playlist
51
- uri.query = Utility.hash_to_params({ "q" => query, "tab" => "global" })
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 = up_to > 200 if use_web.nil?
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
- # Load first page and get info
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
- # Trying to parse out audios
518
- first_json = load_json_playlist_section(owner_id, playlist_id, access_hash, offset: 0)
519
- begin
520
- first_data = first_json["data"][0]
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
- real_size = first_data["totalCount"]
535
+ # Check whether need to make additional requests
527
536
  up_to = real_size if (up_to < 0 || up_to > real_size)
528
- list = first_data_audios.first(up_to)
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: first_data["id"],
542
- owner_id: first_data["owner_id"],
543
- access_hash: first_data["access_hash"],
544
- title: CGI.unescapeHTML(first_data["title"].to_s),
545
- subtitle: CGI.unescapeHTML(first_data["subtitle"].to_s),
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]
@@ -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+)/
@@ -1,5 +1,5 @@
1
1
  module VkMusic
2
2
  ##
3
3
  # Library version.
4
- VERSION = "3.1.2"
4
+ VERSION = "3.1.7"
5
5
  end
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.2
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-03-19 00:00:00.000000000 Z
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.0.4
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