fake_useragent 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/ruby.yml +32 -0
- data/.gitignore +27 -0
- data/Gemfile +2 -0
- data/LICENSE +21 -0
- data/README.md +39 -0
- data/Rakefile +9 -0
- data/fake_useragent.gemspec +14 -0
- data/lib/fake_useragent.rb +484 -0
- data/lib/fake_useragent/data/smartphone_dev_ext.json +2820 -0
- data/lib/fake_useragent/data/smartphone_dev_id.json +180 -0
- data/lib/fake_useragent/data/tablet_dev_ext.json +757 -0
- data/lib/fake_useragent/data/tablet_dev_id.json +52 -0
- data/lib/fake_useragent/device.rb +8 -0
- data/lib/fake_useragent/error.rb +15 -0
- data/lib/fake_useragent/version.rb +1 -0
- data/spec/lib/test_fake_useragent.rb +240 -0
- metadata +58 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d3018c646d27e4571aa0a4d066d4dd57b1d1b2c266ae4c3450041d6a3b504cbb
|
4
|
+
data.tar.gz: 81a2f7ad6a4c9b3354c699ba67bc8e122c27a507aef0f1b1eefb4af189066f82
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6533eb6d2f5978eb780f65f288c0ace51d5965d02f793966c010f896b884c7d7e6140eac04a723b253a803dbb7a35eb2e0159b015071115dfebc40f091d23d7a
|
7
|
+
data.tar.gz: 68e92e1e0420fc832fcbf8faa0d4167a16108f18f729e59ce1507ea7e78f14e74bdd97feb7729ff058513cf69def3ea91f353297576b03cd1c5f992193249cee
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Ruby
|
9
|
+
|
10
|
+
on:
|
11
|
+
push:
|
12
|
+
branches: [ main ]
|
13
|
+
pull_request:
|
14
|
+
branches: [ main ]
|
15
|
+
|
16
|
+
jobs:
|
17
|
+
test:
|
18
|
+
|
19
|
+
runs-on: ubuntu-latest
|
20
|
+
strategy:
|
21
|
+
matrix:
|
22
|
+
ruby-version: ['2.4', '2.6', '2.7', '3.0']
|
23
|
+
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v2
|
26
|
+
- name: Set up Ruby
|
27
|
+
uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
|
28
|
+
with:
|
29
|
+
ruby-version: ${{ matrix.ruby-version }}
|
30
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
31
|
+
- name: Run tests
|
32
|
+
run: rake test
|
data/.gitignore
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/.idea
|
5
|
+
/coverage/
|
6
|
+
/InstalledFiles
|
7
|
+
/pkg/
|
8
|
+
/spec/reports/
|
9
|
+
/spec/examples.txt
|
10
|
+
/test/tmp/
|
11
|
+
/test/version_tmp/
|
12
|
+
/tmp/
|
13
|
+
.byebug_history
|
14
|
+
.dat*
|
15
|
+
.repl_history
|
16
|
+
build/
|
17
|
+
*.bridgesupport
|
18
|
+
build-iPhoneOS/
|
19
|
+
build-iPhoneSimulator/
|
20
|
+
/.yardoc/
|
21
|
+
/_yardoc/
|
22
|
+
/doc/
|
23
|
+
/rdoc/
|
24
|
+
/.bundle/
|
25
|
+
/vendor/bundle
|
26
|
+
/lib/bundler/man/
|
27
|
+
.rvmrc
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2021 A.N.Bockanov
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Fake User Agent
|
2
|
+
|
3
|
+
## For what?
|
4
|
+
Generates random valid web user agents
|
5
|
+
|
6
|
+
## Usage example:
|
7
|
+
This version just a test. You can use `generate_user_agent` or `generate_navigator_js` from `base.rb`.
|
8
|
+
|
9
|
+
parameters: `os`, `navigator`, `device_type` and `platform` (deprecated)
|
10
|
+
Possible values:
|
11
|
+
`os`: `win`, `linux`, `mac`
|
12
|
+
`navigator`: `ie`, `chrome` or `firefox`
|
13
|
+
`device_type`: `desktop`, `smartphone`, `tablet` or `all`
|
14
|
+
Keep in mind array combinations are possible.
|
15
|
+
```ruby
|
16
|
+
generate_user_agent(os: %w[win linux])
|
17
|
+
# → "Mozilla/5.0 (X11; Linux; i686 on x86_64) AppleWebKit/537.36 (KHTML, like Gecko) ..."
|
18
|
+
|
19
|
+
generate_user_agent(os: %w[win linux], device_type: 'all')
|
20
|
+
# → "Mozilla/5.0 (Windows NT 6.3; ; rv:45.0) Gecko/20100101 Firefox/45.0"
|
21
|
+
|
22
|
+
generate_user_agent(device_type: %w[smartphone tablet], navigator: 'chrome')
|
23
|
+
# → "Mozilla/5.0 (Linux; Android 4.4.1; Lenovo S850 Build/KOT49H) AppleWebKit/537.36 ..."
|
24
|
+
|
25
|
+
generate_navigator_js #
|
26
|
+
# → {"appCodeName"=>"Mozilla",
|
27
|
+
# "appName"=>"Netscape",
|
28
|
+
# "appVersion"=>"5.0 (Macintosh)",
|
29
|
+
# "platform"=>"MacIntel",
|
30
|
+
# "userAgent"=>
|
31
|
+
# "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:48.0) Gecko/20100101 Firefox/48.0",
|
32
|
+
# "oscpu"=>"Intel Mac OS X 10.10",
|
33
|
+
# "product"=>"Gecko",
|
34
|
+
# "productSub"=>"20100101",
|
35
|
+
# "vendor"=>"",
|
36
|
+
# "vendorSub"=>"",
|
37
|
+
# "buildID"=>"20160808222632"}
|
38
|
+
```
|
39
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'fake_useragent'
|
5
|
+
s.version = '1.0.0'
|
6
|
+
s.date = '2021-04-17'
|
7
|
+
s.summary = 'FakeUserAgent - simple gem for generating valid web user agents.'
|
8
|
+
s.description = 'Simple gem for generating valid web user agents.'
|
9
|
+
s.author = 'Bokanov Alexander'
|
10
|
+
s.email = 'overhead.nerves@gmail.com'
|
11
|
+
s.homepage = 'https://github.com/TRT360/fake_useragent'
|
12
|
+
s.license = 'MIT'
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
end
|
@@ -0,0 +1,484 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
require 'json'
|
5
|
+
require 'pp'
|
6
|
+
|
7
|
+
require_relative './fake_useragent/error'
|
8
|
+
require_relative './fake_useragent/device'
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
DEVICE_TYPE_OS = {
|
13
|
+
'desktop' => %w[win mac linux],
|
14
|
+
'smartphone' => ['android'],
|
15
|
+
'tablet' => ['android']
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
OS_DEVICE_TYPE = {
|
19
|
+
'win' => ['desktop'],
|
20
|
+
'linux' => ['desktop'],
|
21
|
+
'mac' => ['desktop'],
|
22
|
+
'android' => %w[smartphone tablet]
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
DEVICE_TYPE_NAVIGATOR = {
|
26
|
+
'desktop' => %w[chrome firefox ie],
|
27
|
+
'smartphone' => %w[firefox chrome],
|
28
|
+
'tablet' => %w[firefox chrome]
|
29
|
+
}.freeze
|
30
|
+
|
31
|
+
NAVIGATOR_DEVICE_TYPE = {
|
32
|
+
'ie' => ['desktop'],
|
33
|
+
'chrome' => %w[desktop smartphone tablet],
|
34
|
+
'firefox' => %w[desktop smartphone tablet]
|
35
|
+
}.freeze
|
36
|
+
|
37
|
+
OS_PLATFORM = {
|
38
|
+
'win' => [
|
39
|
+
'Windows NT 5.1', # Windows XP
|
40
|
+
'Windows NT 6.1', # Windows 7
|
41
|
+
'Windows NT 6.2', # Windows 8
|
42
|
+
'Windows NT 6.3', # Windows 8.1
|
43
|
+
'Windows NT 10.0' # Windows 10
|
44
|
+
],
|
45
|
+
'mac' => [
|
46
|
+
'Macintosh; Intel Mac OS X 10.8',
|
47
|
+
'Macintosh; Intel Mac OS X 10.9',
|
48
|
+
'Macintosh; Intel Mac OS X 10.10',
|
49
|
+
'Macintosh; Intel Mac OS X 10.11',
|
50
|
+
'Macintosh; Intel Mac OS X 10.12'
|
51
|
+
],
|
52
|
+
'linux' => [
|
53
|
+
'X11; Linux',
|
54
|
+
'X11; Ubuntu; Linux'
|
55
|
+
],
|
56
|
+
'android' => [
|
57
|
+
'Android 4.4', # 2013-10-31
|
58
|
+
'Android 4.4.1', # 2013-12-05
|
59
|
+
'Android 4.4.2', # 2013-12-09
|
60
|
+
'Android 4.4.3', # 2014-06-02
|
61
|
+
'Android 4.4.4', # 2014-06-19
|
62
|
+
'Android 5.0', # 2014-11-12
|
63
|
+
'Android 5.0.1', # 2014-12-02
|
64
|
+
'Android 5.0.2', # 2014-12-19
|
65
|
+
'Android 5.1', # 2015-03-09
|
66
|
+
'Android 5.1.1', # 2015-04-21
|
67
|
+
'Android 6.0', # 2015-10-05
|
68
|
+
'Android 6.0.1', # 2015-12-07
|
69
|
+
'Android 7.0', # 2016-08-22
|
70
|
+
'Android 7.1', # 2016-10-04
|
71
|
+
'Android 7.1.1' # 2016-12-05
|
72
|
+
]
|
73
|
+
}.freeze
|
74
|
+
|
75
|
+
OS_CPU = {
|
76
|
+
'win' => [
|
77
|
+
'', # 32bit
|
78
|
+
'Win64; x64', # 64bit
|
79
|
+
'WOW64' # 32bit process on 64bit system
|
80
|
+
],
|
81
|
+
'linux' => [
|
82
|
+
'i686', # 32bit
|
83
|
+
'x86_64', # 64bit
|
84
|
+
'i686 on x86_64' # 32bit process on 64bit system
|
85
|
+
],
|
86
|
+
'mac' => [
|
87
|
+
''
|
88
|
+
],
|
89
|
+
'android' => [
|
90
|
+
'armv7l', # 32bit
|
91
|
+
'armv8l' # 64bit
|
92
|
+
]
|
93
|
+
}.freeze
|
94
|
+
|
95
|
+
OS_NAVIGATOR = {
|
96
|
+
'win' => %w[chrome firefox ie],
|
97
|
+
'mac' => %w[firefox chrome],
|
98
|
+
'linux' => %w[chrome firefox],
|
99
|
+
'android' => %w[firefox chrome]
|
100
|
+
}.freeze
|
101
|
+
|
102
|
+
NAVIGATOR_OS = {
|
103
|
+
'chrome' => %w[win linux mac android],
|
104
|
+
'firefox' => %w[win linux mac android],
|
105
|
+
'ie' => ['win']
|
106
|
+
}.freeze
|
107
|
+
|
108
|
+
FIREFOX_VERSION = [
|
109
|
+
['45.0', Time.new(2016, 3, 8)],
|
110
|
+
['46.0', Time.new(2016, 4, 26)],
|
111
|
+
['47.0', Time.new(2016, 6, 7)],
|
112
|
+
['48.0', Time.new(2016, 8, 2)],
|
113
|
+
['49.0', Time.new(2016, 9, 20)],
|
114
|
+
['50.0', Time.new(2016, 11, 15)],
|
115
|
+
['51.0', Time.new(2017, 1, 24)]
|
116
|
+
]
|
117
|
+
|
118
|
+
CHROME_BUILD = '80.0.3987.132
|
119
|
+
80.0.3987.149
|
120
|
+
80.0.3987.99
|
121
|
+
81.0.4044.117
|
122
|
+
81.0.4044.138
|
123
|
+
83.0.4103.101
|
124
|
+
83.0.4103.106
|
125
|
+
83.0.4103.96
|
126
|
+
84.0.4147.105
|
127
|
+
84.0.4147.111
|
128
|
+
84.0.4147.125
|
129
|
+
84.0.4147.135
|
130
|
+
84.0.4147.89
|
131
|
+
85.0.4183.101
|
132
|
+
85.0.4183.102
|
133
|
+
85.0.4183.120
|
134
|
+
85.0.4183.121
|
135
|
+
85.0.4183.127
|
136
|
+
85.0.4183.81
|
137
|
+
85.0.4183.83
|
138
|
+
86.0.4240.110
|
139
|
+
86.0.4240.111
|
140
|
+
86.0.4240.114
|
141
|
+
86.0.4240.183
|
142
|
+
86.0.4240.185
|
143
|
+
86.0.4240.75
|
144
|
+
86.0.4240.78
|
145
|
+
86.0.4240.80
|
146
|
+
86.0.4240.96
|
147
|
+
86.0.4240.99
|
148
|
+
'.strip.split(/\n+/)
|
149
|
+
|
150
|
+
IE_VERSION = [
|
151
|
+
# [numeric ver, string ver, trident ver] # release year
|
152
|
+
[8, 'MSIE 8.0', '4.0'], # 2009
|
153
|
+
[9, 'MSIE 9.0', '5.0'], # 2011
|
154
|
+
[10, 'MSIE 10.0', '6.0'], # 2012
|
155
|
+
[11, 'MSIE 11.0', '7.0'] # 2013
|
156
|
+
].freeze
|
157
|
+
|
158
|
+
MACOSX_CHROME_BUILD_RANGE = {
|
159
|
+
# https://en.wikipedia.org/wiki/MacOS#Release_history
|
160
|
+
'10.8' => [0, 8],
|
161
|
+
'10.9' => [0, 5],
|
162
|
+
'10.10' => [0, 5],
|
163
|
+
'10.11' => [0, 6],
|
164
|
+
'10.12' => [0, 2]
|
165
|
+
}.freeze
|
166
|
+
|
167
|
+
def user_agent_template(tpl_name, system, app)
|
168
|
+
case tpl_name
|
169
|
+
when 'firefox'
|
170
|
+
"Mozilla/5.0 (#{system['ua_platform']}; rv:#{app['build_version']}) Gecko/#{app['gecko_trail']} Firefox/#{app['build_version']}"
|
171
|
+
when 'chrome'
|
172
|
+
"Mozilla/5.0 (#{system['ua_platform']}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/#{app['build_version']} Safari/537.36"
|
173
|
+
when 'chrome_smartphone'
|
174
|
+
"Mozilla/5.0 (#{system['ua_platform']}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/#{app['build_version']} Mobile Safari/537.36"
|
175
|
+
when 'chrome_tablet'
|
176
|
+
"Mozilla/5.0(#{system['ua_platform']}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/#{app['build_version']} Safari/537.36"
|
177
|
+
when 'ie_less_11'
|
178
|
+
"Mozilla/5.0 (compatible; #{app['build_version']}; #{system['ua_platform']}; Trident/#{app['trident_version']})"
|
179
|
+
when 'ie_11'
|
180
|
+
"Mozilla/5.0 (#{system['ua_platform']}; Trident/#{app['trident_version']}; rv:11.0) like Gecko"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def firefox_build
|
185
|
+
firefox_ver = FIREFOX_VERSION.sample
|
186
|
+
build_ver = firefox_ver[0]
|
187
|
+
date_from = firefox_ver[1].to_i
|
188
|
+
|
189
|
+
begin
|
190
|
+
idx = FIREFOX_VERSION.index(firefox_ver)
|
191
|
+
date_to = FIREFOX_VERSION.fetch(idx + 1)[1].to_i
|
192
|
+
rescue IndexError
|
193
|
+
date_to = date_from + 86_399
|
194
|
+
end
|
195
|
+
sec_range = date_to - date_from
|
196
|
+
build_rnd_time = Time.at(date_from + rand(sec_range))
|
197
|
+
|
198
|
+
[build_ver, build_rnd_time.strftime('%Y%m%d%H%M%S')]
|
199
|
+
end
|
200
|
+
|
201
|
+
def chrome_build
|
202
|
+
CHROME_BUILD.sample
|
203
|
+
end
|
204
|
+
|
205
|
+
def ie_build
|
206
|
+
IE_VERSION.sample
|
207
|
+
end
|
208
|
+
|
209
|
+
def fix_chrome_mac_platform(platform)
|
210
|
+
ver = platform.split('OS X ')[1]
|
211
|
+
build_range = 0...MACOSX_CHROME_BUILD_RANGE[ver][1]
|
212
|
+
build = rand(build_range)
|
213
|
+
mac_version = "#{ver.sub('.', '_')}_#{build}"
|
214
|
+
|
215
|
+
"Macintosh; Intel Mac OS X #{mac_version}"
|
216
|
+
end
|
217
|
+
|
218
|
+
def build_system_components(device_type, os_id, navigator_id)
|
219
|
+
case os_id
|
220
|
+
when 'win'
|
221
|
+
platform_version = OS_PLATFORM['win'].sample.to_s
|
222
|
+
cpu = OS_CPU['win'].sample
|
223
|
+
platform = if cpu
|
224
|
+
"#{platform_version}; #{cpu}"
|
225
|
+
else
|
226
|
+
platform_version.to_s
|
227
|
+
end
|
228
|
+
res = {
|
229
|
+
'platform_version' => platform_version,
|
230
|
+
'platform' => platform,
|
231
|
+
'ua_platform' => platform,
|
232
|
+
'os_cpu' => platform
|
233
|
+
}
|
234
|
+
when 'linux'
|
235
|
+
cpu = OS_CPU['linux'].sample
|
236
|
+
platform_version = OS_PLATFORM['linux'].sample
|
237
|
+
platform = "#{platform_version}; #{cpu}"
|
238
|
+
res = {
|
239
|
+
'platform_version' => platform_version,
|
240
|
+
'platform' => platform,
|
241
|
+
'ua_platform' => platform,
|
242
|
+
'os_cpu' => "Linux #{cpu}"
|
243
|
+
}
|
244
|
+
when 'mac'
|
245
|
+
cpu = OS_CPU['mac'].sample
|
246
|
+
platform_version = OS_PLATFORM['mac'].sample
|
247
|
+
platform = platform_version
|
248
|
+
platform = fix_chrome_mac_platform(platform) if navigator_id == 'chrome'
|
249
|
+
res = {
|
250
|
+
'platform_version' => platform_version.to_s,
|
251
|
+
'platform' => 'MacIntel',
|
252
|
+
'ua_platform' => platform.to_s,
|
253
|
+
'os_cpu' => "Intel Mac OS X #{platform.split(' ')[-1]}"
|
254
|
+
}
|
255
|
+
when 'android'
|
256
|
+
raise "#{navigator_id} not firefox or chrome" unless %w[firefox chrome].include? navigator_id
|
257
|
+
raise "#{device_type} not smartphone or tablet" unless %w[smartphone tablet].include? device_type
|
258
|
+
|
259
|
+
platform_version = OS_PLATFORM['android'].sample
|
260
|
+
case navigator_id
|
261
|
+
when 'firefox'
|
262
|
+
case device_type
|
263
|
+
when 'smartphone'
|
264
|
+
ua_platform = "#{platform_version}; Mobile"
|
265
|
+
when 'tablet'
|
266
|
+
ua_platform = "#{platform_version}; Tablet"
|
267
|
+
end
|
268
|
+
when 'chrome'
|
269
|
+
device_id = SMARTPHONE_DEV_IDS.sample
|
270
|
+
ua_platform = "Linux; #{platform_version}; #{device_id}"
|
271
|
+
end
|
272
|
+
os_cpu = "Linux #{OS_CPU['android'].sample}"
|
273
|
+
res = {
|
274
|
+
'platform_version' => platform_version,
|
275
|
+
'ua_platform' => ua_platform,
|
276
|
+
'platform' => os_cpu,
|
277
|
+
'os_cpu' => os_cpu
|
278
|
+
}
|
279
|
+
end
|
280
|
+
res
|
281
|
+
end
|
282
|
+
|
283
|
+
def build_app_components(os_id, navigator_id)
|
284
|
+
case navigator_id
|
285
|
+
when 'firefox'
|
286
|
+
build_version, build_id = firefox_build
|
287
|
+
gecko_trail = if %w[win linux mac].include? os_id
|
288
|
+
'20100101'
|
289
|
+
else
|
290
|
+
build_version
|
291
|
+
end
|
292
|
+
res = {
|
293
|
+
'name' => 'Netscape',
|
294
|
+
'product_sub' => '20100101',
|
295
|
+
'vendor' => '',
|
296
|
+
'build_version' => build_version,
|
297
|
+
'build_id' => build_id,
|
298
|
+
'gecko_trail' => gecko_trail
|
299
|
+
}
|
300
|
+
when 'chrome'
|
301
|
+
res = {
|
302
|
+
'name' => 'Netscape',
|
303
|
+
'product_sub' => '20030107',
|
304
|
+
'vendor' => 'Google Inc.',
|
305
|
+
'build_version' => chrome_build,
|
306
|
+
'build_id' => ''
|
307
|
+
}
|
308
|
+
when 'ie'
|
309
|
+
num_ver, build_version, trident_version = ie_build
|
310
|
+
app_name = if num_ver >= 11
|
311
|
+
'Netscape'
|
312
|
+
else
|
313
|
+
'Microsoft Internet Explorer'
|
314
|
+
end
|
315
|
+
res = {
|
316
|
+
'name' => app_name,
|
317
|
+
'product_sub' => '',
|
318
|
+
'vendor' => '',
|
319
|
+
'build_version' => build_version.to_s,
|
320
|
+
'build_id' => '',
|
321
|
+
'trident_version' => trident_version
|
322
|
+
}
|
323
|
+
end
|
324
|
+
res
|
325
|
+
end
|
326
|
+
|
327
|
+
def option_choices(opt_title, opt_value, default_value, all_choices)
|
328
|
+
choices = []
|
329
|
+
if opt_value.instance_of? String
|
330
|
+
choices = [opt_value]
|
331
|
+
elsif opt_value.instance_of? Array
|
332
|
+
choices = opt_value
|
333
|
+
elsif opt_value.nil?
|
334
|
+
choices = default_value
|
335
|
+
else
|
336
|
+
raise InvalidOption, "Option #{opt_title} has invalid value: #{opt_value}"
|
337
|
+
end
|
338
|
+
|
339
|
+
choices = all_choices if choices.include? 'all'
|
340
|
+
|
341
|
+
choices.each do |item|
|
342
|
+
raise InvalidOption, "Choices of option #{opt_title} contains invalid item: #{item}" unless all_choices.include? item
|
343
|
+
end
|
344
|
+
choices
|
345
|
+
end
|
346
|
+
|
347
|
+
def pick_config_ids(device_type, os, navigator)
|
348
|
+
default_dev_types = if os.nil?
|
349
|
+
['desktop']
|
350
|
+
else
|
351
|
+
DEVICE_TYPE_OS.keys
|
352
|
+
end
|
353
|
+
dev_type_choices = option_choices(
|
354
|
+
'device_type',
|
355
|
+
device_type,
|
356
|
+
default_dev_types,
|
357
|
+
DEVICE_TYPE_OS.keys
|
358
|
+
)
|
359
|
+
os_choices = option_choices(
|
360
|
+
'os',
|
361
|
+
os,
|
362
|
+
OS_NAVIGATOR.keys,
|
363
|
+
OS_NAVIGATOR.keys
|
364
|
+
)
|
365
|
+
navigator_choices = option_choices(
|
366
|
+
'navigator',
|
367
|
+
navigator,
|
368
|
+
NAVIGATOR_OS.keys,
|
369
|
+
NAVIGATOR_OS.keys
|
370
|
+
)
|
371
|
+
variants = []
|
372
|
+
|
373
|
+
prod = dev_type_choices.product(os_choices, navigator_choices)
|
374
|
+
prod.each do |dev, os_, nav|
|
375
|
+
if (DEVICE_TYPE_OS[dev].include? os_) && (DEVICE_TYPE_NAVIGATOR[dev].include? nav) && (OS_NAVIGATOR[os_].include? nav)
|
376
|
+
variants << [dev, os_, nav]
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
raise InvalidOption 'Options device_type, os and navigator conflicts with each other' if variants.nil?
|
381
|
+
|
382
|
+
device_type, os_id, navigator_id = variants.sample
|
383
|
+
|
384
|
+
raise InvalidOption, 'os_id not in OS_PLATFORM' unless OS_PLATFORM.include? os_id
|
385
|
+
raise InvalidOption, 'navigator_id not in NAVIGATOR_OS' unless NAVIGATOR_OS.include? navigator_id
|
386
|
+
raise InvalidOption, 'navigator_id not in DEVICE_TYPE_IDS' unless DEVICE_TYPE_OS.include? device_type
|
387
|
+
|
388
|
+
[device_type, os_id, navigator_id]
|
389
|
+
end
|
390
|
+
|
391
|
+
def choose_ua_template(device_type, navigator_id, app, sys)
|
392
|
+
tpl_name = navigator_id
|
393
|
+
case navigator_id
|
394
|
+
when 'ie'
|
395
|
+
tpl_name = if app['build_version'] == 'MSIE 11.0'
|
396
|
+
'ie_11'
|
397
|
+
else
|
398
|
+
'ie_less_11'
|
399
|
+
end
|
400
|
+
when 'chrome'
|
401
|
+
tpl_name = case device_type
|
402
|
+
when 'smartphone'
|
403
|
+
'chrome_smartphone'
|
404
|
+
when 'tablet'
|
405
|
+
'chrome_tablet'
|
406
|
+
else
|
407
|
+
'chrome'
|
408
|
+
end
|
409
|
+
end
|
410
|
+
user_agent_template(tpl_name, sys, app)
|
411
|
+
end
|
412
|
+
|
413
|
+
def build_navigator_app_version(os_id, navigator_id, platform_version, user_agent)
|
414
|
+
if %w[chrome ie].include? navigator_id
|
415
|
+
raise 'User agent doesn\'t start with "Mozilla/"' unless user_agent.to_s.start_with? 'Mozilla/'
|
416
|
+
|
417
|
+
app_version = user_agent.split('Mozilla/')[1]
|
418
|
+
elsif navigator_id == 'firefox'
|
419
|
+
if os_id == 'android'
|
420
|
+
app_version = "5.0 (#{platform_version})"
|
421
|
+
else
|
422
|
+
os_token = {
|
423
|
+
'win' => 'Windows',
|
424
|
+
'mac' => 'Macintosh',
|
425
|
+
'linux' => 'X11'
|
426
|
+
}[os_id]
|
427
|
+
app_version = "5.0 (#{os_token})"
|
428
|
+
end
|
429
|
+
end
|
430
|
+
app_version
|
431
|
+
end
|
432
|
+
|
433
|
+
def generate_navigator(os: nil, navigator: nil, platform: nil, device_type: nil)
|
434
|
+
unless platform.nil?
|
435
|
+
os = platform
|
436
|
+
warn('The `platform` version is deprecated. Use `os` option instead', uplevel: 3)
|
437
|
+
end
|
438
|
+
device_type, os_id, navigator_id = pick_config_ids(device_type, os, navigator)
|
439
|
+
sys = build_system_components(device_type, os_id, navigator_id)
|
440
|
+
app = build_app_components(os_id, navigator_id)
|
441
|
+
user_agent = choose_ua_template(device_type, navigator_id, app, sys)
|
442
|
+
app_version = build_navigator_app_version(
|
443
|
+
os_id, navigator_id, sys['platform_version'], user_agent
|
444
|
+
)
|
445
|
+
{
|
446
|
+
'os_id' => os_id,
|
447
|
+
'navigator_id' => navigator_id,
|
448
|
+
'platform' => sys['platform'],
|
449
|
+
'os_cpu' => sys['os_cpu'],
|
450
|
+
'build_version' => app['build_version'],
|
451
|
+
'build_id' => app['build_id'],
|
452
|
+
'app_version' => app_version,
|
453
|
+
'app_name' => app['name'],
|
454
|
+
'app_code_name' => 'Mozilla',
|
455
|
+
'product' => 'Gecko',
|
456
|
+
'product_sub' => app['product_sub'],
|
457
|
+
'vendor' => app['vendor'],
|
458
|
+
'vendor_sub' => '',
|
459
|
+
'user_agent' => user_agent
|
460
|
+
}
|
461
|
+
end
|
462
|
+
|
463
|
+
public
|
464
|
+
|
465
|
+
def generate_user_agent(os: nil, navigator: nil, platform: nil, device_type: nil)
|
466
|
+
generate_navigator(os: os, navigator: navigator, platform: platform, device_type: device_type)['user_agent']
|
467
|
+
end
|
468
|
+
|
469
|
+
def generate_navigator_js(os: nil, navigator: nil, platform: nil, device_type: nil)
|
470
|
+
config = generate_navigator(os: os, navigator: navigator, platform: platform, device_type: device_type)
|
471
|
+
{
|
472
|
+
'appCodeName' => config['app_code_name'],
|
473
|
+
'appName' => config['app_name'],
|
474
|
+
'appVersion' => config['app_version'],
|
475
|
+
'platform' => config['platform'],
|
476
|
+
'userAgent' => config['user_agent'],
|
477
|
+
'oscpu' => config['os_cpu'],
|
478
|
+
'product' => config['product'],
|
479
|
+
'productSub' => config['product_sub'],
|
480
|
+
'vendor' => config['vendor'],
|
481
|
+
'vendorSub' => config['vendor_sub'],
|
482
|
+
'buildID' => config['build_id']
|
483
|
+
}
|
484
|
+
end
|