p115client 0.0.5.9__tar.gz → 0.0.5.9.2__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.
Files changed (24) hide show
  1. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/PKG-INFO +1 -1
  2. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/client.py +228 -120
  3. p115client-0.0.5.9.2/p115client/tool/pool.py +409 -0
  4. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/pyproject.toml +1 -1
  5. p115client-0.0.5.9/p115client/tool/pool.py +0 -284
  6. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/LICENSE +0 -0
  7. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/__init__.py +0 -0
  8. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/_upload.py +0 -0
  9. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/const.py +0 -0
  10. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/exception.py +0 -0
  11. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/py.typed +0 -0
  12. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/tool/__init__.py +0 -0
  13. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/tool/download.py +0 -0
  14. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/tool/edit.py +0 -0
  15. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/tool/export_dir.py +0 -0
  16. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/tool/fs_files.py +0 -0
  17. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/tool/history.py +0 -0
  18. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/tool/iterdir.py +0 -0
  19. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/tool/life.py +0 -0
  20. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/tool/request.py +0 -0
  21. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/tool/upload.py +0 -0
  22. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/tool/xys.py +0 -0
  23. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/p115client/type.py +0 -0
  24. {p115client-0.0.5.9 → p115client-0.0.5.9.2}/readme.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: p115client
3
- Version: 0.0.5.9
3
+ Version: 0.0.5.9.2
4
4
  Summary: Python 115 webdisk client.
5
5
  Home-page: https://github.com/ChenyangGao/p115client
6
6
  License: MIT
@@ -939,6 +939,19 @@ class IgnoreCaseDict[V](dict[str, V]):
939
939
  if kwargs:
940
940
  update(((k.lower(), v) for k, v in kwargs.items()))
941
941
 
942
+ def merge(self, *args, **kwargs):
943
+ setdefault = super().setdefault
944
+ for arg in args:
945
+ if not arg:
946
+ continue
947
+ if isinstance(arg, Mapping):
948
+ arg = items(arg)
949
+ for k, v in arg:
950
+ setdefault(k, v)
951
+ if kwargs:
952
+ for k, v in kwargs.items():
953
+ setdefault(k, v)
954
+
942
955
 
943
956
  class ClientRequestMixin:
944
957
 
@@ -1772,7 +1785,7 @@ class ClientRequestMixin:
1772
1785
 
1773
1786
  @overload
1774
1787
  @classmethod
