user_agent_parser 2.4.0 → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of user_agent_parser might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 862bbfc92a30de199a32fd1dbebae607551298fa
4
- data.tar.gz: 303212057c5fad5ce4279a21a966ec27bae860a1
3
+ metadata.gz: 11927dac3bd4e88a9a7be095093a664fd96b8111
4
+ data.tar.gz: 21b998a0a2f0016ad4e75b6e8678e855369dadee
5
5
  SHA512:
6
- metadata.gz: 023e8a39eed689f3a0dbfb958ad90e0023fe4f469fae924248e7eda016930e1519428ebeb087e99f92777cbb7dbce1a468143ab3399a3bf6b0476384e055e448
7
- data.tar.gz: 70978a580d745b38fe07af2e4580696b4fc6200018e522261bd19ec13b3748a6e5d0742002104eed17667e4f00e29625ae1ca902303893577b339c616fe94709
6
+ metadata.gz: 9e374cd5e96daca43ef27002052edb5e1101d35c77a1f18dda370b1c28702709a86a9a2b36d830162b9a068a5259ac2d3d2a1532ae2efaf294d4a955224bcfd6
7
+ data.tar.gz: 020cef494b4307e0921978e213c7c243cbb70c075f17a6f238e95a40dfd999d38c896abae12d17cf1afd834fea9f3be533d308f08e607127b07be1b82a1ed5b5
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'optparse'
4
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'user_agent_parser/parser'
2
4
  require 'user_agent_parser/user_agent'
3
5
  require 'user_agent_parser/version'
@@ -5,10 +7,10 @@ require 'user_agent_parser/operating_system'
5
7
  require 'user_agent_parser/device'
6
8
 
7
9
  module UserAgentParser
8
- DefaultPatternsPath = File.join(File.dirname(__FILE__), "../vendor/uap-core/regexes.yaml")
10
+ DefaultPatternsPath = File.join(File.dirname(__FILE__), '../vendor/uap-core/regexes.yaml')
9
11
 
10
12
  # Parse the given +user_agent_string+, returning a +UserAgent+
11
- def self.parse(user_agent_string, options={})
13
+ def self.parse(user_agent_string, options = {})
12
14
  Parser.new(options).parse(user_agent_string)
13
15
  end
14
16
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module UserAgentParser
2
4
  class Cli
3
5
  def initialize(user_agent, options = {})
@@ -11,9 +13,7 @@ module UserAgentParser
11
13
  elsif @options[:name]
12
14
  @user_agent.name
13
15
  elsif @options[:version]
14
- with_version do |version|
15
- version.to_s
16
- end
16
+ with_version(&:to_s)
17
17
  elsif @options[:major]
18
18
  major
19
19
  elsif @options[:minor]
@@ -21,13 +21,13 @@ module UserAgentParser
21
21
  elsif @options[:os]
22
22
  @user_agent.os.to_s
23
23
  elsif format = @options[:format]
24
- format.
25
- gsub('%f', @user_agent.family).
26
- gsub('%n', @user_agent.name).
27
- gsub('%v', version.to_s).
28
- gsub('%M', major.to_s).
29
- gsub('%m', minor.to_s).
30
- gsub('%o', @user_agent.os.to_s)
24
+ format
25
+ .gsub('%f', @user_agent.family)
26
+ .gsub('%n', @user_agent.name)
27
+ .gsub('%v', version.to_s)
28
+ .gsub('%M', major.to_s)
29
+ .gsub('%m', minor.to_s)
30
+ .gsub('%o', @user_agent.os.to_s)
31
31
  else
32
32
  @user_agent.to_s
33
33
  end
@@ -36,15 +36,11 @@ module UserAgentParser
36
36
  private
37
37
 
38
38
  def major
39
- with_version do |version|
40
- version.major
41
- end
39
+ with_version(&:major)
42
40
  end
43
41
 
44
42
  def minor
45
- with_version do |version|
46
- version.minor
47
- end
43
+ with_version(&:minor)
48
44
  end
49
45
 
