browserino 4.0.0 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +18 -0
- data/.travis.yml +5 -1
- data/bin/browserino +1 -1
- data/bin/console +3 -4
- data/browserino.gemspec +2 -1
- data/lib/browserino/client.rb +48 -31
- data/lib/browserino/config.rb +43 -24
- data/lib/browserino/definitions/aliasses.rb +2 -0
- data/lib/browserino/definitions/filters.rb +32 -20
- data/lib/browserino/definitions/labels.rb +14 -8
- data/lib/browserino/definitions/matchers.rb +434 -167
- data/lib/browserino/{identity.rb → matcher.rb} +9 -8
- data/lib/browserino/methods.rb +42 -45
- data/lib/browserino/options.rb +3 -2
- data/lib/browserino/version.rb +12 -3
- data/lib/browserino.rb +4 -4
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b85dfc764ad259ee956ed4fd456d2a3d157f0e17
|
4
|
+
data.tar.gz: b8f96ecc2cc453dada5c1ca5df9dbd3216c0d6a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 66997f7437d4108c2779f2a1c2d07b0b41b6d95772435e4616ebde8567936bd87545d775db05fc6c81602bbf79a6693e22b938bae2724f130e0c660fddb54c18
|
7
|
+
data.tar.gz: a6f8eed6eedd79d2621a6982f1aa52d37302e7bc0577880f30cbcd8bea4f6864811703ac72e48fa6960f4a48f7bafb3ff5a78e5f9faf7b4765ac11b3183bc402
|
data/.rubocop.yml
CHANGED
@@ -4,6 +4,8 @@ AllCops:
|
|
4
4
|
- 'Guardfile'
|
5
5
|
- '*.gemspec'
|
6
6
|
- 'Rakefile'
|
7
|
+
- 'tmp/**/*'
|
8
|
+
- 'vendor/**/*'
|
7
9
|
|
8
10
|
Documentation:
|
9
11
|
Enabled: false
|
@@ -11,9 +13,25 @@ Documentation:
|
|
11
13
|
Lint/AmbiguousRegexpLiteral:
|
12
14
|
Enabled: false
|
13
15
|
|
16
|
+
Style/CaseEquality:
|
17
|
+
Enabled: false
|
18
|
+
|
14
19
|
Style/RegexpLiteral:
|
15
20
|
Enabled: false
|
16
21
|
|
22
|
+
Style/MethodMissing:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Metrics/BlockLength:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
Metrics/AbcSize:
|
29
|
+
Max: 20
|
30
|
+
|
31
|
+
Metrics/ClassLength:
|
32
|
+
CountComments: false
|
33
|
+
Max: 175
|
34
|
+
|
17
35
|
Metrics/MethodLength:
|
18
36
|
CountComments: false
|
19
37
|
Max: 15
|
data/.travis.yml
CHANGED
data/bin/browserino
CHANGED
data/bin/console
CHANGED
@@ -4,9 +4,8 @@ require 'bundler/setup'
|
|
4
4
|
require 'pry'
|
5
5
|
require 'browserino'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
(KHTML, l ike Gecko) Version/9.0.\
|
10
|
-
2 Safari/601.3.9'
|
7
|
+
smpl = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9' \
|
8
|
+
' (KHTML, l ike Gecko) Version/9.0.2 Safari/601.3.9'
|
11
9
|
|
10
|
+
@client = Browserino.parse(ARGV[0].dup || smpl)
|
12
11
|
Pry.start
|
data/browserino.gemspec
CHANGED
@@ -5,7 +5,7 @@ require 'browserino/version'
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "browserino"
|
8
|
-
spec.version = Browserino
|
8
|
+
spec.version = Browserino.version.full
|
9
9
|
spec.authors = ["Sidney Liebrand"]
|
10
10
|
spec.email = ["sidneyliebrand@gmail.com"]
|
11
11
|
spec.summary = %q{A browser identification gem with command line and Rails (>= 3.2.0) integration}
|
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.add_development_dependency "bundler", "~> 1.14"
|
21
21
|
spec.add_development_dependency "rake", "~> 12.0"
|
22
22
|
spec.add_development_dependency "rspec"
|
23
|
+
spec.add_development_dependency "rubocop"
|
23
24
|
spec.add_development_dependency "coveralls"
|
24
25
|
spec.add_development_dependency "pry"
|
25
26
|
end
|
data/lib/browserino/client.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Browserino
|
3
4
|
class Client
|
4
5
|
attr_reader :property_names
|
5
6
|
|
6
7
|
def initialize(props = {}, like = nil)
|
7
|
-
@property_names = props.
|
8
|
-
@like = like
|
8
|
+
@property_names = props.keys
|
9
|
+
@like = like
|
10
|
+
|
9
11
|
# properties are added as methods that will each be defined in a specific
|
10
12
|
# order below. First, seperate static value methods from procs,
|
11
13
|
# procs will be able to call methods in this instances' context
|
@@ -61,10 +63,8 @@ module Browserino
|
|
61
63
|
@x32_cache ||= architecture == :x32
|
62
64
|
end
|
63
65
|
|
64
|
-
|
65
|
-
|
66
|
-
return type == sym if sym.is_a? Symbol
|
67
|
-
type == sym.to_sym
|
66
|
+
def arm?
|
67
|
+
@arm_cache ||= architecture == :arm
|
68
68
|
end
|
69
69
|
|
70
70
|
# the catch all method, anything it can ask as question will respond
|
@@ -105,12 +105,13 @@ module Browserino
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def to_s
|
108
|
-
@str_cache ||= [
|
109
|
-
|
110
|
-
|
111
|
-
|
108
|
+
@str_cache ||= %i[name engine platform].map do |prop|
|
109
|
+
n = properties[prop]
|
110
|
+
v = version_for prop
|
111
|
+
l = label_for prop
|
112
|
+
a = l ? l : [n, (v.major if v > '0.0.0')].join.to_sym
|
112
113
|
|
113
|
-
[
|
114
|
+
[n, a].uniq
|
114
115
|
end.flatten.uniq.join(' ').gsub(/\s{2,}/, ' ').strip
|
115
116
|
end
|
116
117
|
|
@@ -139,19 +140,39 @@ module Browserino
|
|
139
140
|
|
140
141
|
private
|
141
142
|
|
143
|
+
def name_for(sym)
|
144
|
+
mtd = %i[version label].include?(sym) ? :name : "#{sym}_name".to_sym
|
145
|
+
properties[mtd]
|
146
|
+
end
|
147
|
+
|
148
|
+
def label_for(sym)
|
149
|
+
mtd = %i[version name].include?(sym) ? :label : "#{sym}_label".to_sym
|
150
|
+
properties[mtd]
|
151
|
+
end
|
152
|
+
|
153
|
+
def version_for(sym)
|
154
|
+
mtd = %i[label name].include?(sym) ? :version : "#{sym}_version".to_sym
|
155
|
+
properties[mtd]
|
156
|
+
end
|
157
|
+
|
158
|
+
def get_answer(mtd, res, ver = nil, val = nil)
|
159
|
+
incl = [res, *Browserino.config.aliasses[res]].include? val
|
160
|
+
return res.is_a?(Version) ? res > 0 : res && true unless val
|
161
|
+
ver && incl ? version_for(mtd) == ver : incl
|
162
|
+
end
|
163
|
+
|
142
164
|
def define_simple_methods!(props)
|
143
|
-
props.
|
165
|
+
props.each do |name, value|
|
144
166
|
define_singleton_method(name) { value }
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
end
|
167
|
+
define_question_method! name, value
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def define_question_method!(name, value)
|
172
|
+
define_singleton_method("#{name}?") do |val = nil, opts = {}|
|
173
|
+
ver = opts.delete :version
|
174
|
+
val = val.to_sym if ver
|
175
|
+
get_answer name, value, ver, val
|
155
176
|
end
|
156
177
|
end
|
157
178
|
|
@@ -163,10 +184,9 @@ module Browserino
|
|
163
184
|
end
|
164
185
|
|
165
186
|
def define_name_result_methods!
|
166
|
-
[
|
167
|
-
result =
|
168
|
-
ver_res =
|
169
|
-
ver_res = send("#{prop}_version") if ver_res.nil?
|
187
|
+
%i[name engine platform].each do |prop|
|
188
|
+
result = properties[prop]
|
189
|
+
ver_res = version_for(prop)
|
170
190
|
|
171
191
|
# for each of the props:
|
172
192
|
# -- define a question method using the value of prop
|
@@ -193,11 +213,8 @@ module Browserino
|
|
193
213
|
|
194
214
|
def define_label_methods!
|
195
215
|
property_names.select { |name| name =~ /label/i }.each do |prop|
|
196
|
-
next unless (result =
|
197
|
-
|
198
|
-
ver_type = prop.to_s.gsub /_?label/, ''
|
199
|
-
ver_res = version if ver_type.empty?
|
200
|
-
ver_res = send("#{ver_type}_version") unless prop == :label
|
216
|
+
next unless (result = properties[prop])
|
217
|
+
ver_res = version_for(prop.to_s.split('_').first)
|
201
218
|
|
202
219
|
define_singleton_method("#{result}?") do |value = nil|
|
203
220
|
return ver_res == value if value
|
data/lib/browserino/config.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Browserino
|
3
4
|
class Config < Options
|
4
5
|
def define(&block)
|
5
6
|
instance_eval(&block)
|
6
|
-
return unless identities.any? && identities.all?
|
7
7
|
|
8
|
-
|
9
|
-
properties <<
|
10
|
-
types <<
|
11
|
-
names <<
|
8
|
+
matchers.each do |matcher|
|
9
|
+
properties << matcher.properties.keys
|
10
|
+
types << matcher.type
|
11
|
+
names << matcher.name
|
12
12
|
end
|
13
13
|
|
14
14
|
properties.flatten!.uniq!
|
@@ -32,15 +32,19 @@ module Browserino
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def match(rgxp = nil, **opts, &block)
|
35
|
-
|
35
|
+
if rgxp.is_a? Hash
|
36
|
+
opts = rgxp.dup
|
37
|
+
rgxp = nil
|
38
|
+
end
|
39
|
+
|
36
40
|
opts = @tmp_defaults.merge opts if @tmp_defaults.is_a? Hash
|
37
41
|
|
38
42
|
if rgxp && opts[:like]
|
39
|
-
|
43
|
+
matchers.unshift with_alias(rgxp, opts, &block)
|
40
44
|
elsif rgxp
|
41
|
-
|
45
|
+
matchers << Matcher.new(rgxp, opts, &block).freeze
|
42
46
|
else
|
43
|
-
|
47
|
+
global_matchers.unshift Matcher.new(&block).freeze
|
44
48
|
end
|
45
49
|
end
|
46
50
|
|
@@ -54,37 +58,52 @@ module Browserino
|
|
54
58
|
end
|
55
59
|
|
56
60
|
def preset(props, &block)
|
57
|
-
@
|
61
|
+
@preset_store ||= []
|
62
|
+
@preset_store << props if @preset_store.empty?
|
63
|
+
@preset_store << @tmp_defaults.merge(props) if @tmp_defaults
|
64
|
+
@tmp_defaults = @preset_store.last
|
65
|
+
|
58
66
|
instance_eval(&block)
|
59
|
-
|
67
|
+
|
68
|
+
@preset_store.pop
|
69
|
+
@tmp_defaults = @preset_store.last
|
60
70
|
end
|
61
71
|
|
62
|
-
def like(tmp, &block)
|
63
|
-
preset like: tmp.to_sym, &block
|
72
|
+
def like(tmp, opts = {}, &block)
|
73
|
+
preset opts.merge(like: tmp.to_sym), &block
|
64
74
|
end
|
65
75
|
|
66
|
-
def
|
67
|
-
preset type: :
|
76
|
+
def emails(opts = {}, &block)
|
77
|
+
preset opts.merge(type: :email), &block
|
68
78
|
end
|
69
79
|
|
70
|
-
def
|
71
|
-
preset type: :
|
80
|
+
def validators(opts = {}, &block)
|
81
|
+
preset opts.merge(type: :validator), &block
|
72
82
|
end
|
73
83
|
|
74
|
-
def
|
75
|
-
preset type: :
|
84
|
+
def browsers(opts = {}, &block)
|
85
|
+
preset opts.merge(type: :browser), &block
|
76
86
|
end
|
77
87
|
|
78
|
-
def
|
79
|
-
preset type: :
|
88
|
+
def bots(opts = {}, &block)
|
89
|
+
preset opts.merge(type: :bot), &block
|
90
|
+
end
|
91
|
+
|
92
|
+
def libraries(opts = {}, &block)
|
93
|
+
preset opts.merge(type: :library), &block
|
80
94
|
end
|
81
95
|
|
82
96
|
def with_alias(pattern, **opts, &block)
|
83
|
-
|
97
|
+
alt = matchers.select { |id| id == opts[:like] }.first
|
84
98
|
|
85
|
-
raise "No alias found for: #{opts[:like] || 'nil'}" unless
|
99
|
+
raise "No alias found for: #{opts[:like] || 'nil'}" unless alt
|
100
|
+
|
101
|
+
base = alt.properties
|
102
|
+
if (excl = opts.delete(:except))
|
103
|
+
base = base.reject { |k| excl.include? k }
|
104
|
+
end
|
86
105
|
|
87
|
-
|
106
|
+
Matcher.new(pattern, base.merge(opts), &block).freeze
|
88
107
|
end
|
89
108
|
end
|
90
109
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
Browserino.config.define do
|
3
4
|
# aliasses will be defined after a Client has been initialized
|
4
5
|
# only the aliasses matching the Client will be defined
|
@@ -9,4 +10,5 @@ Browserino.config.define do
|
|
9
10
|
alias_for :ie, :internet_explorer
|
10
11
|
alias_for :facebook, :fb
|
11
12
|
alias_for :duckduckgo, :ddg
|
13
|
+
alias_for :chromeos, :cros
|
12
14
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
Browserino.config.define do
|
3
4
|
# executes before parsing the user agent, 's' in this case is the actual
|
4
5
|
# user agent string in full glory. Do manipulations as you wish, I'm
|
@@ -12,7 +13,7 @@ Browserino.config.define do
|
|
12
13
|
ua = ua.gsub(%r{chrome|safari}i, '').gsub('OPR', 'opera') if ua =~ %r{OPR}
|
13
14
|
ua = ua.gsub %r{9\.80}, '' if ua =~ %r{opera}i
|
14
15
|
ua = ua.gsub %r{webkit/}i, '' if ua =~ %r{presto}i
|
15
|
-
ua = ua.gsub %r{(?:ms)?ie}i, '' if ua =~ %r{rv:}i
|
16
|
+
ua = ua.gsub %r{(?:ms)?ie\b}i, '' if ua =~ %r{rv:}i
|
16
17
|
ua = ua.gsub %r{android|linux}i, '' if ua =~ %r{tizen}i
|
17
18
|
ua = ua.gsub %r{linux}i, '' if ua =~ %r{android|s(unos|olaris)|w(eb)?os}i
|
18
19
|
ua = ua.gsub %r{x11}i, '' if ua =~ %r{bsd|s(unos|olaris)}i
|
@@ -20,10 +21,18 @@ Browserino.config.define do
|
|
20
21
|
ua = ua.gsub %r{rv:}i, '' if ua =~ %r{servo}i
|
21
22
|
ua = ua.gsub %r{mac\sos\sx}i, '' if ua =~ %r{ip(?:[ao]d|hone)}i
|
22
23
|
ua = ua.gsub %r{msie}i, '' if ua =~ %r{huaweisymantecspider}i
|
24
|
+
ua = ua.gsub %r{risc\sos}i, 'risc' if ua =~ %r{risc\sos}i
|
25
|
+
ua = ua.gsub %r{msie}i, '' if ua =~ %r{surf|\w*bot}i
|
26
|
+
ua = ua.gsub %r{safari}i, 'chrome' if ua =~ %r{bluechrome}i
|
27
|
+
ua = ua.gsub %r{msie|windows}i, '' if ua =~ %r{dts\sagent}i
|
28
|
+
ua = ua.gsub %r{blade\sos}i, 'blade-os' if ua =~ %r{future\sstar}i
|
29
|
+
ua = ua.gsub %r{safari}i, '' if ua =~ %r{obigo}i
|
30
|
+
ua = ua.gsub %r{awesomium}i, '' if ua =~ %r{flashfire}i
|
31
|
+
ua = ua.gsub %r{version}i, '' if ua =~ %r{kindle/\d}i
|
23
32
|
ua
|
24
33
|
end
|
25
34
|
|
26
|
-
# after
|
35
|
+
# after a matcher is found, it's values are filtered in two stages
|
27
36
|
# first, filters will parse all statically defined values (e.g.) no regexp
|
28
37
|
# or block within matchers, after that, smart matcher patterns will be
|
29
38
|
# conditionally added and parsed with the previously collected values and
|
@@ -31,34 +40,37 @@ Browserino.config.define do
|
|
31
40
|
|
32
41
|
# this is a global filter, multiple can be defined and they will all run
|
33
42
|
# before any named filters
|
34
|
-
filter do |
|
35
|
-
case
|
36
|
-
when TrueClass, FalseClass, NilClass, Proc then
|
37
|
-
when %r{\A[\d_\.]+\z}i then
|
38
|
-
else
|
43
|
+
filter do |val|
|
44
|
+
case val
|
45
|
+
when TrueClass, FalseClass, NilClass, Proc then val
|
46
|
+
when %r{\A[\d_\.]+\z}i then val.to_s.strip.tr('_', '.')
|
47
|
+
else val.to_s.downcase.strip.gsub(%r{[\s-]+}i, '_').to_sym
|
39
48
|
end
|
40
49
|
end
|
41
50
|
|
42
51
|
# this is a named filter, it defines the same filter for 3 properties
|
43
52
|
# multiple name filters for the same property can be created, they will be
|
44
53
|
# executed in order of addition
|
45
|
-
filter :version, :engine_version, :platform_version do |
|
46
|
-
Browserino::Version.new
|
54
|
+
filter :version, :engine_version, :platform_version do |val|
|
55
|
+
Browserino::Version.new val
|
47
56
|
end
|
48
57
|
|
49
|
-
filter :platform do |
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
58
|
+
filter :platform do |val|
|
59
|
+
if %r{ip(?:[ao]d|hone)}i =~ val then :ios
|
60
|
+
elsif %r{w(?:eb)?os}i =~ val then :webos
|
61
|
+
elsif %r{ubuntu|x11}i =~ val then :linux
|
62
|
+
elsif %r{mac_os_x}i =~ val then :macintosh
|
63
|
+
elsif %r{s(?:unos|olaris)}i =~ val then :solaris
|
64
|
+
elsif %r{cros}i =~ val then :chromeos
|
65
|
+
elsif %r{kindle|kf\w+}i =~ val then :fire_os
|
66
|
+
else val
|
67
|
+
end
|
56
68
|
end
|
57
69
|
|
58
|
-
filter :architecture do |
|
59
|
-
|
60
|
-
|
61
|
-
|
70
|
+
filter :architecture do |val|
|
71
|
+
val = :x64 if val && val != :arm && val =~ %r{(?:x86_|amd|wow)?64|i686}i
|
72
|
+
val = :x32 if val && !%i[arm x64].include?(val)
|
73
|
+
val
|
62
74
|
end
|
63
75
|
|
64
76
|
filter :mobile do |value|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
Browserino.config.define do
|
3
4
|
# labels will be defined before a client has been initialized
|
4
5
|
# they will not be filtered before being injected into the Client
|
@@ -7,7 +8,9 @@ Browserino.config.define do
|
|
7
8
|
# will create #label, #engine_label and #platform_label properties
|
8
9
|
# respectively. These enjoy all the features that regular defined properties
|
9
10
|
# in for instance methods enjoy, such as automatic question methods like
|
10
|
-
# client.platform_label? :mavericks
|
11
|
+
# client.platform_label? :mavericks and they can also be used in
|
12
|
+
# the method this alias is for, e.g. client.platform? :mavericks or
|
13
|
+
# client.is? :mavericks
|
11
14
|
label :android, for: :android, range: '1'..'1.4.9'
|
12
15
|
label :cupcake, for: :android, range: '1.5'..'1.9.9'
|
13
16
|
label :eclair, for: :android, range: '2'..'2.1'
|
@@ -35,11 +38,14 @@ Browserino.config.define do
|
|
35
38
|
label :el_capitan, for: :macintosh, range: '10.11'..'10.11.9'
|
36
39
|
label :sierra, for: :macintosh, range: '10.12'..'10.12.9'
|
37
40
|
|
38
|
-
label :
|
39
|
-
label :
|
40
|
-
label :
|
41
|
-
label :
|
42
|
-
label :
|
43
|
-
label :
|
44
|
-
label :
|
41
|
+
label :dos, for: :windows, range: '3.1'..'4.0'
|
42
|
+
label :windows98, for: :windows, range: '98'..'98.9.9'
|
43
|
+
label :windows2000, for: :windows, range: '5.0'..'5.0.9'
|
44
|
+
label :xp, for: :windows, range: '5.1'..'5.2.9'
|
45
|
+
label :vista, for: :windows, range: '6.0'..'6.0.9'
|
46
|
+
label :windows7, for: :windows, range: '6.1'..'6.1.9'
|
47
|
+
label :windows8, for: :windows, range: '6.2'..'6.3'
|
48
|
+
label :windows10, for: :windows, range: '10.0'..'10.9.9'
|
49
|
+
|
50
|
+
label :outlook2016, for: :outlook, range: '16.0'..'16.9.9'
|
45
51
|
end
|