From 100525e316aaed4b9a7b06b981cf6cec6e7d3146 Mon Sep 17 00:00:00 2001 From: iamdual Date: Sat, 9 Mar 2024 22:37:22 +0300 Subject: [PATCH 1/3] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98c5ce3..1ec8e84 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ device = ('desktop', 'mobile') platform = ('windows', 'macos', 'ios', 'linux', 'android') browser = ('chrome', 'edge', 'firefox', 'safari') ``` -All of the parameters are optional, and the types can be set multiple times by using a tuple.* +*All of the parameters are optional, and the types can be set multiple times by using a tuple.* ## Customized user-agent generation: ```python From 5cf47140c55e27906b66154bb6cd66b7e048e086 Mon Sep 17 00:00:00 2001 From: iamdual Date: Sun, 10 Mar 2024 11:34:01 +0300 Subject: [PATCH 2/3] client hints: bitness and architecture --- src/ua_generator/client_hints.py | 25 +++++++++++++++++++++- src/ua_generator/data/platforms/windows.py | 2 +- src/ua_generator/headers.py | 13 +++++++++-- tests/test_client_hints.py | 19 ++++++++++++++++ tests/test_headers.py | 21 ++++++++++++++++++ 5 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/ua_generator/client_hints.py b/src/ua_generator/client_hints.py index b73ff5c..60d4e66 100644 --- a/src/ua_generator/client_hints.py +++ b/src/ua_generator/client_hints.py @@ -3,7 +3,7 @@ Copyright: 2022-2024 Ekin Karadeniz (github.com/iamdual) License: Apache License 2.0 """ -from . import formats, serialization +from . import formats, serialization, utils from .data import platforms_mobile from .data import generator @@ -17,6 +17,8 @@ class ClientHints: platform_version: str brands: str brands_full_version_list: str + bitness: str + architecture: str def __init__(self, gen: generator.Generator): self.__generator = gen @@ -38,6 +40,9 @@ def __platform(self): return platform def __platform_version(self): + if self.__generator.platform == 'windows' and formats.major_version(self.__generator.platform_version) == '10': + return utils.choice(('10.0.0', '13.0.0')) + return formats.version(self.__generator.platform_version) def __brands(self, full_version_list: bool = False): @@ -57,6 +62,20 @@ def __brands(self, full_version_list: bool = False): return brand_list + def __bitness(self): + if self.__generator.platform == 'android': + return utils.choice(('32', '64', '32', '32')) + + return '64' + + def __architecture(self): + if self.__generator.platform == 'android' or self.__generator.platform == 'ios': + return 'arm' + elif self.__generator.platform == 'macos': + return utils.choice(('arm', 'x86', 'arm', 'arm')) + + return 'x86' + def __getattr__(self, name): if name in self.__cache: return self.__cache[name] @@ -71,6 +90,10 @@ def __getattr__(self, name): self.__cache[name] = serialization.ch_brand_list(self.__brands()) elif name == 'brands_full_version_list': self.__cache[name] = serialization.ch_brand_list(self.__brands(full_version_list=True)) + elif name == 'bitness': + self.__cache[name] = serialization.ch_string(self.__bitness()) + elif name == 'architecture': + self.__cache[name] = serialization.ch_string(self.__architecture()) return self.__cache[name] diff --git a/src/ua_generator/data/platforms/windows.py b/src/ua_generator/data/platforms/windows.py index e4b4cac..b5761cb 100644 --- a/src/ua_generator/data/platforms/windows.py +++ b/src/ua_generator/data/platforms/windows.py @@ -14,4 +14,4 @@ def get_version(): - return {'major': random.choice(versions)} + return {'major': random.choice(versions), 'minor': '0'} diff --git a/src/ua_generator/headers.py b/src/ua_generator/headers.py index 118a852..7aebe1a 100644 --- a/src/ua_generator/headers.py +++ b/src/ua_generator/headers.py @@ -13,8 +13,12 @@ class Headers: def __init__(self, gen: Generator, ch: ClientHints): self.__generator = gen self.__client_hints = ch + self.__headers = {} + self.reset() + + def reset(self): self.__headers = { - 'user-agent': gen.user_agent, + 'user-agent': self.__generator.user_agent, } # https://developer.mozilla.org/en-US/docs/Web/HTTP/Client_hints#low_entropy_hints @@ -28,17 +32,22 @@ def add(self, key: str): self.__headers[key] = self.__client_hints.brands elif key == 'sec-ch-ua-full-version-list': self.__headers[key] = self.__client_hints.brands_full_version_list - if key == 'sec-ch-ua-platform': + elif key == 'sec-ch-ua-platform': self.__headers[key] = self.__client_hints.platform elif key == 'sec-ch-ua-platform-version': self.__headers[key] = self.__client_hints.platform_version elif key == 'sec-ch-ua-mobile': self.__headers[key] = self.__client_hints.mobile + elif key == 'sec-ch-ua-bitness': + self.__headers[key] = self.__client_hints.bitness + elif key == 'sec-ch-ua-arch': + self.__headers[key] = self.__client_hints.architecture def accept_ch(self, val: str): if self.__generator.browser not in ('chrome', 'edge'): return + self.reset() requested_hints = val.split(',') for hint in requested_hints: self.add(hint.strip().lower()) diff --git a/tests/test_client_hints.py b/tests/test_client_hints.py index 8ef32ca..ee933b7 100644 --- a/tests/test_client_hints.py +++ b/tests/test_client_hints.py @@ -28,6 +28,13 @@ def test_ch_platform_version(self): self.assertTrue(type(ua.ch.platform_version) is str) self.assertTrue(len(ua.ch.platform_version) > 0) + def test_ch_platform_version_windows(self): + for i in range(0, 100): + ua = ua_generator.generate(platform='windows') + self.assertIsNotNone(ua.ch) + self.assertTrue(type(ua.ch.platform_version) is str) + self.assertEqual(len(ua.ch.platform_version.split('.')), 3) + def test_ch_mobile(self): for i in range(0, 100): ua = ua_generator.generate(browser=('chrome', 'edge'), platform='android') @@ -56,6 +63,18 @@ def test_ch_brands_full_version_list(self): self.assertTrue('Chromium' in ua.ch.brands_full_version_list) self.assertTrue('Microsoft Edge' in ua.ch.brands_full_version_list) + def test_ch_bitness(self): + for i in range(0, 100): + ua = ua_generator.generate(browser=('chrome', 'edge')) + self.assertIsNotNone(ua.ch) + self.assertIn(ua.ch.bitness, ('"32"', '"64"')) + + def test_ch_architecture(self): + for i in range(0, 100): + ua = ua_generator.generate(browser=('chrome', 'edge')) + self.assertIsNotNone(ua.ch) + self.assertIn(ua.ch.architecture, ('"arm"', '"x86"')) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_headers.py b/tests/test_headers.py index e595878..002f2e1 100644 --- a/tests/test_headers.py +++ b/tests/test_headers.py @@ -34,10 +34,31 @@ def test_client_hints_not_exists(self): def test_accept_ch(self): for i in range(0, 100): ua = ua_generator.generate(browser=('chrome', 'edge')) + ua.headers.accept_ch('Sec-CH-UA-Platform-Version, Sec-CH-UA-Full-Version-List') self.assertTrue('sec-ch-ua-platform-version' in ua.headers.get()) self.assertTrue('sec-ch-ua-full-version-list' in ua.headers.get()) + ua.headers.accept_ch('Sec-CH-UA-Bitness, Sec-CH-UA-Arch') + self.assertTrue('sec-ch-ua-bitness' in ua.headers.get()) + self.assertTrue('sec-ch-ua-arch' in ua.headers.get()) + self.assertFalse('sec-ch-ua-platform-version' in ua.headers.get()) + self.assertFalse('sec-ch-ua-full-version-list' in ua.headers.get()) + + def test_reset(self): + for i in range(0, 100): + ua = ua_generator.generate(browser=('chrome', 'edge')) + + ua.headers.add('sec-ch-ua-bitness') + self.assertTrue('user-agent' in ua.headers.get()) + self.assertTrue('sec-ch-ua' in ua.headers.get()) + self.assertTrue('sec-ch-ua-bitness' in ua.headers.get()) + + ua.headers.reset() + self.assertTrue('user-agent' in ua.headers.get()) + self.assertTrue('sec-ch-ua' in ua.headers.get()) + self.assertFalse('sec-ch-ua-bitness' in ua.headers.get()) + def test_accept_ch_not_exists(self): for i in range(0, 100): ua = ua_generator.generate(browser=('chrome', 'edge')) From 802b0d22e0ae99e6ede818f2e0f245f4319d1a95 Mon Sep 17 00:00:00 2001 From: iamdual Date: Sun, 10 Mar 2024 11:36:25 +0300 Subject: [PATCH 3/3] bump version --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index df12024..5a5be82 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = ua-generator -version = 0.3.0 +version = 0.4.0 author = Ekin Karadeniz author_email = iamdual@icloud.com description = A random user-agent generator