50
46
  def version
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module UserAgentParser
2
4
  class Device
3
5
  attr_reader :family, :model, :brand
4
6
 
5
- alias_method :name, :family
7
+ alias name family
6
8
 
7
9
  def initialize(family = nil, model = nil, brand = nil)
8
10
  @family = family || 'Other'
@@ -15,13 +17,13 @@ module UserAgentParser
15
17
  end
16
18
 
17
19
  def inspect
18
- "#<#{self.class} #{to_s}>"
20
+ "#<#{self.class} #{self}>"
19
21
  end
20
22
 
21
23
  def eql?(other)
22
24
  self.class.eql?(other.class) && family == other.family
23
25
  end
24
26
 
25
- alias_method :==, :eql?
27
+ alias == eql?
26
28
  end
27
29
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module UserAgentParser
2
4
  class OperatingSystem
3
5
  attr_reader :family, :version
4
6
 
5
- alias_method :name, :family
7
+ alias name family
6
8
 
7
9
  def initialize(family = 'Other', version = nil)
8
10
  @family = family
@@ -18,7 +20,7 @@ module UserAgentParser
18
20
  end
19
21
 
20
22
  def inspect
21
- "#<#{self.class} #{to_s}>"
23
+ "#<#{self.class} #{self}>"
22
24
  end
23
25
 
24
26
  def eql?(other)
@@ -27,6 +29,6 @@ module UserAgentParser
27
29
  version == other.version
28
30
  end
29
31
 
30
- alias_method :==, :eql?
32
+ alias == eql?
31
33
  end
32
34
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'yaml'
2
4
 
3
5
  module UserAgentParser
@@ -5,7 +7,7 @@ module UserAgentParser
5
7
  class Parser
6
8
  attr_reader :patterns_path
7
9
 
8
- def initialize(options={})
10
+ def initialize(options = {})
9
11
  @patterns_path = options[:patterns_path] || UserAgentParser::DefaultPatternsPath
10
12
  @ua_patterns, @os_patterns, @device_patterns = load_patterns(patterns_path)
11
13
  end
@@ -24,11 +26,11 @@ module UserAgentParser
24
26
  # Parse all the regexs
25
27
  yml.each_pair do |type, patterns|
26
28
  patterns.each do |pattern|
27
- pattern["regex"] = Regexp.new(pattern["regex"], pattern["regex_flag"] == 'i')
29
+ pattern['regex'] = Regexp.new(pattern['regex'], pattern['regex_flag'] == 'i')
28
30
  end
29
31
  end
30
32
 
31
- [ yml["user_agent_parsers"], yml["os_parsers"], yml["device_parsers"] ]
33
+ [yml['user_agent_parsers'], yml['os_parsers'], yml['device_parsers']]
32
34
  end
33
35
 
34
36
  def parse_ua(user_agent, os = nil, device = nil)
@@ -63,7 +65,7 @@ module UserAgentParser
63
65
 
64
66
  def first_pattern_match(patterns, value)
65
67
  patterns.each do |pattern|
66
- if match = pattern["regex"].match(value)
68
+ if match = pattern['regex'].match(value)
67
69
  return [pattern, match]
68
70
  end
69
71
  end
@@ -73,24 +75,24 @@ module UserAgentParser
73
75
  def user_agent_from_pattern_match(pattern, match, os = nil, device = nil)
74
76
  family, v1, v2, v3, v4 = match[1], match[2], match[3], match[4], match[5]
75
77
 
76
- if pattern["family_replacement"]
77
- family = pattern["family_replacement"].sub('$1', family || '')
78
+ if pattern['family_replacement']
79
+ family = pattern['family_replacement'].sub('$1', family || '')
78
80
  end
79
81
 
80
- if pattern["v1_replacement"]
81
- v1 = pattern["v1_replacement"].sub('$2', v1 || '')
82
+ if pattern['v1_replacement']
83
+ v1 = pattern['v1_replacement'].sub('$2', v1 || '')
82
84
  end
83
85
 
