diff --git a/bilibili_api/data/api/credential.json b/bilibili_api/data/api/credential.json index eef067ab..2625a645 100644 --- a/bilibili_api/data/api/credential.json +++ b/bilibili_api/data/api/credential.json @@ -48,6 +48,14 @@ "refresh_token": "在刷新前 localStorage 中的ac_time_value获取,并非刷新后返回的值" }, "comment": "确认刷新" + }, + "active": { + "url": "https://api.bilibili.com/x/internal/gaia-gateway/ExClimbWuzhi", + "method": "POST", + "verify": false, + "json_body": true, + "data": "see https://github.com/SocialSisterYi/bilibili-API-collect/issues/933", + "comment": "激活 buvid3" } } } diff --git a/bilibili_api/exceptions/ExClimbWuzhiException.py b/bilibili_api/exceptions/ExClimbWuzhiException.py new file mode 100644 index 00000000..68a68eac --- /dev/null +++ b/bilibili_api/exceptions/ExClimbWuzhiException.py @@ -0,0 +1,17 @@ +""" +bilibili_api.exceptions.ExClimbWuzhiException + +ExClimbWuzhi 失败异常 +""" + +from .ApiException import ApiException + + +class ExClimbWuzhiException(ApiException): + """ + ExClimbWuzhi 失败异常 + """ + + def __init__(self, code: int, msg: str): + super().__init__() + self.msg = f"ExClimbWuzhi 失败,信息: {code} - {msg}" diff --git a/bilibili_api/exceptions/__init__.py b/bilibili_api/exceptions/__init__.py index 154f4ca1..abdbda27 100644 --- a/bilibili_api/exceptions/__init__.py +++ b/bilibili_api/exceptions/__init__.py @@ -20,3 +20,4 @@ from .DynamicExceedImagesException import * from .CredentialNoAcTimeValueException import * from .StatementException import * +from .ExClimbWuzhiException import * diff --git a/bilibili_api/login_func.py b/bilibili_api/login_func.py index da61c64d..1d6752c2 100644 --- a/bilibili_api/login_func.py +++ b/bilibili_api/login_func.py @@ -66,7 +66,7 @@ def check_qrcode_events(login_key: str) -> Tuple[QrCodeLoginEvents, Union[str, C elif events["code"] == 86038: return QrCodeLoginEvents.TIMEOUT, events["message"] elif events["code"] == 0: - url: str = events["data"]["url"] + url: str = events["url"] cookies_list = url.split("?")[1].split("&") sessdata = "" bili_jct = "" diff --git a/bilibili_api/user.py b/bilibili_api/user.py index 8197bf65..b2096b82 100644 --- a/bilibili_api/user.py +++ b/bilibili_api/user.py @@ -666,7 +666,6 @@ async def get_dynamics_new(self, offset: int = "") -> dict: Returns: dict: 调用接口返回的内容。 """ - self.credential.raise_for_no_sessdata() api = API["info"]["dynamic_new"] params = { "host_mid": self.__uid, diff --git a/bilibili_api/utils/credential.py b/bilibili_api/utils/credential.py index 0e129360..5bf27133 100644 --- a/bilibili_api/utils/credential.py +++ b/bilibili_api/utils/credential.py @@ -29,6 +29,7 @@ def __init__( buvid3: Union[str, None] = None, dedeuserid: Union[str, None] = None, ac_time_value: Union[str, None] = None, + **kwargs ) -> None: """ 各字段获取方式查看:https://nemo2011.github.io/bilibili-api/#/get-credential.md @@ -43,6 +44,9 @@ def __init__( dedeuserid (str | None, optional): 浏览器 Cookies 中的 DedeUserID 字段值. Defaults to None. ac_time_value (str | None, optional): 浏览器 Cookies 中的 ac_time_value 字段值. Defaults to None. + + + 其他 Cookie 参数可以直接填入,优先级低于上述参数。 """ self.sessdata = ( None @@ -56,6 +60,9 @@ def __init__( self.dedeuserid = dedeuserid self.ac_time_value = ac_time_value + for key, value in kwargs.items(): + setattr(self, key, value) + def get_cookies(self) -> dict: """ 获取请求 Cookies 字典 @@ -71,6 +78,11 @@ def get_cookies(self) -> dict: } if self.dedeuserid: cookies.update({"DedeUserID": self.dedeuserid}) + + # 填入所有其他参数 + for key, value in self.__dict__.items(): + if key not in cookies and value is not None: + cookies[key] = value return cookies def has_dedeuserid(self) -> bool: diff --git a/bilibili_api/utils/credential_refresh.py b/bilibili_api/utils/credential_refresh.py index f50dc58d..ff44bdbc 100644 --- a/bilibili_api/utils/credential_refresh.py +++ b/bilibili_api/utils/credential_refresh.py @@ -183,6 +183,7 @@ async def refresh_cookies(credential: Credential) -> Credential: bili_jct=resp.cookies["bili_jct"], dedeuserid=resp.cookies["DedeUserID"], ac_time_value=resp.json()["data"]["refresh_token"], + **credential.__dict__.items(), ) await confirm_refresh(credential, new_credential) return new_credential diff --git a/bilibili_api/utils/exclimbwuzhi.py b/bilibili_api/utils/exclimbwuzhi.py new file mode 100644 index 00000000..94fa44df --- /dev/null +++ b/bilibili_api/utils/exclimbwuzhi.py @@ -0,0 +1,293 @@ +import time +import random +import struct +import io +import json + + +MOD = 1 << 64 + + +def get_time_milli() -> int: + return int(time.time() * 1000) + + +def rotate_left(x: int, k: int) -> int: + bin_str = bin(x)[2:].rjust(64, "0") + return int(bin_str[k:] + bin_str[:k], base=2) + + +def gen_uuid_infoc() -> str: + t = get_time_milli() % 100000 + mp = list("123456789ABCDEF") + ["10"] + pck = [8, 4, 4, 4, 12] + gen_part = lambda x: "".join([random.choice(mp) for _ in range(x)]) + return "-".join([gen_part(l) for l in pck]) + str(t).ljust(5, "0") + "infoc" + + +def gen_b_lsid() -> str: + ret = "" + for _ in range(8): + ret += hex(random.randint(0, 15))[2:].upper() + ret = f"{ret}_{hex(get_time_milli())[2:].upper()}" + return ret + + +def gen_buvid_fp(key: str, seed: int): + source = io.BytesIO(bytes(key, "ascii")) + m = murmur3_x64_128(source, seed) + return "{}{}".format(hex(m & (MOD - 1))[2:], hex(m >> 64)[2:]) + + +def murmur3_x64_128(source: io.BufferedIOBase, seed: int) -> str: + C1 = 0x87C3_7B91_1142_53D5 + C2 = 0x4CF5_AD43_2745_937F + C3 = 0x52DC_E729 + C4 = 0x3849_5AB5 + R1, R2, R3, M = 27, 31, 33, 5 + h1, h2 = seed, seed + processed = 0 + while 1: + read = source.read(16) + processed += len(read) + if len(read) == 16: + k1 = struct.unpack("= 15: + k2 ^= int(read[14]) << 48 + if len(read) >= 14: + k2 ^= int(read[13]) << 40 + if len(read) >= 13: + k2 ^= int(read[12]) << 32 + if len(read) >= 12: + k2 ^= int(read[11]) << 24 + if len(read) >= 11: + k2 ^= int(read[10]) << 16 + if len(read) >= 10: + k2 ^= int(read[9]) << 8 + if len(read) >= 9: + k2 ^= int(read[8]) + k2 = rotate_left(k2 * C2 % MOD, R3) * C1 % MOD + h2 ^= k2 + if len(read) >= 8: + k1 ^= int(read[7]) << 56 + if len(read) >= 7: + k1 ^= int(read[6]) << 48 + if len(read) >= 6: + k1 ^= int(read[5]) << 40 + if len(read) >= 5: + k1 ^= int(read[4]) << 32 + if len(read) >= 4: + k1 ^= int(read[3]) << 24 + if len(read) >= 3: + k1 ^= int(read[2]) << 16 + if len(read) >= 2: + k1 ^= int(read[1]) << 8 + if len(read) >= 1: + k1 ^= int(read[0]) + k1 = rotate_left(k1 * C1 % MOD, R2) * C2 % MOD + h1 ^= k1 + + +def fmix64(k: int) -> int: + C1 = 0xFF51_AFD7_ED55_8CCD + C2 = 0xC4CE_B9FE_1A85_EC53 + R = 33 + tmp = k + tmp ^= tmp >> R + tmp = tmp * C1 % MOD + tmp ^= tmp >> R + tmp = tmp * C2 % MOD + tmp ^= tmp >> R + return tmp + + +def get_payload(uuid: str) -> str: + content = { + "3064": 1, + "5062": get_time_milli(), + "03bf": "https%3A%2F%2Fwww.bilibili.com%2F", + "39c8": "333.788.fp.risk", + "34f1": "", + "d402": "", + "654a": "", + "6e7c": "839x959", + "3c43": { + "2673": 0, + "5766": 24, + "6527": 0, + "7003": 1, + "807e": 1, + "b8ce": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.3 Safari/605.1.15", + "641c": 0, + "07a4": "en-US", + "1c57": "not available", + "0bd0": 8, + "748e": [900, 1440], + "d61f": [875, 1440], + "fc9d": -480, + "6aa9": "Asia/Shanghai", + "75b8": 1, + "3b21": 1, + "8a1c": 0, + "d52f": "not available", + "adca": "MacIntel", + "80c9": [ + [ + "PDF Viewer", + "Portable Document Format", + [["application/pdf", "pdf"], ["text/pdf", "pdf"]], + ], + [ + "Chrome PDF Viewer", + "Portable Document Format", + [["application/pdf", "pdf"], ["text/pdf", "pdf"]], + ], + [ + "Chromium PDF Viewer", + "Portable Document Format", + [["application/pdf", "pdf"], ["text/pdf", "pdf"]], + ], + [ + "Microsoft Edge PDF Viewer", + "Portable Document Format", + [["application/pdf", "pdf"], ["text/pdf", "pdf"]], + ], + [ + "WebKit built-in PDF", + "Portable Document Format", + [["application/pdf", "pdf"], ["text/pdf", "pdf"]], + ], + ], + "13ab": "0dAAAAAASUVORK5CYII=", + "bfe9": "QgAAEIQAACEIAABCCQN4FXANGq7S8KTZayAAAAAElFTkSuQmCC", + "a3c1": [ + "extensions:ANGLE_instanced_arrays;EXT_blend_minmax;EXT_color_buffer_half_float;EXT_float_blend;EXT_frag_depth;EXT_shader_texture_lod;EXT_texture_compression_bptc;EXT_texture_compression_rgtc;EXT_texture_filter_anisotropic;EXT_sRGB;KHR_parallel_shader_compile;OES_element_index_uint;OES_fbo_render_mipmap;OES_standard_derivatives;OES_texture_float;OES_texture_float_linear;OES_texture_half_float;OES_texture_half_float_linear;OES_vertex_array_object;WEBGL_color_buffer_float;WEBGL_compressed_texture_astc;WEBGL_compressed_texture_etc;WEBGL_compressed_texture_etc1;WEBGL_compressed_texture_pvrtc;WEBKIT_WEBGL_compressed_texture_pvrtc;WEBGL_compressed_texture_s3tc;WEBGL_compressed_texture_s3tc_srgb;WEBGL_debug_renderer_info;WEBGL_debug_shaders;WEBGL_depth_texture;WEBGL_draw_buffers;WEBGL_lose_context;WEBGL_multi_draw", + "webgl aliased line width range:[1, 1]", + "webgl aliased point size range:[1, 511]", + "webgl alpha bits:8", + "webgl antialiasing:yes", + "webgl blue bits:8", + "webgl depth bits:24", + "webgl green bits:8", + "webgl max anisotropy:16", + "webgl max combined texture image units:32", + "webgl max cube map texture size:16384", + "webgl max fragment uniform vectors:1024", + "webgl max render buffer size:16384", + "webgl max texture image units:16", + "webgl max texture size:16384", + "webgl max varying vectors:30", + "webgl max vertex attribs:16", + "webgl max vertex texture image units:16", + "webgl max vertex uniform vectors:1024", + "webgl max viewport dims:[16384, 16384]", + "webgl red bits:8", + "webgl renderer:WebKit WebGL", + "webgl shading language version:WebGL GLSL ES 1.0 (1.0)", + "webgl stencil bits:0", + "webgl vendor:WebKit", + "webgl version:WebGL 1.0", + "webgl unmasked vendor:Apple Inc.", + "webgl unmasked renderer:Apple GPU", + "webgl vertex shader high float precision:23", + "webgl vertex shader high float precision rangeMin:127", + "webgl vertex shader high float precision rangeMax:127", + "webgl vertex shader medium float precision:23", + "webgl vertex shader medium float precision rangeMin:127", + "webgl vertex shader medium float precision rangeMax:127", + "webgl vertex shader low float precision:23", + "webgl vertex shader low float precision rangeMin:127", + "webgl vertex shader low float precision rangeMax:127", + "webgl fragment shader high float precision:23", + "webgl fragment shader high float precision rangeMin:127", + "webgl fragment shader high float precision rangeMax:127", + "webgl fragment shader medium float precision:23", + "webgl fragment shader medium float precision rangeMin:127", + "webgl fragment shader medium float precision rangeMax:127", + "webgl fragment shader low float precision:23", + "webgl fragment shader low float precision rangeMin:127", + "webgl fragment shader low float precision rangeMax:127", + "webgl vertex shader high int precision:0", + "webgl vertex shader high int precision rangeMin:31", + "webgl vertex shader high int precision rangeMax:30", + "webgl vertex shader medium int precision:0", + "webgl vertex shader medium int precision rangeMin:31", + "webgl vertex shader medium int precision rangeMax:30", + "webgl vertex shader low int precision:0", + "webgl vertex shader low int precision rangeMin:31", + "webgl vertex shader low int precision rangeMax:30", + "webgl fragment shader high int precision:0", + "webgl fragment shader high int precision rangeMin:31", + "webgl fragment shader high int precision rangeMax:30", + "webgl fragment shader medium int precision:0", + "webgl fragment shader medium int precision rangeMin:31", + "webgl fragment shader medium int precision rangeMax:30", + "webgl fragment shader low int precision:0", + "webgl fragment shader low int precision rangeMin:31", + "webgl fragment shader low int precision rangeMax:30", + ], + "6bc5": "Apple Inc.~Apple GPU", + "ed31": 0, + "72bd": 0, + "097b": 0, + "52cd": [0, 0, 0], + "a658": [ + "Andale Mono", + "Arial", + "Arial Black", + "Arial Hebrew", + "Arial Narrow", + "Arial Rounded MT Bold", + "Arial Unicode MS", + "Comic Sans MS", + "Courier", + "Courier New", + "Geneva", + "Georgia", + "Helvetica", + "Helvetica Neue", + "Impact", + "LUCIDA GRANDE", + "Microsoft Sans Serif", + "Monaco", + "Palatino", + "Tahoma", + "Times", + "Times New Roman", + "Trebuchet MS", + "Verdana", + "Wingdings", + "Wingdings 2", + "Wingdings 3", + ], + "d02f": "124.04345259929687", + }, + "54ef": '{"in_new_ab":true,"ab_version":{"remove_back_version":"REMOVE","login_dialog_version":"V_PLAYER_PLAY_TOAST","open_recommend_blank":"SELF","storage_back_btn":"HIDE","call_pc_app":"FORBID","clean_version_old":"GO_NEW","optimize_fmp_version":"LOADED_METADATA","for_ai_home_version":"V_OTHER","bmg_fallback_version":"DEFAULT","ai_summary_version":"SHOW","weixin_popup_block":"ENABLE","rcmd_tab_version":"DISABLE","in_new_ab":true},"ab_split_num":{"remove_back_version":11,"login_dialog_version":43,"open_recommend_blank":90,"storage_back_btn":87,"call_pc_app":47,"clean_version_old":46,"optimize_fmp_version":28,"for_ai_home_version":38,"bmg_fallback_version":86,"ai_summary_version":466,"weixin_popup_block":45,"rcmd_tab_version":90,"in_new_ab":0},"pageVersion":"new_video","videoGoOldVersion":-1}', + "8b94": "https%3A%2F%2Fwww.bilibili.com%2F", + "df35": uuid, + "07a4": "en-US", + "5f45": None, + "db46": 0, + } + return json.dumps( + {"payload": json.dumps(content, separators=(",", ":"))}, + separators=(",", ":"), + ) diff --git a/bilibili_api/utils/network.py b/bilibili_api/utils/network.py index ac1ab9e1..594d197a 100644 --- a/bilibili_api/utils/network.py +++ b/bilibili_api/utils/network.py @@ -25,7 +25,8 @@ from .. import settings from .utils import get_api from .credential import Credential -from ..exceptions import ApiException, ResponseCodeException, NetworkException +from ..exceptions import ApiException, ResponseCodeException, NetworkException, ExClimbWuzhiException +from .exclimbwuzhi import * __httpx_session_pool: Dict[asyncio.AbstractEventLoop, httpx.AsyncClient] = {} __aiohttp_session_pool: Dict[asyncio.AbstractEventLoop, aiohttp.ClientSession] = {} @@ -455,7 +456,9 @@ async def _prepare_request(self, **kwargs) -> dict: if self.credential.buvid3 is None: global buvid3 if buvid3 == "" and self.url != API["info"]["spi"]["url"]: - buvid3 = (await get_spi_buvid())["b_3"] + resp = await get_spi_buvid() + buvid3 = resp["b_3"] + await active_buvid(buvid3, resp["b_4"]) cookies["buvid3"] = buvid3 else: cookies["buvid3"] = self.credential.buvid3 @@ -469,9 +472,11 @@ async def _prepare_request(self, **kwargs) -> dict: "files": self.files, "cookies": cookies, "headers": HEADERS.copy() if len(self.headers) == 0 else self.headers, - "timeout": settings.timeout - if settings.http_client == settings.HTTPClient.HTTPX - else aiohttp.ClientTimeout(total=settings.timeout), + "timeout": ( + settings.timeout + if settings.http_client == settings.HTTPClient.HTTPX + else aiohttp.ClientTimeout(total=settings.timeout) + ), } config.update(kwargs) @@ -593,7 +598,9 @@ def _process_response( if OK is None: code = resp_data.get("code") if code is None: - raise ResponseCodeException(-1, "API 返回数据未含 code 字段", resp_data) + raise ResponseCodeException( + -1, "API 返回数据未含 code 字段", resp_data + ) if code != 0: msg = resp_data.get("msg") if msg is None: @@ -665,6 +672,40 @@ def get_spi_buvid_sync() -> dict: return Api(**API["info"]["spi"]).result_sync +async def active_buvid(buvid3: str, buvid4: str) -> dict: + api = API["operate"]["active"] + sess = ( + get_session() + if settings.http_client == settings.HTTPClient.HTTPX + else get_aiohttp_session() + ) + uuid = gen_uuid_infoc() + payload = get_payload(uuid) + headers = HEADERS.copy() + headers["Content-Type"] = "application/json" + resp = await sess.request( + "POST", + api["url"], + data=payload, + headers=headers, + cookies={ + "buvid3": buvid3, + "buvid4": buvid4, + "buvid_fp": gen_buvid_fp(payload, 31), + "_uuid": uuid + }, + ) + if settings.http_client == settings.HTTPClient.HTTPX: + text = resp.text + else: + text = await resp.text() + text = json.loads(text) + if text["code"] != 0: + raise ExClimbWuzhiException(text["code"], text["msg"]) + settings.logger.info("激活 buvid3 成功") + + + def get_nav_sync(credential: Union[Credential, None] = None): """ 获取导航 diff --git a/bilibili_api/video.py b/bilibili_api/video.py index 117ac10f..47e3e239 100644 --- a/bilibili_api/video.py +++ b/bilibili_api/video.py @@ -1586,8 +1586,8 @@ async def submit_subtitle( encoding="utf-8", ) as f: subtitle_lans = json.load(f) - for lan in subtitle_lans: - if lan["lan"] == lan: + for lan_template in subtitle_lans: + if lan_template["lan"] == lan: break else: raise ArgsException("lan 参数错误,请参见 https://s1.hdslb.com/bfs/subtitle/subtitle_lan.json") diff --git a/bilibili_api/video_uploader.py b/bilibili_api/video_uploader.py index f8bb7745..ebd7ea45 100644 --- a/bilibili_api/video_uploader.py +++ b/bilibili_api/video_uploader.py @@ -86,70 +86,12 @@ async def _probe() -> dict: for line in LINES_INFO.values(): start = time.perf_counter() data = bytes(int(1024 * 0.1 * 1024)) # post 0.1MB - httpx.post(f'https:{line["probe_url"]}', data=data, timeout=30) - cost_time = time.perf_counter() - start - if cost_time < min_cost: - min_cost, fastest_line = cost_time, line - return fastest_line - - -async def _choose_line(line: Lines) -> dict: - """ - 选择线路,不存在则直接测速自动选择 - """ - if isinstance(line, Lines): - line_info = LINES_INFO.get(line.value) - if line_info is not None: - return line_info - return await _probe() - - -LINES_INFO = { - "bda2": { - "os": "upos", - "upcdn": "bda2", - "probe_version": 20221109, - "query": "probe_version=20221109&upcdn=bda2", - "probe_url": "//upos-cs-upcdnbda2.bilivideo.com/OK", - }, - "bldsa": { - "os": "upos", - "upcdn": "bldsa", - "probe_version": 20221109, - "query": "upcdn=bldsa&probe_version=20221109", - "probe_url": "//upos-cs-upcdnbldsa.bilivideo.com/OK", - }, - "qn": { - "os": "upos", - "upcdn": "qn", - "probe_version": 20221109, - "query": "probe_version=20221109&upcdn=qn", - "probe_url": "//upos-cs-upcdnqn.bilivideo.com/OK", - }, - "ws": { - "os": "upos", - "upcdn": "ws", - "probe_version": 20221109, - "query": "upcdn=ws&probe_version=20221109", - "probe_url": "//upos-cs-upcdnws.bilivideo.com/OK", - }, -} - - -async def _probe() -> dict: - """ - 测试所有线路 - - 测速网页 https://member.bilibili.com/preupload?r=ping - """ - # api = _API["probe"] - # info = await Api(**api).update_params(r="probe").result # 不实时获取线路直接用 LINES_INFO - min_cost, fastest_line = 30, None - for line in LINES_INFO.values(): - start = time.perf_counter() - data = bytes(int(1024 * 0.1 * 1024)) # post 0.1MB - httpx.post(f'https:{line["probe_url"]}', data=data, timeout=30) - cost_time = time.perf_counter() - start + timeout = 30 + try: + httpx.post(f'https:{line["probe_url"]}', data=data, timeout=timeout) + cost_time = time.perf_counter() - start + except httpx.ReadTimeout: + cost_time = timeout if cost_time < min_cost: min_cost, fastest_line = cost_time, line return fastest_line @@ -580,7 +522,7 @@ def __dict__(self) -> dict: "interactive": 0, "act_reserve_create": 0, # unknown "no_disturbance": 0, # unknown - "porder": self.porder.__dict__(), + "porder": None if self.porder is None else self.porder.__dict__(), "adorder_type": 9, # unknown "no_reprint": 1 if self.no_reprint else 0, "subtitle": self.subtitle @@ -589,7 +531,6 @@ def __dict__(self) -> dict: "open": 0, "lan": "", }, # 莫名其妙没法上传 srt 字幕,显示格式错误,不校验 - "subtitle": self.subtitle, "neutral_mark": self.neutral_mark, # 不知道能不能随便写文本 "dolby": 1 if self.dolby else 0, "lossless_music": 1 if self.lossless_music else 0, @@ -597,6 +538,7 @@ def __dict__(self) -> dict: "up_close_reply": self.up_close_reply, "up_close_danmu": self.up_close_danmu, "web_os": 1, # const 1 + "source": self.source } for k in copy(meta).keys(): if meta[k] is None: @@ -1531,7 +1473,7 @@ async def _submit(self): "user-agent": "Mozilla/5.0", } resp = ( - await Api(**api, credential=self.credential, no_csrf=True) + await Api(**api, credential=self.credential, no_csrf=True, json_body=True) .update_params(**params) .update_data(**data) .update_headers(**headers) diff --git a/docs/examples/user.md b/docs/examples/user.md index aa988ed7..e63989ea 100644 --- a/docs/examples/user.md +++ b/docs/examples/user.md @@ -51,6 +51,8 @@ async def main(): if 'cards' in page: # 若存在 cards 字段(即动态数据),则将该字段列表扩展到 dynamics dynamics.extend(page['cards']) + else: + break if page['has_more'] != 1: # 如果没有更多动态,跳出循环 diff --git a/pyproject.toml b/pyproject.toml index eb0eca64..a2708b6d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ maintainers = [ { name = "Nemo2011" }, ] dynamic = ["version", "readme", "dependencies"] -license = { file = "LICENSE", content-type = "text/plain" } +license = { text = "GPL-3.0-or-later" } description = "The fork of module bilibili-api. 哔哩哔哩的各种 API 调用便捷整合(视频、动态、直播等),另外附加一些常用的功能。" requires-python = ">=3.7" keywords = ["bilibili", "api", "spider"] diff --git a/requirements.txt b/requirements.txt index 0d46d1f4..16e7c133 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ requests~=2.31.0 APScheduler~=3.10.4 rsa~=4.9 pillow~=10.2.0 -tqdm~=4.66.1 +tqdm~=4.66.2 yarl~=1.9.4 pycryptodomex~=3.20.0 qrcode_terminal~=0.8 \ No newline at end of file