manga-tools 0.1.1 → 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: 00e79a7d0c8e37ab036decdaba2d9cd556d97256a523a59d6af0c1c63c07d2b5
4
- data.tar.gz: 46a97ec12c433b9ce51ee222d82df047edc3b8f311304149dd8d3e9a946b27d3
3
+ metadata.gz: da4ed03340c47790056a5ffeaa86a4f986010d8dfcb7c8fd87568300c9f66e30
4
+ data.tar.gz: a4f1644d7fca880a904463bf10376c86aaac49aac3a2233ec323ee8d0287bc42
5
5
  SHA512:
6
- metadata.gz: 3635bfe7dd5cd5c4093fb8281d8137e34c4a3c551c4e377e7332f6712a933190f0515d1159e56bfb78bc6ea917226b6561f1d053afdc5d1b805e4a5e417e9454
7
- data.tar.gz: 6170c78319d8e7a74ed93860dde010b87b23c9281385bb65bfeec4af5eb2c9c51f02ceb771797126c9365f9b3295d8d5b4db5b812e16dc3af3e022f33cba45bd
6
+ metadata.gz: 94e0f51017fd81f30360f03ec4c29cf82318401e507dc267cc354e6e4cba43278b5161e3b12f3af4f0ecfdc2e4dc21af6e8f0c10c0f0ea5b4fd22fb96f06e4dc
7
+ data.tar.gz: 45d686425259594ae0e45114f8e7d70970df515db271f3c3c6dee8c6316c83deaa8d844a6be9b199abe7fe1854032a127a56eed64e2da785245281b8dafbca15
data/Gemfile CHANGED
@@ -6,7 +6,6 @@ source 'https://rubygems.org'
6
6
  gemspec
7
7
 
8
8
  gem 'faraday'
9
- gem 'nokogiri'
10
9
  gem 'pry'
11
10
  gem 'rake', require: false
12
11
  gem 'rspec'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- manga-tools (0.1.1)