84
- if pattern["v2_replacement"]
85
- v2 = pattern["v2_replacement"].sub('$3', v2 || '')
86
+ if pattern['v2_replacement']
87
+ v2 = pattern['v2_replacement'].sub('$3', v2 || '')
86
88
  end
87
89
 
88
- if pattern["v3_replacement"]
89
- v3 = pattern["v3_replacement"].sub('$4', v3 || '')
90
+ if pattern['v3_replacement']
91
+ v3 = pattern['v3_replacement'].sub('$4', v3 || '')
90
92
  end
91
93
 
92
- if pattern["v4_replacement"]
93
- v4 = pattern["v4_replacement"].sub('$5', v4 || '')
94
+ if pattern['v4_replacement']
95
+ v4 = pattern['v4_replacement'].sub('$5', v4 || '')
94
96
  end
95
97
 
96
98
  version = version_from_segments(v1, v2, v3, v4)
@@ -101,24 +103,24 @@ module UserAgentParser
101
103
  def os_from_pattern_match(pattern, match)
102
104
  os, v1, v2, v3, v4 = match[1], match[2], match[3], match[4], match[5]
103
105
 
104
- if pattern["os_replacement"]
105
- os = pattern["os_replacement"].sub('$1', os || '')
106
+ if pattern['os_replacement']
107
+ os = pattern['os_replacement'].sub('$1', os || '')
106
108
  end
107
109
 
108
- if pattern["os_v1_replacement"]
109
- v1 = pattern["os_v1_replacement"].sub('$2', v1 || '')
110
+ if pattern['os_v1_replacement']
111
+ v1 = pattern['os_v1_replacement'].sub('$2', v1 || '')
110
112
  end
111
113
 
112
- if pattern["os_v2_replacement"]
113
- v2 = pattern["os_v2_replacement"].sub('$3', v2 || '')
114
+ if pattern['os_v2_replacement']
115
+ v2 = pattern['os_v2_replacement'].sub('$3', v2 || '')
114
116
  end
115
117
 
116
- if pattern["os_v3_replacement"]
117
- v3 = pattern["os_v3_replacement"].sub('$4', v3 || '')
118
+ if pattern['os_v3_replacement']
119
+ v3 = pattern['os_v3_replacement'].sub('$4', v3 || '')
118
120
  end
119
121
 
120
- if pattern["os_v4_replacement"]
121
- v4 = pattern["os_v4_replacement"].sub('$5', v4 || '')
122
+ if pattern['os_v4_replacement']
123
+ v4 = pattern['os_v4_replacement'].sub('$5', v4 || '')
122
124
  end
123
125
 
124
126
  version = version_from_segments(v1, v2, v3, v4)
@@ -131,8 +133,8 @@ module UserAgentParser
131
133
  family = model = match[1]
132
134
  brand = nil
133
135
 
134
- if pattern["device_replacement"]
135
- family = pattern["device_replacement"]
136
+ if pattern['device_replacement']
137
+ family = pattern['device_replacement']
136
138
  match.each_with_index { |m,i| family = family.sub("$#{i}", m) }
137
139
  end
138
140
  if pattern["model_replacement"]
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module UserAgentParser
2
4
  class UserAgent
3
5
  attr_reader :family, :version, :os, :device
4
6
 
5
- alias_method :name, :family
7
+ alias name family
6
8
 
7
9
  def initialize(family = nil, version = nil, os = nil, device = nil)
8
10
  @family = family || 'Other'
@@ -26,11 +28,11 @@ module UserAgentParser
26
28
 
27
29
  def eql?(other)
28
30
  self.class.eql?(other.class) &&
29
- family == other.family &&
31
+ family == other.family &&
30
32
  version == other.version &&
31
33
  os == other.os
32
34
  end
33
35
 
34
- alias_method :==, :eql?
36
+ alias == eql?
35
37
  end
36
38
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module UserAgentParser
2
4
  class Version
3
5
 
@@ -6,14 +8,14 @@ module UserAgentParser
6
8
  SEGMENTS_REGEX = /\d+\-\d+|\d+[a-zA-Z]+$|\d+|[A-Za-z][0-9A-Za-z-]*$/
