1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
# frozen_string_literal: true
module Browser
class Bot
GENERIC_NAME = "Generic Bot"
def self.matchers
@matchers ||= default_matchers
end
def self.default_matchers
[
EmptyUserAgentMatcher,
KnownBotsMatcher,
KeywordMatcher
]
end
def self.load_yaml(path)
YAML.load_file(Browser.root.join(path))
end
def self.bots
@bots ||= load_yaml("bots.yml")
end
def self.bot_exceptions
@bot_exceptions ||= load_yaml("bot_exceptions.yml")
end
def self.search_engines
@search_engines ||= load_yaml("search_engines.yml")
end
def self.why?(ua)
ua = ua.downcase.strip
browser = Browser.new(ua)
matchers.find {|matcher| matcher.call(ua, browser) }
end
attr_reader :ua, :browser
def initialize(ua)
@ua = ua.downcase.strip
@browser = Browser.new(@ua)
end
def bot?
!bot_exception? && detect_bot?
end
def why?
self.class.matchers.find {|matcher| matcher.call(ua, self) }
end
def search_engine?
self.class.search_engines.any? {|key, _| ua.include?(key) }
end
def name
return unless bot?
self.class.bots.find {|key, _| ua.include?(key) }&.last || GENERIC_NAME
end
private def bot_exception?
self.class.bot_exceptions.any? {|key| ua.include?(key) }
end
private def detect_bot?
self.class.matchers.any? {|matcher| matcher.call(ua, browser) }
end
private :ua
private :browser
end
end
|