gemini-webapi 1.8.1__tar.gz → 1.8.3__tar.gz

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.
Files changed (37) hide show
  1. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/.github/workflows/pypi-publish.yml +1 -1
  2. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/PKG-INFO +8 -6
  3. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/README.md +4 -2
  4. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/pyproject.toml +3 -3
  5. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/client.py +27 -15
  6. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/constants.py +10 -0
  7. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/types/image.py +1 -1
  8. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/utils/get_access_token.py +1 -0
  9. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/utils/rotate_1psidts.py +1 -1
  10. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/utils/upload_file.py +1 -1
  11. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi.egg-info/PKG-INFO +8 -6
  12. gemini_webapi-1.8.3/src/gemini_webapi.egg-info/requires.txt +3 -0
  13. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/tests/test_client_features.py +11 -1
  14. gemini_webapi-1.8.1/src/gemini_webapi.egg-info/requires.txt +0 -3
  15. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/.github/dependabot.yml +0 -0
  16. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/.github/workflows/github-release.yml +0 -0
  17. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/.gitignore +0 -0
  18. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/.vscode/launch.json +0 -0
  19. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/.vscode/settings.json +0 -0
  20. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/LICENSE +0 -0
  21. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/assets/banner.png +0 -0
  22. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/assets/favicon.png +0 -0
  23. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/assets/logo.svg +0 -0
  24. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/setup.cfg +0 -0
  25. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/__init__.py +0 -0
  26. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/exceptions.py +0 -0
  27. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/types/__init__.py +0 -0
  28. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/types/candidate.py +0 -0
  29. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/types/modeloutput.py +0 -0
  30. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/utils/__init__.py +0 -0
  31. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/utils/load_browser_cookies.py +0 -0
  32. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi/utils/logger.py +0 -0
  33. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi.egg-info/SOURCES.txt +0 -0
  34. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi.egg-info/dependency_links.txt +0 -0
  35. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/src/gemini_webapi.egg-info/top_level.txt +0 -0
  36. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/tests/test_rotate_cookies.py +0 -0
  37. {gemini_webapi-1.8.1 → gemini_webapi-1.8.3}/tests/test_save_image.py +0 -0
@@ -36,7 +36,7 @@ jobs:
36
36
  - name: Build package
37
37
  run: python -m build
38
38
  - name: Archive production artifacts
39
- uses: actions/upload-artifact@v4.5.0
39
+ uses: actions/upload-artifact@v4.6.0
40
40
  with:
41
41
  name: dist
42
42
  path: dist
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: gemini-webapi
3
- Version: 1.8.1
3
+ Version: 1.8.3
4
4
  Summary: ✨ An elegant async Python wrapper for Google Gemini web app
5
5
  Author: UZQueen
6
6
  License: GNU AFFERO GENERAL PUBLIC LICENSE
@@ -676,9 +676,9 @@ Classifier: Programming Language :: Python :: 3.12
676
676
  Requires-Python: >=3.10
677
677
  Description-Content-Type: text/markdown
678
678
  License-File: LICENSE
679
- Requires-Dist: httpx~=0.28.0
680
- Requires-Dist: pydantic~=2.10.2
681
- Requires-Dist: loguru~=0.7.2
679
+ Requires-Dist: httpx[http2]~=0.28.1
680
+ Requires-Dist: pydantic~=2.10.5
681
+ Requires-Dist: loguru~=0.7.3
682
682
 
683
683
  <p align="center">
684
684
  <img src="https://raw.githubusercontent.com/HanaokaYuzu/Gemini-API/master/assets/banner.png" width="55%" alt="Gemini Banner" align="center">
@@ -944,10 +944,12 @@ You can choose a specified language model version by passing `model` argument to
944
944
 
945
945
  Currently available models (as of Dec 21, 2024):
946
946
 