7
9
 
8
10
  attr_reader :version
9
- alias :to_s :version
11
+ alias to_s version
10
12
 
11
13
  def initialize(*args)
12
14
  if args.length == 1 && args.first.is_a?(String)
13
15
  @version = args.first.to_s.strip
14
16
  else
15
17
  @segments = args.map(&:to_s).map(&:strip)
16
- @version = segments.join(".")
18
+ @version = segments.join('.')
17
19
  end
18
20
  end
19
21
 
@@ -34,7 +36,7 @@ module UserAgentParser
34
36
  end
35
37
 
36
38
  def inspect
37
- "#<#{self.class} #{to_s}>"
39
+ "#<#{self.class} #{self}>"
38
40
  end
39
41
 
40
42
  def eql?(other)
@@ -42,7 +44,7 @@ module UserAgentParser
42
44
  version == other.version
43
45
  end
44
46
 
45
- alias_method :==, :eql?
47
+ alias == eql?
46
48
 
47
49
  # Private
48
50
  def segments
@@ -1,6 +1,27 @@
1
1
  user_agent_parsers:
2
2
  #### SPECIAL CASES TOP ####
3
3
 
4
+ # CFNetwork Podcast catcher Applications
5
+ - regex: '(ESPN)[%20| ]+Radio/(\d+)\.(\d+)\.(\d+) CFNetwork'
6
+ - regex: '(Antenna)/(\d+) CFNetwork'
7
+ family_replacement: 'AntennaPod'
8
+ - regex: '(TopPodcasts)Pro/(\d+) CFNetwork'
9
+ - regex: '(MusicDownloader)Lite/(\d+)\.(\d+)\.(\d+) CFNetwork'
10
+ - regex: '^(.*)-iPad/(\d+)\.?(\d+)?.?(\d+)?.?(\d+)? CFNetwork'
11
+ - regex: '^(.*)-iPhone/(\d+)\.?(\d+)?.?(\d+)?.?(\d+)? CFNetwork'
12
+ - regex: '^(.*)/(\d+)\.?(\d+)?.?(\d+)?.?(\d+)? CFNetwork'
13
+
14
+ # Podcast catchers
15
+ - regex: '(espn\.go)'
16
+ family_replacement: 'ESPN'
17
+ - regex: '(espnradio\.com)'
18
+ family_replacement: 'ESPN'
19
+ - regex: 'ESPN APP$'
20
+ family_replacement: 'ESPN'
21
+ - regex: '(audioboom\.com)'
22
+ family_replacement: 'AudioBoom'
23
+ - regex: ' (Rivo) RHYTHM'
24
+
4
25
  # @note: iOS / OSX Applications
5
26
  - regex: '(CFNetwork)(?:/(\d+)\.(\d+)\.?(\d+)?)?'
6
27
  family_replacement: 'CFNetwork'
@@ -48,6 +69,10 @@ user_agent_parsers:
48
69
  # Downloader ...
49
70
  - regex: '(Google-HTTP-Java-Client|Apache-HttpClient|http%20client|Python-urllib|HttpMonitor|TLSProber|WinHTTP|JNLP|okhttp)(?:[ /](\d+)(?:\.(\d+)(?:\.(\d+))?)?)?'
50
71
 
72
+ # Pinterestbot
73
+ - regex: '(Pinterest(?:bot)?)/(\d+)(?:\.(\d+)(?:\.(\d+))?)?[;\s\(]+\+https://www.pinterest.com/bot.html'
74
+ family_replacement: 'Pinterestbot'
75
+
51
76
  # Bots
