gemini-webapi 1.11.0__tar.gz → 1.12.0__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.11.0 → gemini_webapi-1.12.0}/.github/workflows/pypi-publish.yml +1 -1
  2. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/PKG-INFO +1 -1
  3. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/client.py +56 -30
  4. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/constants.py +1 -0
  5. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/exceptions.py +16 -0
  6. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi.egg-info/PKG-INFO +1 -1
  7. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/.github/dependabot.yml +0 -0
  8. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/.github/workflows/github-release.yml +0 -0
  9. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/.gitignore +0 -0
  10. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/.vscode/launch.json +0 -0
  11. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/.vscode/settings.json +0 -0
  12. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/LICENSE +0 -0
  13. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/README.md +0 -0
  14. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/assets/banner.png +0 -0
  15. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/assets/favicon.png +0 -0
  16. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/assets/logo.svg +0 -0
  17. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/assets/sample.pdf +0 -0
  18. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/pyproject.toml +0 -0
  19. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/setup.cfg +0 -0
  20. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/__init__.py +0 -0
  21. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/types/__init__.py +0 -0
  22. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/types/candidate.py +0 -0
  23. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/types/image.py +0 -0
  24. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/types/modeloutput.py +0 -0
  25. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/utils/__init__.py +0 -0
  26. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/utils/get_access_token.py +0 -0
  27. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/utils/load_browser_cookies.py +0 -0
  28. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/utils/logger.py +0 -0
  29. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/utils/rotate_1psidts.py +0 -0
  30. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi/utils/upload_file.py +0 -0
  31. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi.egg-info/SOURCES.txt +0 -0
  32. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi.egg-info/dependency_links.txt +0 -0
  33. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi.egg-info/requires.txt +0 -0
  34. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/src/gemini_webapi.egg-info/top_level.txt +0 -0
  35. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/tests/test_client_features.py +0 -0
  36. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/tests/test_rotate_cookies.py +0 -0
  37. {gemini_webapi-1.11.0 → gemini_webapi-1.12.0}/tests/test_save_image.py +0 -0
@@ -52,7 +52,7 @@ jobs:
52
52
  id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
53
53
  steps:
54
54
  - name: Retrieve built artifacts
55
- uses: actions/download-artifact@v4.2.1
55
+ uses: actions/download-artifact@v4.3.0
56
56
  with:
57
57
  name: dist
58
58
  path: dist
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemini-webapi
3
- Version: 1.11.0
3
+ Version: 1.12.0
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
@@ -12,10 +12,12 @@ from .constants import Endpoint, ErrorCode, Headers, Model
12
12
  from .exceptions import (
13
13
  AuthError,
14
14
  APIError,
15
+ ImageGenerationError,
15
16
  TimeoutError,
16
17
  GeminiError,
17
18
  UsageLimitExceeded,
18
19
  ModelInvalid,
20
+ TemporarilyBlocked,
19
21
  )
20
22
  from .types import WebImage, GeneratedImage, Candidate, ModelOutput
21
23
  from .utils import (
@@ -61,10 +63,15 @@ def running(retry: int = 0) -> callable:
61
63
  )
62
64
  else:
63
65
  return await func(client, *args, **kwargs)
64
- except APIError:
66
+ except APIError as e:
67
+ # Image generation takes too long, only retry once
68
+ if isinstance(e, ImageGenerationError):
69
+ retry = min(1, retry)
70
+
65
71
  if retry > 0:
66
72
  await asyncio.sleep(1)
67
73
  return await wrapper(client, *args, retry=retry - 1, **kwargs)
74
+
68
75
  raise
69
76
 
70
77
  return wrapper
@@ -370,11 +377,12 @@ class GeminiClient:
370
377
  response_json = json.loads(response.text.split("\n")[2])
371
378
 
372
379
  body = None
373
- for part in response_json:
380
+ body_index = 0
381
+ for part_index, part in enumerate(response_json):
374
382
  try:
375
383
  main_part = json.loads(part[2])
376
384
  if main_part[4]:
377
- body = main_part
385
+ body_index, body = part_index, main_part
378
386
  break
379
387
  except (IndexError, TypeError, ValueError):
380
388
  continue
@@ -395,6 +403,10 @@ class GeminiClient:
395
403
  "Failed to generate contents. The specified model is not available. Please update gemini_webapi to the latest version. "
396
404
  "If the error persists and is caused by the package, please report it on GitHub."
397
405
  )
406
+ case ErrorCode.IP_TEMPORARILY_BLOCKED:
407
+ raise TemporarilyBlocked(
408
+ "Failed to generate contents. Your IP address is temporarily blocked by Google. Please try using a proxy or waiting for a while."
409
+ )
398
410
  case _:
