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 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