52
77
  - regex: '(1470\.net crawler|50\.nu|8bo Crawler Bot|Aboundex|Accoona-[A-z]+-Agent|AdsBot-Google(?:-[a-z]+)?|altavista|AppEngine-Google|archive.*?\.org_bot|archiver|Ask Jeeves|[Bb]ai[Dd]u[Ss]pider(?:-[A-Za-z]+)*|bingbot|BingPreview|blitzbot|BlogBridge|Bloglovin|BoardReader(?: [A-Za-z]+)*|boitho.com-dc|BotSeer|\b\w*favicon\w*\b|\bYeti(?:-[a-z]+)?|Catchpoint(?: bot)?|[Cc]harlotte|Checklinks|clumboot|Comodo HTTP\(S\) Crawler|Comodo-Webinspector-Crawler|ConveraCrawler|CRAWL-E|CrawlConvera|Daumoa(?:-feedfetcher)?|Feed Seeker Bot|Feedbin|findlinks|Flamingo_SearchEngine|FollowSite Bot|furlbot|Genieo|gigabot|GomezAgent|gonzo1|(?:[a-zA-Z]+-)?Googlebot(?:-[a-zA-Z]+)?|Google SketchUp|grub-client|gsa-crawler|heritrix|HiddenMarket|holmes|HooWWWer|htdig|ia_archiver|ICC-Crawler|Icarus6j|ichiro(?:/mobile)?|IconSurf|IlTrovatore(?:-Setaccio)?|InfuzApp|Innovazion Crawler|InternetArchive|IP2[a-z]+Bot|jbot\b|KaloogaBot|Kraken|Kurzor|larbin|LEIA|LesnikBot|Linguee Bot|LinkAider|LinkedInBot|Lite Bot|Llaut|lycos|Mail\.RU_Bot|masscan|masidani_bot|Mediapartners-Google|Microsoft .*? Bot|mogimogi|mozDex|MJ12bot|msnbot(?:-media *)?|msrbot|Mtps Feed Aggregation System|netresearch|Netvibes|NewsGator[^/]*|^NING|Nutch[^/]*|Nymesis|ObjectsSearch|Orbiter|OOZBOT|PagePeeker|PagesInventory|PaxleFramework|Peeplo Screenshot Bot|PlantyNet_WebRobot|Pompos|Qwantify|Read%20Later|Reaper|RedCarpet|Retreiver|Riddler|Rival IQ|scooter|Scrapy|Scrubby|searchsight|seekbot|semanticdiscovery|Simpy|SimplePie|SEOstats|SimpleRSS|SiteCon|Slackbot-LinkExpanding|Slack-ImgProxy|Slurp|snappy|Speedy Spider|Squrl Java|Stringer|TheUsefulbot|ThumbShotsBot|Thumbshots\.ru|Tiny Tiny RSS|TwitterBot|WhatsApp|URL2PNG|Vagabondo|VoilaBot|^vortex|Votay bot|^voyager|WASALive.Bot|Web-sniffer|WebThumb|WeSEE:[A-z]+|WhatWeb|WIRE|WordPress|Wotbox|www\.almaden\.ibm\.com|Xenu(?:.s)? Link Sleuth|Xerka [A-z]+Bot|yacy(?:bot)?|Yahoo[a-z]*Seeker|Yahoo! Slurp|Yandex\w+|YodaoBot(?:-[A-z]+)?|YottaaMonitor|Yowedo|^Zao|^Zao-Crawler|ZeBot_www\.ze\.bz|ZooShot|ZyBorg)(?:[ /]v?(\d+)(?:\.(\d+)(?:\.(\d+))?)?)?'
53
78
 
@@ -68,11 +93,11 @@ user_agent_parsers:
68
93
 
69
94
  # Social Networks
70
95
  # Facebook
71
- - regex: '\[FB.*;(FBAV)/(\d+)(?:\.(\d+)(?:\.(\d)+)?)?'
96
+ - regex: '\[FB.*;(FBAV)/(\d+)(?:\.(\d+)(?:\.(\d+))?)?'
72
97
  family_replacement: 'Facebook'
73
98
  # Pinterest
74
99
  - regex: '\[(Pinterest)/[^\]]+\]'
75
- - regex: '(Pinterest)(?: for Android(?: Tablet)?)?/(\d+)(?:\.(\d+)(?:\.(\d)+)?)?'
100
+ - regex: '(Pinterest)(?: for Android(?: Tablet)?)?/(\d+)(?:\.(\d+)(?:\.(\d+))?)?'
76
101
 
