diff --git a/pycloudmusic/__init__.py b/pycloudmusic/__init__.py index f70c31e..efb0ea5 100644 --- a/pycloudmusic/__init__.py +++ b/pycloudmusic/__init__.py @@ -59,5 +59,6 @@ def _id_format(id_, dict_str=False): return format_str from pycloudmusic.music163 import LoginMusic163, Music163Api +from pycloudmusic.ahttp import set_proxy, set_proxy_callback from pycloudmusic.tools import * from pycloudmusic.error import * \ No newline at end of file diff --git a/pycloudmusic/ahttp.py b/pycloudmusic/ahttp.py index f461a6a..c3fa985 100644 --- a/pycloudmusic/ahttp.py +++ b/pycloudmusic/ahttp.py @@ -1,11 +1,14 @@ import os -from typing import Any, Optional +from typing import Any, Callable, Optional import aiofiles, aiohttp from pycloudmusic import MUSIC_HEADERS from pycloudmusic.error import CannotConnectApi, Music163BadCode __session = None +__proxy = None +__proxy_auth = None +__proxy_callback: Optional[Callable[[Exception], tuple[str, Optional[aiohttp.BasicAuth]]]] = None __headers = MUSIC_HEADERS @@ -30,12 +33,27 @@ async def _get_session(): return __session +def set_proxy(proxy, proxy_auth = None): + """设置代理""" + global __proxy + global __proxy_auth + + __proxy = proxy + __proxy_auth = proxy_auth + + +def set_proxy_callback(proxy_callback: Callable[[Exception], tuple[str, Optional[aiohttp.BasicAuth]]]): + """设置代理更新回调""" + global __proxy_callback + + __proxy_callback = proxy_callback + + def reconnection(func): """重新连接""" from pycloudmusic import RECONNECTION async def wrapper(*args, **kwargs): - reconnection_count = 0 try: return await func(*args, **kwargs) except RuntimeError: @@ -47,11 +65,22 @@ async def wrapper(*args, **kwargs): except Exception or not Music163BadCode as err: """重新连接""" - reconnection_count =+ 1 - if reconnection_count > RECONNECTION: + global __proxy + global __proxy_callback + + if __proxy != None and __proxy_callback != None: + global __proxy_auth + __proxy, __proxy_auth = __proxy_callback(err) + + if "reconnection_count" not in kwargs: + kwargs["reconnection_count"] = 1 + else: + kwargs["reconnection_count"] += 1 + + if kwargs["reconnection_count"] > RECONNECTION: raise CannotConnectApi(f"超出重连次数 {RECONNECTION} 无法请求到 {args[0]} err: {err}") - return await func(*args, **kwargs) + return await wrapper(*args, **kwargs) return wrapper @@ -60,10 +89,15 @@ async def wrapper(*args, **kwargs): async def _post_url( url: str, data: Optional[dict[str, Any]] = None, + reconnection_count: Optional[int] = None, ) -> dict[str, Any]: """post 请求""" + global __proxy + global __proxy_auth + session = await _get_session() - async with session.post(url, headers=__headers, data=data) as req: + + async with session.post(url, headers=__headers, data=data, proxy=__proxy, proxy_auth=__proxy_auth) as req: return await req.json(content_type=None) @@ -88,6 +122,8 @@ async def _download( ) -> str: """下载文件""" from pycloudmusic import CHUNK_SIZE + global __proxy + global __proxy_auth if file_path is None: from pycloudmusic import DOWNLOAD_PATH @@ -100,7 +136,7 @@ async def _download( session = await _get_session() async with session.get(url, headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36" - }) as req: + }, proxy=__proxy, proxy_auth=__proxy_auth) as req: async with aiofiles.open(file_path_, "wb") as file_: async for chunk in req.content.iter_chunked(CHUNK_SIZE): await file_.write(chunk) diff --git a/setup.py b/setup.py index ca6fc2a..4afaa33 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ setup( name="pycloudmusic", - version="0.1.4.2", + version="0.1.4.3", description="优雅的异步高性能 Python 音乐 API 库 (网易云音乐)", keywords=[ "cloudmusic",