gemini-webapi 1.16.0__py3-none-any.whl → 1.17.0__py3-none-any.whl
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.
- gemini_webapi/client.py +123 -83
- gemini_webapi/constants.py +6 -11
- gemini_webapi/utils/__init__.py +3 -2
- gemini_webapi/utils/parsing.py +79 -0
- {gemini_webapi-1.16.0.dist-info → gemini_webapi-1.17.0.dist-info}/METADATA +4 -8
- {gemini_webapi-1.16.0.dist-info → gemini_webapi-1.17.0.dist-info}/RECORD +9 -8
- {gemini_webapi-1.16.0.dist-info → gemini_webapi-1.17.0.dist-info}/WHEEL +0 -0
- {gemini_webapi-1.16.0.dist-info → gemini_webapi-1.17.0.dist-info}/licenses/LICENSE +0 -0
- {gemini_webapi-1.16.0.dist-info → gemini_webapi-1.17.0.dist-info}/top_level.txt +0 -0
gemini_webapi/client.py
CHANGED
|
@@ -10,31 +10,33 @@ from httpx import AsyncClient, ReadTimeout, Response
|
|
|
10
10
|
from .components import GemMixin
|
|
11
11
|
from .constants import Endpoint, ErrorCode, Headers, Model
|
|
12
12
|
from .exceptions import (
|
|
13
|
-
AuthError,
|
|
14
13
|
APIError,
|
|
15
|
-
|
|
16
|
-
TimeoutError,
|
|
14
|
+
AuthError,
|
|
17
15
|
GeminiError,
|
|
18
|
-
|
|
16
|
+
ImageGenerationError,
|
|
19
17
|
ModelInvalid,
|
|
20
18
|
TemporarilyBlocked,
|
|
19
|
+
TimeoutError,
|
|
20
|
+
UsageLimitExceeded,
|
|
21
21
|
)
|
|
22
22
|
from .types import (
|
|
23
|
-
WebImage,
|
|
24
|
-
GeneratedImage,
|
|
25
23
|
Candidate,
|
|
26
|
-
ModelOutput,
|
|
27
24
|
Gem,
|
|
25
|
+
GeneratedImage,
|
|
26
|
+
ModelOutput,
|
|
28
27
|
RPCData,
|
|
28
|
+
WebImage,
|
|
29
29
|
)
|
|
30
30
|
from .utils import (
|
|
31
|
-
|
|
31
|
+
extract_json_from_response,
|
|
32
|
+
get_access_token,
|
|
33
|
+
get_nested_value,
|
|
34
|
+
logger,
|
|
32
35
|
parse_file_name,
|
|
33
36
|
rotate_1psidts,
|
|
34
|
-
get_access_token,
|
|
35
|
-
running,
|
|
36
37
|
rotate_tasks,
|
|
37
|
-
|
|
38
|
+
running,
|
|
39
|
+
upload_file,
|
|
38
40
|
)
|
|
39
41
|
|
|
40
42
|
|
|
@@ -42,7 +44,7 @@ class GeminiClient(GemMixin):
|
|
|
42
44
|
"""
|
|
43
45
|
Async httpx client interface for gemini.google.com.
|
|
44
46
|
|
|
45
|
-
`secure_1psid` must be provided unless the optional dependency `browser-cookie3` is installed and
|
|
47
|
+
`secure_1psid` must be provided unless the optional dependency `browser-cookie3` is installed, and
|
|
46
48
|
you have logged in to google.com in your local browser.
|
|
47
49
|
|
|
48
50
|
Parameters
|
|
@@ -203,6 +205,7 @@ class GeminiClient(GemMixin):
|
|
|
203
205
|
if self.close_task:
|
|
204
206
|
self.close_task.cancel()
|
|
205
207
|
self.close_task = None
|
|
208
|
+
|
|
206
209
|
self.close_task = asyncio.create_task(self.close(self.close_delay))
|
|
207
210
|
|
|
208
211
|
async def start_auto_refresh(self) -> None:
|
|
@@ -211,18 +214,25 @@ class GeminiClient(GemMixin):
|
|
|
211
214
|
"""
|
|
212
215
|
|
|
213
216
|
while True:
|
|
217
|
+
new_1psidts: str | None = None
|
|
214
218
|
try:
|
|
215
219
|
new_1psidts = await rotate_1psidts(self.cookies, self.proxy)
|
|
216
220
|
except AuthError:
|
|
217
|
-
if task := rotate_tasks.get(self.cookies
|
|
221
|
+
if task := rotate_tasks.get(self.cookies.get("__Secure-1PSID", "")):
|
|
218
222
|
task.cancel()
|
|
219
223
|
logger.warning(
|
|
220
|
-
"Failed to refresh cookies.
|
|
224
|
+
"AuthError: Failed to refresh cookies. Auto refresh task canceled."
|
|
221
225
|
)
|
|
226
|
+
return
|
|
227
|
+
except Exception as exc:
|
|
228
|
+
logger.warning(f"Unexpected error while refreshing cookies: {exc}")
|
|
222
229
|
|
|
223
|
-
logger.debug(f"Cookies refreshed. New __Secure-1PSIDTS: {new_1psidts}")
|
|
224
230
|
if new_1psidts:
|
|
225
231
|
self.cookies["__Secure-1PSIDTS"] = new_1psidts
|
|
232
|
+
if self.running:
|
|
233
|
+
self.client.cookies.set("__Secure-1PSIDTS", new_1psidts)
|
|
234
|
+
logger.debug("Cookies refreshed. New __Secure-1PSIDTS applied.")
|
|
235
|
+
|
|
226
236
|
await asyncio.sleep(self.refresh_interval)
|
|
227
237
|
|
|
228
238
|
@running(retry=2)
|
|
@@ -335,18 +345,24 @@ class GeminiClient(GemMixin):
|
|
|
335
345
|
f"Failed to generate contents. Request failed with status code {response.status_code}"
|
|
336
346
|
)
|
|
337
347
|
else:
|
|
348
|
+
response_json: list[Any] = []
|
|
349
|
+
body: list[Any] = []
|
|
350
|
+
body_index = 0
|
|
351
|
+
|
|
338
352
|
try:
|
|
339
|
-
response_json =
|
|
353
|
+
response_json = extract_json_from_response(response.text)
|
|
340
354
|
|
|
341
|
-
body = None
|
|
342
|
-
body_index = 0
|
|
343
355
|
for part_index, part in enumerate(response_json):
|
|
344
356
|
try:
|
|
345
|
-
|
|
346
|
-
if
|
|
347
|
-
|
|
357
|
+
part_body = get_nested_value(part, [2])
|
|
358
|
+
if not part_body:
|
|
359
|
+
continue
|
|
360
|
+
|
|
361
|
+
part_json = json.loads(part_body)
|
|
362
|
+
if get_nested_value(part_json, [4]):
|
|
363
|
+
body_index, body = part_index, part_json
|
|
348
364
|
break
|
|
349
|
-
except (
|
|
365
|
+
except (TypeError, ValueError):
|
|
350
366
|
continue
|
|
351
367
|
|
|
352
368
|
if not body:
|
|
@@ -355,7 +371,8 @@ class GeminiClient(GemMixin):
|
|
|
355
371
|
await self.close()
|
|
356
372
|
|
|
357
373
|
try:
|
|
358
|
-
|
|
374
|
+
error_code = get_nested_value(response_json, [0, 5, 2, 0, 1, 0], -1)
|
|
375
|
+
match ErrorCode(error_code):
|
|
359
376
|
case ErrorCode.USAGE_LIMIT_EXCEEDED:
|
|
360
377
|
raise UsageLimitExceeded(
|
|
361
378
|
f"Failed to generate contents. Usage limit of {model.model_name} model has exceeded. Please try switching to another model."
|
|
@@ -385,44 +402,51 @@ class GeminiClient(GemMixin):
|
|
|
385
402
|
)
|
|
386
403
|
|
|
387
404
|
try:
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
405
|
+
candidate_list: list[Any] = get_nested_value(body, [4], [])
|
|
406
|
+
output_candidates: list[Candidate] = []
|
|
407
|
+
|
|
408
|
+
for candidate_index, candidate in enumerate(candidate_list):
|
|
409
|
+
rcid = get_nested_value(candidate, [0])
|
|
410
|
+
if not rcid:
|
|
411
|
+
continue # Skip candidate if it has no rcid
|
|
412
|
+
|
|
413
|
+
# Text output and thoughts
|
|
414
|
+
text = get_nested_value(candidate, [1, 0], "")
|
|
391
415
|
if re.match(
|
|
392
416
|
r"^http://googleusercontent\.com/card_content/\d+", text
|
|
393
417
|
):
|
|
394
|
-
text = candidate[22
|
|
418
|
+
text = get_nested_value(candidate, [22, 0]) or text
|
|
395
419
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
420
|
+
thoughts = get_nested_value(candidate, [37, 0, 0])
|
|
421
|
+
|
|
422
|
+
# Web images
|
|
423
|
+
web_images = []
|
|
424
|
+
for web_img_data in get_nested_value(candidate, [12, 1], []):
|
|
425
|
+
url = get_nested_value(web_img_data, [0, 0, 0])
|
|
426
|
+
if not url:
|
|
427
|
+
continue
|
|
428
|
+
|
|
429
|
+
web_images.append(
|
|
405
430
|
WebImage(
|
|
406
|
-
url=
|
|
407
|
-
title=
|
|
408
|
-
alt=
|
|
431
|
+
url=url,
|
|
432
|
+
title=get_nested_value(web_img_data, [7, 0], ""),
|
|
433
|
+
alt=get_nested_value(web_img_data, [0, 4], ""),
|
|
409
434
|
proxy=self.proxy,
|
|
410
435
|
)
|
|
411
|
-
|
|
412
|
-
]
|
|
413
|
-
or []
|
|
414
|
-
)
|
|
436
|
+
)
|
|
415
437
|
|
|
438
|
+
# Generated images
|
|
416
439
|
generated_images = []
|
|
417
|
-
if candidate[12
|
|
440
|
+
if get_nested_value(candidate, [12, 7, 0]):
|
|
418
441
|
img_body = None
|
|
419
442
|
for img_part_index, part in enumerate(response_json):
|
|
420
443
|
if img_part_index < body_index:
|
|
421
444
|
continue
|
|
422
|
-
|
|
423
445
|
try:
|
|
424
446
|
img_part = json.loads(part[2])
|
|
425
|
-
if
|
|
447
|
+
if get_nested_value(
|
|
448
|
+
img_part, [4, candidate_index, 12, 7, 0]
|
|
449
|
+
):
|
|
426
450
|
img_body = img_part
|
|
427
451
|
break
|
|
428
452
|
except (IndexError, TypeError, ValueError):
|
|
@@ -434,57 +458,73 @@ class GeminiClient(GemMixin):
|
|
|
434
458
|
"If the error persists and is caused by the package, please report it on GitHub."
|
|
435
459
|
)
|
|
436
460
|
|
|
437
|
-
img_candidate =
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
img_candidate[1
|
|
443
|
-
)
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
),
|
|
463
|
-
proxy=self.proxy,
|
|
464
|
-
cookies=self.cookies,
|
|
461
|
+
img_candidate = get_nested_value(
|
|
462
|
+
img_body, [4, candidate_index], []
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
if finished_text := get_nested_value(
|
|
466
|
+
img_candidate, [1, 0]
|
|
467
|
+
): # Only overwrite if new text is returned after image generation
|
|
468
|
+
text = re.sub(
|
|
469
|
+
r"http://googleusercontent\.com/image_generation_content/\d+",
|
|
470
|
+
"",
|
|
471
|
+
finished_text,
|
|
472
|
+
).rstrip()
|
|
473
|
+
|
|
474
|
+
for img_index, gen_img_data in enumerate(
|
|
475
|
+
get_nested_value(img_candidate, [12, 7, 0], [])
|
|
476
|
+
):
|
|
477
|
+
url = get_nested_value(gen_img_data, [0, 3, 3])
|
|
478
|
+
if not url:
|
|
479
|
+
continue
|
|
480
|
+
|
|
481
|
+
img_num = get_nested_value(gen_img_data, [3, 6])
|
|
482
|
+
title = (
|
|
483
|
+
f"[Generated Image {img_num}]"
|
|
484
|
+
if img_num
|
|
485
|
+
else "[Generated Image]"
|
|
465
486
|
)
|
|
466
|
-
|
|
467
|
-
|
|
487
|
+
|
|
488
|
+
alt_list = get_nested_value(gen_img_data, [3, 5], [])
|
|
489
|
+
alt = (
|
|
490
|
+
get_nested_value(alt_list, [img_index])
|
|
491
|
+
or get_nested_value(alt_list, [0])
|
|
492
|
+
or ""
|
|
468
493
|
)
|
|
469
|
-
]
|
|
470
494
|
|
|
471
|
-
|
|
495
|
+
generated_images.append(
|
|
496
|
+
GeneratedImage(
|
|
497
|
+
url=url,
|
|
498
|
+
title=title,
|
|
499
|
+
alt=alt,
|
|
500
|
+
proxy=self.proxy,
|
|
501
|
+
cookies=self.cookies,
|
|
502
|
+
)
|
|
503
|
+
)
|
|
504
|
+
|
|
505
|
+
output_candidates.append(
|
|
472
506
|
Candidate(
|
|
473
|
-
rcid=
|
|
507
|
+
rcid=rcid,
|
|
474
508
|
text=text,
|
|
475
509
|
thoughts=thoughts,
|
|
476
510
|
web_images=web_images,
|
|
477
511
|
generated_images=generated_images,
|
|
478
512
|
)
|
|
479
513
|
)
|
|
480
|
-
|
|
514
|
+
|
|
515
|
+
if not output_candidates:
|
|
481
516
|
raise GeminiError(
|
|
482
517
|
"Failed to generate contents. No output data found in response."
|
|
483
518
|
)
|
|
484
519
|
|
|
485
|
-
output = ModelOutput(
|
|
486
|
-
|
|
487
|
-
|
|
520
|
+
output = ModelOutput(
|
|
521
|
+
metadata=get_nested_value(body, [1], []),
|
|
522
|
+
candidates=output_candidates,
|
|
523
|
+
)
|
|
524
|
+
except (TypeError, IndexError) as e:
|
|
525
|
+
logger.debug(
|
|
526
|
+
f"{type(e).__name__}: {e}; Invalid response structure: {response.text}"
|
|
527
|
+
)
|
|
488
528
|
raise APIError(
|
|
489
529
|
"Failed to parse response body. Data structure is invalid."
|
|
490
530
|
)
|
gemini_webapi/constants.py
CHANGED
|
@@ -43,9 +43,14 @@ class Headers(Enum):
|
|
|
43
43
|
|
|
44
44
|
class Model(Enum):
|
|
45
45
|
UNSPECIFIED = ("unspecified", {}, False)
|
|
46
|
+
G_3_0_PRO = (
|
|
47
|
+
"gemini-3.0-pro",
|
|
48
|
+
{"x-goog-ext-525001261-jspb": '[1,null,null,null,"9d8ca3786ebdfbea",null,null,null,[4]]'},
|
|
49
|
+
False,
|
|
50
|
+
)
|
|
46
51
|
G_2_5_FLASH = (
|
|
47
52
|
"gemini-2.5-flash",
|
|
48
|
-
{"x-goog-ext-525001261-jspb": '[1,null,null,null,"
|
|
53
|
+
{"x-goog-ext-525001261-jspb": '[1,null,null,null,"9ec249fc9ad08861",null,null,0,[4]]'},
|
|
49
54
|
False,
|
|
50
55
|
)
|
|
51
56
|
G_2_5_PRO = (
|
|
@@ -53,16 +58,6 @@ class Model(Enum):
|
|
|
53
58
|
{"x-goog-ext-525001261-jspb": '[1,null,null,null,"4af6c7f5da75d65d",null,null,0,[4]]'},
|
|
54
59
|
False,
|
|
55
60
|
)
|
|
56
|
-
G_2_0_FLASH = (
|
|
57
|
-
"gemini-2.0-flash",
|
|
58
|
-
{"x-goog-ext-525001261-jspb": '[1,null,null,null,"f299729663a2343f"]'},
|
|
59
|
-
False,
|
|
60
|
-
) # Deprecated
|
|
61
|
-
G_2_0_FLASH_THINKING = (
|
|
62
|
-
"gemini-2.0-flash-thinking",
|
|
63
|
-
{"x-goog-ext-525001261-jspb": '[null,null,null,null,"7ca48d02d802f20a"]'},
|
|
64
|
-
False,
|
|
65
|
-
) # Deprecated
|
|
66
61
|
|
|
67
62
|
def __init__(self, name, header, advanced_only):
|
|
68
63
|
self.model_name = name
|
gemini_webapi/utils/__init__.py
CHANGED
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
from asyncio import Task
|
|
4
4
|
|
|
5
5
|
from .decorators import running
|
|
6
|
-
from .upload_file import upload_file, parse_file_name
|
|
7
|
-
from .rotate_1psidts import rotate_1psidts
|
|
8
6
|
from .get_access_token import get_access_token
|
|
9
7
|
from .load_browser_cookies import load_browser_cookies
|
|
10
8
|
from .logger import logger, set_log_level
|
|
9
|
+
from .parsing import extract_json_from_response, get_nested_value
|
|
10
|
+
from .rotate_1psidts import rotate_1psidts
|
|
11
|
+
from .upload_file import upload_file, parse_file_name
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
rotate_tasks: dict[str, Task] = {}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
import orjson as json
|
|
4
|
+
|
|
5
|
+
from .logger import logger
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_nested_value(data: list, path: list[int], default: Any = None) -> Any:
|
|
9
|
+
"""
|
|
10
|
+
Safely get a value from a nested list by a sequence of indices.
|
|
11
|
+
|
|
12
|
+
Parameters
|
|
13
|
+
----------
|
|
14
|
+
data: `list`
|
|
15
|
+
The nested list to traverse.
|
|
16
|
+
path: `list[int]`
|
|
17
|
+
A list of indices representing the path to the desired value.
|
|
18
|
+
default: `Any`, optional
|
|
19
|
+
The default value to return if the path is not found.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
current = data
|
|
23
|
+
|
|
24
|
+
for i, key in enumerate(path):
|
|
25
|
+
try:
|
|
26
|
+
current = current[key]
|
|
27
|
+
except (IndexError, TypeError, KeyError) as e:
|
|
28
|
+
current_repr = repr(current)
|
|
29
|
+
if len(current_repr) > 200:
|
|
30
|
+
current_repr = f"{current_repr[:197]}..."
|
|
31
|
+
|
|
32
|
+
logger.debug(
|
|
33
|
+
f"{type(e).__name__}: parsing failed at path {path} (index {i}, key '{key}') "
|
|
34
|
+
f"while attempting to get value from `{current_repr}`"
|
|
35
|
+
)
|
|
36
|
+
return default
|
|
37
|
+
|
|
38
|
+
if current is None and default is not None:
|
|
39
|
+
return default
|
|
40
|
+
|
|
41
|
+
return current
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def extract_json_from_response(text: str) -> list:
|
|
45
|
+
"""
|
|
46
|
+
Clean and extract the JSON content from a Google API response.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
text: `str`
|
|
51
|
+
The raw response text from a Google API.
|
|
52
|
+
|
|
53
|
+
Returns
|
|
54
|
+
-------
|
|
55
|
+
`list`
|
|
56
|
+
The extracted JSON array or object (should be an array).
|
|
57
|
+
|
|
58
|
+
Raises
|
|
59
|
+
------
|
|
60
|
+
`TypeError`
|
|
61
|
+
If the input is not a string.
|
|
62
|
+
`ValueError`
|
|
63
|
+
If no JSON object is found or the response is empty.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
if not isinstance(text, str):
|
|
67
|
+
raise TypeError(
|
|
68
|
+
f"Input text is expected to be a string, got {type(text).__name__} instead."
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Find the first line which is valid JSON
|
|
72
|
+
for line in text.splitlines():
|
|
73
|
+
try:
|
|
74
|
+
return json.loads(line.strip())
|
|
75
|
+
except json.JSONDecodeError:
|
|
76
|
+
continue
|
|
77
|
+
|
|
78
|
+
# If no JSON is found, raise ValueError
|
|
79
|
+
raise ValueError("Could not find a valid JSON object or array in the response.")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gemini-webapi
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.17.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
|
|
@@ -905,16 +905,12 @@ asyncio.run(main())
|
|
|
905
905
|
|
|
906
906
|
You can specify which language model to use by passing `model` argument to `GeminiClient.generate_content` or `GeminiClient.start_chat`. The default value is `unspecified`.
|
|
907
907
|
|
|
908
|
-
Currently available models (as of
|
|
908
|
+
Currently available models (as of November 20, 2025):
|
|
909
909
|
|
|
910
910
|
- `unspecified` - Default model
|
|
911
|
+
- `gemini-3.0-pro` - Gemini 3.0 Pro
|
|
912
|
+
- `gemini-2.5-pro` - Gemini 2.5 Pro
|
|
911
913
|
- `gemini-2.5-flash` - Gemini 2.5 Flash
|
|
912
|
-
- `gemini-2.5-pro` - Gemini 2.5 Pro (daily usage limit imposed)
|
|
913
|
-
|
|
914
|
-
Deprecated models (yet still working):
|
|
915
|
-
|
|
916
|
-
- `gemini-2.0-flash` - Gemini 2.0 Flash
|
|
917
|
-
- `gemini-2.0-flash-thinking` - Gemini 2.0 Flash Thinking
|
|
918
914
|
|
|
919
915
|
```python
|
|
920
916
|
from gemini_webapi.constants import Model
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
gemini_webapi/__init__.py,sha256=7ELCiUoI10ea3daeJxnv0UwqLVKpM7rxsgOZsPMstO8,150
|
|
2
|
-
gemini_webapi/client.py,sha256=
|
|
3
|
-
gemini_webapi/constants.py,sha256=
|
|
2
|
+
gemini_webapi/client.py,sha256=9hcf0MOSiYbysv9rtcPm6wsRnb2aRLv8c8LL9Kxf8k4,28476
|
|
3
|
+
gemini_webapi/constants.py,sha256=frgypJCzQvbtfNxYAOntyc9WSP0MiQ_RpsK4bJ-N6VI,2502
|
|
4
4
|
gemini_webapi/exceptions.py,sha256=qkXrIpr0L7LtGbq3VcTO8D1xZ50pJtt0dDRp5I3uDSg,1038
|
|
5
5
|
gemini_webapi/components/__init__.py,sha256=wolxuAJJ32-jmHOKgpsesexP7hXea1JMo5vI52wysTI,48
|
|
6
6
|
gemini_webapi/components/gem_mixin.py,sha256=WPJkYDS4yQpLMBNQ94LQo5w59RgkllWaSiHsFG1k5GU,8795
|
|
@@ -10,15 +10,16 @@ gemini_webapi/types/gem.py,sha256=3Ppjq9V22Zp4Lb9a9ZnDviDKQpfSQf8UZxqOEjeEWd4,40
|
|
|
10
10
|
gemini_webapi/types/grpc.py,sha256=S64h1oeC7ZJC50kmS_C2CQ7WVTanhJ4kqTFx5ZYayXI,917
|
|
11
11
|
gemini_webapi/types/image.py,sha256=NhW1QY2Agzb6UbrIjZLnqxqukabDSGbmoCsVguzko10,5395
|
|
12
12
|
gemini_webapi/types/modeloutput.py,sha256=h07kQOkL5r-oPLvZ59uVtO1eP4FGy5ZpzuYQzAeQdr8,1196
|
|
13
|
-
gemini_webapi/utils/__init__.py,sha256=
|
|
13
|
+
gemini_webapi/utils/__init__.py,sha256=k8hV2zn6tD_BEpd1Xya6ED0deijsmzb1e9XxdFhJzIE,418
|
|
14
14
|
gemini_webapi/utils/decorators.py,sha256=AuY6sU1_6_ZqeL92dTAi3eRPQ7zubB5VuBZEiz16aBM,1741
|
|
15
15
|
gemini_webapi/utils/get_access_token.py,sha256=VjrHW8VMN3LPs6zCdXQtraWygurOjTY0SJZhe49aQwc,7265
|
|
16
16
|
gemini_webapi/utils/load_browser_cookies.py,sha256=OHCfe27DpV_rloIDgW9Xpeb0mkfzbYONNiholw0ElXU,1791
|
|
17
17
|
gemini_webapi/utils/logger.py,sha256=0VcxhVLhHBRDQutNCpapP1y_MhPoQ2ud1uIFLqxC3Z8,958
|
|
18
|
+
gemini_webapi/utils/parsing.py,sha256=z-t0bDbXVIa0-3_ZmTK19PvL6zBM5vuy56z2jv1Yu1I,2105
|
|
18
19
|
gemini_webapi/utils/rotate_1psidts.py,sha256=XjEeQnZS3ZI6wOl0Zb5CvsbIrg0BVVNas7cE6f3x_XE,1802
|
|
19
20
|
gemini_webapi/utils/upload_file.py,sha256=SJOMr6kryK_ClrKmqI96fqZBNFOMPsyAvFINAGAU3rk,1468
|
|
20
|
-
gemini_webapi-1.
|
|
21
|
-
gemini_webapi-1.
|
|
22
|
-
gemini_webapi-1.
|
|
23
|
-
gemini_webapi-1.
|
|
24
|
-
gemini_webapi-1.
|
|
21
|
+
gemini_webapi-1.17.0.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
|
22
|
+
gemini_webapi-1.17.0.dist-info/METADATA,sha256=EuMINxma9gp-2YC-cd2w_mOecbBNAyJzUcIiZ-oT_1A,61299
|
|
23
|
+
gemini_webapi-1.17.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
24
|
+
gemini_webapi-1.17.0.dist-info/top_level.txt,sha256=dtWtug_ZrmnUqCYuu8NmGzTgWglHeNzhHU_hXmqZGWE,14
|
|
25
|
+
gemini_webapi-1.17.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|