77
102
  # Pale Moon
78
103
  - regex: '(PaleMoon)/(\d+)\.(\d+)\.?(\d+)?'
@@ -307,6 +332,9 @@ user_agent_parsers:
307
332
  # AOL Browser (IE-based)
308
333
  - regex: '(AOL) (\d+)\.(\d+); AOLBuild (\d+)'
309
334
 
335
+ # Podcast catcher Applications using iTunes
336
+ - regex: '(PodCruncher|Downcast)[ /]?(\d+)\.?(\d+)?\.?(\d+)?\.?(\d+)?'
337
+
310
338
  #### END SPECIAL CASES TOP ####
311
339
 
312
340
  #### MAIN CASES - this catches > 50% of all browsers ####
@@ -412,6 +440,54 @@ user_agent_parsers:
412
440
  # Baca Berita App News Reader
413
441
  - regex: '(BacaBerita App)\/(\d+)\.(\d+)\.(\d+)'
414
442
 
443
+ # Podcast catchers
444
+ - regex: '^(bPod|Pocket Casts|Player FM)$'
445
+ - regex: '^(AlexaMediaPlayer|VLC)/(\d+)\.(\d+)\.([^.\s]+)'
446
+ - regex: '^(AntennaPod|WMPlayer|Zune|Podkicker|Radio|ExoPlayerDemo|Overcast|PocketTunes|NSPlayer|okhttp|DoggCatcher|QuickNews|QuickTime|Peapod|Podcasts|GoldenPod|VLC|Spotify|Miro|MediaGo|Juice|iPodder|gPodder|Banshee)/(\d+)\.(\d+)\.?(\d+)?\.?(\d+)?'
447
+ - regex: '^(Peapod|Liferea)/([^.\s]+)\.([^.\s]+)?\.?([^.\s]+)?'
448
+ - regex: '^(bPod|Player FM) BMID/(\S+)'
449
+ - regex: '^(Podcast ?Addict)/v(\d+) '
450
+ - regex: '^(Podcast ?Addict) '
451
+ family_replacement: 'PodcastAddict'
452
+ - regex: '(Replay) AV'
453
+ - regex: '(VOX) Music Player'
454
+ - regex: '(CITA) RSS Aggregator/(\d+)\.(\d+)'
455
+ - regex: '(Pocket Casts)$'
456
+ - regex: '(Player FM)$'
457
+ - regex: '(LG Player|Doppler|FancyMusic|MediaMonkey|Clementine) (\d+)\.(\d+)\.?([^.\s]+)?\.?([^.\s]+)?'
458
+ - regex: '(philpodder)/(\d+)\.(\d+)\.?([^.\s]+)?\.?([^.\s]+)?'
459
+ - regex: '(Player FM|Pocket Casts|DoggCatcher|Spotify|MediaMonkey|MediaGo|BashPodder)'
460
+ - regex: '(QuickTime)\.(\d+)\.(\d+)\.(\d+)'
461
+ - regex: '(Kinoma)(\d+)'
462
+ - regex: '(Fancy) Cloud Music (\d+)\.(\d+)'
463
+ family_replacement: 'FancyMusic'
464
+ - regex: 'EspnDownloadManager'
465
+ family_replacement: 'ESPN'
466
+ - regex: '(ESPN) Radio (\d+)\.(\d+)\.?(\d+)? ?[rv:]?(\d+)? '
467
+ - regex: '(podracer|jPodder) v ?(\d+)\.(\d+)\.?(\d+)?'
468
+ - regex: '(ZDM)/(\d+)\.(\d+)[; ]?'
469
+ - regex: '(Zune|BeyondPod) (\d+)\.?(\d+)?[\);]'
470
+ - regex: '(WMPlayer)/(\d+)\.(\d+)\.(\d+)\.(\d+)'
471
+ - regex: '^(Lavf)'
472
+ family_replacement: 'WMPlayer'
473
+ - regex: '^(RSSRadio)[ /]?(\d+)?'
474
+ - regex: '(RSS_Radio) (\d+)\.(\d+)'
475
+ family_replacement: 'RSSRadio'
476
+ - regex: '(Podkicker) \S+/(\d+)\.(\d+)\.(\d+)'
477
+ family_replacement: 'Podkicker'
478
+ - regex: '^(HTC) Streaming Player \S+ / \S+ / \S+ / (\d+)\.(\d+)\.?(\d+)?'
479
+ - regex: '^(Stitcher)/iOS'
480
+ - regex: '^(Stitcher)/Android'
481
+ - regex: '^(VLC) .*version (\d+)\.(\d+)\.(\d+)'
482
+ - regex: ' (VLC) for'
483
+ - regex: '(vlc)/(\d+)\.(\d+)\.(\d+)'
484
+ family_replacement: 'VLC'
485
+ - regex: '^(foobar)\S+/([^.\s]+)\.([^.\s]+)?\.?([^.\s]+)?'
486
+ - regex: '^(Clementine)\S+ ([^.\s]+)\.([^.\s]+)?\.?([^.\s]+)?'
487
+ - regex: '(amarok)/([^.\s]+)\.([^.\s]+)?\.?([^.\s]+)?'
488
+ family_replacement: 'Amarok'
489
+ - regex: '(Custom)-Feed Reader'
490
+
415
491
  # Browser major_version.minor_version.beta_version (space instead of slash)
