natalia 0.1.0 → 0.1.2

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: a1cd40e71255d902fb12309ee83888b4ea78b322baf87caaaaa8aaafca0d3886
4
- data.tar.gz: de2c722d139e874be4675975a909d745182e73bdf5e41cd6f2542b71e53dc197
3
+ metadata.gz: fa2e17162fde6d6e03709031a6d3c2084418bfb23da0b758e44afd81dc6dd0b1
4
+ data.tar.gz: ac8e18a3060c3b747529bc18085920ae0cdc9c0d78ea05756a27af6b1b91149c
5
5
  SHA512:
6
- metadata.gz: 4f65cc234804d15401dc4902b9dcd87804408cd3c97cfae2c8e17d9044768725781c14d14fdf75b0c467916da795ce5cfaee9b77a4fe548cbb9a5d63684d48dc
7
- data.tar.gz: 583b39aefe55add76fb4af7c25c395ab6e2ab6363fa0e7e81b0a246c957be50087cab8dd48442496d001a2c6e17e16bb61fdb48463e54127335ff829ae8faca7
6
+ metadata.gz: d27b7645635319c47c3c8af0691e2a4339d2981d7755cc361a666d7e4b9e1f78f5c4c29f22aa0aa091017c190b79bc8487328b48d052c0409e89c7481678e4c0
7
+ data.tar.gz: 37f819764e68c428f2c6f594f1fb96aa013e2fb7fcc6e1673bf673e672813275c117677f0a36745b4e8ed2e2c9e2b61e91c60ef59de5902665534798449150d5
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nokogiri'
4
+ require 'time'
5
+ require_relative '../utils'
6
+
7
+ module Natalia
8
+ module JLyric
9
+ # sort という概念はないっぽい
10
+ def self.search(keyword, type: :title, sort: :popularity_desc)
11
+ case type
12
+ when :title
13
+ search_by_title(keyword)
14
+ when :artist
15
+ search_by_artist(keyword, sort: sort)
16
+ else
17
+ raise ArgumentError, "unsupported search type `#{type}`"
18
+ end
19
+ end
20
+
21
+ def self.search_by_title(keyword)
22
+ entries = []
23
+ (1..).each do |page|
24
+ response =
25
+ Natalia::Utils.curl_get('https://search2.j-lyric.net/index.php', {
26
+ kt: keyword,
27
+ ct: '2', # kt 検索方法 (0: 前方, 1: 完全, 2: 中間, 3: 後方)
28
+ search: '検索', # 謎
29
+ ex: 'on', # 謎
30
+ ca: '2', # ka 検索方法
31
+ cl: '2', # kl 検索方法
32
+ p: page
33
+ })
34
+ response.value
35
+
36
+ doc = Nokogiri::HTML.parse(response.body)
37
+ table = doc.css('div#bas div#cnt div#mnb > div.bdy')
38
+ break if table.empty?
39
+
40
+ table.each do |body|
41
+ entries << {
42
+ source: self,
43
+ id: body.at_css('p.mid a')['href'].match(%r{/artist/(.+)\.html\z})[1],
44
+ title: body.at_css('p.mid a').content,
45
+ artist: body.css('p.sml')[0].at_css('a').content,
46
+ artist_id: body.css('p.sml')[0].at_css('a')['href'].match(%r{/artist/(.+)/\z})[1]
47
+ }
48
+ end
49
+ end
50
+
51
+ entries
52
+ end
53
+
54
+ def self.search_by_artist(artist_id, sort: :popularity_desc)
55
+ response = Natalia::Utils.curl_get("https://j-lyric.net/artist/#{artist_id}/")
56
+ response.value
57
+
58
+ doc = Nokogiri::HTML.parse(response.body)
59
+ artist_name = doc.at_css('div#mnb div.cnt div.cap h2').content.match(/\A(.+)の歌詞リスト\z/)[1]
60
+ table = doc.css('div#bas div#cnt div#mnb div.bdy[id^=ly]')
61
+
62
+ entries = table.map do |row|
63
+ order, date, popularity = row.css('input[type=hidden]').map {|e| e['value']}
64
+ {
65
+ source: self,
66
+ id: row.at_css('p.ttl a')['href'].match(%r{/artist/(.+)\.html\z})[1],
67
+ title: row.at_css('p.ttl a').content,
68
+ artist: artist_name,
69
+ artist_id: artist_id,
70
+ order: order.to_i,
71
+ date: Time.parse("#{date} JST"),
72
+ popularity: -popularity.to_i
73
+ }
74
+ end.compact
75
+
76
+ case sort
77
+ when :title
78
+ entries.sort_by {|e| e[:order]}
79
+ when :title_desc
80
+ entries.sort_by {|e| -e[:order]}
81
+ when :popularity
82
+ entries.sort_by {|e| e[:popularity]}
83
+ when :popularity_desc
84
+ entries.sort_by {|e| -e[:popularity]}
85
+ when :date
86
+ entries.sort_by {|e| e[:date]}
87
+ when :date_desc
88
+ entries.sort_by {|e| -e[:date].to_i}
89
+ when :artist, :artist_desc
90
+ entries
91
+ else
92
+ raise ArgumentError, "unsupported sort type `#{sort}`"
93
+ end
94
+ end
95
+
96
+ def self.get(id)
97
+ response = Natalia::Utils.curl_get("https://j-lyric.net/artist/#{id}.html")
98
+ response.value
99
+
100
+ doc = Nokogiri::HTML.parse(response.body)
101
+
102
+ smls = doc.css('div#mnb div.lbdy p.sml')
103
+
104
+ ret = {
105
+ source: self,
106
+ id: id,
107
+ title: doc.at_css('div#mnb div.cap h2').content.match(/\A「(.+)」歌詞\z/)[1],
108
+ artist: smls[0].at_css('a').content,
109
+ artist_id: smls[0].at_css('a')['href'].match(%r{/artist/(.+)/\z})[1]
110
+ }
111
+
112
+ smls[1..].each do |e|
113
+ content = e.content
114
+ ret[:lyricist] = content.match(/作詞:(.+)/)[1] if content.start_with?('作詞:')
115
+ ret[:composer] = content.match(/作曲:(.+)/)[1] if content.start_with?('作曲:')
116
+ end
117
+
118
+ ret[:lyrics] = doc.at_css('p#Lyric').children.map do |e|
119
+ e.name == 'br' ? "\n" : e.content
120
+ end.join.strip
121
+
122
+ ret
123
+ end
124
+ end
125
+ end
@@ -24,7 +24,8 @@ module Natalia
24
24
 
