fake_useragent 1.0.0 → 1.0.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.
- checksums.yaml +4 -4
- data/README.md +4 -1
- data/fake_useragent.gemspec +1 -1
- data/lib/fake_useragent.rb +5 -464
- data/lib/fake_useragent/core.rb +487 -0
- data/spec/lib/test_fake_useragent.rb +14 -13
- metadata +2 -1
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: bd933e3718a55c3d9e4f3e8b81ea5e3b2dbbf06828e27771175301aff0a8e3dc
         | 
| 4 | 
            +
              data.tar.gz: 511210c1c989e109f825c49e6aa36fc7718d2ea9c934b4bad4faf78364e0b569
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 7a528955e7ecfdd44f28b319fee83e4e0b0e5e7af65436ee2aa6b5ee5c1b50d09ac2efea6384b01258213c5eca07076f91e69965cd575f2dad8377cda03a5961
         | 
| 7 | 
            +
              data.tar.gz: c1b06c2e6a42136fa8821fefbc90b6988a24e4c9e7b931cd529075c284729023dfee2cb6484ee35ba7182e08b3a91d629a724dc4157a1f48758cd168949aa318
         | 
    
        data/README.md
    CHANGED
    
    | @@ -3,8 +3,11 @@ | |
| 3 3 | 
             
            ## For what?
         | 
| 4 4 | 
             
            Generates random valid web user agents
         | 
| 5 5 |  | 
| 6 | 
            +
            ## Installation
         | 
| 7 | 
            +
            `gem install fake_useragent`
         | 
| 8 | 
            +
             | 
| 6 9 | 
             
            ## Usage example:
         | 
