uiprotect 7.14.2__py3-none-any.whl → 7.15.1__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.

Potentially problematic release.


This version of uiprotect might be problematic. Click here for more details.

uiprotect/api.py CHANGED
@@ -169,6 +169,7 @@ class BaseApiClient:
169
169
  _last_token_cookie: Morsel[str] | None = None
170
170
  _last_token_cookie_decode: dict[str, Any] | None = None
171
171
  _session: aiohttp.ClientSession | None = None
172
+ _public_api_session: aiohttp.ClientSession | None = None
172
173
  _loaded_session: bool = False
173
174
  _cookiename = "TOKEN"
174
175
 
@@ -192,6 +193,7 @@ class BaseApiClient:
192
193
  api_key: str | None = None,
193
194
  verify_ssl: bool = True,
194
195
  session: aiohttp.ClientSession | None = None,
196
+ public_api_session: aiohttp.ClientSession | None = None,
195
197
  ws_timeout: int = 30,
196
198
  cache_dir: Path | None = None,
197
199
  config_dir: Path | None = None,
@@ -218,6 +220,9 @@ class BaseApiClient:
218
220
  if session is not None:
219
221
  self._session = session
220
222
 
223
+ if public_api_session is not None:
224
+ self._public_api_session = public_api_session
225
+
221
226
  self._update_url()
222
227
 
223
228
  def _update_cookiename(self, cookie: SimpleCookie) -> None:
@@ -261,6 +266,15 @@ class BaseApiClient:
261
266
 
262
267
  return self._session
263
268
 
269
+ async def get_public_api_session(self) -> aiohttp.ClientSession:
270
+ """Gets or creates current public API client session"""
271
+ if self._public_api_session is None or self._public_api_session.closed:
272
+ if self._public_api_session is not None and self._public_api_session.closed:
273
+ _LOGGER.debug("Public API session was closed, creating a new one")
274
+ self._public_api_session = aiohttp.ClientSession()
275
+
276
+ return self._public_api_session
277
+
264
278
  async def _auth_websocket(self, force: bool) -> dict[str, str] | None:
265
279
  """Authenticate for Websocket."""
266
280
  if force:
@@ -306,6 +320,12 @@ class BaseApiClient:
306
320
  self._session = None
307
321
  self._loaded_session = False
308
322
 
323
+ async def close_public_api_session(self) -> None:
324
+ """Closing and deletes public API client session"""
325
+ if self._public_api_session is not None:
326
+ await self._public_api_session.close()
327
+ self._public_api_session = None
328
+
309
329
  async def _cancel_update_task(self) -> None:
310
330
  if self._update_task:
311
331
  self._update_task.cancel()
@@ -345,7 +365,11 @@ class BaseApiClient:
345
365
  _LOGGER.debug("Request url: %s", request_url)
346
366
  if not self._verify_ssl:
347
367
  kwargs["ssl"] = False
348
- session = await self.get_session()
368
+
369
+ if public_api:
370
+ session = await self.get_public_api_session()
371
+ else:
372
+ session = await self.get_session()
349
373
 
350
374
  for attempt in range(2):
351
375
  try:
@@ -777,6 +801,7 @@ class ProtectApiClient(BaseApiClient):
777
801
  api_key: str | None = None,
778
802
  verify_ssl: bool = True,
779
803
  session: aiohttp.ClientSession | None = None,
804
+ public_api_session: aiohttp.ClientSession | None = None,
780
805
  ws_timeout: int = 30,
781
806
  cache_dir: Path | None = None,
782
807
  config_dir: Path | None = None,
@@ -797,6 +822,7 @@ class ProtectApiClient(BaseApiClient):
797
822
  api_key=api_key,
798
823
  verify_ssl=verify_ssl,
799
824
  session=session,
825
+ public_api_session=public_api_session,
800
826
  ws_timeout=ws_timeout,
801
827
  ws_receive_timeout=ws_receive_timeout,
802
828
  cache_dir=cache_dir,
@@ -2063,15 +2089,9 @@ class ProtectApiClient(BaseApiClient):
2063
2089
  if not name:
2064
2090
  raise BadRequest("API key name cannot be empty")
2065
2091
 
2066
- user_id = None
2067
- if self._last_token_cookie_decode is not None:
2068
- user_id = self._last_token_cookie_decode.get("userId")
2069
- if not user_id:
2070
- raise BadRequest("User ID not available for API key creation")
2071
-
2072
2092
  response = await self.api_request(
2073
2093
  api_path="/proxy/users/api/v2",
2074
- url=f"/user/{user_id}/keys",
2094
+ url="/user/self/keys",
2075
2095
  method="post",
2076
2096
  json={"name": name},
2077
2097
  )
uiprotect/cli/__init__.py CHANGED
@@ -173,6 +173,7 @@ def main(
173
173
  async def update() -> None:
174
174
  protect._bootstrap = await protect.get_bootstrap()
175
175
  await protect.close_session()
176
+ await protect.close_public_api_session()
176
177
 
177
178
  run_async(update())
178
179
  ctx.obj = CliContext(protect=protect, output_format=output_format)
@@ -286,6 +287,7 @@ def profile_ws(
286
287
  unsub()
287
288
  await protect.async_disconnect_ws()
288
289
  await protect.close_session()
290
+ await protect.close_public_api_session()
289
291
 
290
292
  _setup_logger()
291
293
 
@@ -325,6 +327,7 @@ def create_api_key(
325
327
  async def callback() -> str:
326
328
  api_key = await protect.create_api_key(name)
327
329
  await protect.close_session()
330
+ await protect.close_public_api_session()
328
331
  return api_key
329
332
 
330
333
  _setup_logger()
@@ -340,6 +343,7 @@ def get_meta_info(ctx: typer.Context) -> None:
340
343
  async def callback() -> MetaInfo:
341
344
  meta = await protect.get_meta_info()
342
345
  await protect.close_session()
346
+ await protect.close_public_api_session()
343
347
  return meta
344
348
 
345
349
  _setup_logger()
uiprotect/cli/backup.py CHANGED
@@ -1064,6 +1064,7 @@ async def _events(
1064
1064
  finally:
1065
1065
  _LOGGER.debug("Cleaning up Protect connection/database...")
1066
1066
  await ctx.protect.close_session()
1067
+ await ctx.protect.close_public_api_session()
1067
1068
  await ctx.db_engine.dispose()
1068
1069
 
1069
1070
 
uiprotect/cli/base.py CHANGED
@@ -36,6 +36,7 @@ def run(ctx: typer.Context, func: Coroutine[Any, Any, T]) -> T:
36
36
  async def callback() -> T:
37
37
  return_value = await func
38
38
  await ctx.obj.protect.close_session()
39
+ await ctx.obj.protect.close_public_api_session()
39
40
  return return_value
40
41
 
41
42
  try:
@@ -142,6 +142,7 @@ class SampleDataGenerator:
142
142
 
143
143
  if close_session:
144
144
  await self.client.close_session()
145
+ await self.client.close_public_api_session()
145
146
 
146
147
  await self.write_json_file("sample_constants", self.constants, anonymize=False)
147
148
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: uiprotect
3
- Version: 7.14.2
3
+ Version: 7.15.1
4
4
  Summary: Python API for Unifi Protect (Unofficial)
5
5
  License: MIT
6
6
  Author: UI Protect Maintainers
@@ -1,11 +1,11 @@
1
1
  uiprotect/__init__.py,sha256=Oz6i1tonIz4QWVnEPkbielJDJ3WQdwZVgYtjY4IwGAQ,636
2
2
  uiprotect/__main__.py,sha256=C_bHCOkv5qj6WMy-6ELoY3Y6HDhLxOa1a30CzmbZhsg,462
3
3
  uiprotect/_compat.py,sha256=HThmb1zQZCEssCxYYbQzFhJq8zYYlVaSnIEZabKc-6U,302
4
- uiprotect/api.py,sha256=YcmXBQy4ktZs61U3f7RqwM7hOZ7QS99U9nlGeTYf8Z4,72447
5
- uiprotect/cli/__init__.py,sha256=ANasP55kd1QJ8H0YpHV7lxlMQTiqa2iDLpR5-JmyZjk,9511
4
+ uiprotect/api.py,sha256=MYAkpQTHgoWrVDlNu_szS7FapjJbOhMfFGoHV6DRHYs,73389
5
+ uiprotect/cli/__init__.py,sha256=rVfmLd4Al4-FQZxq7QrYlfr46fBGZv6Aw5huFtmCn58,9707
6
6
  uiprotect/cli/aiports.py,sha256=wpEr2w_hY18CGpFiQM2Yc0FiVwG_1l2CzZhZLGNigvI,1576
7
- uiprotect/cli/backup.py,sha256=ZiS7RZnJGKI8TJKLW2cOUzkRM8nyTvE5Ov_jZZGtvSM,36708
8
- uiprotect/cli/base.py,sha256=5-z-IS8g9iQqhR_YbjxaJAFiMMAY_7cCtNAtvLdRCoM,7524
7
+ uiprotect/cli/backup.py,sha256=9Coo5K4YTvQIrvGVZ-NYUajGnoMIyPhK_juxQxNkdO0,36761
8
+ uiprotect/cli/base.py,sha256=SFwgIeliu1_l07IGMerSNPPKvV2g3-Amoc9YiCGmaVA,7581
9
9
  uiprotect/cli/cameras.py,sha256=YvvMccQEYG3Wih0Ix8tan1R1vfaJ6cogg6YKWLzMUV8,16973
10
10
  uiprotect/cli/chimes.py,sha256=XANn21bQVkestkKOm9HjxSM8ZGrRrqvUXLouaQ3LTqs,5326
11
11
  uiprotect/cli/doorlocks.py,sha256=Go_Tn68bAcmrRAnUIi4kBiR7ciKQsu_R150ubPTjUAs,3523
@@ -28,12 +28,12 @@ uiprotect/exceptions.py,sha256=kgn0cRM6lTtgLza09SDa3ZiX6ue1QqHCOogQ4qu6KTQ,965
28
28
  uiprotect/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  uiprotect/release_cache.json,sha256=NamnSFy78hOWY0DPO87J9ELFCAN6NnVquv8gQO75ZG4,386
30
30
  uiprotect/stream.py,sha256=ls65vMOXF4IlJ5axewFITfhcaTh_ihaFeCkCTfhy0Nk,5168
31
- uiprotect/test_util/__init__.py,sha256=HlQBgIgdtrvT-gQ5OWP92LbgVr_YzsD5NFImLRonUZk,19320
31
+ uiprotect/test_util/__init__.py,sha256=TLTQrqyuLcIxp7bZTk3nIZ0U9znoMTLu7QyxrJKaLo0,19377
32
32
  uiprotect/test_util/anonymize.py,sha256=f-8ijU-_y9r-uAbhIPn0f0I6hzJpAkvJzc8UpWihObI,8478
33
33
  uiprotect/utils.py,sha256=2fLwXN0oz9dcVTFexzLp8jj97lcYrxLZkeEUGf5ehtU,20587
34
34
  uiprotect/websocket.py,sha256=tEyenqblNXHcjWYuf4oRP1E7buNwx6zoECMwpBr-jig,8191
35
- uiprotect-7.14.2.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
36
- uiprotect-7.14.2.dist-info/METADATA,sha256=5SQTlpnGjKliDHK5OjxSuo5iQEbPyzgSzUV-4jM0NU8,11167
37
- uiprotect-7.14.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
38
- uiprotect-7.14.2.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
39
- uiprotect-7.14.2.dist-info/RECORD,,
35
+ uiprotect-7.15.1.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
36
+ uiprotect-7.15.1.dist-info/METADATA,sha256=RI5yrUfDhDn5ZCRbytbZ3VOaMcEAIuK7z2lTirOrrb8,11167
37
+ uiprotect-7.15.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
38
+ uiprotect-7.15.1.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
39
+ uiprotect-7.15.1.dist-info/RECORD,,