25
25
  def self.search(keyword, type: :title, sort: :popularity_desc)
26
26
  sort = SORT_MAP[sort]
27
- raise ArgumentError, 'invalid sort type' unless sort
27
+ raise ArgumentError, "unsupported sort type `#{sort}`" unless sort
28
+ raise ArgumentError, "unsupported search type `#{type}`" unless KIND_MAP.key?(type)
28
29
 
29
30
  response = Natalia::Utils.curl_post('https://mspxy.joysound.com/Common/ContentsList') do |request|
30
31
  request.content_type = 'application/x-www-form-urlencoded; charset=UTF-8'
@@ -4,7 +4,7 @@ require 'nokogiri'
4
4
  require_relative '../utils'
5
5
 
6
6
  module Natalia
7
- module Utamap
7
+ module UtaNet
8
8
  SORT_MAP = {
9
9
  title: 1,
10
10
  title_desc: 2,
@@ -19,8 +19,8 @@ module Natalia
19
19
  # @param [String] keyword キーワード(タイトル検索)、ID(それ以外)
20
20
  def self.search(keyword, type: :title, sort: :popularity_desc)
21
21
  sort = SORT_MAP[sort]
22
- raise ArgumentError, 'invalid sort type' unless sort
23
- raise ArgumentError, 'type must be :title, :artist, :lyricist, :composer, or :arranger' unless %i[title artist lyricist composer arranger].include?(type)
22
+ raise ArgumentError, "unsupported sort type `#{sort}`" unless sort
23
+ raise ArgumentError, "unsupported search type `#{type}`" unless %i[title artist lyricist composer arranger].include?(type)
24
24
 
25
25
  entries = []
26
26
  (type == :title ? 1.. : [1]).each do |page|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Natalia
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.2'
5
5
  end
data/lib/natalia.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'natalia/services/j_lyric'
3
4
  require_relative 'natalia/services/joysound'
4
- require_relative 'natalia/services/utamap'
5
+ require_relative 'natalia/services/uta_net'
5
6
  require_relative 'natalia/version'
6
7
 
7
8
  module Natalia
@@ -43,7 +44,8 @@ module Natalia
43
44
 
44
45
  # 信頼できるソース順に並べる
45
46
  SERVICES = [
46
- Natalia::Utamap,
47
+ Natalia::UtaNet,
48
+ Natalia::JLyric,
47
49
  Natalia::Joysound
48
50
  ].freeze
49
51
 
@@ -51,6 +53,9 @@ module Natalia
51
53
  entries = []
52
54
  SERVICES.each do |service|
53
55
  entries += service.search(keyword, type: :title, sort: sort)
56
+ rescue StandardError
57
+ warn "Failed to search by #{service}"
58
+ warn $!.full_message
54
59
  end
55
60
  entries.map {|entry| Song.new(entry)}
56
61
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: natalia
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ishotihadus
@@ -37,8 +37,9 @@ files:
37
37
  - README.md
38
38
  - Rakefile
39
39
  - lib/natalia.rb
40
+ - lib/natalia/services/j_lyric.rb
40
41
  - lib/natalia/services/joysound.rb
41
- - lib/natalia/services/utamap.rb
42
+ - lib/natalia/services/uta_net.rb
42
43
  - lib/natalia/utils.rb
43
44
  - lib/natalia/version.rb
44
45
  homepage: https://github.com/natalia