itest5ch 1.0.0
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 +7 -0
- data/.circleci/config.yml +127 -0
- data/.circleci/setup.sh +8 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/.rubocop.yml +15 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +132 -0
- data/Rakefile +16 -0
- data/bin/console +10 -0
- data/bin/setup +8 -0
- data/itest5ch.gemspec +42 -0
- data/lib/itest5ch.rb +18 -0
- data/lib/itest5ch/assert_methods.rb +21 -0
- data/lib/itest5ch/board.rb +76 -0
- data/lib/itest5ch/board_list_page.rb +39 -0
- data/lib/itest5ch/comment.rb +91 -0
- data/lib/itest5ch/config.rb +7 -0
- data/lib/itest5ch/http_methods.rb +26 -0
- data/lib/itest5ch/thread.rb +173 -0
- data/lib/itest5ch/version.rb +3 -0
- metadata +306 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0c541a98e77de8fb2fbdf1e8053fe17701115e8b2ffb20a46a56d3927a5e02cb
|
4
|
+
data.tar.gz: 98be41ebe60e8d3cc30c2334d1dd05003f10864e039d8511413d32d8ccb84ad6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b7133eda1d48f3a1fc852ae5d4b3e4567e442e50afe4f441578fb7376371945643a682949c36decfe41e78699edf5a603d01fee4fa6bcc563e5ab6bcd1d0a32a
|
7
|
+
data.tar.gz: dcf94763f4d7cbc7850263e1207ccfcfcdcb365f1a6f90a8053c82e546bf70a11ec78fd4244d6ecb365f74c53b08ca7e4a77e0dd19ecd9a53fff6406be638e0f
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# Ruby CircleCI 2.0 configuration file
|
2
|
+
#
|
3
|
+
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
|
4
|
+
#
|
5
|
+
version: 2
|
6
|
+
|
7
|
+
default: &default
|
8
|
+
docker:
|
9
|
+
- image: ruby
|
10
|
+
environment:
|
11
|
+
# c.f. https://github.com/ffaker/ffaker/issues/277#issuecomment-263519146
|
12
|
+
LANG: en_US.UTF-8
|
13
|
+
LANGUAGE: en_US.UTF-8
|
14
|
+
LC_ALL: C.UTF-8
|
15
|
+
|
16
|
+
BUNDLE_PATH: vendor/bundle
|
17
|
+
BUNDLE_JOBS: 4
|
18
|
+
|
19
|
+
working_directory: ~/app
|
20
|
+
|
21
|
+
restore_repo_cache_option: &restore_repo_cache_option
|
22
|
+
key: v1-repo-{{ .Environment.CIRCLE_SHA1 }}
|
23
|
+
|
24
|
+
save_repo_cache_option: &save_repo_cache_option
|
25
|
+
key: v1-repo-{{ .Environment.CIRCLE_SHA1 }}
|
26
|
+
paths:
|
27
|
+
- ~/app
|
28
|
+
|
29
|
+
restore_bundle_cache_option: &restore_bundle_cache_option
|
30
|
+
keys:
|
31
|
+
- v3-bundle-{{ .Environment.CIRCLE_JOB }}-{{ checksum "itest5ch.gemspec" }}
|
32
|
+
- v3-bundle-{{ .Environment.CIRCLE_JOB }}
|
33
|
+
|
34
|
+
save_bundle_cache_option: &save_bundle_cache_option
|
35
|
+
key: v3-bundle-{{ .Environment.CIRCLE_JOB }}-{{ checksum "itest5ch.gemspec" }}
|
36
|
+
paths:
|
37
|
+
- ~/app/vendor/bundle
|
38
|
+
- ~/app/Gemfile.lock
|
39
|
+
|
40
|
+
rspec_steps: &rspec_steps
|
41
|
+
- restore_cache:
|
42
|
+
<<: *restore_repo_cache_option
|
43
|
+
- restore_cache:
|
44
|
+
<<: *restore_bundle_cache_option
|
45
|
+
- run: ./.circleci/setup.sh
|
46
|
+
- save_cache:
|
47
|
+
<<: *save_bundle_cache_option
|
48
|
+
|
49
|
+
- run: bundle exec rspec
|
50
|
+
|
51
|
+
build_jobs: &build_jobs
|
52
|
+
- checkout_code
|
53
|
+
- rspec:2.3:
|
54
|
+
requires:
|
55
|
+
- checkout_code
|
56
|
+
- rspec:2.4:
|
57
|
+
requires:
|
58
|
+
- checkout_code
|
59
|
+
- rspec:2.5:
|
60
|
+
requires:
|
61
|
+
- checkout_code
|
62
|
+
- rubocop:
|
63
|
+
requires:
|
64
|
+
- checkout_code
|
65
|
+
|
66
|
+
jobs:
|
67
|
+
checkout_code:
|
68
|
+
<<: *default
|
69
|
+
|
70
|
+
steps:
|
71
|
+
- checkout
|
72
|
+
|
73
|
+
- save_cache:
|
74
|
+
<<: *save_repo_cache_option
|
75
|
+
|
76
|
+
rspec:2.3:
|
77
|
+
<<: *default
|
78
|
+
|
79
|
+
docker:
|
80
|
+
- image: ruby:2.3
|
81
|
+
|
82
|
+
steps: *rspec_steps
|
83
|
+
|
84
|
+
rspec:2.4:
|
85
|
+
<<: *default
|
86
|
+
|
87
|
+
docker:
|
88
|
+
- image: ruby:2.4
|
89
|
+
|
90
|
+
steps: *rspec_steps
|
91
|
+
|
92
|
+
rspec:2.5:
|
93
|
+
<<: *default
|
94
|
+
|
95
|
+
docker:
|
96
|
+
- image: ruby:2.5
|
97
|
+
|
98
|
+
steps: *rspec_steps
|
99
|
+
|
100
|
+
rubocop:
|
101
|
+
<<: *default
|
102
|
+
|
103
|
+
steps:
|
104
|
+
- restore_cache:
|
105
|
+
<<: *restore_repo_cache_option
|
106
|
+
- restore_cache:
|
107
|
+
<<: *restore_bundle_cache_option
|
108
|
+
- run: ./.circleci/setup.sh
|
109
|
+
- save_cache:
|
110
|
+
<<: *save_bundle_cache_option
|
111
|
+
|
112
|
+
- run: bundle exec rubocop
|
113
|
+
|
114
|
+
workflows:
|
115
|
+
version: 2
|
116
|
+
|
117
|
+
build:
|
118
|
+
jobs: *build_jobs
|
119
|
+
|
120
|
+
weekly_build:
|
121
|
+
triggers:
|
122
|
+
- schedule:
|
123
|
+
cron: "00 19 * * 5" # JST 4:00 (Sat)
|
124
|
+
filters:
|
125
|
+
branches:
|
126
|
+
only: master
|
127
|
+
jobs: *build_jobs
|
data/.circleci/setup.sh
ADDED
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
repo_token: ENHg6l26Ivgty7gR2Hjh5vEqOg2gi2Dzk
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
inherit_gem:
|
2
|
+
onkcop:
|
3
|
+
- "config/rubocop.yml"
|
4
|
+
- "config/rspec.yml"
|
5
|
+
|
6
|
+
AllCops:
|
7
|
+
TargetRubyVersion: 2.3
|
8
|
+
# uncomment if use rails cops
|
9
|
+
# TargetRailsVersion: 5.1
|
10
|
+
|
11
|
+
require: rubocop-rspec
|
12
|
+
|
13
|
+
RSpec/FilePath:
|
14
|
+
Exclude:
|
15
|
+
- spec/integration_spec.rb
|
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 sue445
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
# Itest5ch
|
2
|
+
|
3
|
+
5ch (a.k.a. 2ch) reader via http://itest.5ch.net/
|
4
|
+
|
5
|
+
[](https://circleci.com/gh/sue445/itest5ch/tree/master)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'itest5ch'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install itest5ch
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
### [Itest5ch::Board](lib/itest5ch/board.rb)
|
26
|
+
|
27
|
+
#### Get all boards
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
category_boards = Itest5ch::Board.all
|
31
|
+
#=> {"地震"=>
|
32
|
+
[#<Itest5ch::Board:0x00007f821c5bb4b8 @name="地震headline", @url="http://itest.5ch.net/subback/bbynamazu">,
|
33
|
+
#<Itest5ch::Board:0x00007f821c5b9f78 @name="地震速報", @url="http://itest.5ch.net/subback/namazuplus">,
|
34
|
+
#<Itest5ch::Board:0x00007f821c5b8a38 @name="臨時地震", @url="http://itest.5ch.net/subback/eq">,
|
35
|
+
#<Itest5ch::Board:0x00007f821c5c37d0 @name="臨時地震+", @url="http://itest.5ch.net/subback/eqplus">,
|
36
|
+
#<Itest5ch::Board:0x00007f821c5c2290 @name="緊急自然災害", @url="http://itest.5ch.net/subback/lifeline">],
|
37
|
+
"おすすめ"=>
|
38
|
+
[#<Itest5ch::Board:0x00007f821c5d3dd8 @name="スマートフォン", @url="http://itest.5ch.net/subback/smartphone">,
|
39
|
+
#<Itest5ch::Board:0x00007f821c5d2898 @name="ハワイ州", @url="http://itest.5ch.net/subback/hawaii">,
|
40
|
+
#<Itest5ch::Board:0x00007f821c5d1358 @name="大学生活", @url="http://itest.5ch.net/subback/campus">,
|
41
|
+
#<Itest5ch::Board:0x00007f821c5dbf38 @name="恋愛サロン", @url="http://itest.5ch.net/subback/lovesaloon">,
|
42
|
+
#<Itest5ch::Board:0x00007f821c5da9f8 @name="アレルギー", @url="http://itest.5ch.net/subback/allergy">,
|
43
|
+
#<Itest5ch::Board:0x00007f821c5d94b8 @name="ラブライブ!", @url="http://itest.5ch.net/subback/lovelive">,
|
44
|
+
#<Itest5ch::Board:0x00007f821ca0e8d0 @name="Apple", @url="http://itest.5ch.net/subback/apple2">,
|
45
|
+
#<Itest5ch::Board:0x00007f821c5e2ba8 @name="初心者の質問", @url="http://itest.5ch.net/subback/qa">],
|
46
|
+
```
|
47
|
+
|
48
|
+
#### Get boards of a category
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
boards = Itest5ch::Board.find_category_boards("おすすめ")
|
52
|
+
#=> [#<Itest5ch::Board:0x00007f821c639840 @name="スマートフォン", @url="http://itest.5ch.net/subback/smartphone">,
|
53
|
+
#<Itest5ch::Board:0x00007f821c628dd8 @name="ハワイ州", @url="http://itest.5ch.net/subback/hawaii">,
|
54
|
+
#<Itest5ch::Board:0x00007f821c6185c8 @name="大学生活", @url="http://itest.5ch.net/subback/campus">,
|
55
|
+
#<Itest5ch::Board:0x00007f821c67bf10 @name="恋愛サロン", @url="http://itest.5ch.net/subback/lovesaloon">,
|
56
|
+
#<Itest5ch::Board:0x00007f821c66b728 @name="アレルギー", @url="http://itest.5ch.net/subback/allergy">,
|
57
|
+
#<Itest5ch::Board:0x00007f821c65add8 @name="ラブライブ!", @url="http://itest.5ch.net/subback/lovelive">,
|
58
|
+
#<Itest5ch::Board:0x00007f821c64a258 @name="Apple", @url="http://itest.5ch.net/subback/apple2">,
|
59
|
+
#<Itest5ch::Board:0x00007f821c6b9658 @name="初心者の質問", @url="http://itest.5ch.net/subback/qa">]
|
60
|
+
```
|
61
|
+
|
62
|
+
#### Get a board
|
63
|
+
```ruby
|
64
|
+
board = Itest5ch::Board.find("スマートフォン")
|
65
|
+
|
66
|
+
# or
|
67
|
+
|
68
|
+
board = Itest5ch::Board.find("smartphone")
|
69
|
+
```
|
70
|
+
|
71
|
+
### [Itest5ch::Thread](lib/itest5ch/thread.rb)
|
72
|
+
#### Get threads
|
73
|
+
```ruby
|
74
|
+
threads = board.threads
|
75
|
+
```
|
76
|
+
|
77
|
+
#### Get a thread
|
78
|
+
```ruby
|
79
|
+
# with PC url
|
80
|
+
thread = Itest5ch::Thread.new("http://egg.5ch.net/test/read.cgi/smartphone/0000000000")
|
81
|
+
|
82
|
+
# or
|
83
|
+
|
84
|
+
# with Smartphone url
|
85
|
+
thread = Itest5ch::Thread.new("http://itest.5ch.net/egg/test/read.cgi/smartphone/0000000000")
|
86
|
+
```
|
87
|
+
|
88
|
+
### [Itest5ch::Comment](lib/itest5ch/comment.rb)
|
89
|
+
```ruby
|
90
|
+
comments = thread.comments
|
91
|
+
```
|
92
|
+
|
93
|
+
### [Itest5ch::Config](lib/itest5ch/config.rb)
|
94
|
+
```ruby
|
95
|
+
Itest5ch.config.user_agent = "XXXX"
|
96
|
+
```
|
97
|
+
|
98
|
+
* `user_agent` : User Agent
|
99
|
+
|
100
|
+
## ProTip
|
101
|
+
When `Time.zone` is initialized, `Itest5ch::Comment#date` returns `ActiveSupport::TimeWithZone` instead of `Time` (requirements `activesupport`)
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
comment.date
|
105
|
+
#=> 2018-03-06 12:34:56 +0900
|
106
|
+
comment.date.class
|
107
|
+
#=> Time
|
108
|
+
```
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
require "active_support/time"
|
112
|
+
Time.zone = "Tokyo"
|
113
|
+
|
114
|
+
comment.date
|
115
|
+
#=> Tue, 06 Mar 2018 12:34:56 JST +09:00
|
116
|
+
comment.date.class
|
117
|
+
#=> ActiveSupport::TimeWithZone
|
118
|
+
```
|
119
|
+
|
120
|
+
## Development
|
121
|
+
|
122
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
123
|
+
|
124
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
125
|
+
|
126
|
+
## Contributing
|
127
|
+
|
128
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/sue445/itest5ch.
|
129
|
+
|
130
|
+
## License
|
131
|
+
|
132
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
desc "Run RSpec code examples (unit test)"
|
5
|
+
RSpec::Core::RakeTask.new("spec:unit") do |task|
|
6
|
+
task.rspec_opts = "--tag ~type:integration"
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "Run RSpec code examples (integration test)"
|
10
|
+
RSpec::Core::RakeTask.new("spec:integration") do |task|
|
11
|
+
task.rspec_opts = "--tag type:integration"
|
12
|
+
end
|
13
|
+
|
14
|
+
task :spec => ["spec:unit", "spec:integration"]
|
15
|
+
|
16
|
+
task :default => :spec
|
data/bin/console
ADDED
data/bin/setup
ADDED
data/itest5ch.gemspec
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("lib", __dir__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "itest5ch/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "itest5ch"
|
8
|
+
spec.version = Itest5ch::VERSION
|
9
|
+
spec.authors = ["sue445"]
|
10
|
+
spec.email = ["sue445@sue445.net"]
|
11
|
+
|
12
|
+
spec.summary = "5ch (a.k.a. 2ch) reader via itest.5ch.net"
|
13
|
+
spec.description = "5ch (a.k.a. 2ch) reader via itest.5ch.net"
|
14
|
+
spec.homepage = "https://github.com/sue445/itest5ch"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) {|f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_dependency "hpricot"
|
25
|
+
spec.add_dependency "htmlentities"
|
26
|
+
|
27
|
+
spec.add_development_dependency "activesupport"
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
29
|
+
spec.add_development_dependency "coveralls"
|
30
|
+
spec.add_development_dependency "onkcop", "0.53.0.0"
|
31
|
+
spec.add_development_dependency "pry-byebug"
|
32
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
33
|
+
spec.add_development_dependency "retryable"
|
34
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
35
|
+
spec.add_development_dependency "rspec-its"
|
36
|
+
spec.add_development_dependency "rspec-parameterized"
|
37
|
+
spec.add_development_dependency "rubocop", "0.53.0"
|
38
|
+
spec.add_development_dependency "rubocop-rspec", "1.25.1"
|
39
|
+
spec.add_development_dependency "simplecov"
|
40
|
+
spec.add_development_dependency "webmock"
|
41
|
+
spec.add_development_dependency "yard"
|
42
|
+
end
|
data/lib/itest5ch.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "itest5ch/version"
|
2
|
+
require "hpricot"
|
3
|
+
require "htmlentities"
|
4
|
+
|
5
|
+
module Itest5ch
|
6
|
+
autoload :AssertMethods, "itest5ch/assert_methods"
|
7
|
+
autoload :Board, "itest5ch/board"
|
8
|
+
autoload :BoardListPage, "itest5ch/board_list_page"
|
9
|
+
autoload :Comment, "itest5ch/comment"
|
10
|
+
autoload :Config, "itest5ch/config"
|
11
|
+
autoload :HttpMethods, "itest5ch/http_methods"
|
12
|
+
autoload :Thread, "itest5ch/thread"
|
13
|
+
|
14
|
+
# @return [Itest5ch::Config]
|
15
|
+
def self.config
|
16
|
+
@config ||= Config.new
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Itest5ch
|
2
|
+
module AssertMethods
|
3
|
+
# @param hash [Hash]
|
4
|
+
# @param keys [Array<Symbol>]
|
5
|
+
#
|
6
|
+
# @raise [ArgumentError]
|
7
|
+
def assert_required_keys!(hash, *keys)
|
8
|
+
keys.each do |key|
|
9
|
+
assert_required!(key, hash[key])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# @param name [Symbol]
|
14
|
+
# @param value [Object]
|
15
|
+
#
|
16
|
+
# @raise [ArgumentError]
|
17
|
+
def assert_required!(name, value)
|
18
|
+
raise ArgumentError, "#{name} is required" unless value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Itest5ch
|
2
|
+
class Board
|
3
|
+
include HttpMethods
|
4
|
+
|
5
|
+
# @!attribute [rw] url
|
6
|
+
# @return [String]
|
7
|
+
attr_accessor :url
|
8
|
+
|
9
|
+
# @!attribute [rw] name
|
10
|
+
# @return [String]
|
11
|
+
attr_accessor :name
|
12
|
+
|
13
|
+
# @param url [String]
|
14
|
+
# @param name [String]
|
15
|
+
def initialize(url, name: nil)
|
16
|
+
@url = url
|
17
|
+
@name = name
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param other [Itest5ch::Board]
|
21
|
+
#
|
22
|
+
# @return [Boolean]
|
23
|
+
def ==(other)
|
24
|
+
other.is_a?(Board) && url == other.url && name == other.name
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Array<Itest5ch::Thread>]
|
28
|
+
def threads
|
29
|
+
hash = get_json(json_url, referer: url)
|
30
|
+
hash["threads"].map do |thread|
|
31
|
+
board, dat = thread[3].split("/", 2)
|
32
|
+
Itest5ch::Thread.new(
|
33
|
+
subdomain: thread[2],
|
34
|
+
board: board,
|
35
|
+
dat: dat.to_i,
|
36
|
+
name: thread[5],
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [String]
|
42
|
+
def json_url
|
43
|
+
if (m = url.match(%r{^https?://itest\.5ch\.net/subback/(.+?)/?$}))
|
44
|
+
return "http://itest.5ch.net/subbacks/#{m[1]}.json"
|
45
|
+
end
|
46
|
+
|
47
|
+
if (m = url.match(%r{^https?://.+\.5ch\.net/(.+?)/?$}))
|
48
|
+
return "http://itest.5ch.net/subbacks/#{m[1]}.json"
|
49
|
+
end
|
50
|
+
|
51
|
+
raise "Unknown url: #{url}"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Get all boards
|
55
|
+
#
|
56
|
+
# @return [Hash<String, Array<Itest5ch::Board>>] key: category name, value: boards
|
57
|
+
def self.all
|
58
|
+
BoardListPage.new.all
|
59
|
+
end
|
60
|
+
|
61
|
+
# @param category_name [String]
|
62
|
+
#
|
63
|
+
# @return [Array<Itest5ch::Board>]
|
64
|
+
def self.find_category_boards(category_name)
|
65
|
+
all[category_name]
|
66
|
+
end
|
67
|
+
|
68
|
+
# @param board_name [String] name or id
|
69
|
+
#
|
70
|
+
# @return [Itest5ch::Board]
|
71
|
+
def self.find(board_name)
|
72
|
+
url = "#{Itest5ch::BoardListPage::BOARDS_URL}subback/#{board_name}"
|
73
|
+
all.values.flatten.find {|board| board_name == board.name || url == board.url }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Itest5ch
|
2
|
+
class BoardListPage
|
3
|
+
include HttpMethods
|
4
|
+
|
5
|
+
BOARDS_URL = "http://itest.5ch.net/".freeze
|
6
|
+
|
7
|
+
# Get all boards
|
8
|
+
#
|
9
|
+
# @return [Hash<String, Array<Itest5ch::Board>>] key: category name, value: boards
|
10
|
+
def all
|
11
|
+
doc = Hpricot(get_html(BOARDS_URL))
|
12
|
+
|
13
|
+
doc.search("//div[@id='bbsmenu']//ul[@class='pure-menu-list']").
|
14
|
+
reject {|ul| ul["id"] == "history" }.each_with_object({}) do |ul, categories|
|
15
|
+
|
16
|
+
category_name = ul.at("/li[@class='pure-menu-item pure-menu-selected']").inner_text.strip
|
17
|
+
categories[category_name] = get_boards(ul)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def get_boards(ul)
|
24
|
+
ul.search("/li").select {|li| board_element?(li) }.each_with_object([]) do |li, boards|
|
25
|
+
url = URI.join(BOARDS_URL, li.at("/a")["href"]).to_s
|
26
|
+
name = li.inner_text.strip
|
27
|
+
|
28
|
+
boards << Board.new(url, name: name)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def board_element?(li)
|
33
|
+
return false unless li["class"].include?("pure-menu-item")
|
34
|
+
return false if li["class"].include?("pure-menu-selected")
|
35
|
+
|
36
|
+
true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Itest5ch
|
2
|
+
require "base64"
|
3
|
+
|
4
|
+
class Comment
|
5
|
+
# @!attribute number
|
6
|
+
# @return [Integer]
|
7
|
+
attr_accessor :number
|
8
|
+
|
9
|
+
# @!attribute name
|
10
|
+
# @return [String]
|
11
|
+
attr_accessor :name
|
12
|
+
|
13
|
+
# @!attribute mail
|
14
|
+
# @return [String]
|
15
|
+
attr_accessor :mail
|
16
|
+
|
17
|
+
# @!attribute date
|
18
|
+
# @return [Time]
|
19
|
+
attr_accessor :date
|
20
|
+
|
21
|
+
# @!attribute id
|
22
|
+
# @return [String]
|
23
|
+
attr_accessor :id
|
24
|
+
|
25
|
+
# @!attribute message
|
26
|
+
# @return [String]
|
27
|
+
attr_accessor :message
|
28
|
+
|
29
|
+
# @!attribute thread
|
30
|
+
# @return [Itest5ch::Thread]
|
31
|
+
attr_accessor :thread
|
32
|
+
|
33
|
+
# @param number [Integer]
|
34
|
+
# @param name [String]
|
35
|
+
# @param mail [String]
|
36
|
+
# @param date [Time]
|
37
|
+
# @param id [String]
|
38
|
+
# @param message [String]
|
39
|
+
# @param thread [Itest5ch::Thread]
|
40
|
+
def initialize(number:, name:, mail:, date:, id:, message:, thread:) # rubocop:disable Metrics/ParameterLists
|
41
|
+
@number = number
|
42
|
+
@name = name
|
43
|
+
@mail = mail
|
44
|
+
@date = date
|
45
|
+
@id = id
|
46
|
+
@message = message
|
47
|
+
@thread = thread
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Array<Integer>]
|
51
|
+
def anchor_numbers
|
52
|
+
numbers =
|
53
|
+
message.scan(/[>>]+([0-90-9\-]+)/).map do |result|
|
54
|
+
str = result.first.tr("0-9", "0-9")
|
55
|
+
if (m = str.match(/([0-9]+)-([0-9]+)/))
|
56
|
+
(m[1].to_i..m[2].to_i).to_a
|
57
|
+
else
|
58
|
+
str.to_i
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
numbers.flatten.compact
|
63
|
+
end
|
64
|
+
|
65
|
+
alias_method :reply_numbers, :anchor_numbers
|
66
|
+
|
67
|
+
# @return [String]
|
68
|
+
def pc_url
|
69
|
+
"#{thread.pc_url}/#{number}"
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [String]
|
73
|
+
def smartphone_url
|
74
|
+
"#{thread.smartphone_url}/#{number}"
|
75
|
+
end
|
76
|
+
|
77
|
+
# Get Id checker url for http://hissi.org
|
78
|
+
#
|
79
|
+
# @return [String]
|
80
|
+
# @return [nil] {#id} is empty
|
81
|
+
#
|
82
|
+
# @see http://hissi.org
|
83
|
+
def id_checker_url
|
84
|
+
return nil if !id || id.empty?
|
85
|
+
|
86
|
+
ymd = date.strftime("%Y%m%d")
|
87
|
+
encoded_id = Base64.strict_encode64(id).delete("=")
|
88
|
+
"http://hissi.org/read.php/#{thread.board}/#{ymd}/#{encoded_id}.html"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Itest5ch
|
2
|
+
module HttpMethods
|
3
|
+
require "open-uri"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
# @param url [String]
|
7
|
+
# @param referer [String]
|
8
|
+
#
|
9
|
+
# @return [String]
|
10
|
+
def get_html(url, referer: nil)
|
11
|
+
options = {}
|
12
|
+
options["User-Agent"] = Itest5ch.config.user_agent if Itest5ch.config.user_agent
|
13
|
+
options["Referer"] = referer if referer
|
14
|
+
|
15
|
+
open(url, options).read # rubocop:disable Security/Open
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param url [String]
|
19
|
+
# @param referer [String]
|
20
|
+
#
|
21
|
+
# @return [Hash]
|
22
|
+
def get_json(url, referer: nil)
|
23
|
+
JSON.parse(get_html(url, referer: referer))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
module Itest5ch
|
2
|
+
require "securerandom"
|
3
|
+
require "cgi"
|
4
|
+
|
5
|
+
class Thread
|
6
|
+
include HttpMethods
|
7
|
+
include AssertMethods
|
8
|
+
|
9
|
+
# @!attribute [rw] subdomain
|
10
|
+
# @return [String]
|
11
|
+
attr_accessor :subdomain
|
12
|
+
|
13
|
+
# @!attribute [rw] board
|
14
|
+
# @return [String]
|
15
|
+
attr_accessor :board
|
16
|
+
|
17
|
+
# @!attribute [rw] dat
|
18
|
+
# @return [Integer]
|
19
|
+
attr_accessor :dat
|
20
|
+
|
21
|
+
# @!attribute [w] name
|
22
|
+
attr_writer :name
|
23
|
+
|
24
|
+
# @overload initialize(subdomain:, board:, dat:, name: nil)
|
25
|
+
# Set attributes
|
26
|
+
#
|
27
|
+
# @param subdomain [String]
|
28
|
+
# @param board [String]
|
29
|
+
# @param dat [Integer]
|
30
|
+
# @param name [String]
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# thread = Itest5ch::Thread.new(subdomain: "egg", board: "applism", dat: 1234567890)
|
34
|
+
#
|
35
|
+
# @overload initialize(url)
|
36
|
+
# Set thread url (PC or SmartPhone)
|
37
|
+
#
|
38
|
+
# @param url [String] thread url
|
39
|
+
#
|
40
|
+
# @example with SmartPhone url
|
41
|
+
# thread = Itest5ch::Thread.new("http://itest.5ch.net/egg/test/read.cgi/applism/1234567890")
|
42
|
+
#
|
43
|
+
# @example with PC url
|
44
|
+
# thread = Itest5ch::Thread.new("http://egg.5ch.net/test/read.cgi/applism/1234567890")
|
45
|
+
#
|
46
|
+
# @raise [ArgumentError] `arg` is not either Hash and String
|
47
|
+
def initialize(args)
|
48
|
+
case args
|
49
|
+
when Hash
|
50
|
+
initialize_with_hash(args)
|
51
|
+
when String
|
52
|
+
initialize_with_string(args)
|
53
|
+
else
|
54
|
+
raise ArgumentError, "args is either Hash or String is required"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# @param other [Itest5ch::Thread]
|
59
|
+
#
|
60
|
+
# @return [Boolean]
|
61
|
+
def ==(other)
|
62
|
+
other.is_a?(Thread) && subdomain == other.subdomain && board == other.board &&
|
63
|
+
dat == other.dat && name == other.name
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [Array<Itest5ch::Comment>]
|
67
|
+
def comments
|
68
|
+
fetch_data["comments"].map do |comment|
|
69
|
+
Comment.new(
|
70
|
+
number: comment[0].to_i,
|
71
|
+
name: comment[1],
|
72
|
+
mail: comment[2],
|
73
|
+
date: time_at(comment[3].to_i),
|
74
|
+
id: comment[4],
|
75
|
+
message: self.class.normalize_message(comment[6]),
|
76
|
+
thread: self,
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# @param message [String]
|
82
|
+
#
|
83
|
+
# @return [String]
|
84
|
+
def self.normalize_message(message)
|
85
|
+
message = coder.decode(message).scrub("")
|
86
|
+
message = CGI.unescapeHTML(message)
|
87
|
+
message.gsub(/\s*<br>\s*/i, "\n").strip
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.coder
|
91
|
+
@coder ||= HTMLEntities.new
|
92
|
+
end
|
93
|
+
private_class_method :coder
|
94
|
+
|
95
|
+
# @return [String]
|
96
|
+
def smartphone_url
|
97
|
+
"http://itest.5ch.net/#{subdomain}/test/read.cgi/#{board}/#{dat}"
|
98
|
+
end
|
99
|
+
|
100
|
+
# @return [String]
|
101
|
+
def pc_url
|
102
|
+
"http://#{subdomain}.5ch.net/test/read.cgi/#{board}/#{dat}"
|
103
|
+
end
|
104
|
+
|
105
|
+
# @return [String]
|
106
|
+
def name
|
107
|
+
@name ||= fetch_name
|
108
|
+
end
|
109
|
+
|
110
|
+
# @return [String] thread name
|
111
|
+
def fetch_name
|
112
|
+
fetch_data["thread"][5]
|
113
|
+
end
|
114
|
+
|
115
|
+
# @return [String]
|
116
|
+
def json_url
|
117
|
+
"http://itest.5ch.net/public/newapi/client.php?subdomain=#{subdomain}&board=#{board}&dat=#{dat}&rand=#{rand}"
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
# @param hash [Hash]
|
123
|
+
def initialize_with_hash(hash)
|
124
|
+
assert_required_keys!(hash, :subdomain, :board, :dat)
|
125
|
+
|
126
|
+
@subdomain = hash[:subdomain]
|
127
|
+
@board = hash[:board]
|
128
|
+
@dat = hash[:dat]
|
129
|
+
@name = hash[:name]
|
130
|
+
end
|
131
|
+
|
132
|
+
# @param url [String]
|
133
|
+
def initialize_with_string(url)
|
134
|
+
if (m = url.match(%r{https?://itest\.5ch\.net/(.+)/test/read\.cgi/([^/]+)/([0-9]+)}))
|
135
|
+
@subdomain = m[1]
|
136
|
+
@board = m[2]
|
137
|
+
@dat = m[3].to_i
|
138
|
+
return
|
139
|
+
end
|
140
|
+
|
141
|
+
if (m = url.match(%r{https?://(.+)\.5ch\.net/test/read\.cgi/([^/]+)/([0-9]+)}))
|
142
|
+
@subdomain = m[1]
|
143
|
+
@board = m[2]
|
144
|
+
@dat = m[3].to_i
|
145
|
+
return
|
146
|
+
end
|
147
|
+
|
148
|
+
raise ArgumentError, "'#{url}' is invalid url format"
|
149
|
+
end
|
150
|
+
|
151
|
+
# @return [Hash]
|
152
|
+
def fetch_data
|
153
|
+
get_json(json_url, referer: smartphone_url)
|
154
|
+
end
|
155
|
+
|
156
|
+
# @return [String] random 10 char string
|
157
|
+
def rand
|
158
|
+
SecureRandom.hex(5)
|
159
|
+
end
|
160
|
+
|
161
|
+
# @param unixtime [Integer]
|
162
|
+
#
|
163
|
+
# @return [ActiveSupport::TimeWithZone] When `Time.zone` is initialized
|
164
|
+
# @return [Time] When `Time.zone` is not initialized or without activesupport
|
165
|
+
def time_at(unixtime)
|
166
|
+
if Time.respond_to?(:zone) && Time.zone.respond_to?(:at)
|
167
|
+
Time.zone.at(unixtime)
|
168
|
+
else
|
169
|
+
Time.at(unixtime)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
metadata
ADDED
@@ -0,0 +1,306 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: itest5ch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- sue445
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-05-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hpricot
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: htmlentities
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activesupport
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.16'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.16'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: coveralls
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: onkcop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.53.0.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.53.0.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry-byebug
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '10.0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '10.0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: retryable
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rspec
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '3.0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '3.0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rspec-its
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: rspec-parameterized
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: rubocop
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - '='
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: 0.53.0
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - '='
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: 0.53.0
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: rubocop-rspec
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - '='
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: 1.25.1
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - '='
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: 1.25.1
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: simplecov
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - ">="
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '0'
|
223
|
+
- !ruby/object:Gem::Dependency
|
224
|
+
name: webmock
|
225
|
+
requirement: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - ">="
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
requirements:
|
234
|
+
- - ">="
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: '0'
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: yard
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - ">="
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: '0'
|
244
|
+
type: :development
|
245
|
+
prerelease: false
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - ">="
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0'
|
251
|
+
description: 5ch (a.k.a. 2ch) reader via itest.5ch.net
|
252
|
+
email:
|
253
|
+
- sue445@sue445.net
|
254
|
+
executables: []
|
255
|
+
extensions: []
|
256
|
+
extra_rdoc_files: []
|
257
|
+
files:
|
258
|
+
- ".circleci/config.yml"
|
259
|
+
- ".circleci/setup.sh"
|
260
|
+
- ".coveralls.yml"
|
261
|
+
- ".gitignore"
|
262
|
+
- ".rspec"
|
263
|
+
- ".rubocop.yml"
|
264
|
+
- ".yardopts"
|
265
|
+
- CHANGELOG.md
|
266
|
+
- Gemfile
|
267
|
+
- LICENSE.txt
|
268
|
+
- README.md
|
269
|
+
- Rakefile
|
270
|
+
- bin/console
|
271
|
+
- bin/setup
|
272
|
+
- itest5ch.gemspec
|
273
|
+
- lib/itest5ch.rb
|
274
|
+
- lib/itest5ch/assert_methods.rb
|
275
|
+
- lib/itest5ch/board.rb
|
276
|
+
- lib/itest5ch/board_list_page.rb
|
277
|
+
- lib/itest5ch/comment.rb
|
278
|
+
- lib/itest5ch/config.rb
|
279
|
+
- lib/itest5ch/http_methods.rb
|
280
|
+
- lib/itest5ch/thread.rb
|
281
|
+
- lib/itest5ch/version.rb
|
282
|
+
homepage: https://github.com/sue445/itest5ch
|
283
|
+
licenses:
|
284
|
+
- MIT
|
285
|
+
metadata: {}
|
286
|
+
post_install_message:
|
287
|
+
rdoc_options: []
|
288
|
+
require_paths:
|
289
|
+
- lib
|
290
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
291
|
+
requirements:
|
292
|
+
- - ">="
|
293
|
+
- !ruby/object:Gem::Version
|
294
|
+
version: '0'
|
295
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
296
|
+
requirements:
|
297
|
+
- - ">="
|
298
|
+
- !ruby/object:Gem::Version
|
299
|
+
version: '0'
|
300
|
+
requirements: []
|
301
|
+
rubyforge_project:
|
302
|
+
rubygems_version: 2.7.6
|
303
|
+
signing_key:
|
304
|
+
specification_version: 4
|
305
|
+
summary: 5ch (a.k.a. 2ch) reader via itest.5ch.net
|
306
|
+
test_files: []
|