1775
- def login_with_open(
1788
+ def login_with_app_id(
1776
1789
  cls,
1777
1790
  /,
1778
1791
  app_id: int | str = 100195993,
@@ -1784,7 +1797,7 @@ class ClientRequestMixin:
1784
1797
  ...
1785
1798
  @overload
1786
1799
  @classmethod
1787
- def login_with_open(
1800
+ def login_with_app_id(
1788
1801
  cls,
1789
1802
  /,
1790
1803
  app_id: int | str = 100195993,
@@ -1795,7 +1808,7 @@ class ClientRequestMixin:
1795
1808
  ) -> Coroutine[Any, Any, dict]:
1796
1809
  ...
1797
1810
  @classmethod
1798
- def login_with_open(
1811
+ def login_with_app_id(
1799
1812
  cls,
1800
1813
  /,
1801
1814
  app_id: int | str = 100195993,
@@ -2442,7 +2455,7 @@ class P115OpenClient(ClientRequestMixin):
2442
2455
  )
2443
2456
  else:
2444
2457
  app_id = self.app_id = app_id_or_refresh_token
2445
- resp = yield self.login_with_open(
2458
+ resp = yield self.login_with_app_id(
2446
2459
  app_id,
2447
2460
  console_qrcode=console_qrcode,
2448
2461
  async_=async_,
@@ -4263,22 +4276,14 @@ class P115Client(P115OpenClient):
4263
4276
  ) -> None | str:
4264
4277
  cookies_path = self.__dict__.get("cookies_path")
4265
4278
  if not cookies_path:
4266
- return None
4267
- cookies_mtime_old = self.__dict__.get("cookies_mtime", 0)
4268
- try:
4269
- cookies_mtime = cookies_path.stat().st_mtime
4270
- except OSError:
4271
- cookies_mtime = 0
4272
- if cookies_mtime_old >= cookies_mtime:
4273
4279
  return self.cookies_str
4274
4280
  try:
4275
4281
  with cookies_path.open("rb") as f:
4276
4282
  cookies = str(f.read(), encoding)
4277
4283
  setattr(self, "cookies", cookies)
4278
- self.cookies_mtime = cookies_mtime
4279
4284
  return cookies
4280
4285
  except OSError:
4281
- return None
4286
+ return self.cookies_str
4282
4287
 
4283
4288
  def _write_cookies(
4284
4289
  self,
@@ -4293,10 +4298,6 @@ class P115Client(P115OpenClient):
4293
4298
  cookies_bytes = bytes(cookies, encoding)
4294
4299
  with cookies_path.open("wb") as f:
4295
4300
  f.write(cookies_bytes)
4296
- try:
4297
- self.cookies_mtime = cookies_path.stat().st_mtime
4298
- except OSError:
4299
- self.cookies_mtime = 0
4300
4301
 
4301
4302
  @overload # type: ignore
4302
4303
  @classmethod
@@ -4763,6 +4764,8 @@ class P115Client(P115OpenClient):
4763
4764
  def login_without_app(
4764
4765
  self,
4765
4766
  /,
4767
+ show_warning: bool = False,
4768
+ *,
4766
4769
  async_: Literal[False] = False,
4767
4770
  **request_kwargs,
4768
4771
  ) -> str:
@@ -4771,6 +4774,8 @@ class P115Client(P115OpenClient):
4771
4774
  def login_without_app(
4772
4775
  self,
4773
4776
  /,
4777
+ show_warning: bool = False,
4778
+ *,
4774
4779
  async_: Literal[True],
4775
4780
  **request_kwargs,
4776
4781
  ) -> Coroutine[Any, Any, str]:
@@ -4778,29 +4783,93 @@ class P115Client(P115OpenClient):
4778
4783
  def login_without_app(
4779
4784
  self,
4780
4785
  /,
4786
+ show_warning: bool = False,
4787
+ *,
4781
4788
  async_: Literal[False, True] = False,
4782
4789
  **request_kwargs,
4783
4790
  ) -> str | Coroutine[Any, Any, str]:
4784
4791
  """执行一次自动扫登录二维码,但不绑定设备,返回扫码的 uid,可用于之后绑定设备
4792
+
4793
+ :param show_warning: 是否显示提示信息
4794
+ :param async_: 是否异步
4795
+ :param request_kwargs: 其它请求参数
4796
+
4797
+ :return: 二维码的 uid
4785
4798
  """
4786
4799
  def gen_step():
4787
4800
  uid = check_response((yield self.login_qrcode_token(
4788
4801
  async_=async_,
4789
4802
  **request_kwargs,
4790
4803
  )))["data"]["uid"]
4791
- check_response((yield self.login_qrcode_scan(
4804
+ resp = yield self.login_qrcode_scan(
4792
4805
  uid,
4793
4806
  async_=async_,
4794
4807
  **request_kwargs,
4795
- )))
4796
- check_response((yield self.login_qrcode_scan_confirm(
4808
+ )
4809
+ check_response(resp)
4810
+ if show_warning:
4811
+ warn(f"qrcode scanned: {resp}", category=P115Warning)
4812
+ resp = yield self.login_qrcode_scan_confirm(
4797
4813
  uid,
4798
4814
  async_=async_,
4799
4815
  **request_kwargs,
4800
- )))
4816
+ )
4817
+ check_response(resp)
4801
4818
  return uid
4802
4819
  return run_gen_step(gen_step, async_=async_)
4803
4820
 
4821
+ @overload
4822
+ def login_with_open(
4823
+ self,
4824
+ /,
4825
+ app_id: int | str = 100195993,
4826
+ *,
4827
+ show_warning: bool = False,
4828
+ async_: Literal[False] = False,
4829
+ **request_kwargs,
4830
+ ) -> dict:
4831
+ ...
4832
+ @overload
4833
+ def login_with_open(
4834
+ self,
4835
+ /,
4836
+ app_id: int | str = 100195993,
4837
+ *,
4838
+ show_warning: bool = False,
4839
+ async_: Literal[True],
4840
+ **request_kwargs,
4841
+ ) -> Coroutine[Any, Any, dict]:
4842
+ ...
4843
+ def login_with_open(
4844
+ self,
4845
+ /,
4846
+ app_id: int | str = 100195993,
4847
+ *,
4848
+ show_warning: bool = False,
4849
+ async_: Literal[False, True] = False,
4850
+ **request_kwargs,
4851
+ ) -> dict | Coroutine[Any, Any, dict]:
4852
+ """登录某个开放接口应用
4853
+
4854
+ :param app_id: AppID
4855
+ :param show_warning: 是否显示提示信息
4856
+ :param async_: 是否异步
4857
+ :param request_kwargs: 其它请求参数
4858
+
4859
+ :return: 接口返回值
4860
+ """
4861
+ def gen_step():
4862
+ resp = yield self.login_qrcode_token_open(app_id, async_=async_, **request_kwargs)
4863
+ login_uid = check_response(resp)["data"]["uid"]
4864
+ resp = yield self.login_qrcode_scan(login_uid, async_=async_, **request_kwargs)
4865
+ check_response(resp)
4866
+ if show_warning:
4867
+ warn(f"qrcode scanned: {resp}", category=P115Warning)
4868
+ resp = yield self.login_qrcode_scan_confirm(login_uid, async_=async_, **request_kwargs)
4869
+ check_response(resp)
4870
+ return self.login_qrcode_access_token_open(login_uid, async_=async_, **request_kwargs)
4871
+ return run_gen_step(gen_step, async_=async_)
4872
+
4804
4873
  @overload
4805
4874
  def login_another_app(
4806
4875
  self,
@@ -4808,6 +4877,7 @@ class P115Client(P115OpenClient):
4808
4877
  app: None | str = None,
4809
4878
  replace: bool | Self = False,
4810
4879
  check_for_relogin: bool | Callable[[BaseException], bool | int] = False,
4880
+ show_warning: bool = False,
4811
4881
  *,
4812
4882
  async_: Literal[False] = False,
4813
4883
  **request_kwargs,
@@ -4820,6 +4890,7 @@ class P115Client(P115OpenClient):
4820
4890
  app: None | str = None,
4821
4891
  replace: bool | Self = False,
4822
4892
  check_for_relogin: bool | Callable[[BaseException], bool | int] = False,
4893
+ show_warning: bool = False,
4823
4894
  *,
4824
4895
  async_: Literal[True],
4825
4896
  **request_kwargs,
@@ -4831,6 +4902,7 @@ class P115Client(P115OpenClient):
4831
4902
  app: None | str = None,
4832
4903
  replace: bool | Self = False,
4833
4904
  check_for_relogin: bool | Callable[[BaseException], bool | int] = False,
4905
+ show_warning: bool = False,
4834
4906
  *,
4835
4907
  async_: Literal[False, True] = False,
4836
4908
  **request_kwargs,
@@ -4845,8 +4917,8 @@ class P115Client(P115OpenClient):
4845
4917
  :param app: 要登录的 app,如果为 None,则用当前登录设备,如果无当前登录设备,则报错
4846
4918
  :param replace: 替换某个 client 对象的 cookie
4847
4919
 
4848
- - 如果为 P115Client, 则把获取到的 `cookies` 更新到此对象
4849
- - 如果为 True,则把获取到的 `cookies` 更新到 `self`
4920
+ - 如果为 P115Client, 则更新到此对象
4921
+ - 如果为 True,则更新到 `self`
4850
4922
  - 如果为 False,否则返回新的 `P115Client` 对象
4851
4923
 
4852
4924
  :param check_for_relogin: 网页请求抛出异常时,判断是否要重新登录并重试
@@ -4855,9 +4927,12 @@ class P115Client(P115OpenClient):
4855
4927
  - 如果为 True,则自动通过判断 HTTP 响应码为 405 时重新登录并重试
4856
4928
  - 如果为 collections.abc.Callable,则调用以判断,当返回值为 bool 类型且值为 True,或者值为 405 时重新登录,然后循环此流程,直到成功或不可重试
4857
4929
 
4930
+ :param show_warning: 是否显示提示信息
4858
4931
  :param async_: 是否异步
4859
4932
  :param request_kwargs: 其它请求参数
4860
4933
 
4934
+ :return: 客户端实例
4935
+
4861
4936
  -----
4862
4937
 
4863
4938
  :设备列表如下:
@@ -4918,7 +4993,12 @@ class P115Client(P115OpenClient):
4918
4993
  nonlocal app
4919
4994
  if not app and isinstance(replace, P115Client):
4920
4995
  app = yield replace.login_app(async_=True)
4921
- resp = yield self.login_with_app(app, async_=async_, **request_kwargs)
4996
+ resp = yield self.login_with_app(
4997
+ app,
4998
+ show_warning=show_warning,
4999
+ async_=async_,
5000
+ **request_kwargs,
5001
+ )
4922
5002
  cookies = check_response(resp)["data"]["cookie"]
4923
5003
  ssoent = self.login_ssoent
4924
5004
  if isinstance(replace, P115Client):
@@ -4941,6 +5021,7 @@ class P115Client(P115OpenClient):
4941
5021
  app_id: int | str = 100195993,
4942
5022
  *,
4943
5023
  replace: Literal[True] | Self,
5024
+ show_warning: bool = False,
4944
5025
  async_: Literal[False] = False,
4945
5026
  **request_kwargs,
4946
5027
  ) -> Self:
@@ -4952,6 +5033,7 @@ class P115Client(P115OpenClient):
4952
5033
  app_id: int | str = 100195993,
4953
5034
  *,
4954
5035
  replace: Literal[True] | Self,
5036
+ show_warning: bool = False,
4955
5037
  async_: Literal[True],
4956
5038
  **request_kwargs,
4957
5039
  ) -> Coroutine[Any, Any, Self]:
@@ -4963,6 +5045,7 @@ class P115Client(P115OpenClient):
4963
5045
  app_id: int | str = 100195993,
4964
5046
  *,
4965
5047
  replace: Literal[False] = False,
5048
+ show_warning: bool = False,
4966
5049
  async_: Literal[False] = False,
4967
5050
  **request_kwargs,
4968
5051
  ) -> P115OpenClient:
@@ -4974,6 +5057,7 @@ class P115Client(P115OpenClient):
4974
5057
  app_id: int | str = 100195993,
4975
5058
  *,
4976
5059
  replace: Literal[False] = False,
5060
+ show_warning: bool = False,
4977
5061
  async_: Literal[True],
4978
5062
  **request_kwargs,
4979
5063
  ) -> Coroutine[Any, Any, P115OpenClient]:
@@ -4984,23 +5068,33 @@ class P115Client(P115OpenClient):
4984
5068
  app_id: int | str = 100195993,
4985
5069
  *,
4986
5070
  replace: bool | Self = False,
5071
+ show_warning: bool = False,
4987
5072
  async_: Literal[False, True] = False,
4988
5073
  **request_kwargs,
4989
5074
  ) -> P115OpenClient | Coroutine[Any, Any, P115OpenClient] | Self | Coroutine[Any, Any, Self]:
4990
5075
  """登录某个开放接口应用
4991
5076
 
4992
5077
  :param app_id: AppID
5078
+ :param replace: 替换某个 client 对象的 `access_token` 和 `refresh_token`
5079
+
5080
+ - 如果为 P115Client, 则更新到此对象
5081
+ - 如果为 True,则更新到 `self`
5082
+ - 如果为 False,否则返回新的 `P115Client` 对象
5083
+
5084
+ :param show_warning: 是否显示提示信息
4993
5085
  :param async_: 是否异步
4994
5086
  :param request_kwargs: 其它请求参数
5087
+
5088
+ :return: 客户端实例
4995
5089
  """
4996
5090
  def gen_step():
4997
- resp = yield self.login_qrcode_token_open(app_id, async_=async_, **request_kwargs)
4998
- login_uid = check_response(resp)["data"]["uid"]
4999
- yield self.login_qrcode_scan(login_uid, async_=async_, **request_kwargs)
5000
- yield self.login_qrcode_scan_confirm(login_uid, async_=async_, **request_kwargs)
5001
- resp = yield self.login_qrcode_access_token_open(login_uid, async_=async_, **request_kwargs)
5002
- check_response(resp)
5003
- data = resp["data"]
5091
+ resp = yield self.login_with_open(
5092
+ app_id,
5093
+ show_warning=show_warning,
5094
+ async_=async_,
5095
+ **request_kwargs,
5096
+ )
5097
+ data = check_response(resp)["data"]
5004
5098
  if replace is False:
5005
5099
  inst: P115OpenClient | Self = P115OpenClient.from_token(data["access_token"], data["refresh_token"])
5006
5100
  else:
@@ -5175,9 +5269,10 @@ class P115Client(P115OpenClient):
5175
5269
  params = None,
5176
5270
  data = None,
5177
5271
  *,
5272
+ check: bool = False,
5178
5273
  ecdh_encrypt: bool = False,
5179
- get_cookies: None | Callable[..., None | str] = None,
5180
- revert_cookies: None | Callable[[str], Any] = None,
5274
+ fetch_cert_headers: None | Callable[..., Mapping] | Callable[..., Awaitable[Mapping]] = None,
5275
+ revert_cert_headers: None | Callable[[Mapping], Any] = None,
5181
5276
  async_: Literal[False, True] = False,
5182
5277
  request: None | Callable[[Unpack[RequestKeywords]], Any] = None,
5183
5278
  **request_kwargs,
@@ -5187,9 +5282,10 @@ class P115Client(P115OpenClient):
5187
5282
  :param url: HTTP 的请求链接
5188
5283
  :param method: HTTP 的请求方法
5189
5284
  :param params: 查询参数
5285
+ :param check: 是否用 `check_response` 函数检查返回值
5190
5286
  :param ecdh_encrypt: 使用 ecdh 算法进行加密(返回值也要解密)
5191
- :param get_cookies: 调用以获取 cookies
5192
- :param revert_cookies: 调用以退还 cookies
5287
+ :param fetch_cert_headers: 调用以获取认证信息头
5288
+ :param revert_cert_headers: 调用以退还认证信息头
5193
5289
  :param async_: 说明 `request` 是同步调用还是异步调用
5194
5290
  :param request: HTTP 请求调用,如果为 None,则默认用 httpx 执行请求
5195
5291
  如果传入调用,则必须至少能接受以下几个关键词参数:
@@ -5265,18 +5361,39 @@ class P115Client(P115OpenClient):
5265
5361
  url = "http://webapi.115.com" + url
5266
5362
  if params:
5267
5363
  url = make_url(url, params)
5364
+ is_open_api = url.startswith("https://proapi.115.com/open/")
5365
+ headers = IgnoreCaseDict(request_kwargs.get("headers") or {})
5366
+ request_kwargs["headers"] = headers
5367
+ check_for_relogin = self.check_for_relogin
5368
+ need_to_check = callable(check_for_relogin)
5369
+ if need_to_check and fetch_cert_headers is None:
5370
+ if is_open_api:
5371
+ need_to_check = "authorization" not in headers
5372
+ else:
5373
+ need_to_check = "cookie" not in headers
5374
+ need_fetch_cert_first = False
5375
+ if fetch_cert_headers is not None:
5376
+ fetch_cert_headers_argcount = argcount(fetch_cert_headers)
5377
+ if async_:
5378
+ fetch_cert_headers = ensure_async(fetch_cert_headers)
5379
+ if fetch_cert_headers_argcount:
5380
+ fetch_cert_headers = partial(fetch_cert_headers, async_)
5381
+ if revert_cert_headers is not None and async_:
5382
+ revert_cert_headers = ensure_async(revert_cert_headers)
5383
+ if is_open_api:
5384
+ need_fetch_cert_first = "authorization" not in headers
5385
+ else:
5386
+ need_fetch_cert_first = "cookie" not in headers
5268
5387
  if request is None:
5269
5388
  request_kwargs["session"] = self.async_session if async_ else self.session
5270
5389
  request_kwargs["async_"] = async_
5271
- headers: IgnoreCaseDict[str] = IgnoreCaseDict()
5272
5390
  request = get_default_request()
5273
5391
  else:
5274
- headers = IgnoreCaseDict(self.headers)
5275
- headers.update(request_kwargs.get("headers") or {})
5276
- need_set_cookies = get_cookies is not None or "cookie" not in headers
5392
+ headers.merge(self.headers)
5393
+ if is_open_api:
5394
+ headers["cookie"] = ""
5277
5395
  if m := CRE_API_match(url):
5278
5396
  headers["host"] = m.expand(r"\1.api.115.com")
5279
- request_kwargs["headers"] = headers
5280
5397
  if ecdh_encrypt:
5281
5398
  url = make_url(url, _default_k_ec)
5282
5399
  if data:
@@ -5288,112 +5405,103 @@ class P115Client(P115OpenClient):
5288
5405
  elif data is not None:
5289
5406
  request_kwargs["data"] = data
5290
5407
  request_kwargs.setdefault("parse", default_parse)
5291
- use_cookies = not url.startswith("https://proapi.115.com/open/")
5292
- if not use_cookies:
5293
- headers["cookie"] = ""
5294
5408
  def gen_step():
5409
+ cert_headers: None | Mapping = None
5410
+ if need_fetch_cert_first:
5411
+ cert_headers = yield fetch_cert_headers
5412
+ headers.update(cert_headers)
5295
5413
  if async_:
5296
5414
  lock: Lock | AsyncLock = self.request_alock
5297
5415
  else:
5298
5416
  lock = self.request_lock
5299
- check_for_relogin = self.check_for_relogin
5300
- cant_relogin = not callable(check_for_relogin)
5301
- if get_cookies is not None:
5302
- get_cookies_need_arg = argcount(get_cookies) >= 1
5303
- cookies_new: None | str
5304
- cookies_: None | str = None
5417
+ if is_open_api:
5418
+ if "authorization" not in headers:
5419
+ yield lock.acquire
5420
+ try:
5421
+ yield self.login_another_open(
5422
+ async_=async_, # type: ignore
5423
+ )
5424
+ finally:
5425
+ lock.release()
5426
+ elif "cookie" not in headers:
5427
+ headers["cookie"] = self.cookies_str
5305
5428
  for i in count(0):
5306
- exc = None
5307
5429
  try:
5308
- if use_cookies:
5309
- if get_cookies is None:
5310
- if need_set_cookies:
5311
- cookies_old = headers["cookie"] = self.cookies_str
5430
+ if need_fetch_cert_first is None:
5431
+ if is_open_api:
5432
+ cert: str = headers["authorization"]
5312
5433
  else:
5313
- if get_cookies_need_arg:
5314
- cookies_ = yield get_cookies(async_)
5315
- else:
5316
- cookies_ = yield get_cookies()
5317
- if not cookies_:
5318
- raise ValueError("can't get new cookies")
5319
- headers["cookie"] = cookies_
5320
- resp = yield partial(request, url=url, method=method, **request_kwargs)
5321
- return resp
5434
+ cert = headers["cookie"]
5435
+ resp = yield partial(
5436
+ cast(Callable, request),
5437
+ url=url,
5438
+ method=method,
5439
+ **request_kwargs,
5440
+ )
5322
5441
  except BaseException as e:
5323
- exc = e
5324
- if cant_relogin or use_cookies and not need_set_cookies:
5325
- raise
5326
- if isinstance(e, (AuthenticationError, LoginError)):
5327
- if use_cookies and (
5328
- get_cookies is not None or
5329
- cookies_old != self.cookies_str or
5330
- cookies_old != self._read_cookies()
5331
- ):
5332
- continue
5442
+ is_auth_error = isinstance(e, (AuthenticationError, LoginError))
5443
+ if (
5444
+ cert_headers is not None and
5445
+ revert_cert_headers is not None and
5446
+ not is_auth_error and
5447
+ get_status_code(e) != 405
5448
+ ):
5449
+ yield partial(revert_cert_headers, cert_headers)
5450
+ if not need_to_check:
5333
5451
  raise
5334
5452
  res = yield partial(cast(Callable, check_for_relogin), e)
5335
5453
  if not res if isinstance(res, bool) else res != 405:
5336
5454
  raise
5337
- if use_cookies:
5338
- if get_cookies is not None:
5339
- continue
5340
- cookies = self.cookies_str
5341
- if not cookies_equal(cookies, cookies_old):
5342
- continue
5343
- cookies_mtime = getattr(self, "cookies_mtime", 0)
5455
+ if fetch_cert_headers is not None:
5456
+ cert_headers = yield fetch_cert_headers
5457
+ headers.update(cert_headers)
5458
+ elif is_open_api:
5344
5459
  yield lock.acquire
5345
5460
  try:
5346
- cookies_new = self.cookies_str
5347
- cookies_mtime_new = getattr(self, "cookies_mtime", 0)
5348
- if cookies_equal(cookies, cookies_new):
5349
- m = CRE_COOKIES_UID_search(cookies)
5350
- uid = "" if m is None else m[0]
5351
- need_read_cookies = cookies_mtime_new > cookies_mtime
5352
- if need_read_cookies:
5353
- cookies_new = self._read_cookies()
5354
- if i and cookies_equal(cookies_old, cookies_new):
5355
- raise
5356
- if not (need_read_cookies and cookies_new):
5357
- warn(f"relogin to refresh cookies: UID={uid!r} app={self.login_app()!r}", category=P115Warning)
5358
- yield self.login_another_app(
5359
- replace=True,
5360
- async_=async_, # type: ignore
5361
- )
5461
+ if cert != self.access_token:
5462
+ continue
5463
+ if i or is_auth_error:
5464
+ raise
5465
+ app_id = getattr(self, "app_id", 100195993)
5466
+ yield self.login_another_open(
5467
+ app_id,
5468
+ replace=True,
5469
+ async_=async_, # type: ignore
5470
+ )
5471
+ warn(f"relogin to refresh token: {app_id=}", category=P115Warning)
5362
5472
  finally:
5363
5473
  lock.release()
5364
5474
  else:
5365
- access_token = self.access_token
5366
5475
  yield lock.acquire
5367
5476
  try:
5368
- if access_token != self.access_token:
5369
- continue
5370
- if hasattr(self, "app_id"):
5371
- app_id = self.app_id
5372
- yield self.login_another_open(
5373
- app_id,
5477
+ cookies_new: str = self.cookies_str
5478
+ if cookies_equal(cert, cookies_new):
5479
+ if self.__dict__.get("cookies_path"):
5480
+ cookies_new = self._read_cookies() or ""
5481
+ if not cookies_equal(cert, cookies_new):
5482
+ headers["cookie"] = cookies_new
5483
+ continue
5484
+ if i or is_auth_error:
5485
+ raise
5486
+ m = CRE_COOKIES_UID_search(cert)
5487
+ uid = "" if m is None else m[0]
5488
+ if not uid:
5489
+ raise
5490
+ warn(f"relogin to refresh cookies: UID={uid!r} app={self.login_app()!r}", category=P115Warning)
5491
+ yield self.login_another_app(
5374
5492
  replace=True,
5375
5493
  async_=async_, # type: ignore
5376
5494
  )
5377
- warn(f"relogin to refresh token: {app_id=}", category=P115Warning)
5378
5495
  else:
5379
- resp = yield self.refresh_access_token(
5380
- async_=async_, # type: ignore
5381
- )
5382
- check_response(resp)
5383
- warn("relogin to refresh token (using refresh_token)", category=P115Warning)
5496
+ headers["cookie"] = cookies_new
5384
5497
  finally:
5385
5498
  lock.release()
5386
- finally:
5387
- if (use_cookies and cookies_ and
5388
- get_cookies is not None and
5389
- revert_cookies is not None and (
5390
- not exc or not (
5391
- isinstance(exc, (AuthenticationError, LoginError)) or
5392
- get_status_code(exc) == 405
5393
- )
5394
- )
5395
- ):
5396
- yield partial(revert_cookies, cookies_)
5499
+ else:
5500
+ if cert_headers is not None and revert_cert_headers is not None:
5501
+ yield partial(revert_cert_headers, cert_headers)
5502
+ if check and isinstance(resp, dict):
5503
+ check_response(resp)
5504
+ return resp
5397
5505
  return run_gen_step(gen_step, async_=async_)
5398
5506
 
5399
5507
  ########## Activity API ##########