device_detector 1.0.3 → 1.0.7
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 +5 -5
- data/CHANGELOG.md +15 -0
- data/README.md +8 -7
- data/lib/device_detector/bot.rb +2 -2
- data/lib/device_detector/browser.rb +364 -0
- data/lib/device_detector/client.rb +11 -2
- data/lib/device_detector/device.rb +1247 -22
- data/lib/device_detector/memory_cache.rb +5 -5
- data/lib/device_detector/metadata_extractor.rb +7 -8
- data/lib/device_detector/model_extractor.rb +3 -3
- data/lib/device_detector/name_extractor.rb +2 -2
- data/lib/device_detector/os.rb +150 -116
- data/lib/device_detector/parser.rb +23 -10
- data/lib/device_detector/version.rb +1 -1
- data/lib/device_detector/version_extractor.rb +29 -2
- data/lib/device_detector.rb +73 -40
- data/regexes/bots.yml +868 -62
- data/regexes/client/browser_engine.yml +11 -2
- data/regexes/client/browsers.yml +1132 -112
- data/regexes/client/feed_readers.yml +5 -11
- data/regexes/client/libraries.yml +86 -2
- data/regexes/client/mediaplayers.yml +39 -3
- data/regexes/client/mobile_apps.yml +940 -66
- data/regexes/client/pim.yml +66 -3
- data/regexes/device/cameras.yml +6 -6
- data/regexes/device/car_browsers.yml +23 -3
- data/regexes/device/consoles.yml +15 -3
- data/regexes/device/mobiles.yml +18351 -3566
- data/regexes/device/notebooks.yml +114 -0
- data/regexes/device/portable_media_player.yml +36 -9
- data/regexes/device/shell_tv.yml +117 -0
- data/regexes/device/televisions.yml +440 -35
- data/regexes/oss.yml +635 -284
- data/regexes/vendorfragments.yml +5 -1
- metadata +21 -118
- data/.gitignore +0 -14
- data/.travis.yml +0 -14
- data/Gemfile +0 -8
- data/Rakefile +0 -96
- data/device_detector.gemspec +0 -26
- data/spec/device_detector/bot_fixtures_spec.rb +0 -30
- data/spec/device_detector/client_fixtures_spec.rb +0 -31
- data/spec/device_detector/concrete_user_agent_spec.rb +0 -135
- data/spec/device_detector/detector_fixtures_spec.rb +0 -100
- data/spec/device_detector/device_fixtures_spec.rb +0 -36
- data/spec/device_detector/device_spec.rb +0 -151
- data/spec/device_detector/memory_cache_spec.rb +0 -148
- data/spec/device_detector/model_extractor_spec.rb +0 -63
- data/spec/device_detector/os_fixtures_spec.rb +0 -26
- data/spec/device_detector/version_extractor_spec.rb +0 -79
- data/spec/device_detector_spec.rb +0 -189
- data/spec/fixtures/client/browser.yml +0 -2206
- data/spec/fixtures/client/feed_reader.yml +0 -199
- data/spec/fixtures/client/library.yml +0 -175
- data/spec/fixtures/client/mediaplayer.yml +0 -163
- data/spec/fixtures/client/mobile_app.yml +0 -193
- data/spec/fixtures/client/pim.yml +0 -115
- data/spec/fixtures/detector/bots.yml +0 -3260
- data/spec/fixtures/detector/camera.yml +0 -121
- data/spec/fixtures/detector/car_browser.yml +0 -21
- data/spec/fixtures/detector/console.yml +0 -281
- data/spec/fixtures/detector/desktop.yml +0 -5361
- data/spec/fixtures/detector/feature_phone.yml +0 -891
- data/spec/fixtures/detector/feed_reader.yml +0 -551
- data/spec/fixtures/detector/mediaplayer.yml +0 -210
- data/spec/fixtures/detector/mobile_apps.yml +0 -456
- data/spec/fixtures/detector/phablet.yml +0 -3785
- data/spec/fixtures/detector/portable_media_player.yml +0 -178
- data/spec/fixtures/detector/smart_display.yml +0 -61
- data/spec/fixtures/detector/smartphone-1.yml +0 -9953
- data/spec/fixtures/detector/smartphone-10.yml +0 -9924
- data/spec/fixtures/detector/smartphone-11.yml +0 -9889
- data/spec/fixtures/detector/smartphone-12.yml +0 -8655
- data/spec/fixtures/detector/smartphone-2.yml +0 -9967
- data/spec/fixtures/detector/smartphone-3.yml +0 -9887
- data/spec/fixtures/detector/smartphone-4.yml +0 -9911
- data/spec/fixtures/detector/smartphone-5.yml +0 -9933
- data/spec/fixtures/detector/smartphone-6.yml +0 -9923
- data/spec/fixtures/detector/smartphone-7.yml +0 -9892
- data/spec/fixtures/detector/smartphone-8.yml +0 -9896
- data/spec/fixtures/detector/smartphone-9.yml +0 -9928
- data/spec/fixtures/detector/smartphone.yml +0 -9984
- data/spec/fixtures/detector/tablet-1.yml +0 -10023
- data/spec/fixtures/detector/tablet-2.yml +0 -9968
- data/spec/fixtures/detector/tablet-3.yml +0 -7787
- data/spec/fixtures/detector/tablet.yml +0 -9951
- data/spec/fixtures/detector/tv.yml +0 -3333
- data/spec/fixtures/detector/unknown.yml +0 -3283
- data/spec/fixtures/device/camera.yml +0 -19
- data/spec/fixtures/device/car_browser.yml +0 -7
- data/spec/fixtures/device/console.yml +0 -79
- data/spec/fixtures/parser/oss.yml +0 -1047
- data/spec/fixtures/parser/vendorfragments.yml +0 -162
- data/spec/spec_helper.rb +0 -9
@@ -51,12 +51,12 @@ class DeviceDetector
|
|
51
51
|
def purge_cache
|
52
52
|
key_size = data.size
|
53
53
|
|
54
|
-
if key_size
|
55
|
-
# always remove about 1/3 of keys to reduce garbage collecting
|
56
|
-
amount_of_keys = key_size / 3
|
54
|
+
return if key_size < max_keys
|
57
55
|
|
58
|
-
|
59
|
-
|
56
|
+
# always remove about 1/3 of keys to reduce garbage collecting
|
57
|
+
amount_of_keys = key_size / 3
|
58
|
+
|
59
|
+
data.keys.first(amount_of_keys).each { |key| data.delete(key) }
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class DeviceDetector
|
2
4
|
class MetadataExtractor < Struct.new(:user_agent, :regex_meta)
|
3
|
-
|
4
5
|
def call
|
5
6
|
regex_meta.any? ? extract_metadata : nil
|
6
7
|
end
|
@@ -8,22 +9,20 @@ class DeviceDetector
|
|
8
9
|
private
|
9
10
|
|
10
11
|
def metadata_string
|
11
|
-
message = "#{
|
12
|
-
|
12
|
+
message = "#{name} (a child of MetadataExtractor) must implement the '#{__method__}' method."
|
13
|
+
raise NotImplementedError, message
|
13
14
|
end
|
14
15
|
|
15
16
|
def extract_metadata
|
16
17
|
user_agent.match(regex) do |match_data|
|
17
|
-
metadata_string.gsub(/\$(\d)/)
|
18
|
-
match_data[
|
19
|
-
|
18
|
+
metadata_string.gsub(/\$(\d)/) do
|
19
|
+
match_data[Regexp.last_match(1).to_i].to_s
|
20
|
+
end.strip
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
24
|
def regex
|
24
25
|
@regex ||= regex_meta[:regex]
|
25
26
|
end
|
26
|
-
|
27
27
|
end
|
28
28
|
end
|
29
|
-
|
@@ -1,8 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class DeviceDetector
|
2
4
|
class ModelExtractor < MetadataExtractor
|
3
|
-
|
4
5
|
def call
|
5
|
-
s = super.to_s.gsub('_',' ').strip
|
6
|
+
s = super.to_s.gsub('_', ' ').strip
|
6
7
|
s = s.gsub(/ TD$/i, '')
|
7
8
|
|
8
9
|
return nil if s == 'Build'
|
@@ -19,6 +20,5 @@ class DeviceDetector
|
|
19
20
|
def regex
|
20
21
|
@regex ||= regex_meta[:regex_model] || regex_meta[:regex]
|
21
22
|
end
|
22
|
-
|
23
23
|
end
|
24
24
|
end
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class DeviceDetector
|
2
4
|
class NameExtractor < MetadataExtractor
|
3
|
-
|
4
5
|
def call
|
5
6
|
if /\$[0-9]/ =~ metadata_string
|
6
7
|
extract_metadata
|
@@ -14,6 +15,5 @@ class DeviceDetector
|
|
14
15
|
def metadata_string
|
15
16
|
regex_meta[:name]
|
16
17
|
end
|
17
|
-
|
18
18
|
end
|
19
19
|
end
|
data/lib/device_detector/os.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'set'
|
2
4
|
|
3
5
|
class DeviceDetector
|
4
6
|
class OS < Parser
|
5
|
-
|
6
7
|
def name
|
7
8
|
os_info[:name]
|
8
9
|
end
|
@@ -29,7 +30,7 @@ class DeviceDetector
|
|
29
30
|
def os_info
|
30
31
|
from_cache(['os_info', self.class.name, user_agent]) do
|
31
32
|
os_name = NameExtractor.new(user_agent, regex_meta).call
|
32
|
-
if os_name && short = DOWNCASED_OPERATING_SYSTEMS[os_name.downcase]
|
33
|
+
if os_name && (short = DOWNCASED_OPERATING_SYSTEMS[os_name.downcase])
|
33
34
|
os_name = OPERATING_SYSTEMS[short]
|
34
35
|
else
|
35
36
|
short = 'UNK'
|
@@ -38,128 +39,161 @@ class DeviceDetector
|
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
41
|
-
DESKTOP_OSS = Set.new(
|
42
|
+
DESKTOP_OSS = Set.new(
|
43
|
+
[
|
44
|
+
'AmigaOS', 'IBM', 'GNU/Linux', 'Mac', 'Unix', 'Windows', 'BeOS', 'Chrome OS'
|
45
|
+
]
|
46
|
+
)
|
42
47
|
|
43
48
|
# OS short codes mapped to long names
|
44
49
|
OPERATING_SYSTEMS = {
|
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
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
50
|
+
'AIX' => 'AIX',
|
51
|
+
'AND' => 'Android',
|
52
|
+
'AMG' => 'AmigaOS',
|
53
|
+
'ATV' => 'tvOS',
|
54
|
+
'ARL' => 'Arch Linux',
|
55
|
+
'BTR' => 'BackTrack',
|
56
|
+
'SBA' => 'Bada',
|
57
|
+
'BEO' => 'BeOS',
|
58
|
+
'BLB' => 'BlackBerry OS',
|
59
|
+
'QNX' => 'BlackBerry Tablet OS',
|
60
|
+
'BMP' => 'Brew',
|
61
|
+
'CAI' => 'Caixa Mágica',
|
62
|
+
'CES' => 'CentOS',
|
63
|
+
'COS' => 'Chrome OS',
|
64
|
+
'CYN' => 'CyanogenMod',
|
65
|
+
'DEB' => 'Debian',
|
66
|
+
'DEE' => 'Deepin',
|
67
|
+
'DFB' => 'DragonFly',
|
68
|
+
'DVK' => 'DVKBuntu',
|
69
|
+
'FED' => 'Fedora',
|
70
|
+
'FEN' => 'Fenix',
|
71
|
+
'FOS' => 'Firefox OS',
|
72
|
+
'FIR' => 'Fire OS',
|
73
|
+
'FRE' => 'Freebox',
|
74
|
+
'BSD' => 'FreeBSD',
|
75
|
+
'FYD' => 'FydeOS',
|
76
|
+
'GNT' => 'Gentoo',
|
77
|
+
'GRI' => 'GridOS',
|
78
|
+
'GTV' => 'Google TV',
|
79
|
+
'HPX' => 'HP-UX',
|
80
|
+
'HAI' => 'Haiku OS',
|
81
|
+
'IPA' => 'iPadOS',
|
82
|
+
'HAR' => 'HarmonyOS',
|
83
|
+
'HAS' => 'HasCodingOS',
|
84
|
+
'IRI' => 'IRIX',
|
85
|
+
'INF' => 'Inferno',
|
86
|
+
'JME' => 'Java ME',
|
87
|
+
'KOS' => 'KaiOS',
|
88
|
+
'KNO' => 'Knoppix',
|
89
|
+
'KBT' => 'Kubuntu',
|
90
|
+
'LIN' => 'GNU/Linux',
|
91
|
+
'LBT' => 'Lubuntu',
|
92
|
+
'LOS' => 'Lumin OS',
|
93
|
+
'VLN' => 'VectorLinux',
|
94
|
+
'MAC' => 'Mac',
|
95
|
+
'MAE' => 'Maemo',
|
96
|
+
'MAG' => 'Mageia',
|
97
|
+
'MDR' => 'Mandriva',
|
98
|
+
'SMG' => 'MeeGo',
|
99
|
+
'MCD' => 'MocorDroid',
|
100
|
+
'MIN' => 'Mint',
|
101
|
+
'MLD' => 'MildWild',
|
102
|
+
'MOR' => 'MorphOS',
|
103
|
+
'NBS' => 'NetBSD',
|
104
|
+
'MTK' => 'MTK / Nucleus',
|
105
|
+
'MRE' => 'MRE',
|
106
|
+
'WII' => 'Nintendo',
|
107
|
+
'NDS' => 'Nintendo Mobile',
|
108
|
+
'OS2' => 'OS/2',
|
109
|
+
'T64' => 'OSF1',
|
110
|
+
'OBS' => 'OpenBSD',
|
111
|
+
'OWR' => 'OpenWrt',
|
112
|
+
'ORD' => 'Ordissimo',
|
113
|
+
'PCL' => 'PCLinuxOS',
|
114
|
+
'PSP' => 'PlayStation Portable',
|
115
|
+
'PS3' => 'PlayStation',
|
116
|
+
'RHT' => 'Red Hat',
|
117
|
+
'ROS' => 'RISC OS',
|
118
|
+
'ROK' => 'Roku OS',
|
119
|
+
'RSO' => 'Rosa',
|
120
|
+
'REM' => 'Remix OS',
|
121
|
+
'REX' => 'REX',
|
122
|
+
'RZD' => 'RazoDroiD',
|
123
|
+
'SAB' => 'Sabayon',
|
124
|
+
'SSE' => 'SUSE',
|
125
|
+
'SAF' => 'Sailfish OS',
|
126
|
+
'SEE' => 'SeewoOS',
|
127
|
+
'SLW' => 'Slackware',
|
128
|
+
'SOS' => 'Solaris',
|
129
|
+
'SYL' => 'Syllable',
|
130
|
+
'SYM' => 'Symbian',
|
131
|
+
'SYS' => 'Symbian OS',
|
132
|
+
'S40' => 'Symbian OS Series 40',
|
133
|
+
'S60' => 'Symbian OS Series 60',
|
134
|
+
'SY3' => 'Symbian^3',
|
135
|
+
'TDX' => 'ThreadX',
|
136
|
+
'TIZ' => 'Tizen',
|
137
|
+
'TOS' => 'TmaxOS',
|
138
|
+
'UBT' => 'Ubuntu',
|
139
|
+
'WAS' => 'watchOS',
|
140
|
+
'WTV' => 'WebTV',
|
141
|
+
'WHS' => 'Whale OS',
|
142
|
+
'WIN' => 'Windows',
|
143
|
+
'WCE' => 'Windows CE',
|
144
|
+
'WIO' => 'Windows IoT',
|
145
|
+
'WMO' => 'Windows Mobile',
|
146
|
+
'WPH' => 'Windows Phone',
|
147
|
+
'WRT' => 'Windows RT',
|
148
|
+
'XBX' => 'Xbox',
|
149
|
+
'XBT' => 'Xubuntu',
|
150
|
+
'YNS' => 'YunOS',
|
151
|
+
'IOS' => 'iOS',
|
152
|
+
'POS' => 'palmOS',
|
153
|
+
'WOS' => 'webOS'
|
154
|
+
}.freeze
|
155
|
+
|
156
|
+
DOWNCASED_OPERATING_SYSTEMS = OPERATING_SYSTEMS.each_with_object({}) do |(short, long), h|
|
157
|
+
h[long.downcase] = short
|
158
|
+
end.freeze
|
128
159
|
|
129
160
|
OS_FAMILIES = {
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
161
|
+
'Android' => %w[AND CYN FIR REM RZD MLD MCD YNS GRI HAR],
|
162
|
+
'AmigaOS' => %w[AMG MOR],
|
163
|
+
'BlackBerry' => %w[BLB QNX],
|
164
|
+
'Brew' => ['BMP'],
|
165
|
+
'BeOS' => %w[BEO HAI],
|
166
|
+
'Chrome OS' => %w[COS FYD SEE],
|
167
|
+
'Firefox OS' => %w[FOS KOS],
|
168
|
+
'Gaming Console' => %w[WII PS3],
|
169
|
+
'Google TV' => ['GTV'],
|
170
|
+
'IBM' => ['OS2'],
|
171
|
+
'iOS' => %w[IOS ATV WAS IPA],
|
172
|
+
'RISC OS' => ['ROS'],
|
173
|
+
'GNU/Linux' => %w[
|
174
|
+
LIN ARL DEB KNO MIN UBT KBT XBT LBT FED
|
175
|
+
RHT VLN MDR GNT SAB SLW SSE CES BTR SAF
|
176
|
+
ORD TOS RSO DEE FRE MAG FEN CAI PCL HAS
|
177
|
+
LOS DVK ROK OWR
|
178
|
+
],
|
179
|
+
'Mac' => ['MAC'],
|
180
|
+
'Mobile Gaming Console' => %w[PSP NDS XBX],
|
181
|
+
'Real-time OS' => %w[MTK TDX MRE JME REX],
|
182
|
+
'Other Mobile' => %w[WOS POS SBA TIZ SMG MAE],
|
183
|
+
'Symbian' => %w[SYM SYS SY3 S60 S40],
|
184
|
+
'Unix' => %w[SOS AIX HPX BSD NBS OBS DFB SYL IRI T64 INF],
|
185
|
+
'WebTV' => ['WTV'],
|
186
|
+
'Windows' => ['WIN'],
|
187
|
+
'Windows Mobile' => %w[WPH WMO WCE WRT WIO],
|
188
|
+
'Other Smart TV' => ['WHS']
|
189
|
+
}.freeze
|
190
|
+
|
191
|
+
FAMILY_TO_OS = OS_FAMILIES.each_with_object({}) do |(family, oss), h|
|
192
|
+
oss.each { |os| h[os] = family }
|
193
|
+
end.freeze
|
158
194
|
|
159
195
|
def filenames
|
160
196
|
['oss.yml']
|
161
197
|
end
|
162
|
-
|
163
198
|
end
|
164
|
-
|
165
199
|
end
|
@@ -1,7 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class DeviceDetector
|
2
|
-
class Parser
|
4
|
+
class Parser
|
5
|
+
ROOT = File.expand_path('../..', __dir__)
|
6
|
+
|
7
|
+
REGEX_CACHE = ::DeviceDetector::MemoryCache.new({})
|
8
|
+
private_constant :REGEX_CACHE
|
9
|
+
|
10
|
+
def initialize(user_agent)
|
11
|
+
@user_agent = user_agent
|
12
|
+
end
|
3
13
|
|
4
|
-
|
14
|
+
attr_reader :user_agent
|
5
15
|
|
6
16
|
def name
|
7
17
|
from_cache(['name', self.class.name, user_agent]) do
|
@@ -32,17 +42,17 @@ class DeviceDetector
|
|
32
42
|
end
|
33
43
|
|
34
44
|
def filenames
|
35
|
-
|
45
|
+
raise NotImplementedError
|
36
46
|
end
|
37
47
|
|
38
48
|
def filepaths
|
39
49
|
filenames.map do |filename|
|
40
|
-
[
|
50
|
+
[filename.to_sym, File.join(ROOT, 'regexes', filename)]
|
41
51
|
end
|
42
52
|
end
|
43
53
|
|
44
54
|
def regexes_for(file_paths)
|
45
|
-
|
55
|
+
REGEX_CACHE.get_or_set(file_paths) do
|
46
56
|
load_regexes(file_paths).flat_map { |path, regex| parse_regexes(path, regex) }
|
47
57
|
end
|
48
58
|
end
|
@@ -54,16 +64,20 @@ class DeviceDetector
|
|
54
64
|
def symbolize_keys!(object)
|
55
65
|
case object
|
56
66
|
when Array
|
57
|
-
object.map!{ |v| symbolize_keys!(v) }
|
67
|
+
object.map! { |v| symbolize_keys!(v) }
|
58
68
|
when Hash
|
59
|
-
|
69
|
+
keys = object.keys
|
70
|
+
keys.each do |k|
|
71
|
+
object[k.to_sym] = symbolize_keys!(object.delete(k)) if k.is_a?(String)
|
72
|
+
end
|
60
73
|
end
|
61
74
|
object
|
62
75
|
end
|
63
76
|
|
64
77
|
def parse_regexes(path, raw_regexes)
|
65
78
|
raw_regexes.map do |meta|
|
66
|
-
|
79
|
+
raise "invalid device spec: #{meta.inspect}" unless meta[:regex].is_a? String
|
80
|
+
|
67
81
|
meta[:regex] = build_regex(meta[:regex])
|
68
82
|
meta[:path] = path
|
69
83
|
meta
|
@@ -71,12 +85,11 @@ class DeviceDetector
|
|
71
85
|
end
|
72
86
|
|
73
87
|
def build_regex(src)
|
74
|
-
Regexp.new('(?:^|[^A-Z0-9\-_]|[^A-Z0-9\-]_|sprd-)(?:' + src + ')', Regexp::IGNORECASE)
|
88
|
+
Regexp.new('(?:^|[^A-Z0-9\-_]|[^A-Z0-9\-]_|sprd-|MZ-)(?:' + src + ')', Regexp::IGNORECASE)
|
75
89
|
end
|
76
90
|
|
77
91
|
def from_cache(key)
|
78
92
|
DeviceDetector.cache.get_or_set(key) { yield }
|
79
93
|
end
|
80
|
-
|
81
94
|
end
|
82
95
|
end
|
@@ -1,12 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class DeviceDetector
|
2
4
|
class VersionExtractor < MetadataExtractor
|
5
|
+
MAJOR_VERSION_2 = Gem::Version.new('2.0')
|
6
|
+
MAJOR_VERSION_3 = Gem::Version.new('3.0')
|
7
|
+
MAJOR_VERSION_4 = Gem::Version.new('4.0')
|
8
|
+
MAJOR_VERSION_8 = Gem::Version.new('8.0')
|
9
|
+
|
10
|
+
def call
|
11
|
+
simple_version = super&.chomp('.')
|
12
|
+
|
13
|
+
return simple_version unless simple_version&.empty?
|
14
|
+
|
15
|
+
os_version_by_regexes
|
16
|
+
end
|
3
17
|
|
4
18
|
private
|
5
19
|
|
20
|
+
def os_version_by_regexes
|
21
|
+
version_matches = regex_meta[:versions]
|
22
|
+
return '' unless version_matches
|
23
|
+
|
24
|
+
version_matches.detect do |matcher|
|
25
|
+
user_agent.match(matcher[:regex]) do |match_data|
|
26
|
+
return matcher[:version].gsub(/\$(\d)/) do
|
27
|
+
match_data[Regexp.last_match(1).to_i].to_s
|
28
|
+
end.strip
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
''
|
33
|
+
end
|
34
|
+
|
6
35
|
def metadata_string
|
7
36
|
String(regex_meta[:version])
|
8
37
|
end
|
9
|
-
|
10
38
|
end
|
11
39
|
end
|
12
|
-
|