399
411
  raise Exception
400
412
  except GeminiError:
@@ -407,7 +419,7 @@ class GeminiClient:
407
419
 
408
420
  try:
409
421
  candidates = []
410
- for i, candidate in enumerate(body[4]):
422
+ for candidate_index, candidate in enumerate(body[4]):
411
423
  text = candidate[1][0]
412
424
  if re.match(
413
425
  r"^http://googleusercontent\.com/card_content/\d+$", text
@@ -424,45 +436,59 @@ class GeminiClient:
424
436
  and candidate[12][1]
425
437
  and [
426
438
  WebImage(
427
- url=image[0][0][0],
428
- title=image[7][0],
429
- alt=image[0][4],
439
+ url=web_image[0][0][0],
440
+ title=web_image[7][0],
441
+ alt=web_image[0][4],
430
442
  proxy=self.proxy,
431
443
  )
432
- for image in candidate[12][1]
444
+ for web_image in candidate[12][1]
433
445
  ]
434
446
  or []
435
447
  )
436
448
 
437
449
  generated_images = []
438
450
  if candidate[12] and candidate[12][7] and candidate[12][7][0]:
439
- image_generation_body = json.loads(response_json[1][2])
440
- image_generation_candidate = image_generation_body[4][i]
451
+ img_body = None
452
+ for img_part_index, part in enumerate(response_json):
453
+ if img_part_index < body_index:
454
+ continue
455
+
456
+ try:
457
+ img_part = json.loads(part[2])
458
+ if img_part[4][candidate_index][12][7][0]:
459
+ img_body = img_part
460
+ break
461
+ except (IndexError, TypeError, ValueError):
462
+ continue
463
+
464
+ if not img_body:
465
+ raise ImageGenerationError(
466
+ "Failed to parse generated images. Please update gemini_webapi to the latest version. "
467
+ "If the error persists and is caused by the package, please report it on GitHub."
468
+ )
469
+
470
+ img_candidate = img_body[4][candidate_index]
471
+
441
472
  text = re.sub(
442
473
  r"http://googleusercontent\.com/image_generation_content/\d+$",
443
474
  "",
444
- image_generation_candidate[1][0],
475
+ img_candidate[1][0],
445
476
  ).rstrip()
446
477
 
447
- if (
448
- image_generation_candidate[12]
449
- and image_generation_candidate[12][7]
450
- and image_generation_candidate[12][7][0]
451
- ):
452
- generated_images = [
453
- GeneratedImage(
454
- url=image[0][3][3],
455
- title=f"[Generated Image {image[3][6]}]",
456
- alt=len(image[3][5]) > i
457
- and image[3][5][i]
458
- or image[3][5][0],
459
- proxy=self.proxy,
460
- cookies=self.cookies,
461
- )
462
- for i, image in enumerate(
463
- image_generation_candidate[12][7][0]
464
- )
465
- ]
478
+ generated_images = [
479
+ GeneratedImage(
480
+ url=generated_image[0][3][3],
481
+ title=f"[Generated Image {generated_image[3][6]}]",
482
+ alt=len(generated_image[3][5]) > image_index
483
+ and generated_image[3][5][image_index]
484
+ or generated_image[3][5][0],
485
+ proxy=self.proxy,
486
+ cookies=self.cookies,
487
+ )
488
+ for image_index, generated_image in enumerate(
489
+ img_candidate[12][7][0]
490
+ )
491
+ ]
466
492
 
467
493
  candidates.append(
468
494
  Candidate(
@@ -78,3 +78,4 @@ class ErrorCode(Enum):
78
78
 
79
79
  USAGE_LIMIT_EXCEEDED = 1037
80
80
  MODEL_HEADER_INVALID = 1052
81
+ IP_TEMPORARILY_BLOCKED = 1060
@@ -14,6 +14,14 @@ class APIError(Exception):
14
14
  pass
15
15
 
16
16
 
17
+ class ImageGenerationError(APIError):
18
+ """
19
+ Exception for generated image parsing errors.
20
+ """
21
+
22
+ pass
23
+
24
+
17
25
  class GeminiError(Exception):
18
26
  """
19
27
  Exception for errors returned from Gemini server which are not handled by the package.
@@ -44,3 +52,11 @@ class ModelInvalid(GeminiError):
44
52
  """
45
53
 
46
54
  pass
55
+
56
+
57
+ class TemporarilyBlocked(GeminiError):
58
+ """
59
+ Exception for 429 Too Many Requests when IP is temporarily blocked.
60
+ """
61
+
62
+ pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemini-webapi
3
- Version: 1.11.0
3
+ Version: 1.12.0
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
File without changes
File without changes
File without changes