user_agent_parser 2.4.0 → 2.4.1

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.

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