user_agent_parser 2.11.0 → 2.13.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b48c15771051ce967fbd02b30cebe742074d6cc363f202f8136d2da8fcb53eae
4
- data.tar.gz: cec1845c163e7d79d232b9216182f08e4a4ca25236c06328afd1aa7262c4b0f6
3
+ metadata.gz: 5f014ae2d784eb25f63242a361c9c9186ad108c7199fd1655944da1dcfeaff28
4
+ data.tar.gz: 36357407d451f17dada0fa4115f5f19e8a69af6932a1c3fc999ecd55abc958a0
5
5
  SHA512:
6
- metadata.gz: f1c6d56ffe6f50176dd812ca4e717a4c2e63079eae3d91dbadb17fbefe6efa825ae05394c02e3de909c8bd5c76587d41ec33bc5c5fa6b283d5f8d9bc08c081b5
7
- data.tar.gz: 8f50066203f91d2ac548db3326944c7bca38bb8fc355c7b34e012287e09c0199ce6da8aee707227e5944e482f11d53decd2afef63ba500d564045d6e01dc2158
6
+ metadata.gz: 1dfc2207de8b2345dcf21a0f271122f96259165fe115397ecb290f9fb07a9924e399554a5f23110c27f24976feae5b189a9a482386bb9f60d74ce542625eda61
7
+ data.tar.gz: 7abd96ee88bcca1d800323d3d9fd2f508b0b36dc20885a79e5bdfb58154a48a00ed60b0f7750e3eb0fd6570bbbebaac48355f5ba250c35f05ace615c41baa5d5
@@ -4,6 +4,8 @@ require 'yaml'
4
4
 
5
5
  module UserAgentParser
6
6
  class Parser