4
+ manga-tools (0.1.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -14,10 +14,7 @@ GEM
14
14
  multipart-post (>= 1.2, < 3)
15
15
  json (2.3.1)
16
16
  method_source (1.0.0)
17
- mini_portile2 (2.4.0)
18
17
  multipart-post (2.1.1)
19
- nokogiri (1.10.10)
20
- mini_portile2 (~> 2.4.0)
21
18
  parallel (1.19.2)
22
19
  parser (2.7.1.4)
23
20
  ast (~> 2.4.1)
@@ -67,7 +64,6 @@ PLATFORMS
67
64
  DEPENDENCIES
68
65
  faraday
69
66
  manga-tools!
70
- nokogiri
71
67
  pry
72
68
  rake
73
69
  rspec
data/README.md CHANGED
@@ -1,13 +1,10 @@
1
1
  # Manga::Tools
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/manga-tools.svg)](https://badge.fury.io/rb/manga-tools)
3
4
  ![Ruby](https://github.com/yagihiro/manga-tools/workflows/Ruby/badge.svg)
4
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/e2797c91a0bd6f521905/maintainability)](https://codeclimate.com/github/yagihiro/manga-tools/maintainability)
5
6
  [![Test Coverage](https://api.codeclimate.com/v1/badges/e2797c91a0bd6f521905/test_coverage)](https://codeclimate.com/github/yagihiro/manga-tools/test_coverage)
6
7
 
7
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/manga/tools`. To experiment with that code, run `bin/console` for an interactive prompt.
8
-
9
- TODO: Delete this and the text above, and describe your gem
10
-
11
8
  ## Installation
12
9
 
13
10
  Add this line to your application's Gemfile:
@@ -26,7 +23,11 @@ Or install it yourself as:
26
23
 
27
24
  ## Usage
28
25
 
29
- TODO: Write usage instructions here
26
+ * A search command to find out the release date of a manga
27
+
28
+ ```
29
+ $ manga-tools search "ONE PIECE"
30
+ ```
30
31
 
31
32
  ## Development
32
33
 
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'tools/cache'
4
3
  require_relative 'tools/cli'
5
4
  require_relative 'tools/http'
6
5
  require_relative 'tools/version'
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
- require 'nokogiri'
5
- require 'stringio'
6
4
  require 'thor'
5
+ require_relative 'http'
7
6
 
8
7
  module Manga
9
8
  module Tools
@@ -13,150 +12,18 @@ module Manga
13
12
  true
14
13
  end
15
14
 
16
- # desc "pub {name}", "publication date of {name}"
17
- # def pub(name)
18
- # doc = Nokogiri::HTML(
19
- # URI.open('https://tsutaya.tsite.jp/feature/book/release/comic/index', 'User-Agent' => UserAgent)
20
- # )
21
- #
22
- # File.open('.index.txt', 'w') {|f| f.write doc }
23
- #
24
- # results = {}
25
- #
26
- # current_date = ''
27
- # state = :title
28
- # current_data = {}
29
- # doc.css('h3, div.comic_list div.c_cols-1of3 span').each do |element|
30
- # case element.name
31
- # when 'h3'
32
- # results[element.content] = []
33
- # current_date = element.content
34
- # when 'span'
35
- # current_data[state] = element.content
36
- # case state
37
- # when :title
38
- # state = :author
39
- # when :author
40
- # state = :label
41
- # when :label
42
- # state = :title
43
- # results[current_date] << current_data
44
- # current_data = {}
45
- # end
46
- # end
47
- # end
48
- #
49
- # puts JSON.pretty_generate(results)
50
- # end
51
-
52
- desc 'search WORD', 'Search for a given WORD'
15
+ desc 'search WORD', 'Search titles for a given WORD'
53
16
  def search(word)
54
- Manga::Tools::Cache.init
55
-
56
- t = Time.now
57
- url = "https://calendar.gameiroiro.com/manga.php?year=#{t.year}&month=#{t.month}"
58
- data = Manga::Tools::Cache.fetch(key: url) do |cache|
59
- res = Manga::Tools::Http.get(url)
60
- cache.expires_in = Manga::Tools::Http.seconds_to_cache(res)
61
- results = generate_internal_data(t, res.body)
62
- results.to_json
63
- end
64
-
65
- hash = JSON.parse(data)
17
+ url = "https://manga-tools-server.herokuapp.com/publications?keyword=#{CGI.escape(word)}"
18
+ res = Manga::Tools::Http.get(url)
19
+ results = JSON.parse(res.body)
66
20
 
67
21
  puts "Searching '#{word}' ..."
68
- hash.each do |date, items|
69
- next if items.empty?
70
-
71
- items.each do |item|
72
- puts "Found: #{date}, #{item['title']}" if item['title'].index(word)
73
- end
22
+ results.each do |item|
23
+ puts "#{item['published_at']}: #{item['title']}"
74
24
  end
75
25
  puts 'Finished.'
76
26
  end
77
-
78
- private
79
-
80
- # @param time [Time] a target time
81
- # @param data [String] a string of HTTP response body.
82
- def generate_internal_data(time, data)
83
- doc = Nokogiri::HTML(StringIO.open(data))
84
-
85
- results = {}
86
- current_date = nil
87
- state = :genre
88
- data = {}
89
- doc.css(targets.join(', ')).each do |element|
90
- value = rm_spaces(element.content)
91
- case element.name
92
- when 'td'
93
- current_date = format('%<ym>s/%<day>02d', ym: time.strftime('%Y/%m'), day: value.to_i)
94
- results[current_date] = []
95
- when 'p', 'a'
96
- case state
97
- when :genre
98
- guard_genre(element)
99
- data[state] = value
100
- state = :title
101
- when :title
102
- guard_title(element)
103
- data[state] = value
104
- data[:link] = element['href']
105
- state = :company
106
- when :company
107
- guard_company(element)
108
- data[state] = value
109
- state = :authors
110
- when :authors
111
- guard_authors(element)
112
- data[state] = value
113
- state = :genre
114
- results[current_date] << data
115
- data = {}
116
- end
117
- end
118
- rescue StandardError
119
- # when authors, authors may not be present.
120
- if state == :authors
121
- data[state] = ''
122
- state = :genre
123
- results[current_date] << data
124
- data = {}
125
- end
126
- retry
127
- end
128
-
129
- results
130
- end
131
-
132
- def targets
133
- @targets ||= [
134
- 'td.day-td',
135
- 'div.product-description-right p.p-genre',
136
- 'div.product-description-right a',
137
- 'div.product-description-right p.p-company'
138
- ]
139
- end
140
-
141
- # Remove HTML spaces (&nbsp;) and white spaces.
142
- # @param str [String] a string
143
- def rm_spaces(str)
144
- str.gsub("\u00A0", '').strip
145
- end
146
-
147
- def guard_genre(element)
148
- raise 'invalid state' unless element.name == 'p' && element['class'] == 'p-genre'
149
- end
150
-
151
- def guard_title(element)
152
- raise 'invalid state' unless element.name == 'a'
153
- end
154
-
155
- def guard_company(element)
156
- raise 'invalid state' unless element.name == 'p' && element['class'] == 'p-company'
157
- end
158
-
159
- alias guard_authors guard_company
160
27
  end
161
28
  end
162
29
  end
@@ -2,23 +2,20 @@
2
2
 
3
3
  require 'faraday'
4
4
  require 'uri'
5
+ require_relative 'version'
5
6
 
6
7
  module Manga
7
8
  module Tools
8
9
  # HTTP client class
9
10
  module Http
10
- # rubocop:disable Layout/LineLength
11
- UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'
12
- # rubocop:enable Layout/LineLength
13
-
14
11
  # @param url [String] an url string, eg: `https://example.com`
15
12
  # @return [Faraday::Connection] a connection object
16
13
  def self.connection(url)
17
14
  @connection ||= Faraday.new(
18
15
  url: url,
19
- headers: { 'User-Agent' => UA }
16
+ headers: { 'User-Agent' => user_agent }
20
17
  ) do |f|
21
- f.response :logger
18
+ # f.response :logger
22
19
  end
23
20
  end
24
21
 
@@ -40,6 +37,10 @@ module Manga
40
37
 
41
38
  Regexp.last_match(1).to_i
42
39
  end
40
+
41
+ def self.user_agent
42
+ @user_agent ||= "manga-tools #{Manga::Tools::VERSION}"
43
+ end
43
44
  end
44
45
  end
45
46
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Manga
4
4
  module Tools
5
- VERSION = '0.1.1'
5
+ VERSION = '0.1.2'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: manga-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hiroki Yagita
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-09 00:00:00.000000000 Z
11
+ date: 2020-08-18 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Tools to support the automation of daily manga-related activities.
14
14
  email:
@@ -34,7 +34,6 @@ files:
34
34
  - bin/setup
35
35
  - exe/manga-tools
36
36
  - lib/manga/tools.rb
37
- - lib/manga/tools/cache.rb
38
37
  - lib/manga/tools/cli.rb
39
38
  - lib/manga/tools/http.rb
40
39
  - lib/manga/tools/version.rb
@@ -1,113 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'digest/md5'
4
- require 'fileutils'
5
-
6
- module Manga
7
- module Tools
8
- # Cache class
9
- class Cache
10
- class << self
11
- # Initialize cache
12
- def init
13
- FileUtils.mkdir_p(cache_current_year_dir)
14
- end
15
-
16
- def root_dir
17
- @root_dir ||= "#{Dir.home}/.manga-tools"
18
- end
19
-
20
- def cache_root_dir
21
- @cache_root_dir ||= "#{root_dir}/cache"
22
- end
23
-
24
- def cache_current_year_dir
25
- @cache_current_year_dir ||= "#{cache_root_dir}/#{Time.now.year}"
26
- end
27
-
28
- # @return [Integer] default expires in seconds (1day)
29
- def default_expires_in
30
- @default_expires_in ||= 1 * 24 * 60 * 60
31
- end
32
-
33
- # @param key [String] A key to generate a key for the cache
34
- # @return [String] string of cached data
35
- def fetch(key:)
36
- raise ArgumentError, 'mast pass a block' unless block_given?
37
-
38
- cache = new(key)
39
- # cache.clear
40
- return cache.load_data if cache.available?
41
-
42
- result = yield(cache)
43
- cache.save_meta_data
44
- cache.save_data(result)
45
- result
46
- end
47
- end
48
-
49
- # @return [Integer|nil] A cache deadline in seconds.
50
- attr_accessor :expires_in
51
- # @return [String] A key to generate a key for the cache.
52
- attr_reader :key
53
- # @return [String] A key for the cache.
54
- attr_reader :cache_key
55
- # @return [String] A path to the cache metadata file.
56
- attr_reader :meta_file_path
57
- # @return [String] A path to the cached data file.
58
- attr_reader :data_file_path
59
-
60
- # @param key [String] A key to generate a key for the cache.
61
- def initialize(key)
62
- raise ArgumentError, 'mast pass the key param' unless key
63
-
64
- @expires_in = self.class.default_expires_in
65
- @key = key
66
- @cache_key = Digest::MD5.hexdigest(key)
67
- @meta_file_path = "#{self.class.cache_current_year_dir}/#{@cache_key}"
68
- @data_file_path = "#{@meta_file_path}.data"
69
- end
70
-
71
- # @return [Boolean] True if a cache is available, otherwise return false.
72
- def available?
73
- t = File.mtime(meta_file_path)
74
- saved_expires_in = File.read(meta_file_path).strip.to_i
75
-
76
- Time.now <= (t + saved_expires_in)
77
- rescue StandardError
78
- false
79
- end
80
-
81
- # @return [String] Reads and returns the cache data.
82
- def load_data
83
- File.read(data_file_path)
84
- end
85
-
86
- # Save the metadata for the cache.
87
- def save_meta_data
88
- @expires_in = self.class.default_expires_in unless expires_in
89
-
90
- File.open(meta_file_path, 'w') do |f|
91
- f.write(expires_in.to_s)
92
- end
93
-
94
- self
95
- end
96
-
97
- # @param str [String] Save the specified cache data
98
- def save_data(str)
99
- File.open(data_file_path, 'w') do |f|
100
- f.write(str.force_encoding('utf-8'))
101
- end
102
-
103
- self
104
- end
105
-
106
- # for debug
107
- def clear
108
- File.delete(meta_file_path) if File.exist?(meta_file_path)
109
- File.delete(data_file_path) if File.exist?(data_file_path)
110
- end
111
- end
112
- end
113
- end