11from __future__ import annotations
22
3+ import asyncio
34from typing import TYPE_CHECKING
45
6+ from biliass import get_danmaku_meta_size
7+
8+ from yutto .api .user_info import get_user_info
59from yutto .utils .fetcher import Fetcher
610
711if TYPE_CHECKING :
812 import httpx
913
10- from yutto ._typing import CId
14+ from yutto ._typing import AvId , CId
1115 from yutto .utils .danmaku import DanmakuData , DanmakuSaveType
1216
1317
@@ -18,21 +22,34 @@ async def get_xml_danmaku(client: httpx.AsyncClient, cid: CId) -> str:
1822 return results
1923
2024
21- async def get_protobuf_danmaku (client : httpx .AsyncClient , cid : CId , segment_id : int = 1 ) -> bytes :
25+ async def get_protobuf_danmaku_segment (client : httpx .AsyncClient , cid : CId , segment_id : int = 1 ) -> bytes :
2226 danmaku_api = "http://api.bilibili.com/x/v2/dm/web/seg.so?type=1&oid={cid}&segment_index={segment_id}"
2327 results = await Fetcher .fetch_bin (client , danmaku_api .format (cid = cid , segment_id = segment_id ))
2428 assert results is not None
2529 return results
2630
2731
32+ async def get_protobuf_danmaku (client : httpx .AsyncClient , avid : AvId , cid : CId ) -> list [bytes ]:
33+ danmaku_meta_api = "https://api.bilibili.com/x/v2/dm/web/view?type=1&oid={cid}&pid={aid}"
34+ aid = avid .as_aid ()
35+ meta_results = await Fetcher .fetch_bin (client , danmaku_meta_api .format (cid = cid , aid = aid .value ))
36+ assert meta_results is not None
37+ size = get_danmaku_meta_size (meta_results )
38+
39+ results = await asyncio .gather (
40+ * [get_protobuf_danmaku_segment (client , cid , segment_id ) for segment_id in range (1 , size + 1 )]
41+ )
42+ return results
43+
44+
2845async def get_danmaku (
2946 client : httpx .AsyncClient ,
3047 cid : CId ,
48+ avid : AvId ,
3149 save_type : DanmakuSaveType ,
32- last_n_segments : int = 2 ,
3350) -> DanmakuData :
34- # 暂时默认使用 XML 源
35- source_type = "xml" if save_type == "xml" or save_type == "ass" else "protobuf"
51+ # 在已经登录的情况下,使用 protobuf,因为未登录时 protobuf 弹幕会少非常多
52+ source_type = "xml" if save_type == "xml" or not ( await get_user_info ( client ))[ "is_login" ] else "protobuf"
3653 danmaku_data : DanmakuData = {
3754 "source_type" : source_type ,
3855 "save_type" : save_type ,
@@ -42,6 +59,5 @@ async def get_danmaku(
4259 if source_type == "xml" :
4360 danmaku_data ["data" ].append (await get_xml_danmaku (client , cid ))
4461 else :
45- for i in range (1 , last_n_segments + 1 ):
46- danmaku_data ["data" ].append (await get_protobuf_danmaku (client , cid , i ))
62+ danmaku_data ["data" ].extend (await get_protobuf_danmaku (client , avid , cid ))
4763 return danmaku_data
0 commit comments