Skip to content
This repository was archived by the owner on Sep 22, 2024. It is now read-only.

Commit 9665c55

Browse files
committed
Simplification + a way to download a user's profile picture
1 parent 4df6363 commit 9665c55

2 files changed

Lines changed: 30 additions & 29 deletions

File tree

netschoolapi/async_client_wrapper.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,30 @@ def make_requester(self, requests_timeout: Optional[int]) -> Requester:
3333
async def request(
3434
self, requests_timeout: Optional[int], path: str,
3535
method="GET", params: dict = None, json: dict = None,
36-
data: dict = None):
36+
data: dict = None, allow_redirects=False):
3737
if requests_timeout is None:
3838
requests_timeout = self._default_requests_timeout
3939
try:
4040
if requests_timeout == 0:
4141
return await self._infinite_request(
42-
path, method, params, json, data,
42+
path, method, params, json, data, allow_redirects
4343
)
4444
else:
4545
return await asyncio.wait_for(self._infinite_request(
46-
path, method, params, json, data,
46+
path, method, params, json, data, allow_redirects
4747
), requests_timeout)
4848
except asyncio.TimeoutError:
4949
raise errors.NoResponseFromServer from None
5050

5151
async def _infinite_request(
5252
self, path: str, method: str, params: Optional[dict],
53-
json: Optional[dict], data: Optional[dict]):
53+
json: Optional[dict], data: Optional[dict],
54+
allow_redirects: bool):
5455
while True:
5556
try:
5657
response = await self.client.request(
57-
method, path, params=params, json=json, data=data # type: ignore
58+
method, path, params=params, json=json, data=data, # type: ignore
59+
follow_redirects=allow_redirects # type: ignore
5860
)
5961
except httpx.ReadTimeout:
6062
pass

netschoolapi/netschoolapi.py

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414

1515

1616
async def _die_on_bad_status(response: Response):
17-
response.raise_for_status()
17+
if not response.is_redirect:
18+
response.raise_for_status()
1819

1920

2021
class NetSchoolAPI:
@@ -36,6 +37,7 @@ def __init__(
3637

3738
self._assignment_types: Dict[int, str] = {}
3839
self._login_data = ()
40+
self._access_token = None
3941

4042
async def __aenter__(self) -> 'NetSchoolAPI':
4143
return self
@@ -94,6 +96,7 @@ async def login(
9496
if 'at' not in auth_result:
9597
raise errors.AuthError(auth_result['message'])
9698

99+
self._access_token = auth_result["at"]
97100
self._wrapped_client.client.headers['at'] = auth_result['at']
98101

99102
response = await requester('student/diary/init')
@@ -117,10 +120,12 @@ async def login(
117120

118121
async def _request_with_optional_relogin(
119122
self, requests_timeout: Optional[int], path: str,
120-
method="GET", params: dict = None, json: dict = None):
123+
method="GET", params: dict = None, json: dict = None,
124+
data: dict = None, allow_redirects=False):
121125
try:
122126
response = await self._wrapped_client.request(
123127
requests_timeout, path, method, params, json,
128+
data, allow_redirects
124129
)
125130
except httpx.HTTPStatusError as http_status_error:
126131
if (
@@ -130,7 +135,8 @@ async def _request_with_optional_relogin(
130135
if self._login_data:
131136
await self.login(*self._login_data)
132137
return await self._request_with_optional_relogin(
133-
requests_timeout, path, method, params, json
138+
requests_timeout, path, method, params, json,
139+
data, allow_redirects
134140
)
135141
else:
136142
raise errors.AuthError(
@@ -143,33 +149,14 @@ async def _request_with_optional_relogin(
143149
return response
144150

145151
async def download_attachment(
146-
self, attachment_id: int,
147-
path_or_file: Union[BytesIO, str],
152+
self, attachment_id: int, buffer: BytesIO,
148153
requests_timeout: int = None):
149-
if isinstance(path_or_file, str):
150-
file = open(path_or_file, "wb")
151-
file_is_new = True
152-
else:
153-
file = path_or_file
154-
file_is_new = False
155-
file.write((
154+
buffer.write((
156155
await self._request_with_optional_relogin(
157156
requests_timeout,
158157
f"attachments/{attachment_id}",
159158
)
160159
).content)
161-
if file_is_new:
162-
file.close()
163-
164-
async def download_attachment_as_bytes(
165-
self, attachment_id: int, requests_timeout: int = None,
166-
) -> BytesIO:
167-
attachment_contents_buffer = BytesIO()
168-
await self.download_attachment(
169-
attachment_id, path_or_file=attachment_contents_buffer,
170-
requests_timeout=requests_timeout
171-
)
172-
return attachment_contents_buffer
173160

174161
async def diary(
175162
self,
@@ -307,3 +294,15 @@ async def _address(
307294
'scid': school['id'],
308295
}
309296
raise errors.SchoolNotFoundError(school_name_or_id)
297+
298+
async def download_profile_picture(
299+
self, user_id: int, buffer: BytesIO,
300+
requests_timeout: int = None):
301+
buffer.write((
302+
await self._request_with_optional_relogin(
303+
requests_timeout,
304+
"users/photo",
305+
params={"at": self._access_token, "userId": user_id},
306+
allow_redirects=True
307+
)
308+
).content)

0 commit comments

Comments
 (0)