browserino 3.0.1 → 4.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.
@@ -0,0 +1,290 @@
1
+ # frozen_string_literal: true
2
+ Browserino.config.define do
3
+ # a set of global matchers that will use formatted properties found earlier
4
+ # they will also be applied to every matcher unless that matcher has it's own
5
+ # property set for the defined smart matcher
6
+ smart_match :version, with: ':name/([\d\._]+)', flags: [:i]
7
+ smart_match :engine_version, with: ':engine/([\d\._]+)', flags: [:i]
8
+
9
+ # a simple set of global matchers that will be merged
10
+ # with an identity the final client object is created
11
+ match do
12
+ locale %r{(?<!nintendo)[;\s](\w{2}(?:\-\w{2})?)[;)]}i
13
+ architecture %r{((?:(?:x|x86_|amd|wow|win)64)|i[36]86)}i
14
+ mobile %r{(bolt|nokia|samsung(?!b)|mobi(?:le)?|i?p(?:[ao]d|hone)
15
+ |android|bb\d+|blackberry|iemobile|fennec|bada|meego
16
+ |tizen|vodafone|t\-mobile|opera\sm(?:ob|in)i)}xi
17
+ platform %r{.*(xbox|wii|nintendo\sds|playstation|windows(?:\sphone)?
18
+ |macintosh|mac\sos\sx|android|tizen|ip(?:[ao]d|hone)
19
+ |blackberry|linux|ubuntu|x11|bsd|s(?:unos|olaris)
20
+ |w(?:eb)?os)}xi
21
+ platform_version %r{(?:windows(?:\sphone(?:\sos)?)?|nt|mac\sos\sx|android
22
+ |(?:cpu\s|ip(?:[ao]d|hone)\s)os|blackberry|bb
23
+ |s(?:unos|olaris)/?|w(?:eb)?os/|tizen)\s?([\d\._]+)}xi
24
+ end
25
+
26
+ # automatically set type to :browser for each defined matcher
27
+ browsers do
28
+ # a single matcher that will create an Identity for a specific match
29
+ # identities are added in an array in order of definition - higher is better
30
+ # aliasses are prepended to the list instead of appended (e.g. like blocks)
31
+ # this ensures that aliasses will be matched before any regular matcher
32
+ match %r{maxthon}i do
33
+ # define properties by calling a method with the desired name and:
34
+ # -- value # => will create a static method that returns that value
35
+ # -- /(pat)/ # => will create a method that scans the UA and
36
+ # saves the first capture group
37
+ # -- { blk } # => will create a dynamic method that returns the result
38
+ # of the block, it will be executed within an
39
+ # instantiated Client object
40
+ name :maxthon
41
+
42
+ version %r{maxthon[/\s]([\d\.]+)}i
43
+ engine %r{(webkit|presto|gecko|trident)}i
44
+ engine_version %r{(?:webkit|presto|gecko|trident)/([\d\.]+)}i
45
+ end
46
+
47
+ match %r{retawq}i do
48
+ name :retawq
49
+ locale %r{\[(\w{2}(?:\-\w{2})?)\]}i
50
+ end
51
+
52
+ match %r{lynx}i do
53
+ name :lynx
54
+ end
55
+
56
+ match %r{ucbrowser}i do
57
+ name :ucbrowser
58
+
59
+ version %r{ucbrowser/?([\d\.]+)}i
60
+ engine %r{(trident|gecko|webkit|presto)}i
61
+ engine_version %r{(?:trident|gecko|webkit|presto)/([\d\.]+)}i
62
+ end
63
+
64
+ match %r{edge}i do
65
+ name :edge
66
+ engine :edge
67
+ modern? true
68
+ end
69
+
70
+ match %r{ope?ra?\smini}i do
71
+ name :opera_mini
72
+
73
+ version %r{ope?ra?\smini/([\d\.]+)}i
74
+ engine %r{(presto|webkit)}i
75
+ engine_version %r{(?:presto|webkit)/([\d\.]+)}i
76
+ end
77
+
78
+ match %r{opera[^\w]}i do
79
+ name :opera
80
+
81
+ version %r{(?:opera[\s/]|version/)([\d\.]+)}i
82
+ engine %r{(presto|webkit)}i
83
+ engine_version %r{(?:presto|webkit)/([\d\.]+)}i
84
+ end
85
+
86
+ match %r{msie|trident}i do
87
+ name :ie
88
+ engine :trident
89
+
90
+ version %r{(?:(?:ms)?ie\s|rv:)([\d\.]+)}i
91
+ modern? { version >= 10 }
92
+ end
93
+
94
+ match %r{chrome(?:ium)?}i do
95
+ name :chrome
96
+
97
+ version %r{chrome(?:ium)?/([\d\.]+)}i
98
+ engine %r{(webkit|blink)}i
99
+ engine_version %r{(?:webkit|blink)/([\d\.]+)}i
100
+ modern? { version >= 50 }
101
+ end
102
+
103
+ match %r{firefox}i do
104
+ name :firefox
105
+
106
+ engine %r{(gecko|servo)}i
107
+ engine_version %r{(?:rv:\s?|servo/)([\d\.]+)}i
108
+ modern? { version >= 50 }
109
+ end
110
+
111
+ match %r{konqueror}i do
112
+ name :konqueror
113
+ end
114
+
115
+ match %r{midori}i do
116
+ name :midori
117
+ engine :webkit
118
+ end
119
+
120
+ match %r{safari}i do
121
+ name :safari
122
+ engine :webkit
123
+
124
+ version %r{(?:safari|version)/([\d\.]+)}i
125
+ modern? { version >= 9 }
126
+ end
127
+ end
128
+
129
+ # automatically set type to :bot for each defined matcher
130
+ bots do
131
+ match %r{googlebot}i, name: :googlebot
132
+ match %r{yahoo\!\sslurp}i, name: :yahoo_slurp
133
+ match %r{msnbot}i, name: :msnbot
134
+ match %r{bingbot}i, name: :bingbot
135
+ match %r{baiduspider}i, name: :baiduspider
136
+ match %r{yandexbot}i, name: :yandexbot
137
+ match %r{sosospider}i, name: :sosospider
138
+ match %r{exabot}i, name: :exabot
139
+ match %r{sogou\s?spider}i, name: :sogou_spider
140
+ match %r{nutch}i, name: :nutch
141
+ match %r{scrapy}i, name: :scrapy
142
+ match %r{dataparksearch}i, name: :dataparksearch
143
+ match %r{holmes}i, name: :holmes
144
+ match %r{(?:ask)\sjeeves}i, name: :ask
145
+ match %r{duckduckgo}i, name: :duckduckgo
146
+ match %r{beslistbot}i, name: :beslistbot
147
+ match %r{twitterbot}i, name: :twitterbot
148
+ match %r{linkedinbot}i, name: :linkedin
149
+ match %r{instagram}i, name: :instagram
150
+ match %r{pinterest}i, name: :pinterest
151
+ match %r{tumblr}i, name: :tumblr
152
+ match %r{ia_archiver}i, name: :alexa
153
+ match %r{4anything}i, name: :four_anything
154
+ match %r{autoemailspider}i, name: :auto_email_spider
155
+ match %r{boston[_ ]project}i, name: :boston_project
156
+ match %r{atomz}i, name: :atomz
157
+ match %r{atomic_email_hunter}i, name: :atomic_email_hunter
158
+ match %r{altavista}i, name: :altavista
159
+ match %r{alkaline}i, name: :alkalinebot
160
+ match %r{acoi}i, name: :acoi
161
+ match %r{acoon}i, name: :acoon
162
+ match %r{accoona}i, name: :accoona
163
+ match %r{face(?:bookexternalhit|bot)}i, name: :facebook
164
+ match %r{linkdexbot}i, name: :linkdexbot
165
+ match %r{aitcsrobot}i, name: :aitcsrobot
166
+ match %r{alexibot}i, name: :alexibot
167
+ match %r{aqua_products}i, name: :aqua_products
168
+ match %r{arachnophilia}i, name: :arachnophilia
169
+ match %r{aspider}i, name: :aspider
170
+ match %r{asterias}i, name: :asterias
171
+ match %r{auresys}i, name: :auresys
172
+ match %r{b2w}i, name: :b2w
173
+ match %r{backdoorbot}i, name: :backdoorbot
174
+ match %r{backrub}i, name: :backrub
175
+ match %r{big\sbrother}i, name: :big_brother
176
+ match %r{bizbot}i, name: :bizbot
177
+ match %r{black\shole}i, name: :black_hole
178
+ match %r{blackwidow}i, name: :blackwidow
179
+ match %r{blexbot}i, name: :blexbot
180
+ match %r{bspider}i, name: :bspider
181
+ match %r{bullseye}i, name: :bullseye
182
+ match %r{emailcollector}i, name: :emailcollector
183
+ match %r{emailsiphon}i, name: :emailsiphon
184
+ match %r{emailwolf}i, name: :emailwolf
185
+ match %r{ecatch}i, name: :ecatch
186
+ match %r{flaming\sattackbot}i, name: :flaming_attackbot
187
+ match %r{getright}i, name: :getright
188
+ match %r{harvest}i, name: :harvest
189
+ match %r{huaweisymantecspider}i, name: :huaweisymantecspider
190
+
191
+ match %r{mass\sdownloader}i, name: :mass_downloader,
192
+ version: %r{mass\sdownloader/([\d\.]+)}i
193
+ match %r{safetynet\srobot}i, name: :safetynet_robot,
194
+ version: %r{safetynet\srobot\s([\d\.]+)}i
195
+ match %r{internet\sninja}i, name: :internet_ninja,
196
+ version: %r{internet\sninja\s([\d\.]+)}i
197
+ match %r{go\!zilla}i, name: :gozilla,
198
+ version: %r{go\!zilla\s([\d\.]+)}i
199
+ match %r{larbin}i, name: :larbin,
200
+ version: %r{larbin_([\d\.]+)}i
201
+ match %r{download\sdemon}i, name: :download_demon,
202
+ version: %r{download\sdemon/([\d\.]+)}i
203
+ end
204
+
205
+ # automatically set type to :library for each defined matcher
206
+ validators do
207
+ match %r{cse\shtml\svalidator}i, name: :cse_html_validator
208
+ match %r{csscheck}i, name: :csscheck
209
+ match %r{htmlparser}i, name: :htmlparser
210
+ match %r{p3p\svalidator}i, name: :p3p_validator
211
+ match %r{wdg_validator}i, name: :wdg_validator
212
+ match %r{w3c_validator}i, name: :w3c_validator
213
+
214
+ match %r{cynthia}i, name: :cynthia,
215
+ version: %r{cynthia\s([\d\.]+)}i
216
+
217
+ match %r{w3c_css_validator}i,
218
+ name: :w3c_css_validator,
219
+ version: %r{w3c_css_validator_jfouffa/([\d\.]+)}i
220
+ end
221
+
222
+ # automatically set type to :library for each defined matcher
223
+ libraries do
224
+ match %r{php}i, name: :php
225
+ match %r{python}i, name: :python, version: %r{-urllib/([\d\.]+)}i
226
+ match %r{perl}i, name: :perl
227
+ match %r{java}i, name: :java
228
+ match %r{pycurl}i, name: :pycurl
229
+ match %r{curl}i, name: :curl
230
+ end
231
+
232
+ # inherit properties a standard set of properties by the name of a
233
+ # previously defined matcher, overwritten by properties added within matchers
234
+ # inherit properties from Identity where name == :chrome
235
+ like :chrome do
236
+ match %r{brave}i, name: :brave, version: %r{brave/([\d\.]+)}i
237
+ match %r{vivaldi}i, name: :vivaldi, version: %r{vivaldi/([\d\.]+)}i
238
+ match %r{colibri}i, name: :colibri, version: %r{colibri/([\d\.]+)}i
239
+ match %r{rockmelt}i, name: :rockmelt, version: %r{rockmelt/([\d\.]+)}i
240
+ match %r{flock}i, name: :flock, version: %r{flock/([\d\.]+)}i
241
+
242
+ match %r{comodo_dragon}i, name: :comodo_dragon,
243
+ version: %r{comodo_dragon/([\d\.]+)}i
244
+ end
245
+
246
+ # inherit properties from Identity where name == :safari
247
+ like :safari do
248
+ match %r{bolt}i, name: :bolt, version: %r{bolt/([\d\.]+)}i
249
+
250
+ match %r{stainless}i, name: :stainless,
251
+ version: %r{stainless/([\d\.]+)}i
252
+ match %r{samsungbrowser}i, name: :samsungbrowser,
253
+ version: %r{samsungbrowser/([\d\.]+)}i
254
+ match %r{omniweb}i, name: :omniweb,
255
+ version: %r{omniweb/v([\d\.]+)}i
256
+
257
+ match %r{webos|wosbrowser}i,
258
+ name: :webosbrowser,
259
+ version: %r{(?:version|w(?:eb)?osbrowser)/([\d\.]+)}i
260
+ end
261
+
262
+ # inherit properties from Identity where name == :firefox
263
+ like :firefox do
264
+ match %r{prism}i, name: :prism, version: %r{prism/([\d\.]+)}i
265
+ match %r{waterfox}i, name: :waterfox, version: %r{waterfox/([\d\.]+)}i
266
+ match %r{firebird}i, name: :firebird, version: %r{firebird/([\d\.]+)}i
267
+ match %r{netscape}i, name: :netscape, version: %r{netscape/([\d\.]+)}i
268
+ match %r{icecat}i, name: :icecat, version: %r{icecat/([\d\.]+)}i
269
+ match %r{iceweasel}i, name: :iceweasel, version: %r{iceweasel/([\d\.]+)}i
270
+ match %r{seamonkey}i, name: :seamonkey, version: %r{seamonkey/([\d\.]+)}i
271
+ match %r{superswan}i, name: :superswan, version: %r{superswan/([\d\.]+)}i
272
+ match %r{lunascape}i, name: :lunascape, version: %r{lunascape/([\d\.]+)}i
273
+ match %r{camino}i, name: :camino, version: %r{camino/([\d\.]+)}i,
274
+ locale: %r{\s(\w{2}(?:\-\w{2})?),}i
275
+ end
276
+
277
+ # never thought a browser would want to be like IE...
278
+ like :ie do
279
+ # version does not have to be supplied because we simply want to use
280
+ # the version supplied by the MSIE token instead (there is no version on
281
+ # the avant browser or slimbrowser UA itself)
282
+ match %r{avant\sbrowser}i, name: :avant_browser
283
+ match %r{slimbrowser}i, name: :slimbrowser
284
+
285
+ match %r{sleipnir}i, name: :sleipnir,
286
+ version: %r{sleipnir/([\d\.]+)}i
287
+ match %r{deepnet\sexplorer}i, name: :deepnet_explorer,
288
+ version: %r{deepnet\sexplorer ([\d\.]+)}i
289
+ end
290
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+ module Browserino
3
+ class Identity
4
+ attr_reader :pattern, :properties
5
+
6
+ SETTINGS = { name: nil, type: :unknown }.freeze
7
+
8
+ def initialize(pattern = //, opts = {}, **additional, &block)
9
+ opts = pattern if pattern.is_a?(Hash) && opts.empty?
10
+ @properties = SETTINGS.merge(opts.merge(additional))
11
+ @pattern = pattern
12
+
13
+ instance_eval(&block) if block
14
+ end
15
+
16
+ def matches?(user_agent)
17
+ pattern =~ user_agent if pattern.is_a? Regexp
18
+ end
19
+
20
+ def ===(other)
21
+ return false if properties[:name].nil?
22
+
23
+ case other
24
+ when Regexp then other =~ properties[:name]
25
+ when String then other.to_sym == properties[:name]
26
+ when Symbol then other == properties[:name]
27
+ when Identity then other.properties[:name] == properties[:name]
28
+ else false
29
+ end
30
+ end
31
+
32
+ def to_str
33
+ properties[:name].to_s
34
+ end
35
+
36
+ def =~(other)
37
+ self === other
38
+ end
39
+
40
+ def ==(other)
41
+ self === other
42
+ end
43
+
44
+ def method_missing(sym, *args, &block)
45
+ return @properties[sym] = block if block
46
+ return @properties[sym] = args.shift if args.any?
47
+
48
+ @properties[sym]
49
+ end
50
+
51
+ def respond_to_missing?(_, *__, &___)
52
+ true
53
+ end
54
+ end
55
+ end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'action_controller/railtie'
2
4
 
3
5
  module Browserino
4
6
  class ActionController
5
7
  module Base
6
- def agent
7
- @agent ||= Browserino.parse(request.headers['User-Agent'])
8
+ def client
9
+ @client ||= Browserino.parse request.headers['User-Agent']
8
10
  end
9
11
  end
10
12
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails/railtie'
2
4
  require_relative 'action_controller'
3
5
 
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+ module Browserino
3
+ def self.analyze(user_agent, identity = nil)
4
+ props = [*config.global_identities, identity].compact.map(&:properties)
5
+ .reduce(&:merge)
6
+ like = props.delete :like if props.key? :like
7
+ props = collect(props, user_agent)
8
+ props = normalize props
9
+ props = with_smart_matchers props
10
+ left = props.select { |_, val| val.is_a? Regexp }
11
+ props = props.merge normalize(collect(left, user_agent)) if left.any?
12
+ props = with_labels props
13
+
14
+ if like
15
+ repl = user_agent =~ %r{#{like}}i && '' || like.to_s
16
+ like = parse user_agent.gsub identity.pattern, repl
17
+ end
18
+
19
+ Client.new props, like
20
+ end
21
+
22
+ def self.config
23
+ @config ||= Config.new({ before_parse: [],
24
+ global_identities: [],
25
+ properties: [],
26
+ types: [:unknown],
27
+ names: [],
28
+ smart_matchers: {},
29
+ identities: [],
30
+ labels: Hash.new { |h, k| h[k] = [] },
31
+ filters: Hash.new { |h, k| h[k] = [] },
32
+ aliasses: Hash.new { |h, k| h[k] = [] } })
33
+ end
34
+
35
+ def self.label_for(target_name, version = nil)
36
+ return unless config.labels.key?(target_name) && version
37
+ version = Version.new version unless version.is_a? Version
38
+ return unless version > 0
39
+ config.labels[target_name].each do |candidate|
40
+ min = Version.new candidate[:range].min
41
+ max = Version.new candidate[:range].max
42
+
43
+ return candidate[:name] if version >= min && version <= max
44
+ end
45
+ nil
46
+ end
47
+
48
+ def self.with_labels(properties)
49
+ [:name, :engine, :platform].each do |prop|
50
+ lbl_prop = (prop == :name) && :label || "#{prop}_label".to_sym
51
+ ver_prop = (prop == :name) && :version || "#{prop}_version".to_sym
52
+ properties[lbl_prop] ||= label_for properties[prop], properties[ver_prop]
53
+ end
54
+
55
+ properties
56
+ end
57
+
58
+ def self.with_smart_matchers(properties)
59
+ config.smart_matchers.each_with_object properties do |(prop, detector), props|
60
+ props[prop] ||= parse_detector detector, properties
61
+ end
62
+ end
63
+
64
+ def self.parse_detector(detect, properties)
65
+ pat = properties.each_with_object(detect[:with].dup) do |(key, val), str|
66
+ replacement = val.to_s.strip
67
+ str.gsub! ":#{key}", replacement unless replacement.empty?
68
+ end
69
+
70
+ Regexp.new pat, get_flags(*detect[:flags].to_a)
71
+ end
72
+
73
+ def self.collect(properties, ua)
74
+ properties.each_with_object({}) do |(prop, value), res|
75
+ res[prop] = case value
76
+ when Regexp then value.match(ua).to_a[1]
77
+ else value
78
+ end
79
+ end
80
+ end
81
+
82
+ def self.normalize(properties)
83
+ properties.each_with_object({}) do |(prop, value), store|
84
+ store[prop] = convert value, format: prop
85
+ end
86
+ end
87
+
88
+ def self.convert(val, **opts)
89
+ filters = config.filters[:global] + config.filters[opts[:format]]
90
+ filters.compact.each do |fmt|
91
+ val = fmt.call val
92
+ end
93
+
94
+ val
95
+ end
96
+
97
+ def self.get_flags(*flags)
98
+ val = 0
99
+
100
+ flags.each do |flag|
101
+ case flag.to_sym
102
+ when :m then val |= Regexp::MULTILINE
103
+ when :i then val |= Regexp::IGNORECASE
104
+ when :x then val |= Regexp::EXTENDED
105
+ end
106
+ end
107
+
108
+ val
109
+ end
110
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+ module Browserino
3
+ class Options
4
+ def initialize(options = {})
5
+ @options = options
6
+ end
7
+
8
+ def method_missing(sym, *args, &block)
9
+ return @options[opt(sym)] == args.first if args.any?
10
+ @options[opt(sym)]
11
+ end
12
+
13
+ def respond_to_missing?(sym, *args, &block)
14
+ option? sym
15
+ end
16
+
17
+ def merge(other)
18
+ @options.merge! other
19
+ self
20
+ end
21
+
22
+ def to_hash
23
+ @options
24
+ end
25
+
26
+ def to_a
27
+ @options.to_a
28
+ end
29
+
30
+ def to_s
31
+ @options.to_s
32
+ end
33
+
34
+ private
35
+
36
+ def opt(sym)
37
+ sym.to_s.tr('?', '').to_sym
38
+ end
39
+
40
+ def option?(sym)
41
+ @options.keys.include? opt(sym)
42
+ end
43
+ end
44
+ end
@@ -1,3 +1,74 @@
1
+ # frozen_string_literal: true
1
2
  module Browserino
2
- VERSION = '3.0.1'.freeze
3
+ VERSION = '4.0.0'.freeze
4
+
5
+ def self.version
6
+ @verion ||= Version.new VERSION.dup
7
+ end
8
+
9
+ # This class makes versions easily comparable using logical operators
10
+ # it makes it convenient to check versions in a natural way
11
+ class Version < Array
12
+ attr_reader :major, :minor, :patch
13
+
14
+ def initialize(val, *rest)
15
+ super parse_params(val, *rest)
16
+ @major = fetch 0, 0
17
+ @minor = fetch 1, 0
18
+ @patch = fetch 2, 0
19
+ end
20
+
21
+ def full
22
+ to_s
23
+ end
24
+
25
+ def to_s
26
+ @str ||= join '.'
27
+ end
28
+
29
+ def <(other)
30
+ compare :<, other
31
+ end
32
+
33
+ def <=(other)
34
+ compare :<=, other
35
+ end
36
+
37
+ def >(other)
38
+ compare :>, other
39
+ end
40
+
41
+ def >=(other)
42
+ compare :>=, other
43
+ end
44
+
45
+ def ==(other)
46
+ compare :==, other
47
+ end
48
+
49
+ def !=(other)
50
+ compare :!=, other
51
+ end
52
+
53
+ private
54
+
55
+ def parse_params(val, *rest)
56
+ case val
57
+ when Float then val.to_s.split '.'
58
+ when Integer then [val, *rest]
59
+ when String then val.tr('_', '.').split '.'
60
+ when Array then val
61
+ when Hash then [val[:major], val[:minor], val[:patch]]
62
+ when Symbol then []
63
+ else val.to_a
64
+ end.map(&:to_i)
65
+ end
66
+
67
+ def compare(op, other)
68
+ other = Version.new other unless other.is_a? Version
69
+ subsize = [size, other.size].min
70
+
71
+ (self[0...subsize] <=> other[0...subsize]).send op, 0
72
+ end
73
+ end
3
74
  end
data/lib/browserino.rb CHANGED
@@ -1,67 +1,25 @@
1
- require_relative 'browserino/core/mapping'
2
- require_relative 'browserino/core/patterns'
3
- require_relative 'browserino/core/supported'
4
- require_relative 'browserino/core/questions'
5
- require_relative 'browserino/core/helpers'
6
- require_relative 'browserino/core/lies'
7
- require_relative 'browserino/core/alias'
8
-
1
+ # frozen_string_literal: true
9
2
  require_relative 'browserino/integrate/rails' if defined?(::Rails)
10
3
 
11
- require_relative 'browserino/unknown'
12
- require_relative 'browserino/agent'
13
-
4
+ require_relative 'browserino/options'
5
+ require_relative 'browserino/config'
6
+ require_relative 'browserino/methods'
7
+ require_relative 'browserino/client'
14
8
  require_relative 'browserino/version'
15
- require_relative 'browserino/browser'
16
- require_relative 'browserino/engine'
17
- require_relative 'browserino/operating_system'
18
- require_relative 'browserino/console'
19
-
20
- module Browserino
21
- module_function
22
-
23
- def parse(ua)
24
- name = Browser.name(ua)
25
- info = fetch_info(strip_lies(ua), name)
26
- tmp = info[:name].to_s.tr('_', ' ')
27
- info[:name] = tmp.strip == '' ? nil : tmp
28
-
29
- Agent.new check_for_aliases(info), ua
30
- end
9
+ require_relative 'browserino/identity'
31
10
 
32
- def fetch_info(ua, name)
33
- { name: name,
34
- browser_version: Browser.version(ua, name),
35
- engine_name: Engine.name(ua),
36
- engine_version: Engine.version(ua),
37
- system_name: OperatingSystem.name(ua),
38
- system_version: OperatingSystem.version(ua),
39
- system_architecture: OperatingSystem.architecture(ua),
40
- console_name: Console.name(ua),
41
- locale: OperatingSystem.locale(ua) }
42
- end
43
-
44
- def strip_lies(ua)
45
- Core::LIES.inject(ua) do |s, arr|
46
- s = s.gsub(arr[0], '') if arr[1] == true || s =~ arr[1]
47
- s
48
- end
49
- end
11
+ require_relative 'browserino/definitions/matchers'
12
+ require_relative 'browserino/definitions/aliasses'
13
+ require_relative 'browserino/definitions/filters'
14
+ require_relative 'browserino/definitions/labels'
50
15
 
51
- def check_for_aliases(h)
52
- Core::ALIAS.each do |k, v|
53
- h[k] = v.select { |n, re| n if h[k] =~ re }.keys.first || h[k]
16
+ module Browserino
17
+ def self.parse(ua)
18
+ config.before_parse.each { |b| ua = b.call ua } if config.before_parse.any?
19
+ config.identities.each do |identity|
20
+ return analyze ua, identity if identity.matches? ua
54
21
  end
55
- h
56
- end
57
22
 
58
- def extract_match(match, sym)
59
- if match && match.names.include?(sym.to_s)
60
- m = match[sym].to_s.downcase.strip
61
- m = yield(m) if block_given?
62
- m
63
- else
64
- UNKNOWN
65
- end
23
+ analyze ua
66
24
  end
67
25
  end