7
+ extend Gem::Deprecate
8
+
7
9
  FAMILY_REPLACEMENT_KEYS = %w[
8
10
  family_replacement
9
11
  v1_replacement
@@ -22,11 +24,13 @@ module UserAgentParser
22
24
 
23
25
  private_constant :FAMILY_REPLACEMENT_KEYS, :OS_REPLACEMENT_KEYS
24
26
 
25
- attr_reader :patterns_path
27
+ attr_reader :patterns_paths
28
+
29
+ def initialize(patterns_path: nil, patterns_paths: [])
30
+ @patterns_paths = [patterns_path, *patterns_paths].compact
31
+ @patterns_paths = [UserAgentParser::DefaultPatternsPath] if @patterns_paths.empty?
26
32
 
27
- def initialize(options = {})
28
- @patterns_path = options[:patterns_path] || UserAgentParser::DefaultPatternsPath
29
- @ua_patterns, @os_patterns, @device_patterns = load_patterns(patterns_path)
33
+ @ua_patterns, @os_patterns, @device_patterns = load_patterns(@patterns_paths)
30
34
  end
31
35
 
32
36
  def parse(user_agent)
@@ -35,19 +39,41 @@ module UserAgentParser
35
39
  parse_ua(user_agent, os, device)
36
40
  end
37
41
 
42
+ def patterns_path
43
+ patterns_paths.first
44
+ end
45
+ deprecate :patterns_path, :patterns_paths, 2022, 12
46
+
38
47
  private
39
48
 
40
- def load_patterns(path)
41
- yml = YAML.load_file(path)
49
+ def load_patterns(patterns_paths)
50
+ patterns_paths.each_with_object([[], [], []]) do |path, patterns|
51
+ ua_patterns, os_patterns, device_patterns = load_patterns_file(path)
52
+ patterns[0] += ua_patterns
53
+ patterns[1] += os_patterns
54
+ patterns[2] += device_patterns
55
+ end
56
+ end
42
57
 
43
- # Parse all the regexs
44
- yml.each_pair do |_type, patterns|
45
- patterns.each do |pattern|
46
- pattern[:regex] = Regexp.new(pattern['regex'], pattern['regex_flag'] == 'i')
47
- end
58
+ def load_patterns_file(path)
59
+ yml = begin
60
+ YAML.load_file(path, freeze: true)
61
+ rescue ArgumentError
62
+ YAML.load_file(path)
48
63
  end
64
+ [
65
+ parse_pattern(yml['user_agent_parsers']),
66
+ parse_pattern(yml['os_parsers']),
67
+ parse_pattern(yml['device_parsers']),
68
+ ]
69
+ end
49
70
 
50
- [yml['user_agent_parsers'], yml['os_parsers'], yml['device_parsers']]
71
+ def parse_pattern(patterns)
72
+ patterns.map do |pattern|
73
+ pattern = pattern.dup
74
+ pattern[:regex] = Regexp.new(pattern.delete('regex'), pattern.delete('regex_flag') == 'i')
75
+ pattern
76
+ end
51
77
  end
52
78
 
53
79
  def parse_ua(user_agent, os = nil, device = nil)
@@ -80,24 +106,11 @@ module UserAgentParser
80
106
  end
81
107
  end
82
108
 
83
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.4.0')
84
- def first_pattern_match(patterns, value)
85
- patterns.each do |pattern|
86
- if pattern[:regex].match?(value)
87
- return [pattern, pattern[:regex].match(value)]
88
- end
89
- end
90
- nil
91
- end
92
- else
93
- def first_pattern_match(patterns, value)
94
- patterns.each do |pattern|
95
- if (match = pattern[:regex].match(value))
96
- return [pattern, match]
97
- end
98
- end
99
- nil
109
+ def first_pattern_match(patterns, value)
110
+ patterns.each do |pattern|
111
+ return [pattern, pattern[:regex].match(value)] if pattern[:regex].match?(value)
100
112
  end
113
+ nil
101
114
  end
102
115
 
103
116
  def user_agent_from_pattern_match(pattern, match, os = nil, device = nil)
@@ -10,7 +10,7 @@ module UserAgentParser
10
10
  DefaultPatternsPath = File.join(File.dirname(__FILE__), '../vendor/uap-core/regexes.yaml')
11
11
 
12
12
  # Parse the given +user_agent_string+, returning a +UserAgent+
13
- def self.parse(user_agent_string, options = {})
14
- Parser.new(options).parse(user_agent_string)
13
+ def self.parse(user_agent_string, **args)
14
+ Parser.new(**args).parse(user_agent_string)
15
15
  end
16
16
  end
@@ -213,6 +213,10 @@ user_agent_parsers:
213
213
  - regex: '(Twitter for (?:iPhone|iPad)|TwitterAndroid)(?:\/(\d+)\.(\d+)|)'
214
214
  family_replacement: 'Twitter'
215
215
 
216
+ # Phantom app
217
+ - regex: 'Mozilla.{1,200}Mobile.{1,100}(Phantom\/ios|android).(\d+)\.(\d+)\.(\d+)'
218
+ family_replacement: 'Phantom'
219
+
216
220
  # aspiegel.com spider (owned by Huawei)
217
221
  - regex: 'Mozilla.{1,100}Mobile.{1,100}AspiegelBot'
218
222
  family_replacement: 'Spider'
@@ -381,7 +385,7 @@ user_agent_parsers:
381
385
  # Edge Mobile
382
386
  - regex: 'Windows Phone .{0,200}(Edge)/(\d+)\.(\d+)'
383
387
  family_replacement: 'Edge Mobile'
384
- - regex: '(EdgiOS|EdgA)/(\d+)\.(\d+)\.(\d+)\.(\d+)'
388
+ - regex: '(EdgiOS|EdgA)/(\d+)\.(\d+)\.(\d+)(?:\.(\d+)|)'
385
389
  family_replacement: 'Edge Mobile'
386
390
 
387
391
  # Samsung Internet (based on Chrome, but lacking some features)
@@ -517,6 +521,10 @@ user_agent_parsers:
517
521
  # Palo Alto GlobalProtect Linux
518
522
  - regex: 'PAN (GlobalProtect)/(\d+)\.(\d+)\.(\d+) .{1,100} \(X11; Linux x86_64\)'
519
523
 
524
+ # Surveyon https://www.surveyon.com/
525
+ - regex: '^(surveyon)/(\d+)\.(\d+)\.(\d+)'
526
+ family_replacement: 'Surveyon'
527
+
520
528
  #### END SPECIAL CASES TOP ####
521
529
 
522
530
  #### MAIN CASES - this catches > 50% of all browsers ####
@@ -1120,6 +1128,7 @@ os_parsers:
1120
1128
 
1121
1129
  # Android 9; Android 10;
1122
1130
  - regex: '(Android) (\d+);'
1131
+ - regex: '(Android): (\d+)(?:\.(\d+)(?:\.(\d+)|)|);'
1123
1132
 
1124
1133
  # UCWEB
1125
1134
  - regex: '^UCWEB.{0,200}; (Adr) (\d+)\.(\d+)(?:[.\-]([a-z0-9]{1,100})|);'
@@ -1544,9 +1553,48 @@ os_parsers:
1544
1553
  os_replacement: 'iOS'
1545
1554
  os_v1_replacement: '14'
1546
1555
  os_v2_replacement: '5'
1556
+ - regex: 'CFNetwork/12.{0,100} Darwin/20\.5\.\d+'
1557
+ os_replacement: 'iOS'
1558
+ os_v1_replacement: '14'
1559
+ os_v2_replacement: '6'
1560
+ - regex: 'CFNetwork/12.{0,100} Darwin/20\.6\.\d+'
1561
+ os_replacement: 'iOS'
1562
+ os_v1_replacement: '14'
1563
+ os_v2_replacement: '8'
1547
1564
  - regex: 'CFNetwork/.{0,100} Darwin/(20)\.\d+'
1548
1565
  os_replacement: 'iOS'
1549
1566
  os_v1_replacement: '14'
1567
+ - regex: 'CFNetwork/13.{0,100} Darwin/21\.0\.\d+'
1568
+ os_replacement: 'iOS'
1569
+ os_v1_replacement: '15'
1570
+ os_v2_replacement: '0'
1571
+ - regex: 'CFNetwork/13.{0,100} Darwin/21\.1\.\d+'
1572
+ os_replacement: 'iOS'
1573
+ os_v1_replacement: '15'
1574
+ os_v2_replacement: '1'
1575
+ - regex: 'CFNetwork/13.{0,100} Darwin/21\.2\.\d+'
1576
+ os_replacement: 'iOS'
1577
+ os_v1_replacement: '15'
1578
+ os_v2_replacement: '2'
1579
+ - regex: 'CFNetwork/13.{0,100} Darwin/21\.3\.\d+'
1580
+ os_replacement: 'iOS'
1581
+ os_v1_replacement: '15'
1582
+ os_v2_replacement: '3'
1583
+ - regex: 'CFNetwork/13.{0,100} Darwin/21\.4\.\d+'
1584
+ os_replacement: 'iOS'
1585
+ os_v1_replacement: '15'
1586
+ os_v2_replacement: '4'
1587
+ - regex: 'CFNetwork/13.{0,100} Darwin/21\.5\.\d+'
1588
+ os_replacement: 'iOS'
1589
+ os_v1_replacement: '15'
1590
+ os_v2_replacement: '5'
1591
+ - regex: 'CFNetwork/13.{0,100} Darwin/21\.6\.\d+'
1592
+ os_replacement: 'iOS'
1593
+ os_v1_replacement: '15'
1594
+ os_v2_replacement: '6'
1595
+ - regex: 'CFNetwork/.{0,100} Darwin/(21)\.\d+'
1596
+ os_replacement: 'iOS'
1597
+ os_v1_replacement: '15'
1550
1598
  - regex: 'CFNetwork/.{0,100} Darwin/'
1551
1599
  os_replacement: 'iOS'
1552
1600
 
@@ -2461,10 +2509,6 @@ device_parsers:
2461
2509
  device_replacement: 'Dell $1'
2462
2510
  brand_replacement: 'Dell'
2463
2511
  model_replacement: '$1'
2464
- - regex: '; {0,2}Dell ([^;/]{1,100}?)(?: Build|\) AppleWebKit)'
2465
- device_replacement: 'Dell $1'
2466
- brand_replacement: 'Dell'
2467
- model_replacement: '$1'
2468
2512
 
2469
2513
  #########
2470
2514
  # Denver
@@ -2671,10 +2715,14 @@ device_parsers:
2671
2715
  device_replacement: '$1'
2672
2716
  brand_replacement: 'Google'
2673
2717
  model_replacement: '$1'
2674
- - regex: '; {0,2}(Pixel.{0,200}?)(?: Build|\) AppleWebKit)'
2675
- device_replacement: '$1'
2718
+ - regex: '; {0,2}([g|G]oogle)? (Pixel[ a-zA-z0-9]{1,100});(?: Build|.{0,50}\) AppleWebKit)'
2719
+ device_replacement: '$2'
2676
2720
  brand_replacement: 'Google'
2677
- model_replacement: '$1'
2721
+ model_replacement: '$2'
2722
+ - regex: '; {0,2}([g|G]oogle)? (Pixel.{0,200}?)(?: Build|\) AppleWebKit)'
2723
+ device_replacement: '$2'
2724
+ brand_replacement: 'Google'
2725
+ model_replacement: '$2'
2678
2726
 
2679
2727
  #########
2680
2728
  # Gigabyte
@@ -3801,6 +3849,18 @@ device_parsers:
3801
3849
  device_replacement: 'OnePlus $1'
3802
3850
  brand_replacement: 'OnePlus'
3803
3851
  model_replacement: '$1'
3852
+ - regex: '; {0,2}(HD1903|GM1917|IN2025|LE2115|LE2127|HD1907|BE2012|BE2025|BE2026|BE2028|BE2029|DE2117|DE2118|EB2101|GM1900|GM1910|GM1915|HD1905|HD1925|IN2015|IN2017|IN2019|KB2005|KB2007|LE2117|LE2125|BE2015|GM1903|HD1900|HD1901|HD1910|HD1913|IN2010|IN2013|IN2020|LE2111|LE2120|LE2121|LE2123|BE2011|IN2023|KB2003|LE2113|NE2215|DN2101)(?: Build|\) AppleWebKit)'
3853
+ device_replacement: 'OnePlus $1'
3854
+ brand_replacement: 'OnePlus'
3855
+ model_replacement: 'OnePlus $1'
3856
+ - regex: '; (OnePlus[ a-zA-z0-9]{0,50});((?: Build|.{0,50}\) AppleWebKit))'
3857
+ device_replacement: '$1'
3858
+ brand_replacement: 'OnePlus'
3859
+ model_replacement: '$1'
3860
+ - regex: '; (OnePlus[ a-zA-z0-9]{0,50})((?: Build|\) AppleWebKit))'
3861
+ device_replacement: '$1'
3862
+ brand_replacement: 'OnePlus'
3863
+ model_replacement: '$1'
3804
3864
 
3805
3865
  #########
3806
3866
  # Orion
@@ -5481,6 +5541,15 @@ device_parsers:
5481
5541
  device_replacement: 'Motorola $1'
5482
5542
  brand_replacement: 'Motorola'
5483
5543
  model_replacement: '$1'
5544
+ - regex: '; (moto[ a-zA-z0-9()]{0,50});((?: Build|.{0,50}\) AppleWebKit))'
5545
+ device_replacement: '$1'
5546
+ brand_replacement: 'Motorola'
5547
+ model_replacement: '$1'
5548
+ - regex: '; {0,2}(moto)(.{0,50})(?: Build|\) AppleWebKit)'
5549
+ device_replacement: 'Motorola$2'
5550
+ brand_replacement: 'Motorola'
5551
+ model_replacement: '$2'
5552
+
5484
5553
 
5485
5554
  ##########
5486
5555
  # nintendo
metadata CHANGED
@@ -1,17 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: user_agent_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.11.0
4
+ version: 2.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Lucas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-18 00:00:00.000000000 Z
11
+ date: 2022-10-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: A simple, comprehensive Ruby gem for parsing user agent strings with
14
- the help of BrowserScope's UA database
13
+ description: |
14
+ A simple, comprehensive Ruby gem for parsing user agent strings
15
+ with the help of BrowserScope's UserAgent database
15
16
  email: t@toolmantim.com
16
17
  executables:
17
18
  - user_agent_parser
@@ -47,9 +48,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
47
48
  - !ruby/object:Gem::Version
48
49
  version: '0'
49
50
  requirements: []
50
- rubygems_version: 3.3.11
51
+ rubygems_version: 3.3.24
51
52
  signing_key:
52
53
  specification_version: 4
53
- summary: A simple, comprehensive Ruby gem for parsing user agent strings with the
54
- help of BrowserScope's UA database
54
+ summary: Parsing user agent strings with the help of BrowserScope's UA database
55
55
  test_files: []