947
- - `unspecified` - Default model (Gemini 1.5 Flash)
947
+ - `unspecified` - Default model (Gemini 1.5 Pro if account has Gemini Advanced subscription, otherwise Gemini 1.5 Flash)
948
948
  - `gemini-1.5-flash` - Gemini 1.5 Flash
949
+ - `gemini-1.5-pro` - Gemini 1.5 Pro **(requires Gemini Advanced account)**
950
+ - `gemini-1.5-pro-research` - Gemini 1.5 Pro with Deep Research **(requires Gemini Advanced account)**
949
951
  - `gemini-2.0-flash-exp` - Gemini 2.0 Flash Experimental
950
- - `gemini-2.0-exp-advanced` - Gemini 2.0 Experimental Advanced (requires Gemini Advanced account)
952
+ - `gemini-2.0-exp-advanced` - Gemini 2.0 Experimental Advanced **(requires Gemini Advanced account)**
951
953
 
952
954
  ```python
953
955
  from gemini_webapi.constants import Model
@@ -262,10 +262,12 @@ You can choose a specified language model version by passing `model` argument to
262
262
 
263
263
  Currently available models (as of Dec 21, 2024):
264
264
 
265
- - `unspecified` - Default model (Gemini 1.5 Flash)
265
+ - `unspecified` - Default model (Gemini 1.5 Pro if account has Gemini Advanced subscription, otherwise Gemini 1.5 Flash)
266
266
  - `gemini-1.5-flash` - Gemini 1.5 Flash
267
+ - `gemini-1.5-pro` - Gemini 1.5 Pro **(requires Gemini Advanced account)**
268
+ - `gemini-1.5-pro-research` - Gemini 1.5 Pro with Deep Research **(requires Gemini Advanced account)**
267
269
  - `gemini-2.0-flash-exp` - Gemini 2.0 Flash Experimental
268
- - `gemini-2.0-exp-advanced` - Gemini 2.0 Experimental Advanced (requires Gemini Advanced account)
270
+ - `gemini-2.0-exp-advanced` - Gemini 2.0 Experimental Advanced **(requires Gemini Advanced account)**
269
271
 
270
272
  ```python
271
273
  from gemini_webapi.constants import Model
@@ -20,9 +20,9 @@ classifiers = [
20
20
  ]
21
21
  requires-python = ">=3.10"
22
22
  dependencies = [
23
- "httpx~=0.28.0",
24
- "pydantic~=2.10.2",
25
- "loguru~=0.7.2",
23
+ "httpx[http2]~=0.28.1",
24
+ "pydantic~=2.10.5",
25
+ "loguru~=0.7.3",
26
26
  ]
27
27
  dynamic = ["version"]
28
28
 
@@ -174,6 +174,7 @@ class GeminiClient:
174
174
  )
175
175
 
