device_detector 1.0.0 → 1.1.3

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.
Files changed (89) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +58 -4
  3. data/README.md +57 -21
  4. data/lib/device_detector/bot.rb +2 -2
  5. data/lib/device_detector/browser.rb +691 -0
  6. data/lib/device_detector/client.rb +11 -2
  7. data/lib/device_detector/client_hint.rb +249 -0
  8. data/lib/device_detector/device.rb +1954 -23
  9. data/lib/device_detector/memory_cache.rb +26 -19
  10. data/lib/device_detector/metadata_extractor.rb +7 -8
  11. data/lib/device_detector/model_extractor.rb +3 -3
  12. data/lib/device_detector/name_extractor.rb +2 -2
  13. data/lib/device_detector/os.rb +289 -112
  14. data/lib/device_detector/parser.rb +49 -13
  15. data/lib/device_detector/vendor_fragment.rb +25 -0
  16. data/lib/device_detector/version.rb +3 -1
  17. data/lib/device_detector/version_extractor.rb +29 -2
  18. data/lib/device_detector.rb +192 -44
  19. data/regexes/bots.yml +3399 -91
  20. data/regexes/client/browser_engine.yml +28 -4
  21. data/regexes/client/browsers.yml +2697 -408
  22. data/regexes/client/feed_readers.yml +60 -22
  23. data/regexes/client/hints/apps.yml +150 -0
  24. data/regexes/client/hints/browsers.yml +292 -0
  25. data/regexes/client/libraries.yml +598 -4
  26. data/regexes/client/mediaplayers.yml +110 -5
  27. data/regexes/client/mobile_apps.yml +2451 -14
  28. data/regexes/client/pim.yml +128 -3
  29. data/regexes/device/cameras.yml +6 -6
  30. data/regexes/device/car_browsers.yml +39 -3
  31. data/regexes/device/consoles.yml +40 -6
  32. data/regexes/device/mobiles.yml +38844 -2907
  33. data/regexes/device/notebooks.yml +127 -0
  34. data/regexes/device/portable_media_player.yml +75 -12
  35. data/regexes/device/shell_tv.yml +145 -0
  36. data/regexes/device/televisions.yml +981 -40
  37. data/regexes/oss.yml +1560 -311
  38. data/regexes/vendorfragments.yml +6 -2
  39. metadata +31 -105
  40. data/.gitignore +0 -14
  41. data/.travis.yml +0 -18
  42. data/Gemfile +0 -8
  43. data/Rakefile +0 -79
  44. data/device_detector.gemspec +0 -26
  45. data/spec/device_detector/bot_fixtures_spec.rb +0 -30
  46. data/spec/device_detector/client_fixtures_spec.rb +0 -31
  47. data/spec/device_detector/concrete_user_agent_spec.rb +0 -136
  48. data/spec/device_detector/detector_fixtures_spec.rb +0 -60
  49. data/spec/device_detector/device_fixtures_spec.rb +0 -36
  50. data/spec/device_detector/device_spec.rb +0 -151
  51. data/spec/device_detector/memory_cache_spec.rb +0 -116
  52. data/spec/device_detector/model_extractor_spec.rb +0 -63
  53. data/spec/device_detector/os_fixtures_spec.rb +0 -26
  54. data/spec/device_detector/version_extractor_spec.rb +0 -80
  55. data/spec/device_detector_spec.rb +0 -198
  56. data/spec/fixtures/client/browser.yml +0 -1313
  57. data/spec/fixtures/client/feed_reader.yml +0 -187
  58. data/spec/fixtures/client/library.yml +0 -84
  59. data/spec/fixtures/client/mediaplayer.yml +0 -168
  60. data/spec/fixtures/client/mobile_app.yml +0 -30
  61. data/spec/fixtures/client/pim.yml +0 -96
  62. data/spec/fixtures/detector/bots.yml +0 -2418
  63. data/spec/fixtures/detector/camera.yml +0 -115
  64. data/spec/fixtures/detector/car_browser.yml +0 -20
  65. data/spec/fixtures/detector/console.yml +0 -267
  66. data/spec/fixtures/detector/desktop.yml +0 -4828
  67. data/spec/fixtures/detector/feature_phone.yml +0 -782
  68. data/spec/fixtures/detector/feed_reader.yml +0 -486
  69. data/spec/fixtures/detector/mediaplayer.yml +0 -179
  70. data/spec/fixtures/detector/mobile_apps.yml +0 -149
  71. data/spec/fixtures/detector/phablet.yml +0 -2140
  72. data/spec/fixtures/detector/portable_media_player.yml +0 -153
  73. data/spec/fixtures/detector/smart_display.yml +0 -58
  74. data/spec/fixtures/detector/smartphone-1.yml +0 -9469
  75. data/spec/fixtures/detector/smartphone-2.yml +0 -9414
  76. data/spec/fixtures/detector/smartphone-3.yml +0 -9396
  77. data/spec/fixtures/detector/smartphone-4.yml +0 -5742
  78. data/spec/fixtures/detector/smartphone.yml +0 -9411
  79. data/spec/fixtures/detector/tablet-1.yml +0 -9495
  80. data/spec/fixtures/detector/tablet-2.yml +0 -248
  81. data/spec/fixtures/detector/tablet.yml +0 -9484
  82. data/spec/fixtures/detector/tv.yml +0 -2582
  83. data/spec/fixtures/detector/unknown.yml +0 -3196
  84. data/spec/fixtures/device/camera.yml +0 -18
  85. data/spec/fixtures/device/car_browser.yml +0 -6
  86. data/spec/fixtures/device/console.yml +0 -78
  87. data/spec/fixtures/parser/oss.yml +0 -800
  88. data/spec/fixtures/parser/vendorfragments.yml +0 -162
  89. data/spec/spec_helper.rb +0 -9
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class DeviceDetector
2
4
  class MemoryCache