416
492
  - regex: '(iRider|Crazy Browser|SkipStone|iCab|Lunascape|Sleipnir|Maemo Browser) (\d+)\.(\d+)\.(\d+)'
417
493
  # Browser major_version.minor_version (space instead of slash)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: user_agent_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Lucas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-11 00:00:00.000000000 Z
11
+ date: 2017-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coveralls
@@ -33,7 +33,6 @@ extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
35
  - MIT-LICENSE
36
- - Readme.md
37
36
  - bin/user_agent_parser
38
37
  - lib/user_agent_parser.rb
39
38
  - lib/user_agent_parser/cli.rb
data/Readme.md DELETED
@@ -1,143 +0,0 @@
1
- # UserAgentParser [![Build Status](https://secure.travis-ci.org/ua-parser/uap-ruby.png?branch=master)](http://travis-ci.org/ua-parser/uap-ruby) [![Coverage Status](https://coveralls.io/repos/github/ua-parser/uap-ruby/badge.svg)](https://coveralls.io/github/ua-parser/uap-ruby)
2
-
3
- UserAgentParser is a simple, comprehensive Ruby gem for parsing user agent strings. It uses [BrowserScope](http://www.browserscope.org/)'s [parsing patterns](https://github.com/ua-parser/uap-core).
4
-
5
- ## Supported Rubies
6
-
7
- * Ruby 2.4
8
- * Ruby 2.3
9
- * Ruby 2.2
10
- * Ruby 2.1
11
- * Ruby 2.0
12
- * Ruby 1.9.3
13
- * Ruby 1.9.2
14
- * JRuby
15
-
16
- ## Installation
17
-
18
- ```bash
19
- $ gem install user_agent_parser
20
- ```
21
-
22
- ## Example usage
23
-
24
- ```ruby
25
- require 'user_agent_parser'
26
- => true
27
- user_agent = UserAgentParser.parse 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0;)'
28
- => #<UserAgentParser::UserAgent IE 9.0 (Windows Vista)>
29
- user_agent.to_s
30
- => "IE 9.0"
31
- user_agent.family
32
- => "IE"
33
- user_agent.version.to_s
34
- => "9.0"
35
- user_agent.version.major
36
- => "9"
37
- user_agent.version.minor
38
- => "0"
39
- operating_system = user_agent.os
40
- => #<UserAgentParser::OperatingSystem Windows Vista>
41
- operating_system.to_s
42
- => "Windows Vista"
43
-
44
- # Device information can also be determined from some devices
45
- user_agent = UserAgentParser.parse "Mozilla/5.0 (Linux; Android 7.0; SAMSUNG SM-G930T Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/5.0 Chrome/51.0.2704.106 Mobile Safari/537.36"
46
- => #<UserAgentParser::UserAgent Samsung Internet 5.0 (Android 7.0) (Samsung SM-G930T)>
47
- user_agent.device.family
48
- => "Samsung SM-G930T"
49
- user_agent.device.brand
50
- => "Samsung"
51
- user_agent.device.model
52
- => "SM-G930T"
53
-
54
- user_agent = UserAgentParser.parse "Mozilla/5.0 (iPad; CPU OS 10_2_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/23.1.148956103 Mobile/14D27 Safari/600.1.4"
55
- => #<UserAgentParser::UserAgent Mobile Safari 10.2.1 (iOS 10.2.1) (iPad)>
56
- irb(main):026:0> user_agent.device.family
57
- => "iPad"
58
- irb(main):027:0> user_agent.device.brand
59
- => "Apple"
60
- irb(main):028:0> user_agent.device.model
61
- => "iPad"
62
-
63
-
64
- # The parser database will be loaded and parsed on every call to
65
- # UserAgentParser.parse. To avoid this, instantiate your own Parser instance.
66
- parser = UserAgentParser::Parser.new
67
- parser.parse 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0;)'
68
- => #<UserAgentParser::UserAgent IE 9.0 (Windows Vista)>
69
- parser.parse 'Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.5.24 Version/10.53'
70
- => #<UserAgentParser::UserAgent Opera 10.53 (Windows XP)>
71
- ```
72
-
73
- In a larger application, you could store a parser in a global to avoid repeat pattern loading:
74
-
75
- ```ruby
76
- module MyApplication
77
-
78
- # Instantiate the parser on load as it's quite expensive
79
- USER_AGENT_PARSER = UserAgentParser::Parser.new
80
-
81
- def self.user_agent_parser
82
- USER_AGENT_PARSER
83
- end
84
-
85
- end
86
- ```
87
-
88
- ## The pattern database
89
-
90
- The [ua-parser database](https://github.com/ua-parser/uap-core/blob/master/regexes.yaml) is included via a [git submodule](http://help.github.com/submodules/). To update the database the submodule needs to be updated and the gem re-released (pull requests for this are very welcome!).
91
-
92
- You can also specify the path to your own, updated and/or customised `regexes.yaml` file as a second argument to `UserAgentParser.parse`:
93
-
94
- ```ruby
95
- UserAgentParser.parse(ua_string, patterns_path: '/some/path/to/regexes.yaml')
96
- ```
97
-
98
- or when instantiating a `UserAgentParser::Parser`:
99
-
100
- ```ruby
101
- UserAgentParser::Parser.new(patterns_path: '/some/path/to/regexes.yaml').parse(ua_string)
102
- ```
103
-
104
- ## Command line tool
105
-
106
- The gem incldes a `user_agent_parser` bin command which will read from
107
- standard input, parse each line and print the result, for example:
108
-
109
- ```bash
110
- $ cat > SOME-FILE-WITH-USER-AGENTS.txt
111
- USER_AGENT_1
112
- USER_AGENT_2
113
- ...
114
- $ cat SOME-FILE-WITH-USER-AGENTS.txt | user_agent_parser --format '%f %M' | distribution
115
- ```
116
-
117
- See `user_agent_parser -h` for more information.
118
-
119
- ## Contributing
120
-
121
- 1. Fork
122
- 2. Hack
123
- 3. `rake test`
124
- 4. Send a pull request
125
-
126
- All accepted pull requests will earn you commit and release rights.
127
-
128
- ## Releasing a new version
129
-
130
- 1. Update the version in `user_agent_parser.gemspec`
131
- 2. `git commit user_agent_parser.gemspec` with the following message format:
132
-
133
- Version x.x.x
134
-
135
- Changelog:
136
- * Some new feature
137
- * Some new bug fix
138
- 3. `rake release`
139
- 4. Create a [new Github release](https://github.com/ua-parser/uap-ruby/releases/new)
140
-
141
- ## License
142
-
143
- MIT