| 7 | 
            -
            This version just a test. You can use `generate_user_agent | 
| 10 | 
            +
            This version just a test. You can use `generate_user_agent`, or `generate_navigator_js`
         | 
| 8 11 |  | 
| 9 12 | 
             
            parameters: `os`, `navigator`, `device_type` and `platform` (deprecated)  
         | 
| 10 13 | 
             
            Possible values:  
         | 
    
        data/fake_useragent.gemspec
    CHANGED
    
    | @@ -2,7 +2,7 @@ $:.push File.expand_path("../lib", __FILE__) | |
| 2 2 |  | 
| 3 3 | 
             
            Gem::Specification.new do |s|
         | 
| 4 4 | 
             
              s.name = 'fake_useragent'
         | 
| 5 | 
            -
              s.version     = '1.0. | 
| 5 | 
            +
              s.version     = '1.0.2'
         | 
| 6 6 | 
             
              s.date        = '2021-04-17'
         | 
| 7 7 | 
             
              s.summary     = 'FakeUserAgent - simple gem for generating valid web user agents.'
         | 
| 8 8 | 
             
              s.description = 'Simple gem for generating valid web user agents.'
         | 
    
        data/lib/fake_useragent.rb
    CHANGED
    
    | @@ -1,473 +1,14 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require_relative './fake_useragent/core'
         | 
| 2 3 |  | 
| 3 | 
            -
             | 
| 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
         | 
| 4 | 
            +
            public 
         | 
| 464 5 |  | 
| 465 6 | 
             
            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']
         | 
| 7 | 
            +
              Core.generate_navigator(os: os, navigator: navigator, platform: platform, device_type: device_type)['user_agent']
         | 
| 467 8 | 
             
            end
         | 
| 468 9 |  | 
| 469 10 | 
             
            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)
         | 
| 11 | 
            +
              config = Core.generate_navigator(os: os, navigator: navigator, platform: platform, device_type: device_type)
         | 
| 471 12 | 
             
              {
         | 
| 472 13 | 
             
                'appCodeName' => config['app_code_name'],
         | 
| 473 14 | 
             
                'appName' => config['app_name'],
         | 
| @@ -481,4 +22,4 @@ def generate_navigator_js(os: nil, navigator: nil, platform: nil, device_type: n | |
| 481 22 | 
             
                'vendorSub' => config['vendor_sub'],
         | 
| 482 23 | 
             
                'buildID' => config['build_id']
         | 
| 483 24 | 
             
              }
         | 
| 484 | 
            -
            end
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,487 @@ | |
| 1 | 
            +
            require 'time'
         | 
| 2 | 
            +
            require 'json'
         | 
| 3 | 
            +
            require 'pp'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require_relative 'error'
         | 
| 6 | 
            +
            require_relative 'device'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            module Core
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              DEVICE_TYPE_OS = {
         | 
| 11 | 
            +
                'desktop' => %w[win mac linux],
         | 
| 12 | 
            +
                'smartphone' => ['android'],
         | 
| 13 | 
            +
                'tablet' => ['android']
         | 
| 14 | 
            +
              }.freeze
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              OS_DEVICE_TYPE = {
         | 
| 17 | 
            +
                'win' => ['desktop'],
         | 
| 18 | 
            +
                'linux' => ['desktop'],
         | 
| 19 | 
            +
                'mac' => ['desktop'],
         | 
| 20 | 
            +
                'android' => %w[smartphone tablet]
         | 
| 21 | 
            +
              }.freeze
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              DEVICE_TYPE_NAVIGATOR = {
         | 
| 24 | 
            +
                'desktop' => %w[chrome firefox ie],
         | 
| 25 | 
            +
                'smartphone' => %w[firefox chrome],
         | 
| 26 | 
            +
                'tablet' => %w[firefox chrome]
         | 
| 27 | 
            +
              }.freeze
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              NAVIGATOR_DEVICE_TYPE = {
         | 
| 30 | 
            +
                'ie' => ['desktop'],
         | 
| 31 | 
            +
                'chrome' => %w[desktop smartphone tablet],
         | 
| 32 | 
            +
                'firefox' => %w[desktop smartphone tablet]
         | 
| 33 | 
            +
              }.freeze
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              OS_PLATFORM = {
         | 
| 36 | 
            +
                'win' => [
         | 
| 37 | 
            +
                  'Windows NT 5.1', # Windows XP
         | 
| 38 | 
            +
                  'Windows NT 6.1', # Windows 7
         | 
| 39 | 
            +
                  'Windows NT 6.2', # Windows 8
         | 
| 40 | 
            +
                  'Windows NT 6.3', # Windows 8.1
         | 
| 41 | 
            +
                  'Windows NT 10.0' # Windows 10
         | 
| 42 | 
            +
                ],
         | 
| 43 | 
            +
                'mac' => [
         | 
| 44 | 
            +
                  'Macintosh; Intel Mac OS X 10.8',
         | 
| 45 | 
            +
                  'Macintosh; Intel Mac OS X 10.9',
         | 
| 46 | 
            +
                  'Macintosh; Intel Mac OS X 10.10',
         | 
| 47 | 
            +
                  'Macintosh; Intel Mac OS X 10.11',
         | 
| 48 | 
            +
                  'Macintosh; Intel Mac OS X 10.12'
         | 
| 49 | 
            +
                ],
         | 
| 50 | 
            +
                'linux' => [
         | 
| 51 | 
            +
                  'X11; Linux',
         | 
| 52 | 
            +
                  'X11; Ubuntu; Linux'
         | 
| 53 | 
            +
                ],
         | 
| 54 | 
            +
                'android' => [
         | 
| 55 | 
            +
                  'Android 4.4', # 2013-10-31
         | 
| 56 | 
            +
                  'Android 4.4.1', # 2013-12-05
         | 
| 57 | 
            +
                  'Android 4.4.2', # 2013-12-09
         | 
| 58 | 
            +
                  'Android 4.4.3', # 2014-06-02
         | 
| 59 | 
            +
                  'Android 4.4.4', # 2014-06-19
         | 
| 60 | 
            +
                  'Android 5.0', # 2014-11-12
         | 
| 61 | 
            +
                  'Android 5.0.1', # 2014-12-02
         | 
| 62 | 
            +
                  'Android 5.0.2', # 2014-12-19
         | 
| 63 | 
            +
                  'Android 5.1', # 2015-03-09
         | 
| 64 | 
            +
                  'Android 5.1.1', # 2015-04-21
         | 
| 65 | 
            +
                  'Android 6.0', # 2015-10-05
         | 
| 66 | 
            +
                  'Android 6.0.1', # 2015-12-07
         | 
| 67 | 
            +
                  'Android 7.0', # 2016-08-22
         | 
| 68 | 
            +
                  'Android 7.1', # 2016-10-04
         | 
| 69 | 
            +
                  'Android 7.1.1' # 2016-12-05
         | 
| 70 | 
            +
                ]
         | 
| 71 | 
            +
              }.freeze
         | 
| 72 | 
            +
             | 
| 73 | 
            +
              OS_CPU = {
         | 
| 74 | 
            +
                'win' => [
         | 
| 75 | 
            +
                  '', # 32bit
         | 
| 76 | 
            +
                  'Win64; x64', # 64bit
         | 
| 77 | 
            +
                  'WOW64' # 32bit process on 64bit system
         | 
| 78 | 
            +
                ],
         | 
| 79 | 
            +
                'linux' => [
         | 
| 80 | 
            +
                  'i686', # 32bit
         | 
| 81 | 
            +
                  'x86_64', # 64bit
         | 
| 82 | 
            +
                  'i686 on x86_64' # 32bit process on 64bit system
         | 
| 83 | 
            +
                ],
         | 
| 84 | 
            +
                'mac' => [
         | 
| 85 | 
            +
                  ''
         | 
| 86 | 
            +
                ],
         | 
| 87 | 
            +
                'android' => [
         | 
| 88 | 
            +
                  'armv7l', # 32bit
         | 
| 89 | 
            +
                  'armv8l' # 64bit
         | 
| 90 | 
            +
                ]
         | 
| 91 | 
            +
              }.freeze
         | 
| 92 | 
            +
             | 
| 93 | 
            +
              OS_NAVIGATOR = {
         | 
| 94 | 
            +
                'win' => %w[chrome firefox ie],
         | 
| 95 | 
            +
                'mac' => %w[firefox chrome],
         | 
| 96 | 
            +
                'linux' => %w[chrome firefox],
         | 
| 97 | 
            +
                'android' => %w[firefox chrome]
         | 
| 98 | 
            +
              }.freeze
         | 
| 99 | 
            +
             | 
| 100 | 
            +
              NAVIGATOR_OS = {
         | 
| 101 | 
            +
                'chrome' => %w[win linux mac android],
         | 
| 102 | 
            +
                'firefox' => %w[win linux mac android],
         | 
| 103 | 
            +
                'ie' => ['win']
         | 
| 104 | 
            +
              }.freeze
         | 
| 105 | 
            +
             | 
| 106 | 
            +
              FIREFOX_VERSION = [
         | 
| 107 | 
            +
                ['45.0', Time.new(2016, 3, 8)],
         | 
| 108 | 
            +
                ['46.0', Time.new(2016, 4, 26)],
         | 
| 109 | 
            +
                ['47.0', Time.new(2016, 6, 7)],
         | 
| 110 | 
            +
                ['48.0', Time.new(2016, 8, 2)],
         | 
| 111 | 
            +
                ['49.0', Time.new(2016, 9, 20)],
         | 
| 112 | 
            +
                ['50.0', Time.new(2016, 11, 15)],
         | 
| 113 | 
            +
                ['51.0', Time.new(2017, 1, 24)]
         | 
| 114 | 
            +
              ]
         | 
| 115 | 
            +
             | 
| 116 | 
            +
              CHROME_BUILD = '80.0.3987.132
         | 
| 117 | 
            +
            80.0.3987.149
         | 
| 118 | 
            +
            80.0.3987.99
         | 
| 119 | 
            +
            81.0.4044.117
         | 
| 120 | 
            +
            81.0.4044.138
         | 
| 121 | 
            +
            83.0.4103.101
         | 
| 122 | 
            +
            83.0.4103.106
         | 
| 123 | 
            +
            83.0.4103.96
         | 
| 124 | 
            +
            84.0.4147.105
         | 
| 125 | 
            +
            84.0.4147.111
         | 
| 126 | 
            +
            84.0.4147.125
         | 
| 127 | 
            +
            84.0.4147.135
         | 
| 128 | 
            +
            84.0.4147.89
         | 
| 129 | 
            +
            85.0.4183.101
         | 
| 130 | 
            +
            85.0.4183.102
         | 
| 131 | 
            +
            85.0.4183.120
         | 
| 132 | 
            +
            85.0.4183.121
         | 
| 133 | 
            +
            85.0.4183.127
         | 
| 134 | 
            +
            85.0.4183.81
         | 
| 135 | 
            +
            85.0.4183.83
         | 
| 136 | 
            +
            86.0.4240.110
         | 
| 137 | 
            +
            86.0.4240.111
         | 
| 138 | 
            +
            86.0.4240.114
         | 
| 139 | 
            +
            86.0.4240.183
         | 
| 140 | 
            +
            86.0.4240.185
         | 
| 141 | 
            +
            86.0.4240.75
         | 
| 142 | 
            +
            86.0.4240.78
         | 
| 143 | 
            +
            86.0.4240.80
         | 
| 144 | 
            +
            86.0.4240.96
         | 
| 145 | 
            +
            86.0.4240.99
         | 
| 146 | 
            +
            '.strip.split(/\n+/)
         | 
| 147 | 
            +
             | 
| 148 | 
            +
              IE_VERSION = [
         | 
| 149 | 
            +
                # [numeric ver, string ver, trident ver] # release year
         | 
| 150 | 
            +
                [8, 'MSIE 8.0', '4.0'], # 2009
         | 
| 151 | 
            +
                [9, 'MSIE 9.0', '5.0'], # 2011
         | 
| 152 | 
            +
                [10, 'MSIE 10.0', '6.0'], # 2012
         | 
| 153 | 
            +
                [11, 'MSIE 11.0', '7.0'] # 2013
         | 
| 154 | 
            +
              ].freeze
         | 
| 155 | 
            +
             | 
| 156 | 
            +
              MACOSX_CHROME_BUILD_RANGE = {
         | 
| 157 | 
            +
                # https://en.wikipedia.org/wiki/MacOS#Release_history
         | 
| 158 | 
            +
                '10.8' => [0, 8],
         | 
| 159 | 
            +
                '10.9' => [0, 5],
         | 
| 160 | 
            +
                '10.10' => [0, 5],
         | 
| 161 | 
            +
                '10.11' => [0, 6],
         | 
| 162 | 
            +
                '10.12' => [0, 2]
         | 
| 163 | 
            +
              }.freeze
         | 
| 164 | 
            +
             | 
| 165 | 
            +
              def self.user_agent_template(tpl_name, system, app)
         | 
| 166 | 
            +
                case tpl_name
         | 
| 167 | 
            +
                when 'firefox'
         | 
| 168 | 
            +
                  "Mozilla/5.0 (#{system['ua_platform']}; rv:#{app['build_version']}) Gecko/#{app['gecko_trail']} Firefox/#{app['build_version']}"
         | 
| 169 | 
            +
                when 'chrome'
         | 
| 170 | 
            +
                  "Mozilla/5.0 (#{system['ua_platform']}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/#{app['build_version']} Safari/537.36"
         | 
| 171 | 
            +
                when 'chrome_smartphone'
         | 
| 172 | 
            +
                  "Mozilla/5.0 (#{system['ua_platform']}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/#{app['build_version']} Mobile Safari/537.36"
         | 
| 173 | 
            +
                when 'chrome_tablet'
         | 
| 174 | 
            +
                  "Mozilla/5.0(#{system['ua_platform']}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/#{app['build_version']} Safari/537.36"
         | 
| 175 | 
            +
                when 'ie_less_11'
         | 
| 176 | 
            +
                  "Mozilla/5.0 (compatible; #{app['build_version']}; #{system['ua_platform']}; Trident/#{app['trident_version']})"
         | 
| 177 | 
            +
                when 'ie_11'
         | 
| 178 | 
            +
                  "Mozilla/5.0 (#{system['ua_platform']}; Trident/#{app['trident_version']}; rv:11.0) like Gecko"
         | 
| 179 | 
            +
                end
         | 
| 180 | 
            +
              end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
              def self.firefox_build
         | 
| 183 | 
            +
                firefox_ver = FIREFOX_VERSION.sample
         | 
| 184 | 
            +
                build_ver = firefox_ver[0]
         | 
| 185 | 
            +
                date_from = firefox_ver[1].to_i
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                begin
         | 
| 188 | 
            +
                  idx = FIREFOX_VERSION.index(firefox_ver)
         | 
| 189 | 
            +
                  date_to = FIREFOX_VERSION.fetch(idx + 1)[1].to_i
         | 
| 190 | 
            +
                rescue IndexError
         | 
| 191 | 
            +
                  date_to = date_from + 86_399
         | 
| 192 | 
            +
                end
         | 
| 193 | 
            +
                sec_range = date_to - date_from
         | 
| 194 | 
            +
                build_rnd_time = Time.at(date_from + rand(sec_range))
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                [build_ver, build_rnd_time.strftime('%Y%m%d%H%M%S')]
         | 
| 197 | 
            +
              end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
              def self.chrome_build
         | 
| 200 | 
            +
                CHROME_BUILD.sample
         | 
| 201 | 
            +
              end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
              def self.ie_build
         | 
| 204 | 
            +
                IE_VERSION.sample
         | 
| 205 | 
            +
              end
         | 
| 206 | 
            +
             | 
| 207 | 
            +
              def self.fix_chrome_mac_platform(platform)
         | 
| 208 | 
            +
                ver = platform.split('OS X ')[1]
         | 
| 209 | 
            +
                build_range = 0...MACOSX_CHROME_BUILD_RANGE[ver][1]
         | 
| 210 | 
            +
                build = rand(build_range)
         | 
| 211 | 
            +
                mac_version = "#{ver.sub('.', '_')}_#{build}"
         | 
| 212 | 
            +
             | 
| 213 | 
            +
                "Macintosh; Intel Mac OS X #{mac_version}"
         | 
| 214 | 
            +
              end
         | 
| 215 | 
            +
             | 
| 216 | 
            +
              def self.build_system_components(device_type, os_id, navigator_id)
         | 
| 217 | 
            +
                case os_id
         | 
| 218 | 
            +
                when 'win'
         | 
| 219 | 
            +
                  platform_version = OS_PLATFORM['win'].sample.to_s
         | 
| 220 | 
            +
                  cpu = OS_CPU['win'].sample
         | 
| 221 | 
            +
                  platform = if cpu
         | 
| 222 | 
            +
                               "#{platform_version}; #{cpu}"
         | 
| 223 | 
            +
                             else
         | 
| 224 | 
            +
                               platform_version.to_s
         | 
| 225 | 
            +
                             end
         | 
| 226 | 
            +
                  res = {
         | 
| 227 | 
            +
                    'platform_version' => platform_version,
         | 
| 228 | 
            +
                    'platform' => platform,
         | 
| 229 | 
            +
                    'ua_platform' => platform,
         | 
| 230 | 
            +
                    'os_cpu' => platform
         | 
| 231 | 
            +
                  }
         | 
| 232 | 
            +
                when 'linux'
         | 
| 233 | 
            +
                  cpu = OS_CPU['linux'].sample
         | 
| 234 | 
            +
                  platform_version = OS_PLATFORM['linux'].sample
         | 
| 235 | 
            +
                  platform = "#{platform_version}; #{cpu}"
         | 
| 236 | 
            +
                  res = {
         | 
| 237 | 
            +
                    'platform_version' => platform_version,
         | 
| 238 | 
            +
                    'platform' => platform,
         | 
| 239 | 
            +
                    'ua_platform' => platform,
         | 
| 240 | 
            +
                    'os_cpu' => "Linux #{cpu}"
         | 
| 241 | 
            +
                  }
         | 
| 242 | 
            +
                when 'mac'
         | 
| 243 | 
            +
                  cpu = OS_CPU['mac'].sample
         | 
| 244 | 
            +
                  platform_version = OS_PLATFORM['mac'].sample
         | 
| 245 | 
            +
                  platform = platform_version
         | 
| 246 | 
            +
                  platform = fix_chrome_mac_platform(platform) if navigator_id == 'chrome'
         | 
| 247 | 
            +
                  res = {
         | 
| 248 | 
            +
                    'platform_version' => platform_version.to_s,
         | 
| 249 | 
            +
                    'platform' => 'MacIntel',
         | 
| 250 | 
            +
                    'ua_platform' => platform.to_s,
         | 
| 251 | 
            +
                    'os_cpu' => "Intel Mac OS X #{platform.split(' ')[-1]}"
         | 
| 252 | 
            +
                  }
         | 
| 253 | 
            +
                when 'android'
         | 
| 254 | 
            +
                  raise "#{navigator_id} not firefox or chrome" unless %w[firefox chrome].include? navigator_id
         | 
| 255 | 
            +
                  raise "#{device_type} not smartphone or tablet" unless %w[smartphone tablet].include? device_type
         | 
| 256 | 
            +
             | 
| 257 | 
            +
                  platform_version = OS_PLATFORM['android'].sample
         | 
| 258 | 
            +
                  case navigator_id
         | 
| 259 | 
            +
                  when 'firefox'
         | 
| 260 | 
            +
                    case device_type
         | 
| 261 | 
            +
                    when 'smartphone'
         | 
| 262 | 
            +
                      ua_platform = "#{platform_version}; Mobile"
         | 
| 263 | 
            +
                    when 'tablet'
         | 
| 264 | 
            +
                      ua_platform = "#{platform_version}; Tablet"
         | 
| 265 | 
            +
                    end
         | 
| 266 | 
            +
                  when 'chrome'
         | 
| 267 | 
            +
                    device_id = SMARTPHONE_DEV_IDS.sample
         | 
| 268 | 
            +
                    ua_platform = "Linux; #{platform_version}; #{device_id}"
         | 
| 269 | 
            +
                  end
         | 
| 270 | 
            +
                  os_cpu = "Linux #{OS_CPU['android'].sample}"
         | 
| 271 | 
            +
                  res = {
         | 
| 272 | 
            +
                    'platform_version' => platform_version,
         | 
| 273 | 
            +
                    'ua_platform' => ua_platform,
         | 
| 274 | 
            +
                    'platform' => os_cpu,
         | 
| 275 | 
            +
                    'os_cpu' => os_cpu
         | 
| 276 | 
            +
                  }
         | 
| 277 | 
            +
                end
         | 
| 278 | 
            +
                res
         | 
| 279 | 
            +
              end
         | 
| 280 | 
            +
             | 
| 281 | 
            +
              def self.build_app_components(os_id, navigator_id)
         | 
| 282 | 
            +
                case navigator_id
         | 
| 283 | 
            +
                when 'firefox'
         | 
| 284 | 
            +
                  build_version, build_id = firefox_build
         | 
| 285 | 
            +
                  gecko_trail = if %w[win linux mac].include? os_id
         | 
| 286 | 
            +
                                  '20100101'
         | 
| 287 | 
            +
                                else
         | 
| 288 | 
            +
                                  build_version
         | 
| 289 | 
            +
                                end
         | 
| 290 | 
            +
                  res = {
         | 
| 291 | 
            +
                    'name' => 'Netscape',
         | 
| 292 | 
            +
                    'product_sub' => '20100101',
         | 
| 293 | 
            +
                    'vendor' => '',
         | 
| 294 | 
            +
                    'build_version' => build_version,
         | 
| 295 | 
            +
                    'build_id' => build_id,
         | 
| 296 | 
            +
                    'gecko_trail' => gecko_trail
         | 
| 297 | 
            +
                  }
         | 
| 298 | 
            +
                when 'chrome'
         | 
| 299 | 
            +
                  res = {
         | 
| 300 | 
            +
                    'name' => 'Netscape',
         | 
| 301 | 
            +
                    'product_sub' => '20030107',
         | 
| 302 | 
            +
                    'vendor' => 'Google Inc.',
         | 
| 303 | 
            +
                    'build_version' => chrome_build,
         | 
| 304 | 
            +
                    'build_id' => ''
         | 
| 305 | 
            +
                  }
         | 
| 306 | 
            +
                when 'ie'
         | 
| 307 | 
            +
                  num_ver, build_version, trident_version = ie_build
         | 
| 308 | 
            +
                  app_name = if num_ver >= 11
         | 
| 309 | 
            +
                               'Netscape'
         | 
| 310 | 
            +
                             else
         | 
| 311 | 
            +
                               'Microsoft Internet Explorer'
         | 
| 312 | 
            +
                             end
         | 
| 313 | 
            +
                  res = {
         | 
| 314 | 
            +
                    'name' => app_name,
         | 
| 315 | 
            +
                    'product_sub' => '',
         | 
| 316 | 
            +
                    'vendor' => '',
         | 
| 317 | 
            +
                    'build_version' => build_version.to_s,
         | 
| 318 | 
            +
                    'build_id' => '',
         | 
| 319 | 
            +
                    'trident_version' => trident_version
         | 
| 320 | 
            +
                  }
         | 
| 321 | 
            +
                end
         | 
| 322 | 
            +
                res
         | 
| 323 | 
            +
              end
         | 
| 324 | 
            +
             | 
| 325 | 
            +
              def self.option_choices(opt_title, opt_value, default_value, all_choices)
         | 
| 326 | 
            +
                choices = []
         | 
| 327 | 
            +
                if opt_value.instance_of? String
         | 
| 328 | 
            +
                  choices = [opt_value]
         | 
| 329 | 
            +
                elsif opt_value.instance_of? Array
         | 
| 330 | 
            +
                  choices = opt_value
         | 
| 331 | 
            +
                elsif opt_value.nil?
         | 
| 332 | 
            +
                  choices = default_value
         | 
| 333 | 
            +
                else
         | 
| 334 | 
            +
                  raise InvalidOption, "Option #{opt_title} has invalid value: #{opt_value}"
         | 
| 335 | 
            +
                end
         | 
| 336 | 
            +
             | 
| 337 | 
            +
                choices = all_choices if choices.include? 'all'
         | 
| 338 | 
            +
             | 
| 339 | 
            +
                choices.each do |item|
         | 
| 340 | 
            +
                  raise InvalidOption, "Choices of option #{opt_title} contains invalid item: #{item}" unless all_choices.include? item
         | 
| 341 | 
            +
                end
         | 
| 342 | 
            +
                choices
         | 
| 343 | 
            +
              end
         | 
| 344 | 
            +
             | 
| 345 | 
            +
              def self.pick_config_ids(device_type, os, navigator)
         | 
| 346 | 
            +
                default_dev_types = if os.nil?
         | 
| 347 | 
            +
                                      ['desktop']
         | 
| 348 | 
            +
                                    else
         | 
| 349 | 
            +
                                      DEVICE_TYPE_OS.keys
         | 
| 350 | 
            +
                                    end
         | 
| 351 | 
            +
                dev_type_choices = option_choices(
         | 
| 352 | 
            +
                  'device_type',
         | 
| 353 | 
            +
                  device_type,
         | 
| 354 | 
            +
                  default_dev_types,
         | 
| 355 | 
            +
                  DEVICE_TYPE_OS.keys
         | 
| 356 | 
            +
                )
         | 
| 357 | 
            +
                os_choices = option_choices(
         | 
| 358 | 
            +
                  'os',
         | 
| 359 | 
            +
                  os,
         | 
| 360 | 
            +
                  OS_NAVIGATOR.keys,
         | 
| 361 | 
            +
                  OS_NAVIGATOR.keys
         | 
| 362 | 
            +
                )
         | 
| 363 | 
            +
                navigator_choices = option_choices(
         | 
| 364 | 
            +
                  'navigator',
         | 
| 365 | 
            +
                  navigator,
         | 
| 366 | 
            +
                  NAVIGATOR_OS.keys,
         | 
| 367 | 
            +
                  NAVIGATOR_OS.keys
         | 
| 368 | 
            +
                )
         | 
| 369 | 
            +
                variants = []
         | 
| 370 | 
            +
             | 
| 371 | 
            +
                prod = dev_type_choices.product(os_choices, navigator_choices)
         | 
| 372 | 
            +
                prod.each do |dev, os_, nav|
         | 
| 373 | 
            +
                  if (DEVICE_TYPE_OS[dev].include? os_) && (DEVICE_TYPE_NAVIGATOR[dev].include? nav) && (OS_NAVIGATOR[os_].include? nav)
         | 
| 374 | 
            +
                    variants << [dev, os_, nav]
         | 
| 375 | 
            +
                  end
         | 
| 376 | 
            +
                end
         | 
| 377 | 
            +
             | 
| 378 | 
            +
                raise InvalidOption 'Options device_type, os and navigator conflicts with each other' if variants.nil?
         | 
| 379 | 
            +
             | 
| 380 | 
            +
                device_type, os_id, navigator_id = variants.sample
         | 
| 381 | 
            +
             | 
| 382 | 
            +
                raise InvalidOption, 'os_id not in OS_PLATFORM' unless OS_PLATFORM.include? os_id
         | 
| 383 | 
            +
                raise InvalidOption, 'navigator_id not in NAVIGATOR_OS' unless NAVIGATOR_OS.include? navigator_id
         | 
| 384 | 
            +
                raise InvalidOption, 'navigator_id not in DEVICE_TYPE_IDS' unless DEVICE_TYPE_OS.include? device_type
         | 
| 385 | 
            +
             | 
| 386 | 
            +
                [device_type, os_id, navigator_id]
         | 
| 387 | 
            +
              end
         | 
| 388 | 
            +
             | 
| 389 | 
            +
              def self.choose_ua_template(device_type, navigator_id, app, sys)
         | 
| 390 | 
            +
                tpl_name = navigator_id
         | 
| 391 | 
            +
                case navigator_id
         | 
| 392 | 
            +
                when 'ie'
         | 
| 393 | 
            +
                  tpl_name = if app['build_version'] == 'MSIE 11.0'
         | 
| 394 | 
            +
                               'ie_11'
         | 
| 395 | 
            +
                             else
         | 
| 396 | 
            +
                               'ie_less_11'
         | 
| 397 | 
            +
                             end
         | 
| 398 | 
            +
                when 'chrome'
         | 
| 399 | 
            +
                  tpl_name = case device_type
         | 
| 400 | 
            +
                             when 'smartphone'
         | 
| 401 | 
            +
                               'chrome_smartphone'
         | 
| 402 | 
            +
                             when 'tablet'
         | 
| 403 | 
            +
                               'chrome_tablet'
         | 
| 404 | 
            +
                             else
         | 
| 405 | 
            +
                               'chrome'
         | 
| 406 | 
            +
                             end
         | 
| 407 | 
            +
                end
         | 
| 408 | 
            +
                user_agent_template(tpl_name, sys, app)
         | 
| 409 | 
            +
              end
         | 
| 410 | 
            +
             | 
| 411 | 
            +
              def self.build_navigator_app_version(os_id, navigator_id, platform_version, user_agent)
         | 
| 412 | 
            +
                if %w[chrome ie].include? navigator_id
         | 
| 413 | 
            +
                  raise 'User agent doesn\'t start with "Mozilla/"' unless user_agent.to_s.start_with? 'Mozilla/'
         | 
| 414 | 
            +
             | 
| 415 | 
            +
                  app_version = user_agent.split('Mozilla/')[1]
         | 
| 416 | 
            +
                elsif navigator_id == 'firefox'
         | 
| 417 | 
            +
                  if os_id == 'android'
         | 
| 418 | 
            +
                    app_version = "5.0 (#{platform_version})"
         | 
| 419 | 
            +
                  else
         | 
| 420 | 
            +
                    os_token = {
         | 
| 421 | 
            +
                      'win' => 'Windows',
         | 
| 422 | 
            +
                      'mac' => 'Macintosh',
         | 
| 423 | 
            +
                      'linux' => 'X11'
         | 
| 424 | 
            +
                    }[os_id]
         | 
| 425 | 
            +
                    app_version = "5.0 (#{os_token})"
         | 
| 426 | 
            +
                  end
         | 
| 427 | 
            +
                end
         | 
| 428 | 
            +
                app_version
         | 
| 429 | 
            +
              end
         | 
| 430 | 
            +
             | 
| 431 | 
            +
              def self.generate_navigator(os: nil, navigator: nil, platform: nil, device_type: nil)
         | 
| 432 | 
            +
                unless platform.nil?
         | 
| 433 | 
            +
                  os = platform
         | 
| 434 | 
            +
                  warn('The `platform` version is deprecated. Use `os` option instead', uplevel: 3)
         | 
| 435 | 
            +
                end
         | 
| 436 | 
            +
                device_type, os_id, navigator_id = pick_config_ids(device_type, os, navigator)
         | 
| 437 | 
            +
                sys = build_system_components(device_type, os_id, navigator_id)
         | 
| 438 | 
            +
                app = build_app_components(os_id, navigator_id)
         | 
| 439 | 
            +
                user_agent = choose_ua_template(device_type, navigator_id, app, sys)
         | 
| 440 | 
            +
                app_version = build_navigator_app_version(
         | 
| 441 | 
            +
                  os_id, navigator_id, sys['platform_version'], user_agent
         | 
| 442 | 
            +
                )
         | 
| 443 | 
            +
                {
         | 
| 444 | 
            +
                  'os_id' => os_id,
         | 
| 445 | 
            +
                  'navigator_id' => navigator_id,
         | 
| 446 | 
            +
                  'platform' => sys['platform'],
         | 
| 447 | 
            +
                  'os_cpu' => sys['os_cpu'],
         | 
| 448 | 
            +
                  'build_version' => app['build_version'],
         | 
| 449 | 
            +
                  'build_id' => app['build_id'],
         | 
| 450 | 
            +
                  'app_version' => app_version,
         | 
| 451 | 
            +
                  'app_name' => app['name'],
         | 
| 452 | 
            +
                  'app_code_name' => 'Mozilla',
         | 
| 453 | 
            +
                  'product' => 'Gecko',
         | 
| 454 | 
            +
                  'product_sub' => app['product_sub'],
         | 
| 455 | 
            +
                  'vendor' => app['vendor'],
         | 
| 456 | 
            +
                  'vendor_sub' => '',
         | 
| 457 | 
            +
                  'user_agent' => user_agent
         | 
| 458 | 
            +
                }
         | 
| 459 | 
            +
              end
         | 
| 460 | 
            +
             | 
| 461 | 
            +
              private_class_method(
         | 
| 462 | 
            +
                :chrome_build,
         | 
| 463 | 
            +
                :user_agent_template,
         | 
| 464 | 
            +
                :build_navigator_app_version,
         | 
| 465 | 
            +
                :build_app_components,
         | 
| 466 | 
            +
                :build_system_components,
         | 
| 467 | 
            +
                :choose_ua_template,
         | 
| 468 | 
            +
                :pick_config_ids,
         | 
| 469 | 
            +
                :option_choices,
         | 
| 470 | 
            +
                :ie_build,
         | 
| 471 | 
            +
                :firefox_build,
         | 
| 472 | 
            +
                :fix_chrome_mac_platform
         | 
| 473 | 
            +
              )
         | 
| 474 | 
            +
              private_constant(
         | 
| 475 | 
            +
                :IE_VERSION,
         | 
| 476 | 
            +
                :DEVICE_TYPE_OS,
         | 
| 477 | 
            +
                :NAVIGATOR_OS,
         | 
| 478 | 
            +
                :OS_PLATFORM,
         | 
| 479 | 
            +
                :OS_NAVIGATOR,
         | 
| 480 | 
            +
                :DEVICE_TYPE_NAVIGATOR,
         | 
| 481 | 
            +
                :OS_CPU,
         | 
| 482 | 
            +
                :MACOSX_CHROME_BUILD_RANGE,
         | 
| 483 | 
            +
                :CHROME_BUILD,
         | 
| 484 | 
            +
                :NAVIGATOR_DEVICE_TYPE,
         | 
| 485 | 
            +
                :OS_DEVICE_TYPE
         | 
| 486 | 
            +
              )
         | 
| 487 | 
            +
            end
         | 
| @@ -2,6 +2,7 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            require 'minitest/autorun'
         | 
| 4 4 | 
             
            require './lib/fake_useragent'
         | 
| 5 | 
            +
            require './lib/fake_useragent/core'
         | 
| 5 6 | 
             
            require './lib/fake_useragent/error'
         | 
| 6 7 |  | 
| 7 8 | 
             
            class TestSuite < Minitest::Test
         | 
| @@ -94,7 +95,7 @@ class TestSuite < Minitest::Test | |
| 94 95 |  | 
| 95 96 | 
             
              def test_data_integrity
         | 
| 96 97 | 
             
                50.times do
         | 
| 97 | 
            -
                  navigator = generate_navigator
         | 
| 98 | 
            +
                  navigator = Core.generate_navigator
         | 
| 98 99 | 
             
                  navigator.each_value do |value|
         | 
| 99 100 | 
             
                    assert(value.nil? || (value.instance_of? String))
         | 
| 100 101 | 
             
                  end
         | 
| @@ -103,22 +104,22 @@ class TestSuite < Minitest::Test | |
| 103 104 |  | 
| 104 105 | 
             
              def test_feature_platform
         | 
| 105 106 | 
             
                50.times do
         | 
| 106 | 
            -
                  nav = generate_navigator(os: 'win')
         | 
| 107 | 
            +
                  nav = Core.generate_navigator(os: 'win')
         | 
| 107 108 | 
             
                  assert nav['platform'].include? 'Win'
         | 
| 108 | 
            -
                  nav = generate_navigator(os: 'linux')
         | 
| 109 | 
            +
                  nav = Core.generate_navigator(os: 'linux')
         | 
| 109 110 | 
             
                  assert nav['platform'].include? 'Linux'
         | 
| 110 | 
            -
                  nav = generate_navigator(os: 'mac')
         | 
| 111 | 
            +
                  nav = Core.generate_navigator(os: 'mac')
         | 
| 111 112 | 
             
                  assert nav['platform'].include? 'MacIntel'
         | 
| 112 113 | 
             
                end
         | 
| 113 114 | 
             
              end
         | 
| 114 115 |  | 
| 115 116 | 
             
              def test_feature_os_cpu
         | 
| 116 117 | 
             
                10.times do
         | 
| 117 | 
            -
                  nav = generate_navigator(os: 'win')
         | 
| 118 | 
            +
                  nav = Core.generate_navigator(os: 'win')
         | 
| 118 119 | 
             
                  assert nav['os_cpu'].include? 'Windows NT'
         | 
| 119 | 
            -
                  nav = generate_navigator(os: 'linux')
         | 
| 120 | 
            +
                  nav = Core.generate_navigator(os: 'linux')
         | 
| 120 121 | 
             
                  assert nav['os_cpu'].include? 'Linux'
         | 
| 121 | 
            -
                  nav = generate_navigator(os: 'mac')
         | 
| 122 | 
            +
                  nav = Core.generate_navigator(os: 'mac')
         | 
| 122 123 | 
             
                  assert nav['os_cpu'].include? 'Mac OS'
         | 
| 123 124 | 
             
                end
         | 
| 124 125 | 
             
              end
         | 
| @@ -152,22 +153,22 @@ class TestSuite < Minitest::Test | |
| 152 153 |  | 
| 153 154 | 
             
              def test_build_id_no_firefox
         | 
| 154 155 | 
             
                50.times do
         | 
| 155 | 
            -
                  nav = generate_navigator(navigator: 'chrome')
         | 
| 156 | 
            +
                  nav = Core.generate_navigator(navigator: 'chrome')
         | 
| 156 157 | 
             
                  assert nav['build_id'] == ''
         | 
| 157 | 
            -
                  nav = generate_navigator(navigator: 'ie')
         | 
| 158 | 
            +
                  nav = Core.generate_navigator(navigator: 'ie')
         | 
| 158 159 | 
             
                  assert nav['build_id'] == ''
         | 
| 159 160 | 
             
                end
         | 
| 160 161 | 
             
              end
         | 
| 161 162 |  | 
| 162 163 | 
             
              def test_build_id_firefox
         | 
| 163 | 
            -
                original_ff_version = FIREFOX_VERSION.clone
         | 
| 164 | 
            -
                FIREFOX_VERSION.replace [
         | 
| 164 | 
            +
                original_ff_version = Core::FIREFOX_VERSION.clone
         | 
| 165 | 
            +
                Core::FIREFOX_VERSION.replace [
         | 
| 165 166 | 
             
                  ['49.0', Time.new(2016, 9, 20)],
         | 
| 166 167 | 
             
                  ['50.0', Time.new(2016, 11, 15)]
         | 
| 167 168 | 
             
                ].freeze
         | 
| 168 169 | 
             
                begin
         | 
| 169 170 | 
             
                  50.times do
         | 
| 170 | 
            -
                    nav = generate_navigator(navigator: 'firefox')
         | 
| 171 | 
            +
                    nav = Core.generate_navigator(navigator: 'firefox')
         | 
| 171 172 | 
             
                    assert nav['build_id'].length == 14
         | 
| 172 173 | 
             
                    if nav['user_agent'].include? '50.0'
         | 
| 173 174 | 
             
                      assert nav['build_id'].start_with? '20161115'
         | 
| @@ -177,7 +178,7 @@ class TestSuite < Minitest::Test | |
| 177 178 | 
             
                    end
         | 
| 178 179 | 
             
                  end
         | 
| 179 180 | 
             
                ensure
         | 
| 180 | 
            -
                  FIREFOX_VERSION.replace original_ff_version
         | 
| 181 | 
            +
                  Core::FIREFOX_VERSION.replace original_ff_version
         | 
| 181 182 | 
             
                end
         | 
| 182 183 | 
             
              end
         | 
| 183 184 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: fake_useragent
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.0. | 
| 4 | 
            +
              version: 1.0.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Bokanov Alexander
         | 
| @@ -24,6 +24,7 @@ files: | |
| 24 24 | 
             
            - Rakefile
         | 
| 25 25 | 
             
            - fake_useragent.gemspec
         | 
| 26 26 | 
             
            - lib/fake_useragent.rb
         | 
| 27 | 
            +
            - lib/fake_useragent/core.rb
         | 
| 27 28 | 
             
            - lib/fake_useragent/data/smartphone_dev_ext.json
         | 
| 28 29 | 
             
            - lib/fake_useragent/data/smartphone_dev_id.json
         | 
| 29 30 | 
             
            - lib/fake_useragent/data/tablet_dev_ext.json
         |