3
-
4
5
  DEFAULT_MAX_KEYS = 5000
6
+ STORES_NIL_VALUE = :__is_nil__
5
7
 
6
8
  attr_reader :data, :max_keys, :lock
7
9
  private :lock
@@ -15,41 +17,46 @@ class DeviceDetector
15
17
  def set(key, value)
16
18
  lock.synchronize do
17
19
  purge_cache
18
- data[String(key)] = value
20
+ # convert nil values into symbol so we know a value is present
21
+ cache_value = value.nil? ? STORES_NIL_VALUE : value
22
+ data[String(key)] = cache_value
23
+ value
19
24
  end
20
25
  end
21
26
 
22
27
  def get(key)
23
- data[String(key)]
24
- end
25
-
26
- def key?(string_key)
27
- data.key?(string_key)
28
+ value, _hit = get_hit(key)
29
+ value
28
30
  end
29
31
 
30
32
  def get_or_set(key, value = nil)
31
33
  string_key = String(key)
32
34
 
33
- if key?(string_key)
34
- get(string_key)
35
- else
36
- value = yield if block_given?
37
- set(string_key, value)
38
- end
35
+ result, hit = get_hit(string_key)
36
+ return result if hit
37
+
38
+ value = yield if block_given?
39
+ set(string_key, value)
39
40
  end
40
41
 
41
42
  private
42
43
 
44
+ def get_hit(key)
45
+ value = data[String(key)]
46
+ is_hit = !value.nil? || value == STORES_NIL_VALUE
47
+ value = nil if value == STORES_NIL_VALUE
48
+ [value, is_hit]
49
+ end
50
+
43
51
  def purge_cache
44
52
  key_size = data.size
45
53
 
46
- if key_size >= max_keys
47
- # always remove about 1/3 of keys to reduce garbage collecting
48
- amount_of_keys = key_size / 3
54
+ return if key_size < max_keys
49
55
 