176
176
  self.client = AsyncClient(
177
+ http2=True,
177
178
  timeout=timeout,
178
179
  proxy=self.proxy,
179
180
  follow_redirects=True,
@@ -381,7 +382,7 @@ class GeminiClient:
381
382
  for i, candidate in enumerate(body[4]):
382
383
  text = candidate[1][0]
383
384
  if re.match(
384
- r"^http://googleusercontent.com/card_content/\d+$", text
385
+ r"^http://googleusercontent\.com/card_content/\d+$", text
385
386
  ):
386
387
  text = candidate[22] and candidate[22][0] or text
387
388
 
@@ -404,20 +405,31 @@ class GeminiClient:
404
405
  if candidate[12] and candidate[12][7] and candidate[12][7][0]:
405
406
  image_generation_body = json.loads(response_json[1][2])
406
407
  image_generation_candidate = image_generation_body[4][i]
407
- generated_images = [
408
- GeneratedImage(
409
- url=image[0][3][3],
410
- title=f"[Generated Image {image[3][6]}]",
411
- alt=len(image[3][5]) > i
412
- and image[3][5][i]
413
- or image[3][5][0],
414
- proxy=self.proxy,
415
- cookies=self.cookies,
416
- )
417
- for i, image in enumerate(
418
- image_generation_candidate[12][7][0]
419
- )
420
- ] or []
408
+ text = re.sub(
409
+ r"http://googleusercontent\.com/image_generation_content/\d+$",
410
+ "",
411
+ image_generation_candidate[1][0],
412
+ ).rstrip()
413
+
414
+ if (
415
+ image_generation_candidate[12]
416
+ and image_generation_candidate[12][7]
417
+ and image_generation_candidate[12][7][0]
418
+ ):
419
+ generated_images = [
420
+ GeneratedImage(
421
+ url=image[0][3][3],
422
+ title=f"[Generated Image {image[3][6]}]",
423
+ alt=len(image[3][5]) > i
424
+ and image[3][5][i]
425
+ or image[3][5][0],
426
+ proxy=self.proxy,
427
+ cookies=self.cookies,
428
+ )
429
+ for i, image in enumerate(
430
+ image_generation_candidate[12][7][0]
431
+ )
432
+ ]
421
433
 
422
434
  candidates.append(
423
435
  Candidate(
@@ -30,6 +30,16 @@ class Model(Enum):
30
30
  {"x-goog-ext-525001261-jspb": '[null,null,null,null,"7daceb7ef88130f5"]'},
31
31
  False,
32
32
  )
33
+ G_1_5_PRO = (
34
+ "gemini-1.5-pro",
35
+ {"x-goog-ext-525001261-jspb": '[null,null,null,null,"9d60dfae93c9ff1f"]'},
36
+ True,
37
+ )
38
+ G_1_5_PRO_RESEARCH = (
39
+ "gemini-1.5-pro-research",
40
+ {"x-goog-ext-525001261-jspb": '[null,null,null,null,"e5a44cb1dae2b489"]'},
41
+ True,
42
+ )
33
43
  G_2_0_FLASH_EXP = (
34
44
  "gemini-2.0-flash-exp",
35
45
  {"x-goog-ext-525001261-jspb": '[null,null,null,null,"948b866104ccf484"]'},
@@ -80,7 +80,7 @@ class Image(BaseModel):
80
80
  return None
81
81
 
82
82
  async with AsyncClient(
83
- follow_redirects=True, cookies=cookies, proxy=self.proxy
83
+ http2=True, follow_redirects=True, cookies=cookies, proxy=self.proxy
84
84
  ) as client:
85
85
  response = await client.get(self.url)
86
86
  if response.status_code == 200:
@@ -47,6 +47,7 @@ async def get_access_token(
47
47
 
48
48
  async def send_request(cookies: dict) -> tuple[Response | None, dict]:
49
49
  async with AsyncClient(
50
+ http2=True,
50
51
  proxy=proxy,
51
52
  headers=Headers.GEMINI.value,
52
53
  cookies=cookies,
@@ -39,7 +39,7 @@ async def rotate_1psidts(cookies: dict, proxy: str | None = None) -> str:
39
39
 
40
40
  # Check if the cache file was modified in the last minute to avoid 429 Too Many Requests
41
41
  if not (path.is_file() and time.time() - os.path.getmtime(path) <= 60):
42
- async with AsyncClient(proxy=proxy) as client:
42
+ async with AsyncClient(http2=True, proxy=proxy) as client:
43
43
  response = await client.post(
44
44
  url=Endpoint.ROTATE_COOKIES.value,
45
45
  headers=Headers.ROTATE_COOKIES.value,
@@ -34,7 +34,7 @@ async def upload_file(file: bytes | str | Path, proxy: str | None = None) -> str
34
34
  with open(file, "rb") as f:
35
35
  file = f.read()
36
36
 
37
- async with AsyncClient(proxy=proxy) as client:
37
+ async with AsyncClient(http2=True, proxy=proxy) as client:
38
38
  response = await client.post(
39
39
  url=Endpoint.UPLOAD.value,
40
40
  headers=Headers.UPLOAD.value,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: gemini-webapi
3
- Version: 1.8.1
3
+ Version: 1.8.3
4
4
  Summary: ✨ An elegant async Python wrapper for Google Gemini web app
5
5
  Author: UZQueen
6
6
  License: GNU AFFERO GENERAL PUBLIC LICENSE
@@ -676,9 +676,9 @@ Classifier: Programming Language :: Python :: 3.12
676
676
  Requires-Python: >=3.10
677
677
  Description-Content-Type: text/markdown
678
678
  License-File: LICENSE
679
- Requires-Dist: httpx~=0.28.0
680
- Requires-Dist: pydantic~=2.10.2
681
- Requires-Dist: loguru~=0.7.2
679
+ Requires-Dist: httpx[http2]~=0.28.1
680
+ Requires-Dist: pydantic~=2.10.5
681
+ Requires-Dist: loguru~=0.7.3
682
682
 
683
683
  <p align="center">
684
684
  <img src="https://raw.githubusercontent.com/HanaokaYuzu/Gemini-API/master/assets/banner.png" width="55%" alt="Gemini Banner" align="center">
@@ -944,10 +944,12 @@ You can choose a specified language model version by passing `model` argument to
944
944
 
945
945
  Currently available models (as of Dec 21, 2024):
946
946
 
947
- - `unspecified` - Default model (Gemini 1.5 Flash)
947
+ - `unspecified` - Default model (Gemini 1.5 Pro if account has Gemini Advanced subscription, otherwise Gemini 1.5 Flash)
948
948
  - `gemini-1.5-flash` - Gemini 1.5 Flash
949
+ - `gemini-1.5-pro` - Gemini 1.5 Pro **(requires Gemini Advanced account)**
950
+ - `gemini-1.5-pro-research` - Gemini 1.5 Pro with Deep Research **(requires Gemini Advanced account)**
949
951
  - `gemini-2.0-flash-exp` - Gemini 2.0 Flash Experimental
950
- - `gemini-2.0-exp-advanced` - Gemini 2.0 Experimental Advanced (requires Gemini Advanced account)
952
+ - `gemini-2.0-exp-advanced` - Gemini 2.0 Experimental Advanced **(requires Gemini Advanced account)**
951
953
 
952
954
  ```python
953
955
  from gemini_webapi.constants import Model
@@ -0,0 +1,3 @@
1
+ httpx[http2]~=0.28.1
2
+ pydantic~=2.10.5
3
+ loguru~=0.7.3
@@ -85,20 +85,30 @@ class TestGeminiClient(unittest.IsolatedAsyncioTestCase):
85
85
  "Send me some pictures of cats"
86
86
  )
87
87
  self.assertTrue(response.images)
88
+ logger.debug(response.text)
88
89
  for image in response.images:
89
90
  self.assertTrue(image.url)
90
91
  logger.debug(image)
91
92
 
92
93
  @logger.catch(reraise=True)
93
- async def test_ai_image_generation(self):
94
+ async def test_image_generation(self):
94
95
  response = await self.geminiclient.generate_content(
95
96
  "Generate some pictures of cats"
96
97
  )
97
98
  self.assertTrue(response.images)
99
+ logger.debug(response.text)
98
100
  for image in response.images:
99
101
  self.assertTrue(image.url)
100
102
  logger.debug(image)
101
103
 
104
+ @logger.catch(reraise=True)
105
+ async def test_image_generation_failure(self):
106
+ response = await self.geminiclient.generate_content(
107
+ "Generate some pictures of people"
108
+ )
109
+ self.assertFalse(response.images)
110
+ logger.debug(response.text)
111
+
102
112
  @logger.catch(reraise=True)
103
113
  async def test_card_content(self):
104
114
  response = await self.geminiclient.generate_content("How is today's weather?")
@@ -1,3 +0,0 @@
1
- httpx~=0.28.0
2
- pydantic~=2.10.2
3
- loguru~=0.7.2
File without changes
File without changes
File without changes