aioqzone 1.8.4.dev3__tar.gz → 1.8.5.dev1__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.
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/PKG-INFO +1 -1
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/pyproject.toml +1 -1
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/api/h5/model.py +39 -12
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/model/api/request.py +20 -1
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/model/api/response.py +2 -1
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/LICENSE +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/README.md +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/api/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/api/h5/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/api/login/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/api/login/_base.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/exception.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/message.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/model/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/model/api/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/model/api/feed.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/model/api/profile.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/model/protocol/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/model/protocol/config.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/model/protocol/entity.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/utils/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/utils/entity.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/utils/regex.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/utils/retry.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/aioqzone/utils/time.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/base.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/constant.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/exception.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/message.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/py.typed +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/qr/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/qr/type.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/type.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/up/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/up/_model.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/up/captcha/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/up/captcha/_model.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/up/captcha/capsess.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/up/captcha/pil_utils.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/up/captcha/select/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/up/captcha/select/_types.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/up/captcha/slide/__init__.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/up/captcha/slide/_types.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/up/encrypt.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/up/h5.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/up/web.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/utils/encrypt.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/utils/iter.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/utils/jsjson.py +0 -0
- {aioqzone-1.8.4.dev3 → aioqzone-1.8.5.dev1}/src/qqqr/utils/net.py +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from os import PathLike
|
|
2
3
|
|
|
3
4
|
from pydantic import ValidationError
|
|
4
5
|
from tenacity import AsyncRetrying, TryAgain, after_log, stop_after_attempt
|
|
@@ -177,7 +178,7 @@ class QzoneH5API:
|
|
|
177
178
|
async def publish_mood(
|
|
178
179
|
self,
|
|
179
180
|
content: str,
|
|
180
|
-
photos: t.Optional[t.
|
|
181
|
+
photos: t.Optional[t.Sequence[t.Union[PhotoData, PicInfo]]] = None,
|
|
181
182
|
sync_weibo=False,
|
|
182
183
|
ugc_right: UgcRight = UgcRight.all,
|
|
183
184
|
) -> PublishMoodResp:
|
|
@@ -189,21 +190,47 @@ class QzoneH5API:
|
|
|
189
190
|
:param ugc_right: access right, default to "Available to Everyone".
|
|
190
191
|
"""
|
|
191
192
|
photos = photos or []
|
|
192
|
-
return await self.call(
|
|
193
|
+
return await self.call(
|
|
194
|
+
PublishMoodApi(params=PublishMoodParams.model_validate(locals(), from_attributes=True))
|
|
195
|
+
)
|
|
193
196
|
|
|
194
197
|
async def upload_pic(
|
|
195
|
-
self,
|
|
198
|
+
self,
|
|
199
|
+
picture: t.Union[bytes, str, PathLike, t.IO[bytes]],
|
|
200
|
+
width: t.Optional[int] = None,
|
|
201
|
+
height: t.Optional[int] = None,
|
|
202
|
+
quality: t.Union[int, float] = 70,
|
|
196
203
|
) -> UploadPicResponse:
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
204
|
+
"""
|
|
205
|
+
.. versionchanged:: 1.8.5
|
|
206
|
+
|
|
207
|
+
In version <= 1.8.4, user is responsible for compressing a image and this api
|
|
208
|
+
encode the :obj:`picture` with Base64 and send it to Qzone _ASIS_.
|
|
209
|
+
|
|
210
|
+
Since version 1.8.5, we recognize a compressed image by :obj:`width` and :obj:`height`
|
|
211
|
+
parameters. If :obj:`width` and :obj:`height` is provided, this API will keep the former
|
|
212
|
+
behavior. If not provided, the image will be compressed with the given quality.
|
|
213
|
+
"""
|
|
214
|
+
if isinstance(quality, float):
|
|
215
|
+
if quality < 1:
|
|
216
|
+
quality *= 100
|
|
217
|
+
quality = int(quality)
|
|
218
|
+
|
|
219
|
+
assert 0 < quality <= 100
|
|
220
|
+
|
|
221
|
+
if isinstance(picture, (str, PathLike, t.IO)):
|
|
222
|
+
params = UploadPicParams.from_image(picture, quality)
|
|
223
|
+
elif (width is None) or (height is None):
|
|
224
|
+
params = UploadPicParams.from_bytes(picture, quality)
|
|
225
|
+
else:
|
|
226
|
+
params = UploadPicParams(
|
|
227
|
+
picture=picture,
|
|
228
|
+
hd_width=width,
|
|
229
|
+
hd_height=height,
|
|
230
|
+
hd_quality=quality,
|
|
205
231
|
)
|
|
206
|
-
|
|
232
|
+
|
|
233
|
+
return await self.call(UploadPicApi(params=params))
|
|
207
234
|
|
|
208
235
|
async def preupload_photos(
|
|
209
236
|
self, upload_pics: t.List[UploadPicResponse], cur_num=0, upload_hd=False
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import typing as t
|
|
2
2
|
from base64 import b64encode
|
|
3
|
+
from io import BytesIO
|
|
3
4
|
from math import floor
|
|
5
|
+
from os import PathLike
|
|
4
6
|
from time import time
|
|
5
7
|
|
|
6
|
-
from pydantic import BaseModel, Field, field_serializer
|
|
8
|
+
from pydantic import BaseModel, Field, field_serializer, field_validator
|
|
9
|
+
from typing_extensions import Buffer
|
|
7
10
|
|
|
8
11
|
from aioqzone.utils.time import time_ms
|
|
9
12
|
|
|
@@ -183,6 +186,22 @@ class UploadPicParams(QzoneRequestParams):
|
|
|
183
186
|
def b64_picture(self, picture: t.ByteString) -> str:
|
|
184
187
|
return b64encode(picture).decode()
|
|
185
188
|
|
|
189
|
+
@classmethod
|
|
190
|
+
def from_image(cls, image_file: t.Union[str, PathLike, t.IO[bytes]], quality=70):
|
|
191
|
+
import PIL.Image as image
|
|
192
|
+
|
|
193
|
+
with image.open(image_file) as f:
|
|
194
|
+
buf = BytesIO()
|
|
195
|
+
f.save(buf, "JPEG", quality=quality)
|
|
196
|
+
return cls(
|
|
197
|
+
picture=buf.getvalue(), hd_height=f.height, hd_width=f.width, hd_quality=quality
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
@classmethod
|
|
201
|
+
def from_bytes(cls, image_bytes: Buffer, quality=70):
|
|
202
|
+
buf = BytesIO(image_bytes)
|
|
203
|
+
return cls.from_image(buf, quality=quality)
|
|
204
|
+
|
|
186
205
|
|
|
187
206
|
class PhotosPreuploadParams(QzoneRequestParams):
|
|
188
207
|
uin_fields = ("uin",)
|
|
@@ -33,6 +33,7 @@ __all__ = [
|
|
|
33
33
|
"UploadPicResponse",
|
|
34
34
|
"PhotosPreuploadResponse",
|
|
35
35
|
"FeedData",
|
|
36
|
+
"PicInfo",
|
|
36
37
|
"ProfileFeedData",
|
|
37
38
|
]
|
|
38
39
|
|
|
@@ -273,4 +274,4 @@ class PhotosPreuploadResponse(QzoneResponse):
|
|
|
273
274
|
|
|
274
275
|
picinfos = json_loads(m.group(1))
|
|
275
276
|
assert isinstance(picinfos, list)
|
|
276
|
-
return dict(photos=[PicInfo.from_response_object(info["picinfo"]) for info in picinfos])
|
|
277
|
+
return dict(photos=[PicInfo.from_response_object(info["picinfo"]) for info in picinfos]) # type: ignore
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|