legitbot 0.4.2 → 1.1.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 +4 -4
- data/.editorconfig +17 -0
- data/.github/workflows/build.yml +60 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +2 -8
- data/.ruby-version +1 -0
- data/README.md +7 -1
- data/legitbot.gemspec +2 -2
- data/lib/legitbot.rb +1 -0
- data/lib/legitbot/alexa.rb +17 -0
- data/lib/legitbot/duckduckgo.rb +4 -1
- data/lib/legitbot/legitbot.rb +2 -0
- data/lib/legitbot/validators/ip_ranges.rb +11 -7
- data/lib/legitbot/version.rb +1 -1
- data/lib/legitbot/yandex.rb +27 -14
- data/test/alexa_test.rb +36 -0
- data/test/apple_test.rb +2 -2
- data/test/facebook_test.rb +4 -4
- data/test/legitbot/validators/ip_ranges_test.rb +9 -0
- metadata +39 -34
- data/.travis.yml +0 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0ad027c85951667c22f02a0fde2347e5d1503493b07f4f041ab1f0965eae096b
|
|
4
|
+
data.tar.gz: a967d17674592fb06cefbebf8abe7fce9b72e49281f116ab337d0f888d46d326
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: be5c129e2d5e4f381a056744daa29907da3bb42849ff2ff33b7b45525d1175ad465e01f6f3e1b523b5163608ad747edbebea1c4bd3e355d927b3102ad3dca016
|
|
7
|
+
data.tar.gz: 9562a862188263637923035e0cc8b533f1f4153bc863c07a1b01538f2487c1052b0c68a4ca00dcf4085eb6a031c2cc92d264985fd429ecf47f8aadd46801eca0
|
data/.editorconfig
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
end_of_line = lf
|
|
5
|
+
insert_final_newline = true
|
|
6
|
+
trim_trailing_whitespace = true
|
|
7
|
+
charset = utf-8
|
|
8
|
+
|
|
9
|
+
indent_style = space
|
|
10
|
+
indent_size = 2
|
|
11
|
+
|
|
12
|
+
[*.md]
|
|
13
|
+
trim_trailing_whitespace = false
|
|
14
|
+
|
|
15
|
+
[*.yml]
|
|
16
|
+
indent_style = space
|
|
17
|
+
indent_size = 2
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: build
|
|
2
|
+
|
|
3
|
+
on: [pull_request, push]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
test:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
|
|
9
|
+
strategy:
|
|
10
|
+
fail-fast: false
|
|
11
|
+
matrix:
|
|
12
|
+
ruby: [ jruby, 2.6 ]
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v2
|
|
16
|
+
- name: Set up Ruby
|
|
17
|
+
uses: ruby/setup-ruby@v1
|
|
18
|
+
with:
|
|
19
|
+
ruby-version: ${{ matrix.ruby }}
|
|
20
|
+
- name: Cache dependencies
|
|
21
|
+
uses: actions/cache@v1
|
|
22
|
+
with:
|
|
23
|
+
path: vendor/bundle
|
|
24
|
+
key: ${{ runner.os }}-${{ matrix.ruby }}-gems-${{ hashFiles('**/Gemfile.lock') }}
|
|
25
|
+
restore-keys: |
|
|
26
|
+
${{ runner.os }}-${{ matrix.ruby }}-gems-
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: |
|
|
29
|
+
bundle config path vendor/bundle
|
|
30
|
+
bundle install --jobs 4 --retry 3
|
|
31
|
+
- name: Run tests
|
|
32
|
+
run: bundle exec rake test
|
|
33
|
+
|
|
34
|
+
lint:
|
|
35
|
+
needs: test
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
|
|
38
|
+
strategy:
|
|
39
|
+
matrix:
|
|
40
|
+
ruby: [ 2.6 ]
|
|
41
|
+
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v2
|
|
44
|
+
- name: Set up Ruby
|
|
45
|
+
uses: ruby/setup-ruby@v1
|
|
46
|
+
with:
|
|
47
|
+
ruby-version: ${{ matrix.ruby }}
|
|
48
|
+
- name: Cache dependencies
|
|
49
|
+
uses: actions/cache@v1
|
|
50
|
+
with:
|
|
51
|
+
path: vendor/bundle
|
|
52
|
+
key: ${{ runner.os }}-${{ matrix.ruby }}-gems-${{ hashFiles('**/Gemfile.lock') }}
|
|
53
|
+
restore-keys: |
|
|
54
|
+
${{ runner.os }}-${{ matrix.ruby }}-gems-
|
|
55
|
+
- name: Install dependencies
|
|
56
|
+
run: |
|
|
57
|
+
bundle config path vendor/bundle
|
|
58
|
+
bundle install --jobs 4 --retry 3
|
|
59
|
+
- name: Run linter
|
|
60
|
+
run: bundle exec rubocop
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.4
|
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Legitbot
|
|
1
|
+
# Legitbot  [](https://badge.fury.io/rb/legitbot)
|
|
2
2
|
|
|
3
3
|
Ruby gem to check that an IP belongs to a bot, typically a search
|
|
4
4
|
engine. This can be of help in protecting a web site from fake search
|
|
@@ -44,6 +44,7 @@ end
|
|
|
44
44
|
## Supported
|
|
45
45
|
|
|
46
46
|
* [Ahrefs](https://ahrefs.com/robot)
|
|
47
|
+
* [Alexa](https://support.alexa.com/hc/en-us/articles/360046707834-What-are-the-IP-addresses-for-Alexa-s-Certify-and-Site-Audit-crawlers-)
|
|
47
48
|
* [Applebot](https://support.apple.com/en-us/HT204683)
|
|
48
49
|
* [Baidu spider](http://help.baidu.com/question?prod_en=master&class=498&id=1000973)
|
|
49
50
|
* [Bingbot](https://blogs.bing.com/webmaster/2012/08/31/how-to-verify-that-bingbot-is-bingbot/)
|
|
@@ -67,3 +68,8 @@ Apache 2.0
|
|
|
67
68
|
detects bots by `User-Agent`
|
|
68
69
|
* [crawler_detect](https://github.com/loadkpi/crawler_detect) is a Ruby gem and Rack
|
|
69
70
|
middleware to detect crawlers by few different request headers, including `User-Agent`
|
|
71
|
+
* Project Honeypot's
|
|
72
|
+
[http:BL](https://www.projecthoneypot.org/httpbl_api.php) can not only
|
|
73
|
+
classify IP as a search engine, but also label them as suspicious and
|
|
74
|
+
reports the number of days since the last activity. My implementation of
|
|
75
|
+
the protocol in Scala is [here](https://github.com/osinka/httpbl).
|
data/legitbot.gemspec
CHANGED
|
@@ -14,13 +14,13 @@ Gem::Specification.new do |spec|
|
|
|
14
14
|
spec.summary = 'Validate requests from Web crawlers: impersonating or not?'
|
|
15
15
|
spec.description = 'Does Web request come from a real search engine or from an impersonating agent?'
|
|
16
16
|
|
|
17
|
-
spec.required_ruby_version = '>= 2.
|
|
17
|
+
spec.required_ruby_version = '>= 2.4.0'
|
|
18
18
|
spec.add_dependency 'augmented_interval_tree', '~> 0.1', '>= 0.1.1'
|
|
19
19
|
spec.add_dependency 'irrc', '~> 0.2', '>= 0.2.1'
|
|
20
20
|
spec.add_development_dependency 'bump', '~> 0.8', '>= 0.8.0'
|
|
21
21
|
spec.add_development_dependency 'minitest', '~> 5.1', '>= 5.1.0'
|
|
22
22
|
spec.add_development_dependency 'rake', '~> 12.3', '>= 12.3.0'
|
|
23
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
|
23
|
+
spec.add_development_dependency 'rubocop', '~> 0.90', '< 0.91'
|
|
24
24
|
|
|
25
25
|
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
|
26
26
|
spec.rdoc_options = ['--charset=UTF-8']
|
data/lib/legitbot.rb
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legitbot # :nodoc:
|
|
4
|
+
# https://support.alexa.com/hc/en-us/articles/360046707834-What-are-the-IP-addresses-for-Alexa-s-Certify-and-Site-Audit-crawlers-
|
|
5
|
+
# https://support.alexa.com/hc/en-us/articles/200462340
|
|
6
|
+
# https://support.alexa.com/hc/en-us/articles/200450194
|
|
7
|
+
class Alexa < BotMatch
|
|
8
|
+
ip_ranges %w[
|
|
9
|
+
52.86.176.3
|
|
10
|
+
52.4.48.181
|
|
11
|
+
52.2.182.169
|
|
12
|
+
52.86.185.29
|
|
13
|
+
]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
rule Legitbot::Alexa, %w[Alexabot ia_archiver]
|
|
17
|
+
end
|
data/lib/legitbot/duckduckgo.rb
CHANGED
|
@@ -4,6 +4,8 @@ module Legitbot # :nodoc:
|
|
|
4
4
|
# https://duckduckgo.com/duckduckbot
|
|
5
5
|
class DuckDuckGo < BotMatch
|
|
6
6
|
ip_ranges %w[
|
|
7
|
+
23.21.227.69
|
|
8
|
+
40.88.21.235
|
|
7
9
|
50.16.241.113
|
|
8
10
|
50.16.241.114
|
|
9
11
|
50.16.241.117
|
|
@@ -12,7 +14,8 @@ module Legitbot # :nodoc:
|
|
|
12
14
|
52.5.190.19
|
|
13
15
|
54.197.234.188
|
|
14
16
|
54.208.100.253
|
|
15
|
-
|
|
17
|
+
54.208.102.37
|
|
18
|
+
107.21.1.8
|
|
16
19
|
]
|
|
17
20
|
end
|
|
18
21
|
|
data/lib/legitbot/legitbot.rb
CHANGED
|
@@ -18,6 +18,7 @@ module Legitbot
|
|
|
18
18
|
# otherwise.
|
|
19
19
|
# :yields: a found bot
|
|
20
20
|
#
|
|
21
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
21
22
|
def self.bot(user_agent, ip)
|
|
22
23
|
bots = @rules
|
|
23
24
|
.select { |rule| rule[:fragments].any? { |f| user_agent.index f } }
|
|
@@ -32,6 +33,7 @@ module Legitbot
|
|
|
32
33
|
selected
|
|
33
34
|
end
|
|
34
35
|
end
|
|
36
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
35
37
|
|
|
36
38
|
def self.rule(clazz, fragments)
|
|
37
39
|
@rules << { class: clazz, fragments: fragments }
|
|
@@ -59,22 +59,26 @@ module Legitbot
|
|
|
59
59
|
partition_ips(@ip_ranges_loader.call)
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
63
62
|
def partition_ips(ips)
|
|
64
|
-
return []
|
|
63
|
+
return [] unless ips&.any?
|
|
65
64
|
|
|
66
65
|
ips
|
|
67
66
|
.map { |cidr| IPAddr.new(cidr) }
|
|
68
67
|
.partition(&:ipv4?)
|
|
69
68
|
.each_with_index
|
|
70
69
|
.map do |list, index|
|
|
71
|
-
|
|
72
|
-
(r.begin.to_i..r.end.to_i)
|
|
73
|
-
end
|
|
74
|
-
[FAMILIES[index], IntervalTree::Tree.new(ranges)]
|
|
70
|
+
[FAMILIES[index], build_interval_tree(list)]
|
|
75
71
|
end.to_h
|
|
76
72
|
end
|
|
77
|
-
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def build_interval_tree(list)
|
|
77
|
+
ranges = list.map(&:to_range).map do |r|
|
|
78
|
+
(r.begin.to_i..r.end.to_i)
|
|
79
|
+
end
|
|
80
|
+
IntervalTree::Tree.new(ranges)
|
|
81
|
+
end
|
|
78
82
|
end
|
|
79
83
|
end
|
|
80
84
|
end
|
data/lib/legitbot/version.rb
CHANGED
data/lib/legitbot/yandex.rb
CHANGED
|
@@ -7,27 +7,40 @@ module Legitbot # :nodoc:
|
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
rule Legitbot::Yandex, %w[
|
|
10
|
-
YandexBot
|
|
11
10
|
YandexAccessibilityBot
|
|
12
|
-
|
|
13
|
-
YandexDirectDyn
|
|
14
|
-
YandexScreenshotBot
|
|
15
|
-
YandexImages
|
|
16
|
-
YandexVideo
|
|
17
|
-
YandexVideoParser
|
|
18
|
-
YandexMedia
|
|
11
|
+
YandexAdNet
|
|
19
12
|
YandexBlogs
|
|
13
|
+
YandexBot/
|
|
14
|
+
YandexCalendar
|
|
15
|
+
YandexDirect/
|
|
16
|
+
YandexDirectDyn
|
|
20
17
|
YandexFavicons
|
|
21
|
-
YandexWebmaster
|
|
22
|
-
YandexPagechecker
|
|
23
|
-
YandexImageResizer
|
|
24
18
|
YaDirectFetcher
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
YandexForDomain
|
|
20
|
+
YandexImages
|
|
21
|
+
YandexImageResizer
|
|
22
|
+
YandexMobileBot
|
|
23
|
+
YandexMarket
|
|
24
|
+
YandexMedia
|
|
27
25
|
YandexMetrika
|
|
26
|
+
YandexMobileScreenShotBot
|
|
28
27
|
YandexNews
|
|
29
|
-
|
|
28
|
+
YandexOntoDB
|
|
29
|
+
YandexOntoDBAPI
|
|
30
|
+
YandexPagechecker
|
|
31
|
+
YandexPartner
|
|
32
|
+
YandexRCA
|
|
30
33
|
YandexSearchShop
|
|
34
|
+
YandexSitelinks
|
|
35
|
+
YandexSpravBot
|
|
36
|
+
YandexTracker
|
|
37
|
+
YandexTurbo
|
|
38
|
+
YandexVertis
|
|
31
39
|
YandexVerticals
|
|
40
|
+
YandexVideo
|
|
41
|
+
YandexVideoParser
|
|
42
|
+
YandexWebmaster
|
|
43
|
+
YandexScreenshotBot
|
|
44
|
+
YandexMedianaBot
|
|
32
45
|
]
|
|
33
46
|
end
|
data/test/alexa_test.rb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'minitest/autorun'
|
|
4
|
+
require 'legitbot'
|
|
5
|
+
|
|
6
|
+
class AlexaTest < Minitest::Test
|
|
7
|
+
def test_malicious_ip
|
|
8
|
+
ip = '149.210.164.47'
|
|
9
|
+
match = Legitbot::Alexa.new ip
|
|
10
|
+
assert !match.valid?, msg: "#{ip} is not a real Alexa IP"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def test_valid_ip
|
|
14
|
+
ip = '52.86.176.3'
|
|
15
|
+
match = Legitbot::Alexa.new ip
|
|
16
|
+
assert match.valid?, msg: "#{ip} is a valid Alexa IP"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_malicious_ua
|
|
20
|
+
bot = Legitbot.bot(
|
|
21
|
+
'Mozilla/5.0 (compatible; Alexabot/1.0; +http://www.alexa.com/help/certifyscan; certifyscan@alexa.com)',
|
|
22
|
+
'149.210.164.47'
|
|
23
|
+
)
|
|
24
|
+
assert bot, msg: 'Alexa detected from User-Agent'
|
|
25
|
+
assert !bot.valid?, msg: 'Not a valid Alexa'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_valid_ua
|
|
29
|
+
bot = Legitbot.bot(
|
|
30
|
+
'Mozilla/5.0 (compatible; Alexabot/1.0; +http://www.alexa.com/help/certifyscan; certifyscan@alexa.com)',
|
|
31
|
+
'52.86.176.3'
|
|
32
|
+
)
|
|
33
|
+
assert bot, msg: 'Alexa detected from User-Agent'
|
|
34
|
+
assert bot.valid?, msg: 'Valid Alexa'
|
|
35
|
+
end
|
|
36
|
+
end
|
data/test/apple_test.rb
CHANGED
|
@@ -16,7 +16,7 @@ class AppleTest < Minitest::Test
|
|
|
16
16
|
assert match.fake?, msg: "#{ip} is a fake Applebot IP"
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
# rubocop:disable
|
|
19
|
+
# rubocop:disable Layout/LineLength
|
|
20
20
|
def test_user_agent
|
|
21
21
|
bot = Legitbot.bot(
|
|
22
22
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Applebot/0.1; +http://www.apple.com/go/applebot)',
|
|
@@ -25,5 +25,5 @@ class AppleTest < Minitest::Test
|
|
|
25
25
|
assert_equal :apple, bot.detected_as
|
|
26
26
|
assert bot.valid?, msg: 'A valid Applebot User-agent and IP'
|
|
27
27
|
end
|
|
28
|
-
# rubocop:enable
|
|
28
|
+
# rubocop:enable Layout/LineLength
|
|
29
29
|
end
|
data/test/facebook_test.rb
CHANGED
|
@@ -5,14 +5,14 @@ require 'legitbot'
|
|
|
5
5
|
|
|
6
6
|
module Legitbot
|
|
7
7
|
class Facebook
|
|
8
|
-
# rubocop:disable
|
|
8
|
+
# rubocop:disable Layout/LineLength
|
|
9
9
|
def self.whois
|
|
10
10
|
{
|
|
11
11
|
ipv4: ['69.63.176.0/20', '66.220.144.0/20', '66.220.144.0/21', '69.63.184.0/21', '69.63.176.0/21', '74.119.76.0/22', '69.171.255.0/24', '173.252.64.0/18', '69.171.224.0/19', '69.171.224.0/20', '103.4.96.0/22', '69.63.176.0/24', '173.252.64.0/19', '173.252.70.0/24', '31.13.64.0/18', '31.13.24.0/21', '66.220.152.0/21', '66.220.159.0/24', '69.171.239.0/24', '69.171.240.0/20', '31.13.64.0/19', '31.13.64.0/24', '31.13.65.0/24', '31.13.67.0/24', '31.13.68.0/24', '31.13.69.0/24', '31.13.70.0/24', '31.13.71.0/24', '31.13.72.0/24', '31.13.73.0/24', '31.13.74.0/24', '31.13.75.0/24', '31.13.76.0/24', '31.13.77.0/24', '31.13.96.0/19', '31.13.66.0/24', '173.252.96.0/19', '69.63.178.0/24', '31.13.78.0/24', '31.13.79.0/24', '31.13.80.0/24', '31.13.82.0/24', '31.13.83.0/24', '31.13.84.0/24', '31.13.85.0/24', '31.13.86.0/24', '31.13.87.0/24', '31.13.88.0/24', '31.13.89.0/24', '31.13.90.0/24', '31.13.91.0/24', '31.13.92.0/24', '31.13.93.0/24', '31.13.94.0/24', '31.13.95.0/24', '69.171.253.0/24', '69.63.186.0/24', '31.13.81.0/24', '179.60.192.0/22', '179.60.192.0/24', '179.60.193.0/24', '179.60.194.0/24', '179.60.195.0/24', '185.60.216.0/22', '45.64.40.0/22', '185.60.216.0/24', '185.60.217.0/24', '185.60.218.0/24', '185.60.219.0/24', '129.134.0.0/16', '157.240.0.0/16', '157.240.8.0/24', '157.240.0.0/24', '157.240.1.0/24', '157.240.2.0/24', '157.240.3.0/24', '157.240.4.0/24', '157.240.5.0/24', '157.240.6.0/24', '157.240.7.0/24', '157.240.9.0/24', '157.240.10.0/24', '157.240.16.0/24', '157.240.19.0/24', '157.240.11.0/24', '157.240.12.0/24', '157.240.13.0/24', '157.240.14.0/24', '157.240.15.0/24', '157.240.17.0/24', '157.240.18.0/24', '157.240.20.0/24', '157.240.21.0/24', '157.240.22.0/24', '157.240.23.0/24', '157.240.0.0/17', '69.171.250.0/24', '157.240.24.0/24', '157.240.25.0/24', '199.201.64.0/24', '199.201.65.0/24', '199.201.64.0/22', '204.15.20.0/22', '157.240.192.0/24', '129.134.0.0/17', '157.240.198.0/24'],
|
|
12
12
|
ipv6: []
|
|
13
13
|
}
|
|
14
14
|
end
|
|
15
|
-
# rubocop:enable
|
|
15
|
+
# rubocop:enable Layout/LineLength
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
|
|
@@ -33,7 +33,7 @@ class FacebookTest < Minitest::Test
|
|
|
33
33
|
assert match.fake?, msg: "#{ip} is a fake Facebook IP"
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
# rubocop:disable
|
|
36
|
+
# rubocop:disable Layout/LineLength, Metrics/MethodLength
|
|
37
37
|
def test_user_agent
|
|
38
38
|
Legitbot.bot(
|
|
39
39
|
'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)',
|
|
@@ -59,5 +59,5 @@ class FacebookTest < Minitest::Test
|
|
|
59
59
|
assert bot.fake?, msg: 'fake Facebook'
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
|
-
# rubocop:enable
|
|
62
|
+
# rubocop:enable Layout/LineLength, Metrics/MethodLength
|
|
63
63
|
end
|
|
@@ -46,6 +46,11 @@ module Legitbot
|
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
+
class NilRanges
|
|
50
|
+
include IpRanges
|
|
51
|
+
ip_ranges { nil }
|
|
52
|
+
end
|
|
53
|
+
|
|
49
54
|
class IpRangesTest < Minitest::Test
|
|
50
55
|
def test_partition_method
|
|
51
56
|
empty = NoRanges.partition_ips([])
|
|
@@ -108,6 +113,10 @@ module Legitbot
|
|
|
108
113
|
assert_equal 2, LoadRanges.counter
|
|
109
114
|
end
|
|
110
115
|
# rubocop:enable Metrics/AbcSize
|
|
116
|
+
|
|
117
|
+
def test_nil_ranges
|
|
118
|
+
assert NilRanges.valid_ip?('127.0.0.1')
|
|
119
|
+
end
|
|
111
120
|
end
|
|
112
121
|
end
|
|
113
122
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: legitbot
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alexander Azarov
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-
|
|
11
|
+
date: 2020-09-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: augmented_interval_tree
|
|
@@ -54,82 +54,82 @@ dependencies:
|
|
|
54
54
|
name: bump
|
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|
|
56
56
|
requirements:
|
|
57
|
-
- - ">="
|
|
58
|
-
- !ruby/object:Gem::Version
|
|
59
|
-
version: 0.8.0
|
|
60
57
|
- - "~>"
|
|
61
58
|
- !ruby/object:Gem::Version
|
|
62
59
|
version: '0.8'
|
|
60
|
+
- - ">="
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: 0.8.0
|
|
63
63
|
type: :development
|
|
64
64
|
prerelease: false
|
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
|
66
66
|
requirements:
|
|
67
|
-
- - ">="
|
|
68
|
-
- !ruby/object:Gem::Version
|
|
69
|
-
version: 0.8.0
|
|
70
67
|
- - "~>"
|
|
71
68
|
- !ruby/object:Gem::Version
|
|
72
69
|
version: '0.8'
|
|
70
|
+
- - ">="
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: 0.8.0
|
|
73
73
|
- !ruby/object:Gem::Dependency
|
|
74
74
|
name: minitest
|
|
75
75
|
requirement: !ruby/object:Gem::Requirement
|
|
76
76
|
requirements:
|
|
77
|
-
- - ">="
|
|
78
|
-
- !ruby/object:Gem::Version
|
|
79
|
-
version: 5.1.0
|
|
80
77
|
- - "~>"
|
|
81
78
|
- !ruby/object:Gem::Version
|
|
82
79
|
version: '5.1'
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 5.1.0
|
|
83
83
|
type: :development
|
|
84
84
|
prerelease: false
|
|
85
85
|
version_requirements: !ruby/object:Gem::Requirement
|
|
86
86
|
requirements:
|
|
87
|
-
- - ">="
|
|
88
|
-
- !ruby/object:Gem::Version
|
|
89
|
-
version: 5.1.0
|
|
90
87
|
- - "~>"
|
|
91
88
|
- !ruby/object:Gem::Version
|
|
92
89
|
version: '5.1'
|
|
90
|
+
- - ">="
|
|
91
|
+
- !ruby/object:Gem::Version
|
|
92
|
+
version: 5.1.0
|
|
93
93
|
- !ruby/object:Gem::Dependency
|
|
94
94
|
name: rake
|
|
95
95
|
requirement: !ruby/object:Gem::Requirement
|
|
96
96
|
requirements:
|
|
97
|
-
- - ">="
|
|
98
|
-
- !ruby/object:Gem::Version
|
|
99
|
-
version: 12.3.0
|
|
100
97
|
- - "~>"
|
|
101
98
|
- !ruby/object:Gem::Version
|
|
102
99
|
version: '12.3'
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: 12.3.0
|
|
103
103
|
type: :development
|
|
104
104
|
prerelease: false
|
|
105
105
|
version_requirements: !ruby/object:Gem::Requirement
|
|
106
106
|
requirements:
|
|
107
|
-
- - ">="
|
|
108
|
-
- !ruby/object:Gem::Version
|
|
109
|
-
version: 12.3.0
|
|
110
107
|
- - "~>"
|
|
111
108
|
- !ruby/object:Gem::Version
|
|
112
109
|
version: '12.3'
|
|
110
|
+
- - ">="
|
|
111
|
+
- !ruby/object:Gem::Version
|
|
112
|
+
version: 12.3.0
|
|
113
113
|
- !ruby/object:Gem::Dependency
|
|
114
114
|
name: rubocop
|
|
115
115
|
requirement: !ruby/object:Gem::Requirement
|
|
116
116
|
requirements:
|
|
117
|
-
- - ">="
|
|
118
|
-
- !ruby/object:Gem::Version
|
|
119
|
-
version: 0.74.0
|
|
120
117
|
- - "~>"
|
|
121
118
|
- !ruby/object:Gem::Version
|
|
122
|
-
version: '0.
|
|
119
|
+
version: '0.90'
|
|
120
|
+
- - "<"
|
|
121
|
+
- !ruby/object:Gem::Version
|
|
122
|
+
version: '0.91'
|
|
123
123
|
type: :development
|
|
124
124
|
prerelease: false
|
|
125
125
|
version_requirements: !ruby/object:Gem::Requirement
|
|
126
126
|
requirements:
|
|
127
|
-
- - ">="
|
|
128
|
-
- !ruby/object:Gem::Version
|
|
129
|
-
version: 0.74.0
|
|
130
127
|
- - "~>"
|
|
131
128
|
- !ruby/object:Gem::Version
|
|
132
|
-
version: '0.
|
|
129
|
+
version: '0.90'
|
|
130
|
+
- - "<"
|
|
131
|
+
- !ruby/object:Gem::Version
|
|
132
|
+
version: '0.91'
|
|
133
133
|
description: Does Web request come from a real search engine or from an impersonating
|
|
134
134
|
agent?
|
|
135
135
|
email: self@alaz.me
|
|
@@ -137,9 +137,11 @@ executables: []
|
|
|
137
137
|
extensions: []
|
|
138
138
|
extra_rdoc_files: []
|
|
139
139
|
files:
|
|
140
|
+
- ".editorconfig"
|
|
141
|
+
- ".github/workflows/build.yml"
|
|
140
142
|
- ".gitignore"
|
|
141
143
|
- ".rubocop.yml"
|
|
142
|
-
- ".
|
|
144
|
+
- ".ruby-version"
|
|
143
145
|
- Gemfile
|
|
144
146
|
- LICENSE.txt
|
|
145
147
|
- README.md
|
|
@@ -147,6 +149,7 @@ files:
|
|
|
147
149
|
- legitbot.gemspec
|
|
148
150
|
- lib/legitbot.rb
|
|
149
151
|
- lib/legitbot/ahrefs.rb
|
|
152
|
+
- lib/legitbot/alexa.rb
|
|
150
153
|
- lib/legitbot/apple.rb
|
|
151
154
|
- lib/legitbot/baidu.rb
|
|
152
155
|
- lib/legitbot/bing.rb
|
|
@@ -164,6 +167,7 @@ files:
|
|
|
164
167
|
- lib/legitbot/version.rb
|
|
165
168
|
- lib/legitbot/yandex.rb
|
|
166
169
|
- test/ahrefs_test.rb
|
|
170
|
+
- test/alexa_test.rb
|
|
167
171
|
- test/apple_as_google_test.rb
|
|
168
172
|
- test/apple_test.rb
|
|
169
173
|
- test/botmatch_test.rb
|
|
@@ -179,7 +183,7 @@ homepage: https://github.com/alaz/legitbot
|
|
|
179
183
|
licenses:
|
|
180
184
|
- Apache-2.0
|
|
181
185
|
metadata: {}
|
|
182
|
-
post_install_message:
|
|
186
|
+
post_install_message:
|
|
183
187
|
rdoc_options:
|
|
184
188
|
- "--charset=UTF-8"
|
|
185
189
|
require_paths:
|
|
@@ -188,15 +192,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
188
192
|
requirements:
|
|
189
193
|
- - ">="
|
|
190
194
|
- !ruby/object:Gem::Version
|
|
191
|
-
version: 2.
|
|
195
|
+
version: 2.4.0
|
|
192
196
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
193
197
|
requirements:
|
|
194
198
|
- - ">="
|
|
195
199
|
- !ruby/object:Gem::Version
|
|
196
200
|
version: '0'
|
|
197
201
|
requirements: []
|
|
198
|
-
rubygems_version: 3.
|
|
199
|
-
signing_key:
|
|
202
|
+
rubygems_version: 3.1.2
|
|
203
|
+
signing_key:
|
|
200
204
|
specification_version: 4
|
|
201
205
|
summary: 'Validate requests from Web crawlers: impersonating or not?'
|
|
202
206
|
test_files:
|
|
@@ -204,6 +208,7 @@ test_files:
|
|
|
204
208
|
- test/legitbot/validators/domains_test.rb
|
|
205
209
|
- test/legitbot/validators/ip_ranges_test.rb
|
|
206
210
|
- test/pinterest_test.rb
|
|
211
|
+
- test/alexa_test.rb
|
|
207
212
|
- test/ahrefs_test.rb
|
|
208
213
|
- test/apple_test.rb
|
|
209
214
|
- test/apple_as_google_test.rb
|