legitbot 0.4.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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://github.com/alaz/legitbot/workflows/build/badge.svg) [![Gem Version](https://badge.fury.io/rb/legitbot.svg)](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
|