browserino 4.0.0 → 4.1.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.
- 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
|