50
- data.keys.first(amount_of_keys).each { |key| data.delete(key) }
51
- end
52
- end
56
+ # always remove about 1/3 of keys to reduce garbage collecting
57
+ amount_of_keys = key_size / 3
53
58
 
59
+ data.keys.first(amount_of_keys).each { |key| data.delete(key) }
60
+ end
54
61
  end
55
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 = "#{self.name} (a child of MetadataExtractor) must implement the '#{__method__}' method."
12
- fail NotImplementedError, message
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[$1.to_i].to_s
19
- }.strip
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
@@ -1,7 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'set'
2
4
 
3
5
  class DeviceDetector
4
6
  class OS < Parser
7
+ class << self
8
+ def mapped_os_version(version, mapping)
9
+ return if version.nil?
10
+
11
+ major_version = version.split('.').first
12
+
13
+ mapping[version] || mapping[major_version]
14
+ end
15
+ end
5
16
 
6
17
  def name
7
18
  os_info[:name]
@@ -29,7 +40,7 @@ class DeviceDetector
29
40
  def os_info
30
41
  from_cache(['os_info', self.class.name, user_agent]) do
31
42
  os_name = NameExtractor.new(user_agent, regex_meta).call
32
- if os_name && short = DOWNCASED_OPERATING_SYSTEMS[os_name.downcase]
43
+ if os_name && (short = DOWNCASED_OPERATING_SYSTEMS[os_name.downcase])
33
44
  os_name = OPERATING_SYSTEMS[short]
34
45
  else
35
46
  short = 'UNK'
@@ -38,125 +49,291 @@ class DeviceDetector
38
49
  end
39
50
  end
40
51
 
41
- DESKTOP_OSS = Set.new(['AmigaOS', 'IBM', 'GNU/Linux', 'Mac', 'Unix', 'Windows', 'BeOS', 'Chrome OS'])
52
+ # https://github.com/matomo-org/device-detector/blob/75d88bbefb0182f9207c9f48dc39b1bc8c7cc43f/Parser/OperatingSystem.php#L286-L288
53
+ DESKTOP_OSS = Set.new(
54
+ [
55
+ 'AmigaOS', 'IBM', 'GNU/Linux', 'Mac', 'Unix', 'Windows', 'BeOS', 'Chrome OS', 'Chromium OS'
56
+ ]
57
+ )
42
58
 
43
59
  # OS short codes mapped to long names
