browserino 4.2.1 → 4.2.2

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.
data/README.md CHANGED
@@ -1,3 +1,1238 @@
1
- # Readme
1
+ Browserino has been completely rewritten! While some components remain backwards compatible, the inner workings of Browserino have completely changed.
2
+ It has taken on a DSL-like form to allow for easy addition of features and more detection in general. This allowed me to clean up lots of constants and other messy constructions I've built to add things such as aliasses for instance. The test suite had also become a quite cumbersome task to maintain, it was hard to read and all the test data was structured using Ruby, again using structures more complex than they could and should be.
2
3
 
3
- The documentation has been moved here: [https://sidofc.github.io/projects/browserino/](https://sidofc.github.io/projects/browserino/)
4
+ In the new version, test data is written in YAML format and then parsed to usable test data in the respective spec. Each spec generates their own tests based on what is present in the YAML, this helped test a lot of the methods added using `define_singleton_method` upon instantiation of a `Browserino::Client` object. Don't let this scare you into submitting your own tests tho, as all you'll have to do is write the YAML and the tests will simply be generated for you :)
5
+
6
+ The below sections will explain how the new Browserino works, enjoy!
7
+
8
+ ## Status
9
+
10
+ ![Licence](https://img.shields.io/badge/license-MIT-E9573F.svg)
11
+ [![Gem Version](https://img.shields.io/gem/v/browserino.svg?colorB=E9573F&style=square)](rubygems.org/gems/browserino)
12
+ [![Issues](https://img.shields.io/github/issues/SidOfc/browserino.svg)](https://github.com/SidOfc/browserino/issues)
13
+ [![Build Status](https://img.shields.io/travis/SidOfc/browserino.svg)](https://travis-ci.org/SidOfc/browserino)
14
+ [![Coverage Status](https://img.shields.io/coveralls/SidOfc/browserino.svg)](https://coveralls.io/github/SidOfc/browserino?branch=master)
15
+ [![Code Climate](https://img.shields.io/codeclimate/github/SidOfc/browserino.svg)](https://img.shields.io/codeclimate/github/SidOfc/browserino)
16
+
17
+ ---
18
+
19
+ ## Sources
20
+
21
+ Many thanks to the creators and maintainers of the following sources of user agents and timelines:
22
+
23
+ - [udger.com](https://udger.com/)
24
+ - [ua.theafh.net](http://ua.theafh.net/)
25
+ - [user-agents.org](http://www.user-agents.org/)
26
+ - [zytrax.com](http://www.zytrax.com/tech/web/browser_ids.htm)
27
+ - [useragentstring.com](http://www.useragentstring.com/)
28
+ - [whatismybrowser.com](https://www.whatismybrowser.com/developers/tools/user-agent-parser/browse)
29
+ - [mobile247.eu](http://www.mobile247.eu/online-tools/user-agent-strings)
30
+ - [commons.wikimedia.org browser timeline](https://commons.wikimedia.org/wiki/File:Timeline_of_web_browsers.svg)
31
+
32
+ ---
33
+
34
+ ## Changelog
35
+
36
+ _dates are in dd-mm-yyyy format_
37
+ older changes can be found in the [changelog](/projects/browserino/changelog/)
38
+
39
+ ### 12-10-2017 VERSION 4.2.2
40
+
41
+ - Added support for `high_sierra`
42
+
43
+ ### 11-06-2017 VERSION 4.2.1
44
+
45
+ - Fixed a bug which caused arguments in the form of `version: v` to return true by default
46
+ - Added 174 additional clients
47
+ - Added some global properties
48
+ - `smarttv?` and `tablet?` in addition to `mobile?`
49
+ - Added device detection using `device? :namOfDevice`
50
+ - Added `not` method that allows calling `client.not.firefox?`. It simply inverts the original result
51
+ - Added `not?` method which is the opposite of `is?`
52
+ - Added `:mediaplayer` type
53
+
54
+ ### 30-04-2017 VERSION 4.1.0
55
+
56
+ - Changed some internal naming
57
+ - Added ~200 additional browsers / bots
58
+ - Added list of browsers / bots and platforms to the documentation
59
+
60
+ ## Installation
61
+
62
+ Add this line to your application's Gemfile:
63
+
64
+ ```ruby
65
+ gem 'browserino'
66
+ ```
67
+
68
+ And then execute:
69
+
70
+ ```
71
+ $ bundle
72
+ ```
73
+
74
+ Or install it yourself with:
75
+
76
+ ```
77
+ $ gem install browserino
78
+ ```
79
+
80
+ Browserino is tested with the following ruby versions
81
+
82
+ - 2.0.0
83
+ - 2.1.0
84
+ - 2.2.0
85
+ - 2.3.0
86
+ - 2.4.0
87
+
88
+ ## Usage
89
+
90
+ After installing the gem globally or in your application you'll have to `require` the gem before being able to use it.
91
+
92
+ ```ruby
93
+ require 'browserino'
94
+ ```
95
+
96
+ Afterwards, the gem is loaded and you can proceed by calling:
97
+
98
+ ```ruby
99
+ Browserino.parse '<user agent>'
100
+ ```
101
+
102
+ ### Rails (>= 3.2.0)
103
+
104
+ If you're using Rails (>= 3.2.0) you'll have access to a `client` object. Browserino will initialize itself using the `request.headers['User-Agent']`
105
+
106
+
107
+ A quick example on how to get going:
108
+
109
+ ```ruby
110
+ class ExampleController < ApplicationController
111
+ def example_method
112
+ render json: client.to_json
113
+ end
114
+ end
115
+ ```
116
+
117
+ #### Initializer
118
+
119
+ If you would like to extend Browserino within your rails app, this is certainly possible.
120
+ Create a file _config/initializers/browserino.rb_ and add the following:
121
+
122
+ ```ruby
123
+ Browserino.config.define do
124
+ # your magic here
125
+ end
126
+ ```
127
+
128
+ Please skip ahead to the [**Config**](#config) part of the documentation, that section contains information on how to make use of Browserino's builtin DSL
129
+
130
+ ### General
131
+
132
+ #### Client
133
+
134
+ the `parse` method will **always** return a `Browserino::Client` object. This object is special in that it simply resonds to everything. If a property does not exist or isn't defined on the current instance of `client` then it will simply return `nil`. Parsing an empty user agent will result in the following output:
135
+
136
+ ```ruby
137
+ client = Browserino.parse ''
138
+ client.is_a? Browserino::Client # => true
139
+ ```
140
+
141
+ #### Formatting
142
+
143
+ This section explains the output / return values given by calling a method on an instantiated `Browserino::client` object.
144
+
145
+ ##### Non version-like properties
146
+
147
+ Non-version-like properties are properties that are not solely digits seperated by a delimiter like '.' or '_'.
148
+ All the non-version-like property values will be formatted in the following order:
149
+
150
+ - lowercase all characters
151
+ - strip spaces on either side
152
+ - replace one or more spaces or dashes with a single underscore (`_`)
153
+ - convert to symbol
154
+
155
+ ```ruby
156
+ client = Browserino.parse 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:24.0) Gecko/20100101 Firefox/24.0 Waterfox/24.0'
157
+
158
+ client.name # => :waterfox
159
+ client.type # => :browser
160
+ client.platform # => :windows
161
+ client.engine # => :gecko
162
+ client.platform_label # => :windows7
163
+ ```
164
+
165
+ ##### Version-like properties
166
+
167
+ All the version-like property values will be converted to `Browserino::Version` objects.
168
+ These objects are comparable to numbers and version-like strings (e.g. `'1.2.4'`)
169
+
170
+ ```ruby
171
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36'
172
+
173
+ client.version # => [37, 0, 2062, 124]
174
+ client.version.is_a? Browserino::Version # => true
175
+ client.version.is_a? Array # => true
176
+
177
+ # get full version
178
+ client.version.full # => '37.0.2062.124'
179
+ client.version.to_s # => '37.0.2062.124'
180
+
181
+ # get version components [major, minor, patch]
182
+ client.version.major # => 37
183
+ client.version.minor # => 0
184
+ client.version.patch # => 2062
185
+
186
+ # comparing with integers
187
+ client.version >= 32 # => true
188
+ client.version < 40 # => true
189
+
190
+ # comparing with strings
191
+ client.version >= '37.0.2000' # => true
192
+ client.version > '37.1.2000' # => false
193
+ ```
194
+
195
+ #### Config
196
+
197
+ ##### Matchers
198
+
199
+ Browserino is based on a concept of _matchers_, a matcher is a single client entity.
200
+ They are defined in a `Browserino.config.define { ... }` block. A small example:
201
+
202
+ ```ruby
203
+ Browserino.config.define do
204
+ # define a matcher that looks for the pattern %r{mybrowser}i in the UA
205
+ # when found, give it a name of :mybrowser and a type of :browser
206
+ match %r{mybrowser}i, name: :mybrowser, type: :browser
207
+ end
208
+
209
+ ua = "Mozilla/5.0 (Windows NT 5.1; rv: 1.8.3.2) Gecko/13370420 MyBrowser/1.4.9"
210
+
211
+ client = Browserino.parse ua
212
+ client.to_h
213
+ # => { :name => :mybrowser,
214
+ # :type => :browser,
215
+ # :locale => nil,
216
+ # :architecture => nil,
217
+ # :mobile => false,
218
+ # :smarttv => false,
219
+ # :tablet => false,
220
+ # :platform => :windows,
221
+ # :platform_version => [5, 1],
222
+ # :version => [1, 4, 9],
223
+ # :engine_version => [],
224
+ # :device => nil,
225
+ # :label => nil,
226
+ # :engine_label => nil,
227
+ # :platform_label => :xp }
228
+
229
+ client.name
230
+ # => :mybrowser
231
+ ```
232
+
233
+ In the above example, I've simply created a fictive UA to simulate how to add a matcher to Browserino.
234
+ This matcher however, isn't all that powerful as all it does is match a pattern and assign a name and type.
235
+ Browserino hosts a large list of defaults that you don't have to support anymore, these are all matchers themselves.
236
+ The matcher for Firefox looks like this for instance:
237
+
238
+ ```ruby
239
+ Browserino.config.define do
240
+ # this matcher is written using the dsl style, calling a method and giving
241
+ # it a value, something to look for in the user agent, or a block will
242
+ # add that method name as a property with the parsed value as result
243
+
244
+ # match pattern %r{firefox|phoenix}i
245
+ match %r{firefox|phoenix}i do
246
+ # give this matcher a name of :firefox
247
+ name :firefox
248
+ # engine is a regexp, these will be matched on the UA and return their
249
+ # respective match (what is captured in a capture group)
250
+ engine %r{(gecko|servo)}i
251
+ # engine_version is also a regexp, because the gecko version isn't defined
252
+ # like gecko/[VERSION] but rather rv:[VERSION] while for servo it is
253
+ # servo/[VERSION]
254
+ engine_version %r{(?:rv:\s?|servo/)([\d\.]+)}i
255
+ # last but not least we can also define a block, the block
256
+ # will be executed once after all other properties have been defined on a
257
+ # client, the block itself will be executed in client context so
258
+ # everything you can do on a `client` can also be used within blocks
259
+ modern? { version >= 50 }
260
+ end
261
+ end
262
+ ```
263
+
264
+ Now as you may have noticed, there is no `type` defined in the above matcher, so how does Browserino know that Firefox is a browser?
265
+ In truth, you aren't seeing the whole file here, if you want to go take a look, you can [find it here](https://github.com/SidOfc/browserino/blob/master/lib/browserino/definitions/matchers.rb). To elaborate, Browserino has a few builtin convenience methods
266
+ That allow presetting of `type` in a nice way using:
267
+
268
+
269
+ ```ruby
270
+ Browserino.config.define do
271
+ # sets type: :browser for each matcher defined within the block
272
+ browsers do
273
+ # matcher %r{...}i
274
+ # matcher %r{...}i
275
+ # matcher %r{...}i
276
+ end
277
+
278
+ # sets type: :email for each matcher defined within the block
279
+ emails do
280
+ # ....
281
+ end
282
+
283
+ # sets type: :validator for each matcher defined within the block
284
+ validators do
285
+ # ....
286
+ end
287
+
288
+ # sets type: :bot for each matcher defined within the block
289
+ bot do
290
+ # ....
291
+ end
292
+
293
+ # sets type: :library for each matcher defined within the block
294
+ libraries do
295
+ # ....
296
+ end
297
+ end
298
+ ```
299
+
300
+ Under the hood, these all use a more generic `preset` method as also seen in the [source](https://github.com/SidOfc/browserino/blob/master/lib/browserino/config.rb#L71-L89):
301
+
302
+ ```ruby
303
+ # snipped from Browserino::Config
304
+ def emails(opts = {}, &block)
305
+ preset opts.merge(type: :email), &block
306
+ end
307
+
308
+ def validators(opts = {}, &block)
309
+ preset opts.merge(type: :validator), &block
310
+ end
311
+
312
+ def browsers(opts = {}, &block)
313
+ preset opts.merge(type: :browser), &block
314
+ end
315
+
316
+ def bots(opts = {}, &block)
317
+ preset opts.merge(type: :bot), &block
318
+ end
319
+
320
+ def libraries(opts = {}, &block)
321
+ preset opts.merge(type: :library), &block
322
+ end
323
+ ```
324
+
325
+ All that these methods, and `preset` do is they set an instance variable with all the properties you'll have supplied in an options hash and these will simply be applied to every matcher defined within them. The Firefox matcher could have been written in the following ways:
326
+
327
+ ```ruby
328
+ Browserino.config.define do
329
+ # using `browsers`
330
+
331
+ browsers do
332
+ match %r{firefox|phoenix}i do
333
+ name :firefox
334
+ engine %r{(gecko|servo)}i
335
+ engine_version %r{(?:rv:\s?|servo/)([\d\.]+)}i
336
+ modern? { version >= 50 }
337
+ end
338
+ end
339
+
340
+ # using `preset`
341
+ preset type: :browser do
342
+ match %r{firefox|phoenix}i do
343
+ name :firefox
344
+ engine %r{(gecko|servo)}i
345
+ engine_version %r{(?:rv:\s?|servo/)([\d\.]+)}i
346
+ modern? { version >= 50 }
347
+ end
348
+ end
349
+
350
+ # define type inline
351
+ match %r{firefox|phoenix}i, type: :browser do
352
+ name :firefox
353
+ engine %r{(gecko|servo)}i
354
+ engine_version %r{(?:rv:\s?|servo/)([\d\.]+)}i
355
+ modern? { version >= 50 }
356
+ end
357
+ # or
358
+ match %r{firefox|phoenix}i do
359
+ name :firefox
360
+ type :browser
361
+ engine %r{(gecko|servo)}i
362
+ engine_version %r{(?:rv:\s?|servo/)([\d\.]+)}i
363
+ modern? { version >= 50 }
364
+ end
365
+ end
366
+ ```
367
+
368
+ You'll have also noticed that so far, no `version` property has been defined either, and that when we created the `mybrowser` matcher, it could actually find it's version without supplying it.
369
+ This is a different type of matcher at work. It is not a matcher for a single entity but rather, one that will be applied by default if nothing is specified.
370
+ It is then capable of extracting preprocessed information into a pattern that will magically detect the version for you.
371
+
372
+ They look like this:
373
+
374
+
375
+ ```ruby
376
+ Browserino.config.define do
377
+ # prop pattern flags
378
+ smart_match :version, with: ':name[\s/]?v?([\d\._]+)', flags: [:i]
379
+ smart_match :engine_version, with: ':engine[\s/]?([\d\._]+)', flags: [:i]
380
+ end
381
+ ```
382
+
383
+ What the above code does is, if no `version` property has been supplied to a matcher, it will try to look for a `smart_watcher` with a prop of `version`, then, using other parsed properties, it will replace the `:name` in this case with `mybrowser` (if we were to use our made-up UA). The pattern would then look like this: `/mybrowser[\s/]?v?([\d\.]+)/i` and go a head and match itself against the UA to get a value back.
384
+
385
+ If you supply your own `version` property, this `smart_matcher` will not be applied.
386
+
387
+ ##### Aliasses
388
+
389
+ Aliasses are a bit simpler than `Matchers`, they look like this taken from the [source](https://github.com/SidOfc/browserino/blob/master/lib/browserino/definitions/aliasses.rb):
390
+
391
+ ```ruby
392
+ Browserino.config.define do
393
+ # aliasses will be defined after a Client has been initialized
394
+ # only the aliasses matching the Client will be defined
395
+ alias_for :firefox, :ff
396
+ alias_for :windows, :win
397
+ alias_for :windows7, :win7
398
+ alias_for :windows8, :win8
399
+ alias_for :windows10, :win10
400
+ alias_for :macintosh, :mac, :osx, :macos
401
+ alias_for :blackberry, :bb
402
+ alias_for :ie, :internet_explorer
403
+ alias_for :facebook, :fb
404
+ alias_for :duckduckgo, :ddg
405
+ alias_for :chromeos, :cros
406
+ end
407
+ ```
408
+
409
+ What they do is they look for a value within the properties of a specific client and if found, all the aliasses specified will also be applied to that client.
410
+ This means that for a `client.is? :firefox` you can do `client.is? :ff` or `client.ff?` instead. This works for all the names like `name, label`, `engine`, `engine_label`, `platform` and `platform_label`
411
+
412
+ ##### Labels
413
+
414
+ A label could be a codename or a specific OS name for instance, it applies to a name and it's respective version combination.
415
+ It autodetects against which version it should match, this will always be the correct version. Here are some examples (also not the complete file - [source](https://github.com/SidOfc/browserino/blob/master/lib/browserino/definitions/labels.rb):
416
+
417
+ ```ruby
418
+ # small subset of labels from the source
419
+ Browserino.config.define do
420
+ label :yosemite, for: :macintosh, range: '10.10'..'10.10.9'
421
+ label :el_capitan, for: :macintosh, range: '10.11'..'10.11.9'
422
+ label :sierra, for: :macintosh, range: '10.12'..'10.12.9'
423
+ end
424
+ ```
425
+
426
+ So now it looks for a value of `:macintosh` in the properties gathered from a client, if it finds it, it will remember it's key (e.g. `platform` in this case.) and use it to find out the current version (e.g. `platform_version` in this case). If a version is supplied it will be compared to be `>= min` and `<= max` (which is inclusive) where `min` and `max` are the left and right values of the `range` option respectively.
427
+
428
+ #### Methods
429
+
430
+ The below methods are available by default, all methods with a questionmark at the end return either boolean `true` or `false` or `nil`.
431
+
432
+ ##### \#name
433
+
434
+ Returns either a symbol containing the name of the agent or `nil` otherwise.
435
+
436
+ ```ruby
437
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
438
+
439
+ client.name
440
+ # => :colibri
441
+ ```
442
+
443
+ ##### \#name?(sym, opts = {})
444
+
445
+ Returns true if supplied `sym` equals (`==`) the current `client.name`, if `opts` contains a `:version` key, it will be compared against `#version`
446
+ Returns false if the supplied criteria doesn't match the current client.
447
+ Returns nil if `sym` isn't the current client, regardless of version constraint
448
+
449
+ ```ruby
450
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
451
+
452
+ client.name? :colibri
453
+ # => true
454
+
455
+ client.name? :colibri, version: '1.0.0'
456
+ # => true
457
+
458
+ client.name? :colibri, version: '1.1.0'
459
+ # => false
460
+
461
+ client.name? :not_colibri
462
+ # => nil
463
+
464
+ client.name? :not_colibri, version: '1.0.0'
465
+ # => nil
466
+ ```
467
+
468
+ ##### \#version
469
+
470
+ Returns a `Browserino::Version` object. This object allows for more flexible comparing of long version numbers where simple numbers or floats don't suffice.
471
+
472
+ ```ruby
473
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
474
+
475
+ client.version
476
+ # => [1, 0, 0]
477
+
478
+ client.version.is_a? Browserino::Version
479
+ # => true
480
+
481
+ # logical operators can be used for comparison
482
+
483
+ # it can work with integers
484
+ client.version >= 1
485
+ # => true
486
+
487
+ # or strings
488
+ client.version >= '1.0.0'
489
+ # true
490
+
491
+ client.version.to_s
492
+ # or
493
+ client.version.full
494
+ # => '1.0.0'
495
+ ```
496
+
497
+ ##### \#version?(version)
498
+
499
+ Returns true if the supplied version equals (`==`) the current clients version.
500
+ Returns false otherwise
501
+
502
+ ```ruby
503
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
504
+
505
+ client.version? 1
506
+ # true
507
+
508
+ client.version? '1.0'
509
+ # true
510
+
511
+ client.version? '1.0.0'
512
+ # true
513
+
514
+ client.version? '1.0.1'
515
+ # false
516
+ ```
517
+
518
+ ##### \#engine
519
+
520
+ Returns either a symbol containing the engine of the agent or `nil` otherwise.
521
+
522
+ ```ruby
523
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
524
+
525
+ client.engine
526
+ # => :webkit
527
+ ```
528
+
529
+ ##### \#engine?(sym, opts = {})
530
+
531
+ Returns true if supplied `sym` equals (`==`) the current `client.version`, if `opts` contains a `:version` key, it will be compared against `#engine_version`
532
+ Returns false if the supplied criteria doesn't match the current client.
533
+ Returns nil if `sym` isn't the current client, regardless of version constraint
534
+
535
+ ```ruby
536
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
537
+
538
+ client.engine? :webkit
539
+ # => true
540
+
541
+ client.engine? :webkit, version: '537.36'
542
+ # => true
543
+
544
+ client.engine? :webkit, version: '537.38'
545
+ # => false
546
+
547
+ client.engine? :not_webkit
548
+ # => nil
549
+
550
+ client.engine? :not_webkit, version: '537.36'
551
+ # => nil
552
+ ```
553
+
554
+ ##### \#engine_version
555
+
556
+ Returns a [`Browserino::Version`](#version) object.
557
+
558
+ ```ruby
559
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
560
+
561
+ client.engine_version
562
+ # => [537, 36]
563
+
564
+ client.engine_version >= 530
565
+ # true
566
+
567
+ client.engine_version.to_s
568
+ # or
569
+ client.engine_version.full
570
+ # => '537.36'
571
+ ```
572
+
573
+ ##### \#engine_version?(version)
574
+
575
+ Returns true if the supplied version equals (`==`) the current clients engine_version.
576
+ Returns false otherwise
577
+
578
+ ```ruby
579
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
580
+
581
+ client.engine_version? '537.36'
582
+ # true
583
+ ```
584
+
585
+ ##### \#platform
586
+
587
+ Returns either a symbol containing the platform of the agent or `nil` otherwise.
588
+
589
+ ```ruby
590
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
591
+
592
+ client.platform
593
+ # => :macintosh
594
+ ```
595
+
596
+ ##### \#platform?(sym, opts = {})
597
+
598
+ Returns true if supplied `sym` equals (`==`) the current `client.platform`, if `opts` contains a `:version` key, it will be compared against `#platform_version`
599
+ Returns false if the supplied criteria doesn't match the current client.
600
+ Returns nil if `sym` isn't the current client, regardless of version constraint
601
+
602
+ ```ruby
603
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
604
+
605
+ client.platform? :macintosh
606
+ # => true
607
+
608
+ client.platform? :macintosh, version: '10.12'
609
+ # => true
610
+
611
+ client.platform? :macintosh, version: '10.12.2'
612
+ # => false
613
+
614
+ client.platform? :not_macintosh
615
+ # => nil
616
+
617
+ client.platform? :not_macintosh, version: '10.12.1'
618
+ # => nil
619
+ ```
620
+
621
+ ##### \#platform_label
622
+
623
+ Returns either a symbol containing the platform_label of the agent or `nil` otherwise.
624
+
625
+ ```ruby
626
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
627
+ client2 = Browserino.parse 'Mozilla/5.0 (Linux; Android 7.0; LG-H910 Build/NRD90C) AppleWebKit/537.26 (KHTML, like Gecko) Chrome/51.0.2704.90 Mobile Safari/537.36'
628
+
629
+ # macOS 10.12's name is Sierra
630
+ client.platform_label
631
+ # => :sierra
632
+
633
+ # Android 7's name is Nougat
634
+ client2.platform_label
635
+ # => :nougat
636
+ ```
637
+
638
+ ##### \#platform_version
639
+
640
+ Returns a [`Browserino::Version`](#version) object.
641
+
642
+ ```ruby
643
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
644
+
645
+ client.platform_version
646
+ # => [10, 12, 1]
647
+
648
+ client.platform_version >= 10
649
+ # => true
650
+
651
+ client.platform_version.to_s
652
+ # or
653
+ client.platform_version.full
654
+ # => '10.12.1'
655
+ ```
656
+
657
+ ##### \#platform_version?(version)
658
+
659
+ Returns true if the supplied version equals (`==`) the current clients platform_version.
660
+ Returns false otherwise
661
+
662
+ ```ruby
663
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
664
+
665
+ client.platform_version? '10.12'
666
+ # => true
667
+ ```
668
+ ##### \#device
669
+
670
+ Returns either a symbol containing the device of the client or `nil` otherwise
671
+
672
+ ```ruby
673
+ client = Browserino.parse 'Mozilla/5.0 (Linux; Android 5.1; ZTE Blade L6 Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.91 Mobile Safari/537.36'
674
+
675
+ client.device
676
+ # => :zte
677
+ ```
678
+
679
+ ##### \#device?(sym)
680
+
681
+ Returns true if the supplied sym equals (`==`) the current clients device.
682
+
683
+ ```ruby
684
+ client = Browserino.parse 'Mozilla/5.0 (Linux; Android 5.1; ZTE Blade L6 Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.91 Mobile Safari/537.36'
685
+
686
+ client.device
687
+ # => :zte
688
+ ```
689
+
690
+ ##### \#architecture
691
+
692
+ Returns either `nil`, `:x32` or `:x64` depending on wether it could be found in the user agent
693
+
694
+ ```ruby
695
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
696
+ client2 = Browserino.parse 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36 Vivaldi/1.0.288.3'
697
+
698
+ client.architecture
699
+ # => nil
700
+
701
+ client2.architecture
702
+ # => :x64
703
+ ```
704
+
705
+ ##### \#architecture?(sym)
706
+
707
+ sym must be one of `:x32` or `:x64`, returns `true` if it matches the current client architecture, false otherwise.
708
+
709
+ ```ruby
710
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
711
+
712
+ client.architecture? :x64
713
+ # => false
714
+ ```
715
+
716
+ ##### \#x64?
717
+
718
+ A shorthand for `client.architecture? :x64` returns a boolean value
719
+
720
+ ```ruby
721
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
722
+
723
+ client.x64?
724
+ # => false
725
+ ```
726
+
727
+ ##### \#x32?
728
+
729
+ A shorthand for `client.architecture? :x32` returns a boolean value
730
+
731
+ ```ruby
732
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
733
+
734
+ client.x32?
735
+ # => false
736
+ ```
737
+
738
+ ##### \#mobile and #mobile?
739
+
740
+ Returns boolean `true` or `false` depending on wether the device user agent is a mobile device
741
+
742
+ ```ruby
743
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
744
+
745
+ client.mobile
746
+ # or
747
+ client.mobile?
748
+ # => false
749
+ ```
750
+
751
+ ##### \#type
752
+
753
+ There are currently 6 types defined, `:browser`, `:bot`, `:library`, `:validator`, `:email` and `:unknown` _(default)_
754
+ This method simply returns the type of the current client, e.g.
755
+
756
+ ```ruby
757
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
758
+
759
+ client.type
760
+ # => :browser
761
+ ```
762
+
763
+ ##### \#type?(sym)
764
+
765
+ Returns true if `sym` equals (`==`) the current clients type
766
+
767
+ ```ruby
768
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
769
+
770
+ client.type? :browser
771
+ # => true
772
+
773
+ client.type? :bot
774
+ # => false
775
+ ```
776
+
777
+ ##### \#like
778
+
779
+ Like is something different. Within the defaults a few browsers are defined to be `like` others. This is the full list:
780
+
781
+ - Like `:chrome` includes:
782
+ - `:brave`
783
+ - `:vivaldi`
784
+ - `:colibri`
785
+ - `:rockmelt`
786
+ - `:flock`
787
+ - `:comodo_dragon`
788
+ - `:steam` (Game interface)
789
+ - `:chromeplus`
790
+ - `:bluechrome`
791
+ - `:awesomium`
792
+ - `:qqbrowser`
793
+ - `:yabrowser`
794
+ - `:coolnovo`
795
+ - `:iridium`
796
+ - `:origin`
797
+ - `:puffin`
798
+ - `:fluid`
799
+ - `:hana`
800
+ - `:iron`
801
+ - Like `:safari` includes:
802
+ - `:bolt`
803
+ - `:samsungbrowser`
804
+ - `:webosbrowser`
805
+ - `:stainless`
806
+ - `:omnibrowser`
807
+ - `:cheshire`
808
+ - `:skyfire`
809
+ - `:mercury`
810
+ - `:rekonq`
811
+ - `:arora`
812
+ - `:raptr`
813
+ - `:icab`
814
+ - `:silk`
815
+ - `:qt`
816
+ - Like `:firefox` includes:
817
+ - `:seamonkey`
818
+ - `:minefield` (FF nightly)
819
+ - `:kmeleon`
820
+ - `:kninja`
821
+ - `:granparadiso`
822
+ - `:tenfourfox`
823
+ - `:enigmafox`
824
+ - `:kazehakase`
825
+ - `:shiretoko`
826
+ - `:classilla`
827
+ - `:cometbird`
828
+ - `:icedragon`
829
+ - `:palemoon`
830
+ - `:namoroka`
831
+ - `:songbird`
832
+ - `:vonkeror`
833
+ - `:conkeror`
834
+ - `:bonecho`
835
+ - `:chimera`
836
+ - `:lolifox`
837
+ - `:lorentz`
838
+ - `:myibrow`
839
+ - `:sylera`
840
+ - `:iceape`
841
+ - `:madfox`
842
+ - `:kapiko`
843
+ - `:kmlite`
844
+ - `:beonex`
845
+ - `:galeon`
846
+ - `:vision`
847
+ - `:pogo`
848
+ - `:orca`
849
+ - `:superswan`
850
+ - `:firebird`
851
+ - `:iceweasel`
852
+ - `:icecat`
853
+ - `:waterfox`
854
+ - `:netscape`
855
+ - `:prism`
856
+ - `:lunascape`
857
+ - `:camino`
858
+ - Like `:ie` includes:
859
+ - `:avant_browser`
860
+ - `:deepnet_explorer`
861
+ - `:slimbrowser`
862
+ - `:sleipnir`
863
+ - `:greenbrowser`
864
+ - `:browzar`
865
+ - `:theworld`
866
+ - `:crazy_browser`
867
+ - `:solid_core`
868
+ - `:tencenttraveler`
869
+ - `:enigma_browser`
870
+ - `:simulbrowse`
871
+ - `:netcaptor`
872
+ - `:irider`
873
+ - `:kkman`
874
+ - `:lobo`
875
+ - `:aol`
876
+
877
+ ```ruby
878
+ # In this case, seamonkey is like firefox so like will represent the same user agent parsed as firefox to gather information
879
+ client = Browserino.parse 'Mozilla/5.0 (Windows NT 5.2; RW; rv:7.0a1) Gecko/20091211 SeaMonkey/9.23a1pre'
880
+
881
+ client.name
882
+ # => :seamonkey
883
+
884
+ client.is_a? Browserino::Client
885
+ # => true
886
+
887
+ client.like.name
888
+ # => :firefox
889
+
890
+ client.like.is_a? Browserino::Client
891
+ # => true
892
+
893
+ client == client.like
894
+ # => false
895
+
896
+ # This client isn't `like` anything, it's just chrome so in this case, we assign the value of like to itself.
897
+ client2 = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'
898
+
899
+ client2.name
900
+ # => :chrome
901
+
902
+ client2.is_a? Browserino::Client
903
+
904
+ client.like.name
905
+ # => :chrome
906
+
907
+ client2.like.is_a? Browserino::Client
908
+ # => true
909
+
910
+ client == client.like
911
+ # => true
912
+ ```
913
+
914
+ ##### \#like?(sym, opts = {})
915
+
916
+ This method acts much like the `name?` method on a client except that like `like` method will match a broader set of things like it.
917
+ Additionally, you can also supply an optional `:version` option which will then be compared to the `like.version` property.
918
+ Seamonkey in the last example is the browser I chose to be an example for the `like` documentation, since Seamonkey is like firefox we can do this:
919
+
920
+ ```ruby
921
+ # In this case, seamonkey is like firefox so like will represent the same user agent parsed as firefox to gather information
922
+ client = Browserino.parse 'Mozilla/5.0 (Windows NT 5.2; RW; rv:7.0a1) Gecko/20091211 SeaMonkey/9.23a1pre'
923
+
924
+ client.name
925
+ # => :seamonkey
926
+
927
+ client.name? :seamonkey
928
+ # => true
929
+
930
+ client.name? :firefox
931
+ # => false
932
+
933
+ client.like? :firefox
934
+ # => true
935
+
936
+ # A version can be supplied too but in this case, FireFox's version number
937
+ # isn't present in the user agent
938
+ # client.like? :firefox, version: '9.23'
939
+ # => false
940
+ ```
941
+
942
+ ##### \#is?(sym, opts = {})
943
+
944
+ The `is?` method is a bit more loose, it will recognize what it is and what it isn't automagically depending on what's passed in.
945
+ It can be a more general replacement for [#name?](#name), [#engine?](#engine) and [#platform?](#platform)
946
+
947
+ ##### \#not
948
+
949
+ Inverts the result returned by any method ending in a question mark (e.g. `client.version? == true && client.not.version? == false`)
950
+
951
+ ##### \#not?(sym, opts = {})
952
+
953
+ An inverted version of `#is?`
954
+
955
+ ```ruby
956
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'
957
+ client.to_h
958
+ # => { :name => :chrome,
959
+ # :type => :browser,
960
+ # :locale => nil,
961
+ # :architecture => nil,
962
+ # :mobile => false,
963
+ # :smarttv => false,
964
+ # :tablet => false,
965
+ # :platform => :macintosh,
966
+ # :platform_version => [10, 11, 2],
967
+ # :version => [47, 0, 2526, 106],
968
+ # :engine => :webkit,
969
+ # :engine_version => [537, 36],
970
+ # :device => nil
971
+ # :label => nil,
972
+ # :engine_label => nil,
973
+ # :platform_label => :el_capitan }
974
+
975
+ client.not? :chrome
976
+ # => false
977
+
978
+ # compares to a name of chrome with version of 47.0
979
+ client.not? :chrome, version: '47.0'
980
+ # => false
981
+
982
+ # but it also knows about platforms
983
+ client.not? :macintosh
984
+ # => false
985
+
986
+ # the version is matched against the platform_version in this case
987
+ client.not? :macintosh, version: '10.11'
988
+ # => false
989
+
990
+ # and engine names
991
+ client.not? :webkit
992
+ # => false
993
+
994
+ # where the version is compared to the engine_version
995
+ client.not? :webkit, version: 537
996
+ # => false
997
+ ```
998
+
999
+ #### Magic methods
1000
+
1001
+ ##### Names
1002
+
1003
+ For each of `#name`, `#engine`, `#platform`, `#platform_label` and `#device`, upon instantiation of the current client object, the **results** of these methods will also be defined as methods if they aren't nil e.g:
1004
+
1005
+ ```ruby
1006
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'
1007
+ client.to_h
1008
+ # => { :name => :chrome,
1009
+ # :type => :browser,
1010
+ # :locale => nil,
1011
+ # :architecture => nil,
1012
+ # :mobile => false,
1013
+ # :smarttv => false,
1014
+ # :tablet => false,
1015
+ # :platform => :macintosh,
1016
+ # :platform_version => [10, 11, 2],
1017
+ # :version => [47, 0, 2526, 106],
1018
+ # :engine => :webkit,
1019
+ # :engine_version => [537, 36],
1020
+ # :device => nil,
1021
+ # :label => nil,
1022
+ # :engine_label => nil,
1023
+ # :platform_label => :el_capitan }
1024
+
1025
+ ### NAME ###
1026
+
1027
+ # since client.name is :chrome, a method #chrome? is defined
1028
+ client.chrome?
1029
+ # => true
1030
+
1031
+ # an optional version can also be suppied
1032
+ client.chrome? 47
1033
+ # => true
1034
+
1035
+ # since client.name isn't :firefox, no method named #firefox? is defined
1036
+ # instead, it is sent to method_missing which will return nil
1037
+ client.firefox?
1038
+ # => nil
1039
+
1040
+ # supplying a version of course, makes no difference in this case
1041
+ client.firefox? 47
1042
+ # => nil
1043
+
1044
+ ### ENGINE NAME ###
1045
+
1046
+ # since client.engine_name is :webkit, a method #webkit? is defined
1047
+ client.webkit?
1048
+ # => true
1049
+
1050
+ # an optional version can also be suppied
1051
+ client.webkit? '537.36'
1052
+ # => true
1053
+
1054
+ # since client.engine_name isn't :gecko, no method named #gecko? is defined
1055
+ # instead, it is sent to method_missing which will return nil
1056
+ client.gecko?
1057
+ # => nil
1058
+
1059
+ # supplying a version of course, makes no difference in this case
1060
+ client.gecko? 50
1061
+ # => nil
1062
+
1063
+ ### PLATFORM NAME ###
1064
+
1065
+ # since client.platform_name is :macintosh, a method #macintosh? is defined
1066
+ client.macintosh?
1067
+ # => true
1068
+
1069
+ # an optional version can also be suppied
1070
+ client.macintosh? '10.11'
1071
+ # => true
1072
+
1073
+ # since client.platform_name isn't :windows, no method named #windows? is defined
1074
+ # instead, it is sent to method_missing which will return nil
1075
+ client.windows?
1076
+ # => nil
1077
+
1078
+ # supplying a version of course, makes no difference in this case
1079
+ client.windows? 10
1080
+ # => nil
1081
+
1082
+ ### PLATFORM LABEL ###
1083
+
1084
+ # since client.platform_label is :el_capitan, a method #el_capitan? is defined
1085
+ client.el_capitan?
1086
+ # => true
1087
+
1088
+ # an optional version can also be suppied
1089
+ client.el_capitan? '10.10'
1090
+ # => true
1091
+ ```
1092
+
1093
+ ##### Aliasses
1094
+
1095
+ For each of the defined keys in `Browserino.config.aliasses` that matches with any value of `#name`, `#engine`, `#platform` or `#platform_label`, define every alias as a method.
1096
+
1097
+ ```ruby
1098
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:33.0) Gecko/20100101 Firefox/33.0'
1099
+
1100
+ ### NAME ###
1101
+
1102
+ client.name
1103
+ # => :firefox
1104
+
1105
+ Browserino.config.aliasses[client.name]
1106
+ # => [:ff]
1107
+
1108
+ client.firefox?
1109
+ # => true
1110
+
1111
+ client.ff?
1112
+ # => true
1113
+
1114
+ ### PLATFORM NAME ###
1115
+
1116
+ client.platform
1117
+ # => :macintosh
1118
+
1119
+ Browserino.config.aliasses[client.platform]
1120
+ # => [:macos, :osx, :mac]
1121
+
1122
+ client.macos?
1123
+ # => true
1124
+
1125
+ client.osx?
1126
+ # => true
1127
+
1128
+ client.mac?
1129
+ # => true
1130
+ ```
1131
+
1132
+ Aliasses can also be used in `#name?`, `#engine?`, `#platform?` and `#is?` methods, e.g:
1133
+
1134
+ ```ruby
1135
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:33.0) Gecko/20100101 Firefox/33.0'
1136
+
1137
+ ### NAME ###
1138
+
1139
+ client.name
1140
+ # => :firefox
1141
+
1142
+ client.name? :firefox
1143
+ # => true
1144
+
1145
+ client.name? :ff
1146
+ # => true
1147
+
1148
+ client.name? :ff, version: 33
1149
+ # => true
1150
+
1151
+ client.is? :firefox
1152
+ # => true
1153
+
1154
+ client.is? :ff
1155
+ # => true
1156
+
1157
+ client.is? :ff, version: 33
1158
+ # => true
1159
+
1160
+ ### PLATFORM NAME ###
1161
+
1162
+ client.platform
1163
+ # => :macintosh
1164
+
1165
+ # Browserino.config.aliasses[:macintosh] defines [:mac, :osx, :macos] as aliasses
1166
+
1167
+ client.platform? :macintosh
1168
+ # => true
1169
+
1170
+ client.platform? :mac
1171
+ # => true
1172
+
1173
+ client.platform? :osx
1174
+ # => true
1175
+
1176
+ client.platform? :macos
1177
+ # => true
1178
+
1179
+ client.platform? :macos, version: '10.10'
1180
+ # => true
1181
+ ```
1182
+
1183
+ ## Supported
1184
+
1185
+ ### Browsers
1186
+
1187
+ `aol`, `ion`, `foxy`, `lobo`, `kkman`, `irider`, `sleipnir`, `netcaptor`, `sitekiosk`, `gomezagent`, `solid_core`, `simulbrowse`, `crazy_browser`, `enigma_browser`, `tencenttraveler`, `deepnet_explorer`, `sogou_browser`, `netflix_desktop`, `browzar`, `theworld`, `smart_bro`, `slimbrowser`, `greenbrowser`, `avant_browser`, `orca`, `pogo`, `epic`, `kylo`, `wyzo`, `light`, `prism`, `strata`, `vision`, `galeon`, `icecat`, `minimo`, `beonex`, `kmlite`, `kapiko`, `madfox`, `iceape`, `fennec`, `sylera`, `myibrow`, `lorentz`, `lolifox`, `chimera`, `sundial`, `bonecho`, `k_ninja`, `k_meleon`, `netscape`, `conkeror`, `vonkeror`, `firebird`, `songbird`, `namoroka`, `cyberfox`, `palemoon`, `swiftfox`, `cunaguaro`, `icedragon`, `blackbird`, `cometbird`, `classilla`, `shiretoko`, `lunascape`, `superswan`, `lightning`, `multizilla`, `seamonkey`, `iceweasel`, `enigmafox`, `kazehakase`, `tenfourfox`, `swiftweasel`, `granparadiso`, `maemo_browser`, `sailfishbrowser`, `monyq`, `waterfox`, `minefield`, `fireweb_navigator`, `camino`, `maemo`, `opera_mobile`, `blackberry_browser`, `webosbrowser`, `leechcraft`, `kindle`, `nook`, `xiaomi_miui`, `qt`, `coda`, `silk`, `bolt`, `icab`, `raptr`, `maple`, `arora`, `coast`, `rekonq`, `mercury`, `skyfire`, `omniweb`, `teashark`, `cheshire`, `stainless`, `webbrowser`, `mqqbrowser`, `nokiabrowser`, `samsungbrowser`, `playbook_browser`, `obigo`, `qtweb_browser`, `maxthon_nitro`, `nichrome`, `iron`, `hana`, `perk`, `brave`, `swing`, `kinza`, `fluid`, `amigo`, `puffin`, `origin`, `yowser`, `iridium`, `colibri`, `vivaldi`, `safepay`, `slimboat`, `coolnovo`, `rockmelt`, `polarity`, `chromeum`, `yabrowser`, `qqbrowser`, `awesomium`, `mxbrowser`, `fabrowser`, `blackhawk`, `taobrowser`, `bluechrome`, `chromeplus`, `comodo_dragon`, `coc_coc_browser`, `whitehat_aviator`, `steam`, `maxthon`, `ucbrowser`, `edge`, `opera_mini`, `opera`, `escape`, `flock`, `sunrise`, `ie`, `origyn`, `webpositive`, `nintendobrowser`, `deskbrowse`, `qupzilla`, `midori`, `shiira`, `element_browser`, `amigavoyager`, `browse`, `mothra`, `surf`, `spray_can`, `bunjalloo`, `inet_browser`, `webpro`, `sundance`, `ibm_webexplorer`, `navscape`, `firefox`, `chrome`, `safari`, `tizenbrowser`, `epiphany`, `uzbl`, `roccat`, `dolfin`, `dooble`, `adobeair`, `abrowse`, `vimprobable`, `osb_browser`, `edbrowse`, `amaya`, `lynx`, `linemode`, `elinks`, `netpositive`, `mucommander`, `onebrowser`, `flashfire`, `konqueror`, `cyberdog`, `offbyone`, `hotjava`, `netsurf`, `contiki`, `mosaic`, `netbox`, `dillo`, `ice_browser`, `emacs`, `openwave_browser`, `alienblue`, `ovibrowser`, `links`, `oregano`, `browsex`, `doris`, `retawq`
1188
+
1189
+ ### Bots
1190
+
1191
+ `huaweisymantecspider`, `atomic_email_hunter`, `netresearchserver`, `auto_email_spider`, `flaming_attackbot`, `addsugarspiderbot`, `semanticdiscovery`, `xaldon_webspider`, `yooglifetchagent`, `keyword_density`, `mass_downloader`, `safetynet_robot`, `download_demon`, `internet_ninja`, `dataparksearch`, `boston_project`, `emailcollector`, `webemailextrac`, `sitelockspider`, `morning_paper`, `four_anything`, `aqua_products`, `arachnophilia`, `smartdownload`, `emeraldshield`, `womlpefactory`, `israelisearch`, `issuecrawler`, `jaxified_bot`, `stackrambler`, `turnitinbot`, `covario_ids`, `alkalinebot`, `yahoo_slurp`, `propowerbot`, `emailsiphon`, `backdoorbot`, `terrawizbot`, `searchsight`, `baiduspider`, `sandcrawler`, `fyberspider`, `linguee_bot`, `big_brother`, `yahooseeker`, `noxtrumbot`, `black_hole`, `blackwidow`, `sosospider`, `duckduckgo`, `beslistbot`, `twitterbot`, `linkdexbot`, `aitcsrobot`, `litefinder`, `mabontland`, `yasaklibot`, `httpclient`, `ahrefsbot`, `mojeekbot`, `incywincy`, `seznambot`, `girafabot`, `becomebot`, `dts_agent`, `emailwolf`, `googlebot`, `omgilibot`, `labelgrab`, `altavista`, `yandexbot`, `newsgator`, `instagram`, `pinterest`, `gurujibot`, `lapozzbot`, `mvaclient`, `ng_search`, `youdaobot`, `webcopier`, `ips_agent`, `yodaobot`, `ldspider`, `lexxebot`, `scoutjet`, `linkedin`, `bullseye`, `alexibot`, `whatsapp`, `facebook`, `getright`, `asterias`, `catchbot`, `discobot`, `geniebot`, `koepabot`, `synoobot`, `rufusbot`, `rampybot`, `mogimogi`, `lmspider`, `blowfish`, `superbot`, `valkyrie`, `yacybot`, `jyxobot`, `orbiter`, `polybot`, `accoona`, `mj12bot`, `aspider`, `blexbot`, `bspider`, `auresys`, `bingbot`, `gaisbot`, `zealbot`, `zspider`, `backrub`, `harvest`, `nymesis`, `radian6`, `scrubby`, `gcreep`, `snappy`, `vortex`, `tineye`, `zyborg`, `sqworm`, `qseero`, `pompos`, `solbot`, `ichiro`, `bizbot`, `msnbot`, `exabot`, `msrbot`, `dotbot`, `cosmos`, `ecatch`, `scrapy`, `tumblr`, `holmes`, `okhttp`, `mxbot`, `moget`, `occam`, `acoon`, `nutch`, `alexa`, `atomz`, `htdig`, `peew`, `yeti`, `wf84`, `vyu2`, `acoi`, `obot`, `ask`, `b2w`, `ipd`, `zao`, `furlbot`, `jakarta`, `oegp`, `lwebis`, `cerberian_drtrs`, `gigamega`, `sogou_spider`, `megaindex`, `gozilla`, `larbin`, `netseer`
1192
+
1193
+ ### Validators
1194
+
1195
+ `xenu_link_sleuth`, `screaming_frog_seo_spider`, `rel_link_checker_lite`, `a1_website_analyzer`, `w3c_multipage_validator`, `cse_html_validator`, `p3p_validator`, `w3c_checklink`, `w3c_i18n_checker`, `w3c_unicorn`, `w3c_mobileok`, `wdg_validator`, `w3c_validator`, `fplinkchecker`, `linkchecker`, `linkwalker`, `linkexaminer`, `feedvalidator`, `htmlparser`, `csscheck`, `checkbot`, `cynthia`, `validator_nu`, `anw_htmlchecker`, `w3c_css_validator`
1196
+
1197
+ ### Libraries
1198
+
1199
+ `golang`, `python`, `luakit`, `webfetch`, `pycurl`, `perl`, `java`, `curl`, `wget`, `php`
1200
+
1201
+ ### Email Clients
1202
+
1203
+ `:outlook`, `:airmail`, `:barca`, `:gmail`, `:thunderbird`, `:postbox`, `spicebird`
1204
+
1205
+ ### RSS
1206
+
1207
+ `windows_rss`, `apple_pubsub`, `safari_rss`, `sharpreader`, `netnewswire`, `omea_reader`, `rssbandit`, `feeddemon`, `lucknews`, `inoreader`, `rss_menu`, `rss_popper`, `seznam_rss`, `nfreader`, `magpierss`, `gregarius`, `newsbreak`, `blogbridge`, `yeahreader`, `newsbeuter`, `greatnews`, `bloglines`, `icatcher`, `newsfox`, `quiterss`, `liferea`, `aiderss`, `reeder`, `rssowl`, `feedly`, `abilon`, `shrook`, `awasu`, `sage`, `akregator`, `trileet_newsroom`, `dragonfly_rss`, `digg_feed_fetcher`, `yahoofeedseeker`, `universalfeedparser`, `feedfetcher_google`, `fastladder_feedfetcher`
1208
+
1209
+ ### Platforms
1210
+
1211
+ In addition to just supporting regular platform names as `client.android?`, there are also specific methods that get added if a certain version matches a platform.
1212
+ This is the _platform_label_ property and allows you to do things like `client.froyo?` for instance.
1213
+
1214
+ Below are a list of versions the agent can identify so far
1215
+
1216
+ #### Android
1217
+
1218
+ Regular: `:android`
1219
+
1220
+ `:android`, `:cupcake`, `:eclair`, `:froyo`, `:gingerbread`, `:honeycomb`, `:ice_cream_sandwich`, `:jelly_bean`, `:kitkat`, `:lollipop`, `:marshmallow`, `:nougat`
1221
+
1222
+ #### Windows
1223
+
1224
+ Regular: `:windows`
1225
+
1226
+ `:dos`, `:windows98`, `:windows2000`, `:xp`, `:vista`, `:windows7`, `:windows8`, `:windows10`
1227
+
1228
+ #### Macintosh
1229
+
1230
+ Regular: `:macintosh`
1231
+
1232
+ `:cheetah`, `:puma`, `:jaguar`, `:panther`, `:tiger`, `:leopard`, `:snow_leopard`, `:lion`, `:mountain_lion`, `:mavericks`, `:yosemite`, `:el_capitan`, `:sierra`
1233
+
1234
+ ### Devices
1235
+
1236
+ Finally, Browserino can also detect devices in addition to the above.
1237
+
1238
+ `htc`, `kindle`, `alcatel`, `appletv`, `iphone`, `ipad`, `archos`, `asus`, `zte`, `blackberry`, `oneplus`, `lenovo`, `nokia`, `motorola`, `huawei`, `nexus`, `hp`, `lg`, `dell`