File: bot.rb

package info (click to toggle)
ruby-browser 5.3.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 872 kB
  • sloc: ruby: 4,752; makefile: 13
file content (77 lines) | stat: -rw-r--r-- 1,541 bytes parent folder | download | duplicates (2)
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