60
+ # https://github.com/matomo-org/device-detector/blob/75d88bbefb0182f9207c9f48dc39b1bc8c7cc43f/Parser/OperatingSystem.php#L42-L220
44
61
  OPERATING_SYSTEMS = {
45
- 'AIX' => 'AIX',
46
- 'AND' => 'Android',
47
- 'AMG' => 'AmigaOS',
48
- 'ATV' => 'Apple TV',
49
- 'ARL' => 'Arch Linux',
50
- 'BTR' => 'BackTrack',
51
- 'SBA' => 'Bada',
52
- 'BEO' => 'BeOS',
53
- 'BLB' => 'BlackBerry OS',
54
- 'QNX' => 'BlackBerry Tablet OS',
55
- 'BMP' => 'Brew',
56
- 'CES' => 'CentOS',
57
- 'COS' => 'Chrome OS',
58
- 'CYN' => 'CyanogenMod',
59
- 'DEB' => 'Debian',
60
- 'DFB' => 'DragonFly',
61
- 'FED' => 'Fedora',
62
- 'FOS' => 'Firefox OS',
63
- 'BSD' => 'FreeBSD',
64
- 'GNT' => 'Gentoo',
65
- 'GTV' => 'Google TV',
66
- 'HPX' => 'HP-UX',
67
- 'HAI' => 'Haiku OS',
68
- 'IRI' => 'IRIX',
69
- 'INF' => 'Inferno',
70
- 'KNO' => 'Knoppix',
71
- 'KBT' => 'Kubuntu',
72
- 'LIN' => 'GNU/Linux',
73
- 'LBT' => 'Lubuntu',
74
- 'VLN' => 'VectorLinux',
75
- 'MAC' => 'Mac',
76
- 'MAE' => 'Maemo',
77
- 'MDR' => 'Mandriva',
78
- 'SMG' => 'MeeGo',
79
- 'MCD' => 'MocorDroid',
80
- 'MIN' => 'Mint',
81
- 'MLD' => 'MildWild',
82
- 'MOR' => 'MorphOS',
83
- 'NBS' => 'NetBSD',
84
- 'MTK' => 'MTK / Nucleus',
85
- 'WII' => 'Nintendo',
86
- 'NDS' => 'Nintendo Mobile',
87
- 'OS2' => 'OS/2',
88
- 'T64' => 'OSF1',
89
- 'OBS' => 'OpenBSD',
90
- 'PSP' => 'PlayStation Portable',
91
- 'PS3' => 'PlayStation',
92
- 'RHT' => 'Red Hat',
93
- 'ROS' => 'RISC OS',
94
- 'REM' => 'Remix OS',
95
- 'RZD' => 'RazoDroiD',
96
- 'SAB' => 'Sabayon',
97
- 'SSE' => 'SUSE',
98
- 'SAF' => 'Sailfish OS',
99
- 'SLW' => 'Slackware',
100
- 'SOS' => 'Solaris',
101
- 'SYL' => 'Syllable',
102
- 'SYM' => 'Symbian',
103
- 'SYS' => 'Symbian OS',
104
- 'S40' => 'Symbian OS Series 40',
105
- 'S60' => 'Symbian OS Series 60',
106
- 'SY3' => 'Symbian^3',
107
- 'TDX' => 'ThreadX',
108
- 'TIZ' => 'Tizen',
109
- 'UBT' => 'Ubuntu',
110
- 'WTV' => 'WebTV',
111
- 'WIN' => 'Windows',
112
- 'WCE' => 'Windows CE',
113
- 'WMO' => 'Windows Mobile',
114
- 'WPH' => 'Windows Phone',
115
- 'WRT' => 'Windows RT',
116
- 'XBX' => 'Xbox',
117
- 'XBT' => 'Xubuntu',
118
- 'YNS' => 'YunOs',
119
- 'IOS' => 'iOS',
120
- 'POS' => 'palmOS',
121
- 'WOS' => 'webOS'
122
- }
123
-
124
- DOWNCASED_OPERATING_SYSTEMS = OPERATING_SYSTEMS.each_with_object({}){|(short,long),h| h[long.downcase] = short}
62
+ 'AIX' => 'AIX',
63
+ 'AND' => 'Android',
64
+ 'ADR' => 'Android TV',
65
+ 'ALP' => 'Alpine Linux',
66
+ 'AMZ' => 'Amazon Linux',
67
+ 'AMG' => 'AmigaOS',
68
+ 'ARM' => 'Armadillo OS',
69
+ 'ARO' => 'AROS',
70
+ 'ATV' => 'tvOS',
71
+ 'ARL' => 'Arch Linux',
72
+ 'AOS' => 'AOSC OS',
73
+ 'ASP' => 'ASPLinux',
74
+ 'BTR' => 'BackTrack',
75
+ 'SBA' => 'Bada',
76
+ 'BYI' => 'Baidu Yi',
77
+ 'BEO' => 'BeOS',
78
+ 'BLB' => 'BlackBerry OS',
79
+ 'QNX' => 'BlackBerry Tablet OS',
80
+ 'BOS' => 'Bliss OS',
81
+ 'BMP' => 'Brew',
82
+ 'BSN' => 'BrightSignOS',
83
+ 'CAI' => 'Caixa Mágica',
84
+ 'CES' => 'CentOS',
85
+ 'CST' => 'CentOS Stream',
86
+ 'CLO' => 'Clear Linux OS',
87
+ 'CLR' => 'ClearOS Mobile',
88
+ 'COS' => 'Chrome OS',
89
+ 'CRS' => 'Chromium OS',
90
+ 'CHN' => 'China OS',
91
+ 'CYN' => 'CyanogenMod',
92
+ 'DEB' => 'Debian',
93
+ 'DEE' => 'Deepin',
94
+ 'DFB' => 'DragonFly',
95
+ 'DVK' => 'DVKBuntu',
96
+ 'ELE' => 'ElectroBSD',
97
+ 'EUL' => 'EulerOS',
98
+ 'FED' => 'Fedora',
99
+ 'FEN' => 'Fenix',
100
+ 'FOS' => 'Firefox OS',
101
+ 'FIR' => 'Fire OS',
102
+ 'FOR' => 'Foresight Linux',
103
+ 'FRE' => 'Freebox',
104
+ 'BSD' => 'FreeBSD',
105
+ 'FRI' => 'FRITZ!OS',
106
+ 'FYD' => 'FydeOS',
107
+ 'FUC' => 'Fuchsia',
108
+ 'GNT' => 'Gentoo',
109
+ 'GNX' => 'GENIX',
110
+ 'GEO' => 'GEOS',
111
+ 'GNS' => 'gNewSense',
112
+ 'GRI' => 'GridOS',
113
+ 'GTV' => 'Google TV',
114
+ 'HPX' => 'HP-UX',
115
+ 'HAI' => 'Haiku OS',
116
+ 'IPA' => 'iPadOS',
117
+ 'HAR' => 'HarmonyOS',
118
+ 'HAS' => 'HasCodingOS',
119
+ 'HEL' => 'HELIX OS',
120
+ 'IRI' => 'IRIX',
121
+ 'INF' => 'Inferno',
122
+ 'JME' => 'Java ME',
123
+ 'JOL' => 'Joli OS',
124
+ 'KOS' => 'KaiOS',
125
+ 'KAL' => 'Kali',
126
+ 'KAN' => 'Kanotix',
127
+ 'KIN' => 'KIN OS',
128
+ 'KNO' => 'Knoppix',
129
+ 'KTV' => 'KreaTV',
130
+ 'KBT' => 'Kubuntu',
131
+ 'LIN' => 'GNU/Linux',
132
+ 'LND' => 'LindowsOS',
133
+ 'LNS' => 'Linspire',
134
+ 'LEN' => 'Lineage OS',
135
+ 'LIR' => 'Liri OS',
136
+ 'LOO' => 'Loongnix',
137
+ 'LBT' => 'Lubuntu',
138
+ 'LOS' => 'Lumin OS',
139
+ 'LUN' => 'LuneOS',
140
+ 'VLN' => 'VectorLinux',
141
+ 'MAC' => 'Mac',
142
+ 'MAE' => 'Maemo',
143
+ 'MAG' => 'Mageia',
144
+ 'MDR' => 'Mandriva',
145
+ 'SMG' => 'MeeGo',
146
+ 'MCD' => 'MocorDroid',
147
+ 'MON' => 'moonOS',
148
+ 'EZX' => 'Motorola EZX',
149
+ 'MIN' => 'Mint',
150
+ 'MLD' => 'MildWild',
151
+ 'MOR' => 'MorphOS',
152
+ 'NBS' => 'NetBSD',
153
+ 'MTK' => 'MTK / Nucleus',
154
+ 'MRE' => 'MRE',
155
+ 'NXT' => 'NeXTSTEP',
156
+ 'NWS' => 'NEWS-OS',
157
+ 'WII' => 'Nintendo',
158
+ 'NDS' => 'Nintendo Mobile',
159
+ 'NOV' => 'Nova',
160
+ 'OS2' => 'OS/2',
161
+ 'T64' => 'OSF1',
162
+ 'OBS' => 'OpenBSD',
163
+ 'OVS' => 'OpenVMS',
164
+ 'OVZ' => 'OpenVZ',
165
+ 'OWR' => 'OpenWrt',
166
+ 'OTV' => 'Opera TV',
167
+ 'ORA' => 'Oracle Linux',
168
+ 'ORD' => 'Ordissimo',
169
+ 'PAR' => 'Pardus',
170
+ 'PCL' => 'PCLinuxOS',
171
+ 'PIC' => 'PICO OS',
172
+ 'PLA' => 'Plasma Mobile',
173
+ 'PSP' => 'PlayStation Portable',
174
+ 'PS3' => 'PlayStation',
175
+ 'PVE' => 'Proxmox VE',
176
+ 'PUR' => 'PureOS',
177
+ 'QTP' => 'Qtopia',
178
+ 'PIO' => 'Raspberry Pi OS',
179
+ 'RAS' => 'Raspbian',
180
+ 'RHT' => 'Red Hat',
181
+ 'RST' => 'Red Star',
182
+ 'RED' => 'RedOS',
183
+ 'REV' => 'Revenge OS',
184
+ 'ROS' => 'RISC OS',
185
+ 'ROC' => 'Rocky Linux',
186
+ 'ROK' => 'Roku OS',
187
+ 'RSO' => 'Rosa',
188
+ 'ROU' => 'RouterOS',
189
+ 'REM' => 'Remix OS',
190
+ 'RRS' => 'Resurrection Remix OS',
191
+ 'REX' => 'REX',
192
+ 'RZD' => 'RazoDroiD',
193
+ 'SAB' => 'Sabayon',
194
+ 'SSE' => 'SUSE',
195
+ 'SAF' => 'Sailfish OS',
196
+ 'SCI' => 'Scientific Linux',
197
+ 'SEE' => 'SeewoOS',
198
+ 'SER' => 'SerenityOS',
199
+ 'SIR' => 'Sirin OS',
200
+ 'SLW' => 'Slackware',
201
+ 'SOS' => 'Solaris',
202
+ 'SBL' => 'Star-Blade OS',
203
+ 'SYL' => 'Syllable',
204
+ 'SYM' => 'Symbian',
205
+ 'SYS' => 'Symbian OS',
206
+ 'S40' => 'Symbian OS Series 40',
207
+ 'S60' => 'Symbian OS Series 60',
208
+ 'SY3' => 'Symbian^3',
209
+ 'TEN' => 'TencentOS',
210
+ 'TDX' => 'ThreadX',
211
+ 'TIZ' => 'Tizen',
212
+ 'TIV' => 'TiVo OS',
213
+ 'TOS' => 'TmaxOS',
214
+ 'TUR' => 'Turbolinux',
215
+ 'UBT' => 'Ubuntu',
216
+ 'ULT' => 'ULTRIX',
217
+ 'UOS' => 'UOS',
218
+ 'VID' => 'VIDAA',
219
+ 'WAS' => 'watchOS',
220
+ 'WER' => 'Wear OS',
221
+ 'WTV' => 'WebTV',
222
+ 'WHS' => 'Whale OS',
223
+ 'WIN' => 'Windows',
224
+ 'WCE' => 'Windows CE',
225
+ 'WIO' => 'Windows IoT',
226
+ 'WMO' => 'Windows Mobile',
227
+ 'WPH' => 'Windows Phone',
228
+ 'WRT' => 'Windows RT',
229
+ 'WPO' => 'WoPhone',
230
+ 'XBX' => 'Xbox',
231
+ 'XBT' => 'Xubuntu',
232
+ 'YNS' => 'YunOS',
233
+ 'ZEN' => 'Zenwalk',
234
+ 'ZOR' => 'ZorinOS',
235
+ 'IOS' => 'iOS',
236
+ 'POS' => 'palmOS',
237
+ 'WEB' => 'Webian',
238
+ 'WOS' => 'webOS'
239
+ }.freeze
240
+
241
+ DOWNCASED_OPERATING_SYSTEMS = OPERATING_SYSTEMS.each_with_object({}) do |(short, long), h|
242
+ h[long.downcase] = short
243
+ end.freeze
244
+
245
+ APPLE_OS_NAMES = Set.new(%w[iPadOS tvOS watchOS iOS Mac]).freeze
125
246
 
