diff --git a/nonebot_bison/platform/bilibili.py b/nonebot_bison/platform/bilibili.py index 369cf11ad..37ca732b5 100644 --- a/nonebot_bison/platform/bilibili.py +++ b/nonebot_bison/platform/bilibili.py @@ -105,18 +105,19 @@ def get_date(self, post: RawPost) -> int: return post["desc"]["timestamp"] def _do_get_category(self, post_type: int) -> Category: - if post_type == 2: - return Category(1) - elif post_type == 64: - return Category(2) - elif post_type == 8: - return Category(3) - elif post_type == 4: - return Category(4) - elif post_type == 1: - # 转发 - return Category(5) - raise CategoryNotRecognize(post_type) + match post_type: + case 2: + return Category(1) + case 64: + return Category(2) + case 8: + return Category(3) + case 4: + return Category(4) + case 1: + return Category(5) + case _: + raise CategoryNotRecognize(post_type) def get_category(self, post: RawPost) -> Category: post_type = post["desc"]["type"] @@ -140,60 +141,76 @@ def _text_process(self, dynamic: str, desc: str, title: str) -> str: return text def _get_info(self, post_type: Category, card) -> tuple[str, list]: - if post_type == 1: - # 一般动态 - text = card["item"]["description"] - pic = [img["img_src"] for img in card["item"]["pictures"]] - elif post_type == 2: - # 专栏文章 - text = "{} {}".format(card["title"], card["summary"]) - pic = card["image_urls"] - elif post_type == 3: - # 视频 - dynamic = card.get("dynamic", "") - title = card["title"] - desc = card.get("desc", "") - text = self._text_process(dynamic, desc, title) - pic = [card["pic"]] - elif post_type == 4: - # 纯文字 - text = card["item"]["content"] - pic = [] - else: - raise CategoryNotSupport(post_type) + match post_type: + case 1: + # 一般动态 + text = card["item"]["description"] + pic = [img["img_src"] for img in card["item"]["pictures"]] + case 2: + # 专栏文章 + text = "{} {}".format(card["title"], card["summary"]) + pic = card["image_urls"] + case 3: + # 视频 + dynamic = card.get("dynamic", "") + title = card["title"] + desc = card.get("desc", "") + text = self._text_process(dynamic, desc, title) + pic = [card["pic"]] + case 4: + # 纯文字 + text = card["item"]["content"] + pic = [] + case _: + raise CategoryNotSupport(post_type) return text, pic async def parse(self, raw_post: RawPost) -> Post: card_content = json.loads(raw_post["card"]) - post_type = self.get_category(raw_post) + post_category = self.get_category(raw_post) + orig_category = Category(0) target_name = raw_post["desc"]["user_profile"]["info"]["uname"] - if post_type >= 1 and post_type < 5: - url = "" - if post_type == 1: + + if post_category not in range(1, 6): + raise CategoryNotSupport(post_category) + + match post_category: + case 1: # 一般动态 url = "https://t.bilibili.com/{}".format(raw_post["desc"]["dynamic_id_str"]) - elif post_type == 2: + text, pic = self._get_info(post_category, card_content) + case 2: # 专栏文章 url = "https://www.bilibili.com/read/cv{}".format(raw_post["desc"]["rid"]) - elif post_type == 3: + text, pic = self._get_info(post_category, card_content) + case 3: # 视频 url = "https://www.bilibili.com/video/{}".format(raw_post["desc"]["bvid"]) - elif post_type == 4: + text, pic = self._get_info(post_category, card_content) + case 4: # 纯文字 url = "https://t.bilibili.com/{}".format(raw_post["desc"]["dynamic_id_str"]) - text, pic = self._get_info(post_type, card_content) - elif post_type == 5: - # 转发 - url = "https://t.bilibili.com/{}".format(raw_post["desc"]["dynamic_id_str"]) - text = card_content["item"]["content"] - orig_type = card_content["item"]["orig_type"] - orig = json.loads(card_content["origin"]) - orig_text, pic = self._get_info(self._do_get_category(orig_type), orig) - text += "\n--------------\n" - text += orig_text - else: - raise CategoryNotSupport(post_type) - return Post("bilibili", text=text, url=url, pics=pic, target_name=target_name) + text, pic = self._get_info(post_category, card_content) + case 5: + # 转发 + url = "https://t.bilibili.com/{}".format(raw_post["desc"]["dynamic_id_str"]) + text = card_content["item"]["content"] + orig_category = self._do_get_category(card_content["item"]["orig_type"]) + orig = json.loads(card_content["origin"]) + orig_text, pic = self._get_info(orig_category, orig) + text += "\n--------------\n" + text += orig_text + case _: + raise CategoryNotSupport(post_category) + + return Post( + "bilibili", + text=text, + url=url, + pics=pic, + target_name=target_name, + category=self.categories[post_category] if not orig_category else f"转发自{self.categories[orig_category]}", + ) class Bilibililive(StatusChange): @@ -331,14 +348,14 @@ def get_category(self, status: Info) -> Category: async def parse(self, raw_post: Info) -> Post: url = f"https://live.bilibili.com/{raw_post.room_id}" pic = [raw_post.cover] if raw_post.category == Category(1) else [raw_post.keyframe] - title = f"[{self.categories[raw_post.category].rstrip('提醒')}] {raw_post.title}" target_name = f"{raw_post.uname} {raw_post.area_name}" return Post( self.name, - text=title, + text=raw_post.title, url=url, pics=list(pic), target_name=target_name, + category=self.categories[self.get_category(raw_post)].rstrip("提醒"), compress=True, ) diff --git a/nonebot_bison/platform/mcbbsnews.py b/nonebot_bison/platform/mcbbsnews.py index 1784698a3..b87e7d7d3 100644 --- a/nonebot_bison/platform/mcbbsnews.py +++ b/nonebot_bison/platform/mcbbsnews.py @@ -160,6 +160,7 @@ async def parse(self, post: RawPost) -> Post: url=post_url, pics=list(pics), target_name=post["category"], + category=self.categories[self.get_category(post)], ) async def _news_render(self, url: str, selector: str) -> list[bytes]: diff --git a/nonebot_bison/platform/weibo.py b/nonebot_bison/platform/weibo.py index be09d95d1..bfe63da24 100644 --- a/nonebot_bison/platform/weibo.py +++ b/nonebot_bison/platform/weibo.py @@ -160,4 +160,5 @@ async def parse(self, raw_post: RawPost) -> Post: url=detail_url, pics=pics, target_name=info["user"]["screen_name"], + category=self.categories[self.get_category(raw_post)], ) diff --git a/nonebot_bison/post/post.py b/nonebot_bison/post/post.py index 4c2a2398c..5f087949d 100644 --- a/nonebot_bison/post/post.py +++ b/nonebot_bison/post/post.py @@ -17,6 +17,8 @@ class _Post(BasePost): url: str | None = None target_name: str | None = None pics: list[str | bytes] = field(default_factory=list) + category: str | None = None + """展现在消息开头的分类信息,如“视频”、“转发”等。""" _message: list[MessageSegmentFactory] | None = None _pic_message: list[MessageSegmentFactory] | None = None @@ -101,7 +103,7 @@ async def generate_text_messages(self) -> list[MessageSegmentFactory]: if self._message is None: await self._pic_merge() msg_segments: list[MessageSegmentFactory] = [] - text = "" + text = f"[{self.category}] " if self.category else "" if self.text: text += "{}".format(self.text if len(self.text) < 500 else self.text[:500] + "...") if text: @@ -142,7 +144,7 @@ def __str__(self): self.target_name, self.text if len(self.text) < 500 else self.text[:500] + "...", self.url, - ", ".join("b64img" if isinstance(x, bytes) or x.startswith("base64") else x for x in self.pics), + ", ".join("b64img" if not isinstance(x, str) or x.startswith("base64") else x for x in self.pics), ) diff --git a/poetry.lock b/poetry.lock index 5cdd61463..1b522c8fe 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "aiofiles" @@ -2493,7 +2493,7 @@ files = [ [package.dependencies] aiosqlite = {version = "*", optional = true, markers = "extra == \"aiosqlite\""} greenlet = {version = "!=0.4.17", optional = true, markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\" or extra == \"aiosqlite\""} -typing-extensions = {version = ">=4.6.0", optional = true, markers = "extra == \"aiosqlite\""} +typing-extensions = ">=4.6.0" [package.extras] aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] diff --git a/tests/platforms/test_bilibili.py b/tests/platforms/test_bilibili.py index 1e5f418b2..405d6cd36 100644 --- a/tests/platforms/test_bilibili.py +++ b/tests/platforms/test_bilibili.py @@ -80,6 +80,7 @@ async def test_video_forward(bilibili, bing_dy_list): " \n档案类型:可见 \n档案描述:今天请了病假在宿舍休息。很舒适。" " \n提供者:赫默\n=================\n《可露希尔的秘密档案》11话:来宿舍休息一下吧" ) + assert post.category == "转发自视频" @pytest.mark.asyncio @@ -115,6 +116,7 @@ async def test_article_forward(bilibili, bing_dy_list): "心狠手辣)前言感谢楪筱祈ぺ的动态-哔哩哔哩 (bilibili.com) 对饼学的贡献!后续排期:9.17【风暴瞭望】、" "10.01【玛莉娅·临光】复刻、10.1" ) + assert post.category == "转发自专栏文章" @pytest.mark.asyncio @@ -131,6 +133,7 @@ async def test_dynamic_forward(bilibili, bing_dy_list): "星极自费参加了这项企划,尝试着用大众能接受的方式演绎天空之上的故事。\n\n_____________\n谦逊留给观众," "骄傲发自歌喉,此夜,唯我璀璨。 " ) + assert post.category == "转发自一般动态" @pytest.mark.asyncio @@ -178,6 +181,7 @@ async def test_fetch_new(bilibili, dummy_user_subinfo): " 01:高脚羽兽烤串与罗德岛的领袖\r\n\r\n哔哩哔哩漫画阅读:https://manga.bilibili.com/detail/mc31998?from=manga_search\r\n\r\n关注并转发本动态," "我们将会在5月27日抽取10位博士赠送【兔兔奇境】周边礼盒一份。 互动抽奖" ) + assert post.category == "一般动态" async def test_parse_target(bilibili: "Bilibili"): diff --git a/tests/platforms/test_bilibili_live.py b/tests/platforms/test_bilibili_live.py index 1889694c0..fb30f39a5 100644 --- a/tests/platforms/test_bilibili_live.py +++ b/tests/platforms/test_bilibili_live.py @@ -71,11 +71,12 @@ async def test_fetch_first_live(bili_live, dummy_only_open_user_subinfo): assert len(res2) == 1 post = res2[0][1][0] assert post.target_type == "Bilibili直播" - assert post.text == "[开播] 【Zc】从0挑战到15肉鸽!目前10难度" + assert post.text == "【Zc】从0挑战到15肉鸽!目前10难度" assert post.url == "https://live.bilibili.com/3044248" assert post.target_name == "魔法Zc目录 其他单机" assert post.pics == ["https://i0.hdslb.com/bfs/live/new_room_cover/fd357f0f3cbbb48e9acfbcda616b946c2454c56c.jpg"] assert post.compress is True + assert post.category == "开播" @pytest.mark.asyncio @@ -101,11 +102,12 @@ async def test_fetch_bililive_only_live_open(bili_live, dummy_only_open_user_sub res2 = await bili_live.batch_fetch_new_post([(SubUnit(target, [dummy_only_open_user_subinfo]))]) post = res2[0][1][0] assert post.target_type == "Bilibili直播" - assert post.text == "[开播] 【Zc】从0挑战到15肉鸽!目前10难度" + assert post.text == "【Zc】从0挑战到15肉鸽!目前10难度" assert post.url == "https://live.bilibili.com/3044248" assert post.target_name == "魔法Zc目录 其他单机" assert post.pics == ["https://i0.hdslb.com/bfs/live/new_room_cover/fd357f0f3cbbb48e9acfbcda616b946c2454c56c.jpg"] assert post.compress is True + assert post.category == "开播" # 标题变更 mock_bili_live_status["data"][target]["title"] = "【Zc】从0挑战到15肉鸽!目前11难度" bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status)) @@ -165,11 +167,12 @@ async def test_fetch_bililive_only_title_change(bili_live, dummy_only_title_user res3 = await bili_live.batch_fetch_new_post([(SubUnit(target, [dummy_only_title_user_subinfo]))]) post = res3[0][1][0] assert post.target_type == "Bilibili直播" - assert post.text == "[标题更新] 【Zc】从0挑战到15肉鸽!目前12难度" + assert post.text == "【Zc】从0挑战到15肉鸽!目前12难度" assert post.url == "https://live.bilibili.com/3044248" assert post.target_name == "魔法Zc目录 其他单机" assert post.pics == ["https://i0.hdslb.com/bfs/live-key-frame/keyframe10170435000003044248mwowx0.jpg"] assert post.compress is True + assert post.category == "标题更新" # 直播状态更新-下播 mock_bili_live_status["data"][target]["live_status"] = 0 bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status)) @@ -230,11 +233,12 @@ async def test_fetch_bililive_only_close(bili_live, dummy_only_close_user_subinf assert bili_live_router.call_count == 5 post = res4[0][1][0] assert post.target_type == "Bilibili直播" - assert post.text == "[下播] 【Zc】从0挑战到15肉鸽!目前12难度" + assert post.text == "【Zc】从0挑战到15肉鸽!目前12难度" assert post.url == "https://live.bilibili.com/3044248" assert post.target_name == "魔法Zc目录 其他单机" assert post.pics == ["https://i0.hdslb.com/bfs/live-key-frame/keyframe10170435000003044248mwowx0.jpg"] assert post.compress is True + assert post.category == "下播" @pytest.fixture() @@ -276,30 +280,33 @@ async def test_fetch_bililive_combo(bili_live, dummy_bililive_user_subinfo): res2 = await bili_live.batch_fetch_new_post([(SubUnit(target, [dummy_bililive_user_subinfo]))]) post2 = res2[0][1][0] assert post2.target_type == "Bilibili直播" - assert post2.text == "[开播] 【Zc】从0挑战到15肉鸽!目前11难度" + assert post2.text == "【Zc】从0挑战到15肉鸽!目前11难度" assert post2.url == "https://live.bilibili.com/3044248" assert post2.target_name == "魔法Zc目录 其他单机" assert post2.pics == ["https://i0.hdslb.com/bfs/live/new_room_cover/fd357f0f3cbbb48e9acfbcda616b946c2454c56c.jpg"] assert post2.compress is True + assert post2.category == "开播" # 标题变更 mock_bili_live_status["data"][target]["title"] = "【Zc】从0挑战到15肉鸽!目前12难度" bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status)) res3 = await bili_live.batch_fetch_new_post([(SubUnit(target, [dummy_bililive_user_subinfo]))]) post3 = res3[0][1][0] assert post3.target_type == "Bilibili直播" - assert post3.text == "[标题更新] 【Zc】从0挑战到15肉鸽!目前12难度" + assert post3.text == "【Zc】从0挑战到15肉鸽!目前12难度" assert post3.url == "https://live.bilibili.com/3044248" assert post3.target_name == "魔法Zc目录 其他单机" assert post3.pics == ["https://i0.hdslb.com/bfs/live-key-frame/keyframe10170435000003044248mwowx0.jpg"] assert post3.compress is True + assert post3.category == "标题更新" # 直播状态更新-下播 mock_bili_live_status["data"][target]["live_status"] = 0 bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status)) res4 = await bili_live.batch_fetch_new_post([(SubUnit(target, [dummy_bililive_user_subinfo]))]) post4 = res4[0][1][0] assert post4.target_type == "Bilibili直播" - assert post4.text == "[下播] 【Zc】从0挑战到15肉鸽!目前12难度" + assert post4.text == "【Zc】从0挑战到15肉鸽!目前12难度" assert post4.url == "https://live.bilibili.com/3044248" assert post4.target_name == "魔法Zc目录 其他单机" assert post4.pics == ["https://i0.hdslb.com/bfs/live-key-frame/keyframe10170435000003044248mwowx0.jpg"] assert post4.compress is True + assert post4.category == "下播" diff --git a/tests/platforms/test_mcbbsnews.py b/tests/platforms/test_mcbbsnews.py index 55291f246..010ac185f 100644 --- a/tests/platforms/test_mcbbsnews.py +++ b/tests/platforms/test_mcbbsnews.py @@ -43,6 +43,7 @@ async def test_fetch_new(mcbbsnews, dummy_user_subinfo, raw_post_list): assert post.url == "https://www.mcbbs.net/{}".format(raw_post["url"]) assert post.target_name == raw_post["category"] assert len(post.pics) == 1 + assert post.category == "Java版资讯" @pytest.mark.asyncio diff --git a/tests/platforms/test_platform.py b/tests/platforms/test_platform.py index eb1fefdbd..ef054de4f 100644 --- a/tests/platforms/test_platform.py +++ b/tests/platforms/test_platform.py @@ -578,7 +578,7 @@ class BatchStatusChange(StatusChange): enable_tag = False schedule_type = "interval" schedule_kw = {"seconds": 10} - has_target = False + has_target = True categories = { Category(1): "转发", Category(2): "视频", diff --git a/tests/platforms/test_weibo.py b/tests/platforms/test_weibo.py index ee6f7cb26..ebd527e47 100644 --- a/tests/platforms/test_weibo.py +++ b/tests/platforms/test_weibo.py @@ -70,6 +70,7 @@ async def test_fetch_new(weibo, dummy_user_subinfo): assert post.url == "https://weibo.com/6279793937/KkBtUx2dv" assert post.target_name == "明日方舟Arknights" assert len(post.pics) == 1 + assert post.category == "图文" @pytest.mark.asyncio diff --git a/tests/post/test_generate.py b/tests/post/test_generate.py new file mode 100644 index 000000000..7bef16f07 --- /dev/null +++ b/tests/post/test_generate.py @@ -0,0 +1,20 @@ +from nonebug import App + + +async def test_gen_text(app: App): + from nonebot_bison.post import Post + + p = Post( + target_type="bili", + text="111", + ) + p_text = await p.generate_text_messages() + assert p_text[0].data["text"] == "111\n来源: bili" + + p_c = Post( + target_type="bili", + text="222", + category="动态", + ) + p_c_text = await p_c.generate_text_messages() + assert p_c_text[0].data["text"] == "[动态] 222\n来源: bili"