newapi-python 0.2.0__py3-none-any.whl → 0.3.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.
- newapi/__init__.py +1 -1
- newapi/_client.py +23 -7
- {newapi_python-0.2.0.dist-info → newapi_python-0.3.0.dist-info}/METADATA +5 -2
- {newapi_python-0.2.0.dist-info → newapi_python-0.3.0.dist-info}/RECORD +6 -6
- {newapi_python-0.2.0.dist-info → newapi_python-0.3.0.dist-info}/WHEEL +0 -0
- {newapi_python-0.2.0.dist-info → newapi_python-0.3.0.dist-info}/licenses/LICENSE +0 -0
newapi/__init__.py
CHANGED
newapi/_client.py
CHANGED
|
@@ -218,6 +218,12 @@ class NewAPI:
|
|
|
218
218
|
) -> int | None:
|
|
219
219
|
if access_token and session_token:
|
|
220
220
|
raise ConfigurationError("pass either access_token or session_token, not both")
|
|
221
|
+
if access_token and user_id is None:
|
|
222
|
+
raise ConfigurationError(
|
|
223
|
+
"user_id is required when authenticating with an access_token; "
|
|
224
|
+
"new-api instances reject such requests with 401 "
|
|
225
|
+
"'Unauthorized, New-Api-User header not provided'"
|
|
226
|
+
)
|
|
221
227
|
if not session_token or user_id is not None:
|
|
222
228
|
return user_id
|
|
223
229
|
try:
|
|
@@ -342,6 +348,8 @@ class NewAPI:
|
|
|
342
348
|
return
|
|
343
349
|
refresh_token = self._tokens.refresh_token
|
|
344
350
|
headers: dict[str, str] = {"Origin": self._origin()}
|
|
351
|
+
if self._tokens.user_id is not None:
|
|
352
|
+
headers[_USER_ID_HEADER] = str(self._tokens.user_id)
|
|
345
353
|
if self._tokens.access_token:
|
|
346
354
|
headers["Authorization"] = f"{self._tokens.token_type} {self._tokens.access_token}"
|
|
347
355
|
try:
|
|
@@ -508,16 +516,17 @@ class NewAPI:
|
|
|
508
516
|
request_headers = {
|
|
509
517
|
"Accept": "application/json",
|
|
510
518
|
"Accept-Language": self.language,
|
|
511
|
-
"User-Agent": "newapi-python/0.
|
|
519
|
+
"User-Agent": "newapi-python/0.3.0",
|
|
512
520
|
}
|
|
513
|
-
if authenticated
|
|
514
|
-
request_headers["Cookie"] = f"{self._session_cookie}={self._tokens.session_token}"
|
|
521
|
+
if authenticated:
|
|
515
522
|
if self._tokens.user_id is not None:
|
|
516
523
|
request_headers[_USER_ID_HEADER] = str(self._tokens.user_id)
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
524
|
+
if self._tokens.session_token:
|
|
525
|
+
request_headers["Cookie"] = f"{self._session_cookie}={self._tokens.session_token}"
|
|
526
|
+
elif self._tokens.access_token:
|
|
527
|
+
request_headers["Authorization"] = (
|
|
528
|
+
f"{self._tokens.token_type} {self._tokens.access_token}"
|
|
529
|
+
)
|
|
521
530
|
if refresh_cookie and not self._session_has_refresh_cookie():
|
|
522
531
|
request_headers["Cookie"] = f"{_REFRESH_COOKIE}={refresh_cookie}"
|
|
523
532
|
if headers:
|
|
@@ -677,12 +686,19 @@ class NewAPI:
|
|
|
677
686
|
if isinstance(session, Mapping):
|
|
678
687
|
raw_session_id = session.get("sid")
|
|
679
688
|
session_id = raw_session_id if isinstance(raw_session_id, str) else None
|
|
689
|
+
user_id = self._tokens.user_id
|
|
690
|
+
user_data = auth.get("user")
|
|
691
|
+
if isinstance(user_data, Mapping):
|
|
692
|
+
raw_user_id = user_data.get("id")
|
|
693
|
+
if isinstance(raw_user_id, int) and not isinstance(raw_user_id, bool):
|
|
694
|
+
user_id = raw_user_id
|
|
680
695
|
return SessionTokens(
|
|
681
696
|
access_token=str(auth["access_token"]),
|
|
682
697
|
refresh_token=refresh_token,
|
|
683
698
|
expires_at=expires_at,
|
|
684
699
|
token_type=str(token_type) if token_type else "Bearer",
|
|
685
700
|
session_id=session_id,
|
|
701
|
+
user_id=user_id,
|
|
686
702
|
)
|
|
687
703
|
|
|
688
704
|
def _resolve_quota_per_unit(self) -> float:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: newapi-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Python client for the user-facing dashboard API of new-api instances
|
|
5
5
|
Author: Eight Labs
|
|
6
6
|
License-Expression: MIT
|
|
@@ -55,10 +55,13 @@ client = NewAPI(
|
|
|
55
55
|
"https://newapi.example.com",
|
|
56
56
|
access_token=os.environ["NEWAPI_ACCESS_TOKEN"],
|
|
57
57
|
refresh_token=os.environ.get("NEWAPI_REFRESH_TOKEN"),
|
|
58
|
+
user_id=int(os.environ["NEWAPI_USER_ID"]),
|
|
58
59
|
)
|
|
59
60
|
```
|
|
60
61
|
|
|
61
|
-
Pass either the instance origin or its full `/api` URL. Tokens are retained only in memory. If a refresh token is supplied, the client sends it as the `new_api_refresh` cookie, rotates the pair after an authenticated `401`, and refreshes proactively when `expires_at` is known.
|
|
62
|
+
Pass either the instance origin or its full `/api` URL. Tokens are retained only in memory. If a refresh token is supplied, the client sends it as the `new_api_refresh` cookie, rotates the pair after an authenticated `401`, and refreshes proactively when `expires_at` is known.
|
|
63
|
+
|
|
64
|
+
Users can also generate a long-lived system access token from the dashboard and pass it as `access_token`. Access-token authentication additionally requires `user_id`: new-api instances verify the numeric `New-Api-User` header on every authenticated request and reject requests without it with `401 Unauthorized, New-Api-User header not provided`. The client sends the header automatically from `user_id`, and `login()` and `refresh()` capture the id from the instance's responses. Such tokens cannot refresh browser sessions on their own.
|
|
62
65
|
|
|
63
66
|
The default browser fingerprint is Chrome. Choose another `curl_cffi` fingerprint or configure proxies by supplying your own `curl_cffi.requests.Session`:
|
|
64
67
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
newapi/__init__.py,sha256=
|
|
2
|
-
newapi/_client.py,sha256=
|
|
1
|
+
newapi/__init__.py,sha256=_BZDS3mvNV8s4ckB4x4duVPa5QxruHLHxCeuS5gYc5I,1310
|
|
2
|
+
newapi/_client.py,sha256=ci7AU9R0_IA_xx-Ev01xjv8NMdxgPoJr2dgrMu85zaI,25791
|
|
3
3
|
newapi/_crypto.py,sha256=ocWpBUsQoZlg_dk1Q_vLVKLGEc6I80RpgYlHmLQXZ-I,3902
|
|
4
4
|
newapi/_exceptions.py,sha256=YlZVzYf6VUKSN-fVVvFHfunoNJg6LLcuR2IdHNKzaCg,2049
|
|
5
5
|
newapi/_models.py,sha256=FWUDMqjroiaZLZdj8v_CKcANB6XZZMULrXWdu5mrxE0,6379
|
|
6
6
|
newapi/_resources.py,sha256=IQ1B3QoufC4p8KpXg6NlU9nmUQgTYmncSIYPLoLKYUc,28476
|
|
7
7
|
newapi/_session_blob.py,sha256=GIv4k2H0YrPghNGRg8iY2LZ8kgkFLrlMCpvUtIy35kw,3547
|
|
8
8
|
newapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
newapi_python-0.
|
|
10
|
-
newapi_python-0.
|
|
11
|
-
newapi_python-0.
|
|
12
|
-
newapi_python-0.
|
|
9
|
+
newapi_python-0.3.0.dist-info/METADATA,sha256=SFbWbiKQppLpy6HXcJ5uTuVVn-KGoV36wDLyjroxlro,11367
|
|
10
|
+
newapi_python-0.3.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
11
|
+
newapi_python-0.3.0.dist-info/licenses/LICENSE,sha256=SIZvsDcR9_4_Q4IMiJNqUwZWvdAmwjRHlXIQkXFwCwE,1067
|
|
12
|
+
newapi_python-0.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|