247
+ # https://github.com/matomo-org/device-detector/blob/75d88bbefb0182f9207c9f48dc39b1bc8c7cc43f/Parser/OperatingSystem.php#L227-L269
126
248
  OS_FAMILIES = {
127
- 'Android' => ['AND', 'CYN', 'REM', 'RZD', 'MLD', 'MCD', 'YNS'],
128
- 'AmigaOS' => ['AMG', 'MOR'],
129
- 'Apple TV' => ['ATV'],
130
- 'BlackBerry' => ['BLB', 'QNX'],
131
- 'Brew' => ['BMP'],
132
- 'BeOS' => ['BEO', 'HAI'],
133
- 'Chrome OS' => ['COS'],
134
- 'Firefox OS' => ['FOS'],
135
- 'Gaming Console' => ['WII', 'PS3'],
136
- 'Google TV' => ['GTV'],
137
- 'IBM' => ['OS2'],
138
- 'iOS' => ['IOS'],
139
- 'RISC OS' => ['ROS'],
140
- 'GNU/Linux' => ['LIN', 'ARL', 'DEB', 'KNO', 'MIN', 'UBT', 'KBT', 'XBT', 'LBT', 'FED', 'RHT', 'VLN', 'MDR', 'GNT', 'SAB', 'SLW', 'SSE', 'CES', 'BTR', 'SAF'],
141
- 'Mac' => ['MAC'],
142
- 'Mobile Gaming Console' => ['PSP', 'NDS', 'XBX'],
143
- 'Real-time OS' => ['MTK', 'TDX'],
144
- 'Other Mobile' => ['WOS', 'POS', 'SBA', 'TIZ', 'SMG', 'MAE'],
145
- 'Symbian' => ['SYM', 'SYS', 'SY3', 'S60', 'S40'],
146
- 'Unix' => ['SOS', 'AIX', 'HPX', 'BSD', 'NBS', 'OBS', 'DFB', 'SYL', 'IRI', 'T64', 'INF'],
147
- 'WebTV' => ['WTV'],
148
- 'Windows' => ['WIN'],
149
- 'Windows Mobile' => ['WPH', 'WMO', 'WCE', 'WRT']
150
- }
151
-
152
- FAMILY_TO_OS = OS_FAMILIES.each_with_object({}) do |(family,oss),h|
153
- oss.each{|os| h[os] = family}
154
- end
249
+ 'Android' => %w[ AND CYN FIR REM RZD MLD MCD YNS GRI HAR
250
+ ADR CLR BOS REV LEN SIR RRS WER PIC ARM
251
+ HEL BYI],
252
+ 'AmigaOS' => %w[AMG MOR ARO],
253
+ 'BlackBerry' => %w[BLB QNX],
254
+ 'Brew' => ['BMP'],
255
+ 'BeOS' => %w[BEO HAI],
256
+ 'Chrome OS' => %w[COS CRS FYD SEE],
257
+ 'Firefox OS' => %w[FOS KOS],
258
+ 'Gaming Console' => %w[WII PS3],
259
+ 'Google TV' => ['GTV'],
260
+ 'IBM' => ['OS2'],
261
+ 'iOS' => %w[IOS ATV WAS IPA],
262
+ 'RISC OS' => ['ROS'],
263
+ 'GNU/Linux' => %w[
264
+ LIN ARL DEB KNO MIN UBT KBT XBT LBT FED
265
+ RHT VLN MDR GNT SAB SLW SSE CES BTR SAF
266
+ ORD TOS RSO DEE FRE MAG FEN CAI PCL HAS
267
+ LOS DVK ROK OWR OTV KTV PUR PLA FUC PAR
268
+ FOR MON KAN ZEN LND LNS CHN AMZ TEN CST
269
+ NOV ROU ZOR RED KAL ORA VID TIV BSN RAS
270
+ UOS PIO FRI LIR WEB SER ASP AOS LOO EUL
271
+ SCI ALP CLO ROC OVZ PVE RST EZX GNS JOL
272
+ TUR QTP WPO
273
+ ],
274
+ 'Mac' => ['MAC'],
275
+ 'Mobile Gaming Console' => %w[PSP NDS XBX],
276
+ 'OpenVMS' => ['OVS'],
277
+ 'Real-time OS' => %w[MTK TDX MRE JME REX],
278
+ 'Other Mobile' => %w[WOS POS SBA TIZ SMG MAE LUN GEO],
279
+ 'Symbian' => %w[SYM SYS SY3 S60 S40],
280
+ 'Unix' => %w[
281
+ SOS AIX HPX BSD NBS OBS DFB SYL IRI T64
282
+ INF ELE GNX ULT NWS NXT SBL
283
+ ],
284
+ 'WebTV' => ['WTV'],
285
+ 'Windows' => ['WIN'],
286
+ 'Windows Mobile' => %w[WPH WMO WCE WRT WIO KIN],
287
+ 'Other Smart TV' => ['WHS']
288
+ }.freeze
289
+
290
+ FAMILY_TO_OS = OS_FAMILIES.each_with_object({}) do |(family, oss), h|
291
+ oss.each { |os| h[os] = family }
292
+ end.freeze
293
+
294
+ # https://github.com/matomo-org/device-detector/blob/75d88bbefb0182f9207c9f48dc39b1bc8c7cc43f/Parser/OperatingSystem.php#L295-L308
295
+ FIRE_OS_VERSION_MAPPING = {
296
+ '11' => '8',
297
+ '10' => '8',
298
+ '9' => '7',
299
+ '7' => '6',
300
+ '5' => '5',
301
+ '4.4.3' => '4.5.1',
302
+ '4.4.2' => '4',
303
+ '4.2.2' => '3',
304
+ '4.0.3' => '3',
305
+ '4.0.2' => '3',
306
+ '4' => '2',
307
+ '2' => '1',
308
+ }.freeze
309
+
310
+ # https://github.com/matomo-org/device-detector/blob/75d88bbefb0182f9207c9f48dc39b1bc8c7cc43f/Parser/OperatingSystem.php#L315-L337
311
+ LINEAGE_OS_VERSION_MAPPING = {
312
+ '14' => '21',
313
+ '13' => '20.0',
314
+ '12.1' => '19.1',
315
+ '12' => '19.0',
316
+ '11' => '18.0',
317
+ '10' => '17.0',
318
+ '9' => '16.0',
319
+ '8.1.0' => '15.1',
320
+ '8.0.0' => '15.0',
321
+ '7.1.2' => '14.1',
322
+ '7.1.1' => '14.1',
323
+ '7.0' => '14.0',
324
+ '6.0.1' => '13.0',
325
+ '6.0' => '13.0',
326
+ '5.1.1' => '12.1',
327
+ '5.0.2' => '12.0',
328
+ '5.0' => '12.0',
329
+ '4.4.4' => '11.0',
330
+ '4.3' => '10.2',
331
+ '4.2.2' => '10.1',
332
+ '4.0.4' => '9.1.0'
333
+ }.freeze
155
334
 
156
335
  def filenames
157
336
  ['oss.yml']
158
337
  end
159
-
160
338
  end
161
-
162
339
  end