gemini-webapi 1.17.0__py3-none-any.whl → 1.17.2__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 +32 -19
- gemini_webapi/constants.py +31 -7
- gemini_webapi/types/image.py +27 -10
- gemini_webapi/utils/decorators.py +4 -3
- gemini_webapi/utils/parsing.py +2 -2
- {gemini_webapi-1.17.0.dist-info → gemini_webapi-1.17.2.dist-info}/METADATA +23 -6
- {gemini_webapi-1.17.0.dist-info → gemini_webapi-1.17.2.dist-info}/RECORD +10 -10
- {gemini_webapi-1.17.0.dist-info → gemini_webapi-1.17.2.dist-info}/WHEEL +0 -0
- {gemini_webapi-1.17.0.dist-info → gemini_webapi-1.17.2.dist-info}/licenses/LICENSE +0 -0
- {gemini_webapi-1.17.0.dist-info → gemini_webapi-1.17.2.dist-info}/top_level.txt +0 -0
gemini_webapi/client.py
CHANGED
|
@@ -68,7 +68,7 @@ class GeminiClient(GemMixin):
|
|
|
68
68
|
__slots__ = [
|
|
69
69
|
"cookies",
|
|
70
70
|
"proxy",
|
|
71
|
-
"
|
|
71
|
+
"_running",
|
|
72
72
|
"client",
|
|
73
73
|
"access_token",
|
|
74
74
|
"timeout",
|
|
@@ -91,7 +91,7 @@ class GeminiClient(GemMixin):
|
|
|
91
91
|
super().__init__()
|
|
92
92
|
self.cookies = {}
|
|
93
93
|
self.proxy = proxy
|
|
94
|
-
self.
|
|
94
|
+
self._running: bool = False
|
|
95
95
|
self.client: AsyncClient | None = None
|
|
96
96
|
self.access_token: str | None = None
|
|
97
97
|
self.timeout: float = 300
|
|
@@ -152,7 +152,7 @@ class GeminiClient(GemMixin):
|
|
|
152
152
|
)
|
|
153
153
|
self.access_token = access_token
|
|
154
154
|
self.cookies = valid_cookies
|
|
155
|
-
self.
|
|
155
|
+
self._running = True
|
|
156
156
|
|
|
157
157
|
self.timeout = timeout
|
|
158
158
|
self.auto_close = auto_close
|
|
@@ -188,7 +188,7 @@ class GeminiClient(GemMixin):
|
|
|
188
188
|
if delay:
|
|
189
189
|
await asyncio.sleep(delay)
|
|
190
190
|
|
|
191
|
-
self.
|
|
191
|
+
self._running = False
|
|
192
192
|
|
|
193
193
|
if self.close_task:
|
|
194
194
|
self.close_task.cancel()
|
|
@@ -229,7 +229,7 @@ class GeminiClient(GemMixin):
|
|
|
229
229
|
|
|
230
230
|
if new_1psidts:
|
|
231
231
|
self.cookies["__Secure-1PSIDTS"] = new_1psidts
|
|
232
|
-
if self.
|
|
232
|
+
if self._running:
|
|
233
233
|
self.client.cookies.set("__Secure-1PSIDTS", new_1psidts)
|
|
234
234
|
logger.debug("Cookies refreshed. New __Secure-1PSIDTS applied.")
|
|
235
235
|
|
|
@@ -240,7 +240,7 @@ class GeminiClient(GemMixin):
|
|
|
240
240
|
self,
|
|
241
241
|
prompt: str,
|
|
242
242
|
files: list[str | Path] | None = None,
|
|
243
|
-
model: Model | str = Model.UNSPECIFIED,
|
|
243
|
+
model: Model | str | dict = Model.UNSPECIFIED,
|
|
244
244
|
gem: Gem | str | None = None,
|
|
245
245
|
chat: Optional["ChatSession"] = None,
|
|
246
246
|
**kwargs,
|
|
@@ -254,9 +254,10 @@ class GeminiClient(GemMixin):
|
|
|
254
254
|
Prompt provided by user.
|
|
255
255
|
files: `list[str | Path]`, optional
|
|
256
256
|
List of file paths to be attached.
|
|
257
|
-
model: `Model
|
|
257
|
+
model: `Model | str | dict`, optional
|
|
258
258
|
Specify the model to use for generation.
|
|
259
|
-
Pass either a `gemini_webapi.constants.Model` enum or a model name string.
|
|
259
|
+
Pass either a `gemini_webapi.constants.Model` enum or a model name string to use predefined models.
|
|
260
|
+
Pass a dictionary to use custom model header strings ("model_name" and "model_header" keys must be provided).
|
|
260
261
|
gem: `Gem | str`, optional
|
|
261
262
|
Specify a gem to use as system prompt for the chat session.
|
|
262
263
|
Pass either a `gemini_webapi.types.Gem` object or a gem id string.
|
|
@@ -287,8 +288,15 @@ class GeminiClient(GemMixin):
|
|
|
287
288
|
|
|
288
289
|
assert prompt, "Prompt cannot be empty."
|
|
289
290
|
|
|
290
|
-
if
|
|
291
|
+
if isinstance(model, str):
|
|
291
292
|
model = Model.from_name(model)
|
|
293
|
+
elif isinstance(model, dict):
|
|
294
|
+
model = Model.from_dict(model)
|
|
295
|
+
elif not isinstance(model, Model):
|
|
296
|
+
raise TypeError(
|
|
297
|
+
f"'model' must be a `gemini_webapi.constants.Model` instance, "
|
|
298
|
+
f"string, or dictionary; got `{type(model).__name__}`"
|
|
299
|
+
)
|
|
292
300
|
|
|
293
301
|
if isinstance(gem, Gem):
|
|
294
302
|
gem_id = gem.id
|
|
@@ -362,7 +370,7 @@ class GeminiClient(GemMixin):
|
|
|
362
370
|
if get_nested_value(part_json, [4]):
|
|
363
371
|
body_index, body = part_index, part_json
|
|
364
372
|
break
|
|
365
|
-
except
|
|
373
|
+
except json.JSONDecodeError:
|
|
366
374
|
continue
|
|
367
375
|
|
|
368
376
|
if not body:
|
|
@@ -372,7 +380,7 @@ class GeminiClient(GemMixin):
|
|
|
372
380
|
|
|
373
381
|
try:
|
|
374
382
|
error_code = get_nested_value(response_json, [0, 5, 2, 0, 1, 0], -1)
|
|
375
|
-
match
|
|
383
|
+
match error_code:
|
|
376
384
|
case ErrorCode.USAGE_LIMIT_EXCEEDED:
|
|
377
385
|
raise UsageLimitExceeded(
|
|
378
386
|
f"Failed to generate contents. Usage limit of {model.model_name} model has exceeded. Please try switching to another model."
|
|
@@ -443,13 +451,17 @@ class GeminiClient(GemMixin):
|
|
|
443
451
|
if img_part_index < body_index:
|
|
444
452
|
continue
|
|
445
453
|
try:
|
|
446
|
-
|
|
454
|
+
img_part_body = get_nested_value(part, [2])
|
|
455
|
+
if not img_part_body:
|
|
456
|
+
continue
|
|
457
|
+
|
|
458
|
+
img_part_json = json.loads(img_part_body)
|
|
447
459
|
if get_nested_value(
|
|
448
|
-
|
|
460
|
+
img_part_json, [4, candidate_index, 12, 7, 0]
|
|
449
461
|
):
|
|
450
|
-
img_body =
|
|
462
|
+
img_body = img_part_json
|
|
451
463
|
break
|
|
452
|
-
except
|
|
464
|
+
except json.JSONDecodeError:
|
|
453
465
|
continue
|
|
454
466
|
|
|
455
467
|
if not img_body:
|
|
@@ -614,9 +626,10 @@ class ChatSession:
|
|
|
614
626
|
Reply id, if provided together with metadata, will override the second value in it.
|
|
615
627
|
rcid: `str`, optional
|
|
616
628
|
Reply candidate id, if provided together with metadata, will override the third value in it.
|
|
617
|
-
model: `Model
|
|
629
|
+
model: `Model | str | dict`, optional
|
|
618
630
|
Specify the model to use for generation.
|
|
619
|
-
Pass either a `gemini_webapi.constants.Model` enum or a model name string.
|
|
631
|
+
Pass either a `gemini_webapi.constants.Model` enum or a model name string to use predefined models.
|
|
632
|
+
Pass a dictionary to use custom model header strings ("model_name" and "model_header" keys must be provided).
|
|
620
633
|
gem: `Gem | str`, optional
|
|
621
634
|
Specify a gem to use as system prompt for the chat session.
|
|
622
635
|
Pass either a `gemini_webapi.types.Gem` object or a gem id string.
|
|
@@ -637,13 +650,13 @@ class ChatSession:
|
|
|
637
650
|
cid: str | None = None, # chat id
|
|
638
651
|
rid: str | None = None, # reply id
|
|
639
652
|
rcid: str | None = None, # reply candidate id
|
|
640
|
-
model: Model | str = Model.UNSPECIFIED,
|
|
653
|
+
model: Model | str | dict = Model.UNSPECIFIED,
|
|
641
654
|
gem: Gem | str | None = None,
|
|
642
655
|
):
|
|
643
656
|
self.__metadata: list[str | None] = [None, None, None]
|
|
644
657
|
self.geminiclient: GeminiClient = geminiclient
|
|
645
658
|
self.last_output: ModelOutput | None = None
|
|
646
|
-
self.model: Model | str = model
|
|
659
|
+
self.model: Model | str | dict = model
|
|
647
660
|
self.gem: Gem | str | None = gem
|
|
648
661
|
|
|
649
662
|
if metadata:
|
gemini_webapi/constants.py
CHANGED
|
@@ -45,17 +45,23 @@ class Model(Enum):
|
|
|
45
45
|
UNSPECIFIED = ("unspecified", {}, False)
|
|
46
46
|
G_3_0_PRO = (
|
|
47
47
|
"gemini-3.0-pro",
|
|
48
|
-
{
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
G_2_5_FLASH = (
|
|
52
|
-
"gemini-2.5-flash",
|
|
53
|
-
{"x-goog-ext-525001261-jspb": '[1,null,null,null,"9ec249fc9ad08861",null,null,0,[4]]'},
|
|
48
|
+
{
|
|
49
|
+
"x-goog-ext-525001261-jspb": '[1,null,null,null,"9d8ca3786ebdfbea",null,null,0,[4]]'
|
|
50
|
+
},
|
|
54
51
|
False,
|
|
55
52
|
)
|
|
56
53
|
G_2_5_PRO = (
|
|
57
54
|
"gemini-2.5-pro",
|
|
58
|
-
{
|
|
55
|
+
{
|
|
56
|
+
"x-goog-ext-525001261-jspb": '[1,null,null,null,"4af6c7f5da75d65d",null,null,0,[4]]'
|
|
57
|
+
},
|
|
58
|
+
False,
|
|
59
|
+
)
|
|
60
|
+
G_2_5_FLASH = (
|
|
61
|
+
"gemini-2.5-flash",
|
|
62
|
+
{
|
|
63
|
+
"x-goog-ext-525001261-jspb": '[1,null,null,null,"9ec249fc9ad08861",null,null,0,[4]]'
|
|
64
|
+
},
|
|
59
65
|
False,
|
|
60
66
|
)
|
|
61
67
|
|
|
@@ -69,10 +75,28 @@ class Model(Enum):
|
|
|
69
75
|
for model in cls:
|
|
70
76
|
if model.model_name == name:
|
|
71
77
|
return model
|
|
78
|
+
|
|
72
79
|
raise ValueError(
|
|
73
80
|
f"Unknown model name: {name}. Available models: {', '.join([model.model_name for model in cls])}"
|
|
74
81
|
)
|
|
75
82
|
|
|
83
|
+
@classmethod
|
|
84
|
+
def from_dict(cls, model_dict: dict):
|
|
85
|
+
if "model_name" not in model_dict or "model_header" not in model_dict:
|
|
86
|
+
raise ValueError(
|
|
87
|
+
"When passing a custom model as a dictionary, 'model_name' and 'model_header' keys must be provided."
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if not isinstance(model_dict["model_header"], dict):
|
|
91
|
+
raise ValueError(
|
|
92
|
+
"When passing a custom model as a dictionary, 'model_header' must be a dictionary containing valid header strings."
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
custom_model = cls.UNSPECIFIED
|
|
96
|
+
custom_model.model_name = model_dict["model_name"]
|
|
97
|
+
custom_model.model_header = model_dict["model_header"]
|
|
98
|
+
return custom_model
|
|
99
|
+
|
|
76
100
|
|
|
77
101
|
class ErrorCode(IntEnum):
|
|
78
102
|
"""
|
gemini_webapi/types/image.py
CHANGED
|
@@ -71,9 +71,10 @@ class Image(BaseModel):
|
|
|
71
71
|
"""
|
|
72
72
|
|
|
73
73
|
filename = filename or self.url.split("/")[-1].split("?")[0]
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
match = re.search(r"^(.*\.\w+)", filename)
|
|
75
|
+
if match:
|
|
76
|
+
filename = match.group()
|
|
77
|
+
else:
|
|
77
78
|
if verbose:
|
|
78
79
|
logger.warning(f"Invalid filename: {filename}")
|
|
79
80
|
if skip_invalid_filename:
|
|
@@ -137,19 +138,33 @@ class GeneratedImage(Image):
|
|
|
137
138
|
return v
|
|
138
139
|
|
|
139
140
|
# @override
|
|
140
|
-
async def save(
|
|
141
|
+
async def save(
|
|
142
|
+
self,
|
|
143
|
+
path: str = "temp",
|
|
144
|
+
filename: str | None = None,
|
|
145
|
+
cookies: dict | None = None,
|
|
146
|
+
verbose: bool = False,
|
|
147
|
+
skip_invalid_filename: bool = False,
|
|
148
|
+
full_size: bool = True,
|
|
149
|
+
) -> str | None:
|
|
141
150
|
"""
|
|
142
151
|
Save the image to disk.
|
|
143
152
|
|
|
144
153
|
Parameters
|
|
145
154
|
----------
|
|
155
|
+
path: `str`, optional
|
|
156
|
+
Path to save the image, by default will save to "./temp".
|
|
146
157
|
filename: `str`, optional
|
|
147
158
|
Filename to save the image, generated images are always in .png format, but file extension will not be included in the URL.
|
|
148
159
|
And since the URL ends with a long hash, by default will use timestamp + end of the hash as the filename.
|
|
160
|
+
cookies: `dict`, optional
|
|
161
|
+
Cookies used for requesting the content of the image. If not provided, will use the cookies from the GeneratedImage instance.
|
|
162
|
+
verbose : `bool`, optional
|
|
163
|
+
If True, will print the path of the saved file or warning for invalid file name, by default False.
|
|
164
|
+
skip_invalid_filename: `bool`, optional
|
|
165
|
+
If True, will only save the image if the file name and extension are valid, by default False.
|
|
149
166
|
full_size: `bool`, optional
|
|
150
|
-
If True, will modify the default preview (512*512) URL to get the full size image.
|
|
151
|
-
kwargs: `dict`, optional
|
|
152
|
-
Other arguments to pass to `Image.save`.
|
|
167
|
+
If True, will modify the default preview (512*512) URL to get the full size image, by default True.
|
|
153
168
|
|
|
154
169
|
Returns
|
|
155
170
|
-------
|
|
@@ -161,8 +176,10 @@ class GeneratedImage(Image):
|
|
|
161
176
|
self.url += "=s2048"
|
|
162
177
|
|
|
163
178
|
return await super().save(
|
|
164
|
-
|
|
179
|
+
path=path,
|
|
180
|
+
filename=filename
|
|
165
181
|
or f"{datetime.now().strftime('%Y%m%d%H%M%S')}_{self.url[-10:]}.png",
|
|
166
|
-
cookies=self.cookies,
|
|
167
|
-
|
|
182
|
+
cookies=cookies or self.cookies,
|
|
183
|
+
verbose=verbose,
|
|
184
|
+
skip_invalid_filename=skip_invalid_filename,
|
|
168
185
|
)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import functools
|
|
3
|
+
from collections.abc import Callable
|
|
3
4
|
|
|
4
5
|
from ..exceptions import APIError, ImageGenerationError
|
|
5
6
|
|
|
6
7
|
|
|
7
|
-
def running(retry: int = 0) ->
|
|
8
|
+
def running(retry: int = 0) -> Callable:
|
|
8
9
|
"""
|
|
9
10
|
Decorator to check if GeminiClient is running before making a request.
|
|
10
11
|
|
|
@@ -18,7 +19,7 @@ def running(retry: int = 0) -> callable:
|
|
|
18
19
|
@functools.wraps(func)
|
|
19
20
|
async def wrapper(client, *args, retry=retry, **kwargs):
|
|
20
21
|
try:
|
|
21
|
-
if not client.
|
|
22
|
+
if not client._running:
|
|
22
23
|
await client.init(
|
|
23
24
|
timeout=client.timeout,
|
|
24
25
|
auto_close=client.auto_close,
|
|
@@ -27,7 +28,7 @@ def running(retry: int = 0) -> callable:
|
|
|
27
28
|
refresh_interval=client.refresh_interval,
|
|
28
29
|
verbose=False,
|
|
29
30
|
)
|
|
30
|
-
if client.
|
|
31
|
+
if client._running:
|
|
31
32
|
return await func(client, *args, **kwargs)
|
|
32
33
|
|
|
33
34
|
# Should not reach here
|
gemini_webapi/utils/parsing.py
CHANGED
|
@@ -30,8 +30,8 @@ def get_nested_value(data: list, path: list[int], default: Any = None) -> Any:
|
|
|
30
30
|
current_repr = f"{current_repr[:197]}..."
|
|
31
31
|
|
|
32
32
|
logger.debug(
|
|
33
|
-
f"
|
|
34
|
-
f"
|
|
33
|
+
f"Safe navigation: path {path} ended at index {i} (key '{key}'), "
|
|
34
|
+
f"returning default. <Debug: {type(e).__name__}; Context: {current_repr}>"
|
|
35
35
|
)
|
|
36
36
|
return default
|
|
37
37
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gemini-webapi
|
|
3
|
-
Version: 1.17.
|
|
3
|
+
Version: 1.17.2
|
|
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
|
|
@@ -783,11 +783,11 @@ pip install -U browser-cookie3
|
|
|
783
783
|
|
|
784
784
|
```yaml
|
|
785
785
|
services:
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
786
|
+
main:
|
|
787
|
+
environment:
|
|
788
|
+
GEMINI_COOKIE_PATH: /tmp/gemini_webapi
|
|
789
|
+
volumes:
|
|
790
|
+
- ./gemini_cookies:/tmp/gemini_webapi
|
|
791
791
|
```
|
|
792
792
|
|
|
793
793
|
> [!NOTE]
|
|
@@ -929,6 +929,23 @@ async def main():
|
|
|
929
929
|
asyncio.run(main())
|
|
930
930
|
```
|
|
931
931
|
|
|
932
|
+
You can also pass custom model header strings directly to access models which are not listed above.
|
|
933
|
+
|
|
934
|
+
```python
|
|
935
|
+
# "model_name" and "model_header" keys must be present
|
|
936
|
+
custom_model = {
|
|
937
|
+
"model_name": "xxx",
|
|
938
|
+
"model_header": {
|
|
939
|
+
"x-goog-ext-525001261-jspb": "[1,null,null,null,'e6fa609c3fa255c0',null,null,null,[4]]"
|
|
940
|
+
},
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
response = await client.generate_content(
|
|
944
|
+
"What's your model version?",
|
|
945
|
+
model=custom_model
|
|
946
|
+
)
|
|
947
|
+
```
|
|
948
|
+
|
|
932
949
|
### Apply system prompt with Gemini Gems
|
|
933
950
|
|
|
934
951
|
System prompt can be applied to conversations via [Gemini Gems](https://gemini.google.com/gems/view). To use a gem, you can pass `gem` argument to `GeminiClient.generate_content` or `GeminiClient.start_chat`. `gem` can be either a string of gem id or a `gemini_webapi.Gem` object. Only one gem can be applied to a single conversation.
|
|
@@ -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=6A1K6Tq1cXdW_RGwLIFtDE0jhS1WAtrGvGqAY5-FREc,29282
|
|
3
|
+
gemini_webapi/constants.py,sha256=tm9y8oKuD3QhKXUbVXZKroYCoPpqgBJdSTwoeue43Ss,3295
|
|
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
|
|
@@ -8,18 +8,18 @@ gemini_webapi/types/__init__.py,sha256=1DU4JEw2KHQJbtOgOuvoEXtzQCMwAkyo0koSFVdT9
|
|
|
8
8
|
gemini_webapi/types/candidate.py,sha256=67BhY75toE5mVuB21cmHcTFtw332V_KmCjr3-9VTbJo,1477
|
|
9
9
|
gemini_webapi/types/gem.py,sha256=3Ppjq9V22Zp4Lb9a9ZnDviDKQpfSQf8UZxqOEjeEWd4,4070
|
|
10
10
|
gemini_webapi/types/grpc.py,sha256=S64h1oeC7ZJC50kmS_C2CQ7WVTanhJ4kqTFx5ZYayXI,917
|
|
11
|
-
gemini_webapi/types/image.py,sha256=
|
|
11
|
+
gemini_webapi/types/image.py,sha256=JotV2FA8XdIKPHCRIExEOwnE-167AQ-Qoy3bIIREvw4,6185
|
|
12
12
|
gemini_webapi/types/modeloutput.py,sha256=h07kQOkL5r-oPLvZ59uVtO1eP4FGy5ZpzuYQzAeQdr8,1196
|
|
13
13
|
gemini_webapi/utils/__init__.py,sha256=k8hV2zn6tD_BEpd1Xya6ED0deijsmzb1e9XxdFhJzIE,418
|
|
14
|
-
gemini_webapi/utils/decorators.py,sha256=
|
|
14
|
+
gemini_webapi/utils/decorators.py,sha256=uzIXoZOC0_Om19bbVXf_nw2w2NhI2qJL1o45FU6o6fI,1780
|
|
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=
|
|
18
|
+
gemini_webapi/utils/parsing.py,sha256=CJPf7V0R_EJz1srrbVQBuOOQkLFyZovqLOHwEFYbSbY,2113
|
|
19
19
|
gemini_webapi/utils/rotate_1psidts.py,sha256=XjEeQnZS3ZI6wOl0Zb5CvsbIrg0BVVNas7cE6f3x_XE,1802
|
|
20
20
|
gemini_webapi/utils/upload_file.py,sha256=SJOMr6kryK_ClrKmqI96fqZBNFOMPsyAvFINAGAU3rk,1468
|
|
21
|
-
gemini_webapi-1.17.
|
|
22
|
-
gemini_webapi-1.17.
|
|
23
|
-
gemini_webapi-1.17.
|
|
24
|
-
gemini_webapi-1.17.
|
|
25
|
-
gemini_webapi-1.17.
|
|
21
|
+
gemini_webapi-1.17.2.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
|
22
|
+
gemini_webapi-1.17.2.dist-info/METADATA,sha256=PgjuOn0s9cY4sccrBUAglaLxu-SSaefZbQRnyzOc1Cg,61763
|
|
23
|
+
gemini_webapi-1.17.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
24
|
+
gemini_webapi-1.17.2.dist-info/top_level.txt,sha256=dtWtug_ZrmnUqCYuu8NmGzTgWglHeNzhHU_hXmqZGWE,14
|
|
25
|
+
gemini_webapi-1.17.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|