添加 Theme 功能

This commit is contained in:
Azide
2023-10-13 23:18:39 +08:00
committed by felinae98
parent 6aaec45d15
commit f202071e9f
57 changed files with 1709 additions and 802 deletions
+1
View File
@@ -41,6 +41,7 @@ async def app(tmp_path: Path, request: pytest.FixtureRequest, mocker: MockerFixt
plugin_config.bison_config_path = str(tmp_path / "legacy_config")
plugin_config.bison_filter_log = False
plugin_config.bison_theme_use_browser = True
datastore_config.datastore_config_dir = tmp_path / "config"
datastore_config.datastore_cache_dir = tmp_path / "cache"
+51 -30
View File
@@ -1,3 +1,5 @@
from time import time
import respx
import pytest
from nonebug.app import App
@@ -49,6 +51,7 @@ async def test_fetch_new(
monster_siren_list_0,
monster_siren_list_1,
):
from nonebot_bison.post import Post
from nonebot_bison.types import Target, SubUnit
ak_list_router = respx.get("https://ak-webview.hypergryph.com/api/game/bulletinList?target=IOS")
@@ -60,37 +63,50 @@ async def test_fetch_new(
monster_siren_router = respx.get("https://monster-siren.hypergryph.com/api/news")
terra_list = respx.get("https://terra-historicus.hypergryph.com/api/recentUpdate")
ak_list_router.mock(return_value=Response(200, json=arknights_list__1))
detail_router.mock(return_value=Response(200, text=get_file("arknights-detail-807")))
mock_detail = get_json("arknights-detail-807")
mock_detail["data"]["bannerImageUrl"] = "https://example.com/1.jpg"
detail_router.mock(return_value=Response(200, json=mock_detail))
version_router.mock(return_value=Response(200, json=get_json("arknights-version-0.json")))
preannouncement_router.mock(return_value=Response(200, json=get_json("arknights-pre-0.json")))
monster_siren_router.mock(return_value=Response(200, json=monster_siren_list_0))
terra_list.mock(return_value=Response(200, json=get_json("terra-hist-0.json")))
target = Target("")
res = await arknights.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
res1 = await arknights.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert ak_list_router.called
assert len(res) == 0
assert len(res1) == 0
assert not detail_router.called
mock_data = arknights_list_0
mock_data["data"]["list"][0]["updatedAt"] = int(time())
ak_list_router.mock(return_value=Response(200, json=mock_data))
res3 = await arknights.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert len(res3[0][1]) == 1
res2 = await arknights.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert len(res2[0][1]) == 1
assert detail_router.called
post = res3[0][1][0]
assert post.target_type == "arknights"
assert post.text == ""
assert post.url == ""
assert post.target_name == "明日方舟游戏内公告"
assert len(post.pics) == 1
post2: Post = res2[0][1][0]
assert post2.platform.platform_name == "arknights"
assert post2.content
assert post2.title == "2023「夏日嘉年华」限时活动即将开启"
assert not post2.url
assert post2.nickname == "明日方舟游戏内公告"
assert post2.images
assert post2.images == ["https://example.com/1.jpg"]
assert post2.timestamp
assert "arknights" == post2.get_priority_themes()[0]
# assert(post.pics == ['https://ak-fs.hypergryph.com/announce/images/20210623/e6f49aeb9547a2278678368a43b95b07.jpg'])
await post.generate_messages()
terra_list.mock(return_value=Response(200, json=get_json("terra-hist-1.json")))
res = await arknights.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert len(res) == 1
post = res[0][1][0]
assert post.target_type == "terra-historicus"
assert post.text == "123罗德岛!? - 「掠风」篇"
assert post.url == "https://terra-historicus.hypergryph.com/comic/6253/episode/4938"
assert post.pics == ["https://web.hycdn.cn/comic/pic/20220507/ab8a2ff408ec7d587775aed70b178ec0.png"]
res3 = await arknights.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert len(res3) == 1
post3: Post = res3[0][1][0]
assert post3.platform.platform_name == "arknights"
assert post3.nickname == "泰拉记事社漫画"
assert post3.title == "123罗德岛!? - 「掠风」篇"
assert post3.content == "你可能不知道的罗德岛小剧场!"
assert post3.url == "https://terra-historicus.hypergryph.com/comic/6253/episode/4938"
assert post3.images == ["https://web.hycdn.cn/comic/pic/20220507/ab8a2ff408ec7d587775aed70b178ec0.png"]
assert "brief" == post3.get_priority_themes()[0]
@pytest.mark.render()
@@ -103,6 +119,7 @@ async def test_send_with_render(
monster_siren_list_0,
monster_siren_list_1,
):
from nonebot_bison.post import Post
from nonebot_bison.types import Target, SubUnit
ak_list_router = respx.get("https://ak-webview.hypergryph.com/api/game/bulletinList?target=IOS")
@@ -119,22 +136,26 @@ async def test_send_with_render(
preannouncement_router.mock(return_value=Response(200, json=get_json("arknights-pre-0.json")))
monster_siren_router.mock(return_value=Response(200, json=monster_siren_list_0))
terra_list.mock(return_value=Response(200, json=get_json("terra-hist-0.json")))
target = Target("")
res = await arknights.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
res1 = await arknights.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert ak_list_router.called
assert len(res) == 0
assert len(res1) == 0
assert not detail_router.called
mock_data = arknights_list_1
mock_data["data"]["list"][0]["updatedAt"] = int(time())
ak_list_router.mock(return_value=Response(200, json=mock_data))
res3 = await arknights.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert len(res3[0][1]) == 1
res2 = await arknights.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert len(res2[0][1]) == 1
assert detail_router.called
post = res3[0][1][0]
assert post.target_type == "arknights"
assert post.text == ""
assert post.url == ""
assert post.target_name == "明日方舟游戏内公告"
assert len(post.pics) == 1
post2: Post = res2[0][1][0]
assert post2.platform.platform_name == "arknights"
assert "《明日方舟》将于08月01日10:00 ~16:00的更新维护中对游戏内【公开招募】进行新增干员。" in post2.content
assert post2.title == "【公开招募】标签强制刷新通知"
assert post2.nickname == "明日方舟游戏内公告"
assert not post2.images
# assert(post.pics == ['https://ak-fs.hypergryph.com/announce/images/20210623/e6f49aeb9547a2278678368a43b95b07.jpg'])
r = await post.generate_messages()
r = await post2.generate_messages()
assert r
+12 -6
View File
@@ -72,14 +72,17 @@ async def test_get_tag_without_topic_info(bilibili, bing_dy_list):
@pytest.mark.asyncio
async def test_video_forward(bilibili, bing_dy_list):
post = await bilibili.parse(bing_dy_list[1])
from nonebot_bison.post import Post
post: Post = await bilibili.parse(bing_dy_list[1])
assert (
post.text
post.content
== "答案揭晓:宿舍!来看看投票结果\nhttps://t.bilibili.com/568093580488553786\n--------------\n#可露希尔的秘密档案#"
" \n11:来宿舍休息一下吧 \n档案来源:lambda:\\罗德岛内务\\秘密档案 \n发布时间:9/12 1:00 P.M."
" \n档案类型:可见 \n档案描述:今天请了病假在宿舍休息。很舒适。"
" \n提供者:赫默\n=================\n《可露希尔的秘密档案》11话:来宿舍休息一下吧"
)
assert post.get_priority_themes()[0] == "basic"
@pytest.mark.asyncio
@@ -87,7 +90,7 @@ async def test_video_forward_without_dynamic(bilibili, bing_dy_list):
# 视频简介和动态文本其中一方为空的情况
post = await bilibili.parse(bing_dy_list[2])
assert (
post.text
post.content
== "阿消的罗德岛闲谈直播#01:《女人最喜欢的女人,就是在战场上熠熠生辉的女人》"
+ "\n\n"
+ "本系列视频为饼组成员的有趣直播录播,主要内容为方舟相关,未来可能系列其他视频会包含部分饼组团建日常等。"
@@ -96,13 +99,14 @@ async def test_video_forward_without_dynamic(bilibili, bing_dy_list):
"包含慕夏对新PV的个人解读,风笛厨力疯狂放出,CP言论输出,9.16轮换池预测视频分析和理智规划杂谈内容。"
"\n注意:内含大量个人性质对风笛的厨力观点,与多CP混乱发言,不适者请及时点击退出或跳到下一片段。"
)
assert post.get_priority_themes()[0] == "basic"
@pytest.mark.asyncio
async def test_article_forward(bilibili, bing_dy_list):
post = await bilibili.parse(bing_dy_list[4])
assert (
post.text
post.content
== "#明日方舟##饼学大厦#\n9.11专栏更新完毕,"
"这还塌了实属没跟新运营对上\n后边除了周日发饼和PV没提及的中文语音,"
"稳了\n别忘了来参加#可露希尔的秘密档案#的主题投票\nhttps://t.bilibili.com/568093580488553786?tab=2"
@@ -121,7 +125,7 @@ async def test_article_forward(bilibili, bing_dy_list):
async def test_dynamic_forward(bilibili, bing_dy_list):
post = await bilibili.parse(bing_dy_list[5])
assert (
post.text
post.content
== "饼组主线饼学预测——9.11版\n①今日结果\n9.11 殿堂上的游禽-星极(x"
"新运营实锤了)\n②后续预测\n9.12 #罗德岛相簿#+#可露希尔的秘密档案#11话\n9.13"
" 六星先锋(执旗手)干员-琴柳\n9.14 宣传策略-空弦+家具\n9.15 轮换池(+中文语音前瞻)\n9.16"
@@ -161,7 +165,9 @@ async def test_fetch_new(bilibili, dummy_user_subinfo):
post_router.mock(return_value=Response(200, json=get_json("bilibili_strange_post-0.json")))
bilibili_main_page_router = respx.get("https://www.bilibili.com/")
bilibili_main_page_router.mock(return_value=Response(200))
target = Target("161775300")
res = await bilibili.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert post_router.called
assert len(res) == 0
@@ -173,7 +179,7 @@ async def test_fetch_new(bilibili, dummy_user_subinfo):
assert len(res2[0][1]) == 1
post = res2[0][1][0]
assert (
post.text
post.content
== "#罗德厨房——回甘##明日方舟#\r\n明日方舟官方美食漫画,正式开餐。\r\n往事如烟,安然即好。\r\nMenu"
" 01:高脚羽兽烤串与罗德岛的领袖\r\n\r\n哔哩哔哩漫画阅读:https://manga.bilibili.com/detail/mc31998?from=manga_search\r\n\r\n关注并转发本动态,"
"我们将会在5月27日抽取10位博士赠送【兔兔奇境】周边礼盒一份。 互动抽奖"
+19 -12
View File
@@ -24,10 +24,13 @@ async def test_parse_target(bili_bangumi: "BilibiliBangumi"):
res1 = await bili_bangumi.parse_target("28339726")
assert res1 == "28339726"
res2 = await bili_bangumi.parse_target("md28339726")
assert res2 == "28339726"
res3 = await bili_bangumi.parse_target("https://www.bilibili.com/bangumi/media/md28339726")
assert res3 == "28339726"
with pytest.raises(Platform.ParseTargetException):
await bili_bangumi.parse_target("https://www.bilibili.com/bangumi/play/ep683045")
@@ -42,21 +45,25 @@ async def test_fetch_bilibili_bangumi_status(bili_bangumi: "BilibiliBangumi", du
bili_bangumi_router.mock(return_value=Response(200, json=get_json("bilibili-gangumi-hanhua0.json")))
bilibili_main_page_router = respx.get("https://www.bilibili.com/")
bilibili_main_page_router.mock(return_value=Response(200))
target = Target("28235413")
res = await bili_bangumi.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert len(res) == 0
res = await bili_bangumi.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert len(res) == 0
target = Target("28235413")
res0 = await bili_bangumi.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert len(res0) == 0
res1 = await bili_bangumi.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert len(res1) == 0
bili_bangumi_router.mock(return_value=Response(200, json=get_json("bilibili-gangumi-hanhua1.json")))
bili_bangumi_detail_router.mock(return_value=Response(200, json=get_json("bilibili-gangumi-hanhua1-detail.json")))
res2 = await bili_bangumi.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
post = res2[0][1][0]
assert post.target_type == "Bilibili剧集"
assert post.text == "《汉化日记 第三季》第2话 什么是战区导弹防御系统工作日"
assert post.url == "https://www.bilibili.com/bangumi/play/ep519207"
assert post.target_name == "汉化日记 第三季"
assert post.pics == ["http://i0.hdslb.com/bfs/archive/ea0a302c954f9dbc3d593e676486396c551529c9.jpg"]
assert post.compress is True
post2 = res2[0][1][0]
assert post2.platform.name == "Bilibili剧集"
assert post2.title == "《汉化日记 第三季》第2话 什么是战区导弹防御系统工作日"
assert post2.content == "更新至第2话"
assert post2.url == "https://www.bilibili.com/bangumi/play/ep519207"
assert post2.nickname == "汉化日记 第三季"
assert post2.images == ["http://i0.hdslb.com/bfs/archive/ea0a302c954f9dbc3d593e676486396c551529c9.jpg"]
assert post2.compress is True
assert "brief" == post2.get_priority_themes()[0]
+62 -48
View File
@@ -1,4 +1,5 @@
from copy import deepcopy
from typing import TYPE_CHECKING
import respx
import pytest
@@ -7,6 +8,9 @@ from httpx import Response, AsyncClient
from .utils import get_json
if TYPE_CHECKING:
from nonebot_bison.platform.bilibili import Bilibililive
@pytest.fixture()
def bili_live(app: App):
@@ -48,6 +52,7 @@ async def test_fetch_bililive_no_room(bili_live, dummy_only_open_user_subinfo):
@pytest.mark.asyncio
@respx.mock
async def test_fetch_first_live(bili_live, dummy_only_open_user_subinfo):
from nonebot_bison.post import Post
from nonebot_bison.types import Target, SubUnit
mock_bili_live_status = get_json("bili_live_status.json")
@@ -60,27 +65,31 @@ async def test_fetch_first_live(bili_live, dummy_only_open_user_subinfo):
bilibili_main_page_router.mock(return_value=Response(200))
target = Target("13164144")
res = await bili_live.batch_fetch_new_post([(SubUnit(target, [dummy_only_open_user_subinfo]))])
res1 = await bili_live.batch_fetch_new_post([(SubUnit(target, [dummy_only_open_user_subinfo]))])
assert bili_live_router.call_count == 1
assert len(res) == 0
assert len(res1) == 0
mock_bili_live_status["data"][target]["live_status"] = 1
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
res2 = await bili_live.batch_fetch_new_post([(SubUnit(target, [dummy_only_open_user_subinfo]))])
assert bili_live_router.call_count == 2
assert len(res2) == 1
post = res2[0][1][0]
assert post.target_type == "Bilibili直播"
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
post2: Post = res2[0][1][0]
assert post2.platform.name == "Bilibili直播"
assert post2.title == "[开播] 【Zc】从0挑战到15肉鸽!目前10难度"
assert post2.content == ""
assert post2.url == "https://live.bilibili.com/3044248"
assert post2.nickname == "魔法Zc目录 其他单机"
assert post2.images == ["https://i0.hdslb.com/bfs/live/new_room_cover/fd357f0f3cbbb48e9acfbcda616b946c2454c56c.jpg"]
assert post2.compress is True
assert "brief" == post2.get_priority_themes()[0]
@pytest.mark.asyncio
@respx.mock
async def test_fetch_bililive_only_live_open(bili_live, dummy_only_open_user_subinfo):
async def test_fetch_bililive_only_live_open(bili_live: "Bilibililive", dummy_only_open_user_subinfo):
from nonebot_bison.post import Post
from nonebot_bison.types import Target, SubUnit
mock_bili_live_status = get_json("bili_live_status.json")
@@ -92,20 +101,22 @@ async def test_fetch_bililive_only_live_open(bili_live, dummy_only_open_user_sub
bilibili_main_page_router.mock(return_value=Response(200))
target = Target("13164144")
res = await bili_live.batch_fetch_new_post([(SubUnit(target, [dummy_only_open_user_subinfo]))])
bili_live.set_stored_data(target, None)
res1 = await bili_live.batch_fetch_new_post([(SubUnit(target, [dummy_only_open_user_subinfo]))])
assert bili_live_router.call_count == 1
assert len(res[0][1]) == 0
assert len(res1) == 0
# 直播状态更新-上播
mock_bili_live_status["data"][target]["live_status"] = 1
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
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.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
post2: Post = res2[0][1][0]
assert post2.platform.name == "Bilibili直播"
assert post2.title == "[开播] 【Zc】从0挑战到15肉鸽!目前10难度"
assert post2.url == "https://live.bilibili.com/3044248"
assert post2.nickname == "魔法Zc目录 其他单机"
assert post2.images == ["https://i0.hdslb.com/bfs/live/new_room_cover/fd357f0f3cbbb48e9acfbcda616b946c2454c56c.jpg"]
assert post2.compress is True
# 标题变更
mock_bili_live_status["data"][target]["title"] = "【Zc】从0挑战到15肉鸽!目前11难度"
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
@@ -133,6 +144,7 @@ def dummy_only_title_user_subinfo(app: App):
@pytest.mark.asyncio()
@respx.mock
async def test_fetch_bililive_only_title_change(bili_live, dummy_only_title_user_subinfo):
from nonebot_bison.post import Post
from nonebot_bison.types import Target, SubUnit
mock_bili_live_status = get_json("bili_live_status.json")
@@ -163,13 +175,13 @@ async def test_fetch_bililive_only_title_change(bili_live, dummy_only_title_user
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_only_title_user_subinfo]))])
post = res3[0][1][0]
assert post.target_type == "Bilibili直播"
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
post3: Post = res3[0][1][0]
assert post3.platform.name == "Bilibili直播"
assert post3.title == "[标题更新] 【Zc】从0挑战到15肉鸽!目前12难度"
assert post3.url == "https://live.bilibili.com/3044248"
assert post3.nickname == "魔法Zc目录 其他单机"
assert post3.images == ["https://i0.hdslb.com/bfs/live-key-frame/keyframe10170435000003044248mwowx0.jpg"]
assert post3.compress is True
# 直播状态更新-下播
mock_bili_live_status["data"][target]["live_status"] = 0
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
@@ -191,6 +203,7 @@ def dummy_only_close_user_subinfo(app: App):
@pytest.mark.asyncio
@respx.mock
async def test_fetch_bililive_only_close(bili_live, dummy_only_close_user_subinfo):
from nonebot_bison.post import Post
from nonebot_bison.types import Target, SubUnit
mock_bili_live_status = get_json("bili_live_status.json")
@@ -228,13 +241,13 @@ async def test_fetch_bililive_only_close(bili_live, dummy_only_close_user_subinf
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
res4 = await bili_live.batch_fetch_new_post([(SubUnit(target, [dummy_only_close_user_subinfo]))])
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.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
post4: Post = res4[0][1][0]
assert post4.platform.name == "Bilibili直播"
assert post4.title == "[下播] 【Zc】从0挑战到15肉鸽!目前12难度"
assert post4.url == "https://live.bilibili.com/3044248"
assert post4.nickname == "魔法Zc目录 其他单机"
assert post4.images == ["https://i0.hdslb.com/bfs/live-key-frame/keyframe10170435000003044248mwowx0.jpg"]
assert post4.compress is True
@pytest.fixture()
@@ -250,6 +263,7 @@ def dummy_bililive_user_subinfo(app: App):
@pytest.mark.asyncio
@respx.mock
async def test_fetch_bililive_combo(bili_live, dummy_bililive_user_subinfo):
from nonebot_bison.post import Post
from nonebot_bison.types import Target, SubUnit
mock_bili_live_status = get_json("bili_live_status.json")
@@ -274,32 +288,32 @@ async def test_fetch_bililive_combo(bili_live, dummy_bililive_user_subinfo):
mock_bili_live_status["data"][target]["live_status"] = 1
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
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难度"
post2: Post = res2[0][1][0]
assert post2.platform.name == "Bilibili直播"
assert post2.title == "[开播] 【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.nickname == "魔法Zc目录 其他单机"
assert post2.images == ["https://i0.hdslb.com/bfs/live/new_room_cover/fd357f0f3cbbb48e9acfbcda616b946c2454c56c.jpg"]
assert post2.compress is True
# 标题变更
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难度"
post3: Post = res3[0][1][0]
assert post3.platform.name == "Bilibili直播"
assert post3.title == "[标题更新] 【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.nickname == "魔法Zc目录 其他单机"
assert post3.images == ["https://i0.hdslb.com/bfs/live-key-frame/keyframe10170435000003044248mwowx0.jpg"]
assert post3.compress is True
# 直播状态更新-下播
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难度"
post4: Post = res4[0][1][0]
assert post4.platform.name == "Bilibili直播"
assert post4.title == "[下播] 【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.nickname == "魔法Zc目录 其他单机"
assert post4.images == ["https://i0.hdslb.com/bfs/live-key-frame/keyframe10170435000003044248mwowx0.jpg"]
assert post4.compress is True
+6 -4
View File
@@ -27,6 +27,7 @@ def ff14_newdata_json_1():
@pytest.mark.asyncio
@respx.mock
async def test_fetch_new(ff14, dummy_user_subinfo, ff14_newdata_json_0, ff14_newdata_json_1):
from nonebot_bison.post import Post
from nonebot_bison.types import Target, SubUnit
newdata = respx.get(
@@ -40,8 +41,9 @@ async def test_fetch_new(ff14, dummy_user_subinfo, ff14_newdata_json_0, ff14_new
newdata.mock(return_value=Response(200, json=ff14_newdata_json_1))
res = await ff14.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert newdata.called
post = res[0][1][0]
assert post.target_type == "ff14"
assert post.text == "最终幻想XIV 银质坠饰 <友谊永存>预售开启!\n最终幻想XIV 银质坠饰 <友谊永存>现已开启预售!"
post: Post = res[0][1][0]
assert post.platform.name == "最终幻想XIV官方公告"
assert post.title == "最终幻想XIV 银质坠饰 <友谊永存>预售开启!"
assert post.content == "最终幻想XIV 银质坠饰 <友谊永存>现已开启预售!"
assert post.url == "https://ff.web.sdo.com/web8/index.html#/newstab/newscont/336870"
assert post.target_name == "最终幻想XIV官方公告"
assert post.nickname == "最终幻想XIV官方公告"
+11 -6
View File
@@ -25,24 +25,29 @@ def raw_post_list():
@respx.mock
@flaky(max_runs=3, min_passes=1)
async def test_fetch_new(mcbbsnews, dummy_user_subinfo, raw_post_list):
from nonebot_bison.post import Post
news_router = respx.get("https://www.mcbbs.net/forum-news-1.html")
news_router.mock(return_value=Response(200, text=get_file("mcbbsnews/mock/mcbbsnews_post_list_html-0.html")))
new_post = respx.get("https://www.mcbbs.net/thread-1340927-1-1.html")
new_post.mock(return_value=Response(200, text=get_file("mcbbsnews/mock/mcbbsnews_new_post_html.html")))
target = ""
res = await mcbbsnews.fetch_new_post(target, [dummy_user_subinfo])
assert news_router.called
assert len(res) == 0
news_router.mock(return_value=Response(200, text=get_file("mcbbsnews/mock/mcbbsnews_post_list_html-1.html")))
res = await mcbbsnews.fetch_new_post(target, [dummy_user_subinfo])
res1 = await mcbbsnews.fetch_new_post(target, [dummy_user_subinfo])
assert news_router.called
post = res[0][1][0]
post: Post = res1[0][1][0]
raw_post = raw_post_list[0]
assert post.target_type == "MCBBS幻翼块讯"
assert post.text == "{}\n\n└由 {} 发表".format(raw_post["title"], raw_post["author"])
assert post.platform.name == "MCBBS幻翼块讯"
assert post.content == "{}\n\n└由 {} 发表".format(raw_post["title"], raw_post["author"])
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.nickname == raw_post["category"]
assert post.images
assert len(post.images) == 1
@pytest.mark.asyncio
+2 -2
View File
@@ -52,8 +52,8 @@ async def test_fetch_new(ncm_artist, ncm_artist_0, ncm_artist_1, dummy_user_subi
ncm_router.mock(return_value=Response(200, json=ncm_artist_1))
res2 = await ncm_artist.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
post = res2[0][1][0]
assert post.target_type == "ncm-artist"
assert post.text == "新专辑发布:Y1K"
assert post.platform.platform_name == "ncm-artist"
assert post.content == "新专辑发布:Y1K"
assert post.url == "https://music.163.com/#/album?id=131074504"
+6 -5
View File
@@ -41,6 +41,7 @@ def ncm_radio_1(ncm_radio_raw: dict):
@pytest.mark.asyncio
@respx.mock
async def test_fetch_new(ncm_radio, ncm_radio_0, ncm_radio_1, dummy_user_subinfo):
from nonebot_bison.post import Post
from nonebot_bison.types import Target, SubUnit
ncm_router = respx.post("http://music.163.com/api/dj/program/byradio")
@@ -51,12 +52,12 @@ async def test_fetch_new(ncm_radio, ncm_radio_0, ncm_radio_1, dummy_user_subinfo
assert len(res) == 0
ncm_router.mock(return_value=Response(200, json=ncm_radio_1))
res2 = await ncm_radio.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
post = res2[0][1][0]
assert post.target_type == "ncm-radio"
assert post.text == "网易云电台更新:「松烟行动」灰齐山麓"
post: Post = res2[0][1][0]
assert post.platform.platform_name == "ncm-radio"
assert post.content == "网易云电台更新:「松烟行动」灰齐山麓"
assert post.url == "https://music.163.com/#/program/2494997688"
assert post.pics == ["http://p1.music.126.net/H5em5xUNIYXcjJhOmeaSqQ==/109951166647436789.jpg"]
assert post.target_name == "《明日方舟》游戏原声OST"
assert post.images == ["http://p1.music.126.net/H5em5xUNIYXcjJhOmeaSqQ==/109951166647436789.jpg"]
assert post.nickname == "《明日方舟》游戏原声OST"
async def test_parse_target(ncm_radio: "NcmRadio"):
+25 -25
View File
@@ -65,10 +65,10 @@ def mock_platform_without_cats_tags(app: App):
async def parse(self, raw_post: "RawPost") -> "Post":
return Post(
"mock_platform",
self,
raw_post["text"],
"http://t.tt/" + str(self.get_id(raw_post)),
target_name="Mock",
nickname="Mock",
)
@classmethod
@@ -127,10 +127,10 @@ def mock_platform(app: App):
async def parse(self, raw_post: "RawPost") -> "Post":
return Post(
"mock_platform",
self,
raw_post["text"],
"http://t.tt/" + str(self.get_id(raw_post)),
target_name="Mock",
nickname="Mock",
)
@classmethod
@@ -194,10 +194,10 @@ def mock_platform_no_target(app: App, mock_scheduler_conf):
async def parse(self, raw_post: "RawPost") -> "Post":
return Post(
"mock_platform",
self,
raw_post["text"],
"http://t.tt/" + str(self.get_id(raw_post)),
target_name="Mock",
nickname="Mock",
)
@classmethod
@@ -250,10 +250,10 @@ def mock_platform_no_target_2(app: App, mock_scheduler_conf):
async def parse(self, raw_post: "RawPost") -> "Post":
return Post(
"mock_platform_2",
self,
raw_post["text"],
"http://t.tt/" + str(self.get_id(raw_post)),
target_name="Mock",
nickname="Mock",
)
@classmethod
@@ -314,7 +314,7 @@ def mock_status_change(app: App):
return []
async def parse(self, raw_post) -> "Post":
return Post("mock_status", raw_post["text"], "")
return Post(self, raw_post["text"], "")
def get_category(self, raw_post):
return raw_post["cat"]
@@ -337,7 +337,7 @@ async def test_new_message_target_without_cats_tags(mock_platform_without_cats_t
assert len(res2) == 1
posts_1 = res2[0][1]
assert len(posts_1) == 3
id_set_1 = {x.text for x in posts_1}
id_set_1 = {x.content for x in posts_1}
assert "p2" in id_set_1
assert "p3" in id_set_1
assert "p4" in id_set_1
@@ -369,9 +369,9 @@ async def test_new_message_target(mock_platform, user_info_factory):
assert len(posts_1) == 2
assert len(posts_2) == 1
assert len(posts_3) == 1
id_set_1 = {x.text for x in posts_1}
id_set_2 = {x.text for x in posts_2}
id_set_3 = {x.text for x in posts_3}
id_set_1 = {x.content for x in posts_1}
id_set_2 = {x.content for x in posts_2}
id_set_3 = {x.content for x in posts_3}
assert "p2" in id_set_1
assert "p3" in id_set_1
assert "p2" in id_set_2
@@ -404,9 +404,9 @@ async def test_new_message_no_target(mock_platform_no_target, user_info_factory)
assert len(posts_1) == 2
assert len(posts_2) == 1
assert len(posts_3) == 1
id_set_1 = {x.text for x in posts_1}
id_set_2 = {x.text for x in posts_2}
id_set_3 = {x.text for x in posts_3}
id_set_1 = {x.content for x in posts_1}
id_set_2 = {x.content for x in posts_2}
id_set_3 = {x.content for x in posts_3}
assert "p2" in id_set_1
assert "p3" in id_set_1
assert "p2" in id_set_2
@@ -432,7 +432,7 @@ async def test_status_change(mock_status_change, user_info_factory):
assert len(res2) == 1
posts = res2[0][1]
assert len(posts) == 1
assert posts[0].text == "on"
assert posts[0].content == "on"
res3 = await mock_status_change(ProcessContext(), AsyncClient()).fetch_new_post(
SubUnit(
Target("dummy"),
@@ -444,7 +444,7 @@ async def test_status_change(mock_status_change, user_info_factory):
)
assert len(res3) == 2
assert len(res3[0][1]) == 1
assert res3[0][1][0].text == "off"
assert res3[0][1][0].content == "off"
assert len(res3[1][1]) == 0
res4 = await mock_status_change(ProcessContext(), AsyncClient()).fetch_new_post(
SubUnit(Target("dummy"), [user_info_factory([1, 2], [])])
@@ -473,7 +473,7 @@ async def test_group(
assert len(res2) == 1
posts = res2[0][1]
assert len(posts) == 2
id_set_2 = {x.text for x in posts}
id_set_2 = {x.content for x in posts}
assert "p2" in id_set_2
assert "p6" in id_set_2
res3 = await group_platform.fetch_new_post(SubUnit(dummy, [user_info_factory([1, 4], [])]))
@@ -512,10 +512,10 @@ async def test_batch_fetch_new_message(app: App):
async def parse(self, raw_post: "RawPost") -> "Post":
return Post(
"mock_platform",
self,
raw_post["text"],
"http://t.tt/" + str(self.get_id(raw_post)),
target_name="Mock",
nickname="Mock",
)
@classmethod
@@ -556,7 +556,7 @@ async def test_batch_fetch_new_message(app: App):
send_set = set()
for platform_target, posts in res2:
for post in posts:
send_set.add((platform_target, post.text))
send_set.add((platform_target, post.content))
assert (TargetQQGroup(group_id=123), "p3") in send_set
assert (TargetQQGroup(group_id=123), "p4") in send_set
assert (TargetQQGroup(group_id=234), "p4") in send_set
@@ -578,7 +578,7 @@ async def test_batch_fetch_compare_status(app: App):
enable_tag = False
schedule_type = "interval"
schedule_kw = {"seconds": 10}
has_target = False
has_target = True
categories = {
Category(1): "转发",
Category(2): "视频",
@@ -603,7 +603,7 @@ async def test_batch_fetch_compare_status(app: App):
return []
async def parse(self, raw_post) -> "Post":
return Post("mock_status", raw_post["text"], "")
return Post(self, raw_post["text"], "")
def get_category(self, raw_post):
return raw_post["cat"]
@@ -627,7 +627,7 @@ async def test_batch_fetch_compare_status(app: App):
send_set = set()
for platform_target, posts in res2:
for post in posts:
send_set.add((platform_target, post.text))
send_set.add((platform_target, post.content))
assert len(send_set) == 3
assert (TargetQQGroup(group_id=123), "off") in send_set
assert (TargetQQGroup(group_id=123), "on") in send_set
+8 -7
View File
@@ -46,7 +46,7 @@ def update_time_feed_1():
root = ET.fromstring(file)
item = root.find("channel/item")
current_time = datetime.now(pytz.timezone("GMT")).strftime("%a, %d %b %Y %H:%M:%S %Z")
assert item
assert item is not None
pubdate_elem = item.find("pubDate")
assert pubdate_elem is not None
pubdate_elem.text = current_time
@@ -85,8 +85,9 @@ async def test_fetch_new_1(
assert len(res2[0][1]) == 1
post1 = res2[0][1][0]
assert post1.url == "https://twitter.com/ArknightsStaff/status/1659091539023282178"
assert post1.title is None
assert (
post1.text
post1.content
== "【#統合戦略】 引き続き新テーマ「ミヅキと紺碧の樹」の新要素及びシステムの変更点を一部ご紹介します!"
" 今回は「灯火」、「ダイス」、「記号認識」、「鍵」についてです。詳細は添付の画像をご確認ください。"
"#アークナイツ https://t.co/ARmptV0Zvu"
@@ -114,9 +115,8 @@ async def test_fetch_new_2(
assert len(res2[0][1]) == 1
post1 = res2[0][1][0]
assert post1.url == "http://www.ruanyifeng.com/blog/2023/05/weekly-issue-255.html"
assert (
post1.text == "科技爱好者周刊(第 255 期):对待 AI 的正确态度\n\n这里记录每周值得分享的科技内容,周五发布。..."
)
assert post1.title == "科技爱好者周刊(第 255 期):对待 AI 的正确态度"
assert post1.content == "这里记录每周值得分享的科技内容,周五发布。..."
@pytest.fixture()
@@ -150,7 +150,8 @@ async def test_fetch_new_3(
assert len(res2[0][1]) == 1
post1 = res2[0][1][0]
assert post1.url == "https://github.com/R3nzTheCodeGOD/R3nzSkin/releases/tag/v3.0.9"
assert post1.text == "R3nzSkin\n\nNo content."
assert post1.title == "R3nzSkin"
assert post1.content == "No content."
@pytest.mark.asyncio
@@ -173,7 +174,7 @@ async def test_fetch_new_4(
assert len(res2[0][1]) == 1
post1 = res2[0][1][0]
assert post1.url == "https://wallhaven.cc/w/85rjej"
assert post1.text == "85rjej.jpg"
assert post1.content == "85rjej.jpg"
def test_similar_text_process():
+8 -6
View File
@@ -41,6 +41,7 @@ async def test_get_name(weibo):
@pytest.mark.asyncio
@respx.mock
async def test_fetch_new(weibo, dummy_user_subinfo):
from nonebot_bison.post import Post
from nonebot_bison.types import Target, SubUnit
ak_list_router = respx.get("https://m.weibo.cn/api/container/getIndex?containerid=1076036279793937")
@@ -64,12 +65,13 @@ async def test_fetch_new(weibo, dummy_user_subinfo):
res3 = await weibo.fetch_new_post(SubUnit(target, [dummy_user_subinfo]))
assert len(res3[0][1]) == 1
assert not detail_router.called
post = res3[0][1][0]
assert post.target_type == "weibo"
assert post.text == "#明日方舟#\nSideStory「沃伦姆德的薄暮」复刻现已开启! "
post: Post = res3[0][1][0]
assert post.platform.platform_name == "weibo"
assert post.content == "#明日方舟#\nSideStory「沃伦姆德的薄暮」复刻现已开启! "
assert post.url == "https://weibo.com/6279793937/KkBtUx2dv"
assert post.target_name == "明日方舟Arknights"
assert len(post.pics) == 1
assert post.nickname == "明日方舟Arknights"
assert post.images
assert len(post.images) == 1
@pytest.mark.asyncio
@@ -93,7 +95,7 @@ async def test_parse_long(weibo):
detail_router.mock(return_value=Response(200, text=get_file("weibo_detail_4645748019299849")))
raw_post = get_json("weibo_ak_list_1.json")["data"]["cards"][0]
post = await weibo.parse(raw_post)
assert "全文" not in post.text
assert "全文" not in post.content
assert detail_router.called
+111
View File
@@ -0,0 +1,111 @@
from time import time
from typing import Any
import pytest
from nonebug.app import App
from httpx import AsyncClient
now = time()
passed = now - 3 * 60 * 60
raw_post_list_1 = [{"id": 1, "text": "p1", "date": now, "tags": ["tag1"], "category": 1}]
raw_post_list_2 = raw_post_list_1 + [
{"id": 2, "text": "p2", "date": now, "tags": ["tag1"], "category": 1},
{"id": 3, "text": "p3", "date": now, "tags": ["tag2"], "category": 2},
{"id": 4, "text": "p4", "date": now, "tags": ["tag2"], "category": 3},
]
@pytest.fixture()
def mock_platform(app: App):
from nonebot_bison.post import Post
from nonebot_bison.types import Target, RawPost
from nonebot_bison.platform.platform import NewMessage
class MockPlatform(NewMessage):
platform_name = "mock_platform"
name = "Mock Platform"
enabled = True
is_common = True
schedule_interval = 10
enable_tag = False
categories = {}
has_target = True
sub_index = 0
@classmethod
async def get_target_name(cls, client, _: "Target"):
return "MockPlatform"
def get_id(self, post: "RawPost") -> Any:
return post["id"]
def get_date(self, raw_post: "RawPost") -> float:
return raw_post["date"]
async def parse(self, raw_post: "RawPost") -> "Post":
return Post(
self,
raw_post["text"],
url="http://t.tt/" + str(self.get_id(raw_post)),
nickname="Mock",
)
@classmethod
async def get_sub_list(cls, _: "Target"):
if cls.sub_index == 0:
cls.sub_index += 1
return raw_post_list_1
else:
return raw_post_list_2
return MockPlatform
@pytest.mark.asyncio
async def test_generate_msg(mock_platform):
from nonebot_plugin_saa import Text, Image
from nonebot_bison.post import Post
from nonebot_bison.utils import ProcessContext
from nonebot_bison.plugin_config import plugin_config
post: Post = await mock_platform(ProcessContext(), AsyncClient()).parse(raw_post_list_1[0])
assert post.platform.default_theme == "basic"
res = await post.generate()
assert len(res) == 1
assert isinstance(res[0], Text)
assert str(res[0]) == "p1\n来源: Mock Platform Mock\n详情: http://t.tt/1"
post.platform.default_theme = "ht2i"
assert post.get_config_theme() is None
assert set(post.get_priority_themes()) == {"basic", "ht2i"}
assert post.get_priority_themes()[0] == "ht2i"
res1 = await post.generate()
assert isinstance(res1[0], Image)
plugin_config.bison_theme_use_browser = False
res3 = await post.generate()
assert res3[0]
assert isinstance(res3[0], Text)
@pytest.mark.asyncio
@pytest.mark.render
async def test_msg_segments_convert(mock_platform):
from nonebot_plugin_saa import Image
from nonebot_bison.post import Post
from nonebot_bison.utils import ProcessContext
from nonebot_bison.plugin_config import plugin_config
plugin_config.bison_use_pic = True
post: Post = await mock_platform(ProcessContext(), AsyncClient()).parse(raw_post_list_1[0])
assert post.platform.default_theme == "basic"
res = await post.generate_messages()
assert len(res) == 1
assert isinstance(res[0][0], Image)
-58
View File
@@ -1,58 +0,0 @@
from pathlib import Path
import respx
import pytest
from httpx import Response
from nonebug.app import App
@pytest.fixture()
def ms_list():
from nonebot_plugin_saa import Text, Image, MessageSegmentFactory
msg_segments: list[MessageSegmentFactory] = []
msg_segments.append(Text("【Zc】每早合约日替攻略!"))
msg_segments.append(
Image(
image="http://i0.hdslb.com/bfs/live/new_room_cover/cf7d4d3b2f336c6dba299644c3af952c5db82612.jpg",
)
)
msg_segments.append(Text("来源: Bilibili直播 魔法Zc目录"))
msg_segments.append(Text("详情: https://live.bilibili.com/3044248"))
return msg_segments
@pytest.fixture()
def expected_md():
return (
"【Zc】每早合约日替攻略!<br>![Image](http://i0.hdslb.com/bfs/live/new_room_cover/cf7d4d3b2f336c6dba299644c3af952c5db82612.jpg)\n来源:"
" Bilibili直播 魔法Zc目录<br>详情: https://live.bilibili.com/3044248<br>"
)
def test_gene_md(app: App, expected_md, ms_list):
from nonebot_bison.post.custom_post import CustomPost
cp = CustomPost(ms_factories=ms_list)
cp_md = cp._generate_md()
assert cp_md == expected_md
@respx.mock
@pytest.mark.asyncio
async def test_gene_pic(app: App, ms_list, expected_md):
from nonebot_bison.post.custom_post import CustomPost
pic_router = respx.get("http://i0.hdslb.com/bfs/live/new_room_cover/cf7d4d3b2f336c6dba299644c3af952c5db82612.jpg")
pic_path = Path(__file__).parent / "platforms" / "static" / "custom_post_pic.jpg"
with open(pic_path, mode="rb") as f:
mock_pic = f.read()
pic_router.mock(return_value=Response(200, stream=mock_pic)) # type: ignore
cp = CustomPost(ms_factories=ms_list)
cp_pic_msg_md: str = cp._generate_md()
assert cp_pic_msg_md == expected_md
+18 -26
View File
@@ -65,60 +65,52 @@ async def downloaded_resource_2():
@pytest.mark.external
@flaky
async def test_9_merge(app: App, downloaded_resource: list[bytes]):
from nonebot_bison.post import Post
from nonebot_bison.utils import pic_merge, http_client
post = Post("", "", "", pics=list(downloaded_resource))
await post._pic_merge()
assert len(post.pics) == 5
await post.generate_messages()
pics = await pic_merge(list(downloaded_resource), http_client())
assert len(pics) == 5
@pytest.mark.external
@flaky
async def test_9_merge_2(app: App, downloaded_resource_2: list[bytes]):
from nonebot_bison.post import Post
from nonebot_bison.utils import pic_merge, http_client
post = Post("", "", "", pics=list(downloaded_resource_2))
await post._pic_merge()
assert len(post.pics) == 4
await post.generate_messages()
pics = await pic_merge(list(downloaded_resource_2), http_client())
assert len(pics) == 4
@pytest.mark.external
@flaky
async def test_6_merge(app: App, downloaded_resource: list[bytes]):
from nonebot_bison.post import Post
from nonebot_bison.utils import pic_merge, http_client
post = Post("", "", "", pics=list(downloaded_resource[0:6] + downloaded_resource[9:]))
await post._pic_merge()
assert len(post.pics) == 5
pics = await pic_merge(list(downloaded_resource[0:6] + downloaded_resource[9:]), http_client())
assert len(pics) == 5
@pytest.mark.external
@flaky
async def test_3_merge(app: App, downloaded_resource: list[bytes]):
from nonebot_bison.post import Post
from nonebot_bison.utils import pic_merge, http_client
post = Post("", "", "", pics=list(downloaded_resource[0:3] + downloaded_resource[9:]))
await post._pic_merge()
assert len(post.pics) == 5
pics = await pic_merge(list(downloaded_resource[0:3] + downloaded_resource[9:]), http_client())
assert len(pics) == 5
@pytest.mark.external
@flaky
async def test_6_merge_only(app: App, downloaded_resource: list[bytes]):
from nonebot_bison.post import Post
from nonebot_bison.utils import pic_merge, http_client
post = Post("", "", "", pics=list(downloaded_resource[0:6]))
await post._pic_merge()
assert len(post.pics) == 1
pics = await pic_merge(list(downloaded_resource[0:6]), http_client())
assert len(pics) == 1
@pytest.mark.external
@flaky
async def test_3_merge_only(app: App, downloaded_resource: list[bytes]):
from nonebot_bison.post import Post
from nonebot_bison.utils import pic_merge, http_client
post = Post("", "", "", pics=list(downloaded_resource[0:3]))
await post._pic_merge()
assert len(post.pics) == 1
pics = await pic_merge(list(downloaded_resource[0:3]), http_client())
assert len(pics) == 1
+15
View File
@@ -20,3 +20,18 @@ async def test_render(app: App):
"并将其转换成一个完整的单页应用(SPA),其他的页面则会只在用户浏览到的时候才按需加载。"
)
assert isinstance(res, Image)
@pytest.mark.asyncio
@pytest.mark.render
async def test_convert(app: App):
from nonebot_plugin_saa import Text, Image
from nonebot_bison.utils import text_to_image
from nonebot_bison.plugin_config import plugin_config
plugin_config.bison_use_pic = True
text = Text("如果,生命的脚印终有一天会被时间的尘埃掩埋......那我们就永远不能——停下脚步")
res = await text_to_image(text)
assert isinstance(res, Image)
+33
View File
@@ -0,0 +1,33 @@
from typing import Literal
import pytest
from nonebug import App
@pytest.mark.asyncio
async def test_registry_new_theme(app: App):
from nonebot_bison.theme import Theme, ThemeRegistrationError, theme_manager
class MockTheme(Theme):
name: Literal["mock_theme"] = "mock_theme"
async def render(self, _):
return ""
assert len(theme_manager) == 5
assert "arknights" in theme_manager
assert "basic" in theme_manager
assert "brief" in theme_manager
assert "ceobecanteen" in theme_manager
assert "ht2i" in theme_manager
assert "mock_theme" not in theme_manager
theme_manager.register(MockTheme())
assert len(theme_manager) == 6
assert "mock_theme" in theme_manager
# duplicated registration
with pytest.raises(ThemeRegistrationError, match="duplicate"):
theme_manager.register(MockTheme())
theme_manager.unregister("mock_theme")
+222
View File
@@ -0,0 +1,222 @@
from time import time
from typing import Any
import pytest
from flaky import flaky
from nonebug import App
from httpx import AsyncClient
now = time()
passed = now - 3 * 60 * 60
raw_post_list_1 = [{"id": 1, "text": "p1", "date": now, "tags": ["tag1"], "category": 1}]
raw_post_list_2 = raw_post_list_1 + [
{"id": 2, "text": "p2", "date": now, "tags": ["tag1"], "category": 1},
{"id": 3, "text": "p3", "date": now, "tags": ["tag2"], "category": 2},
{"id": 4, "text": "p4", "date": now, "tags": ["tag2"], "category": 3},
]
@pytest.fixture()
def mock_platform(app: App):
from nonebot_bison.post import Post
from nonebot_bison.types import Target, RawPost
from nonebot_bison.platform.platform import NewMessage
class MockPlatform(NewMessage):
platform_name = "mock_platform"
name = "Mock Platform"
enabled = True
is_common = True
schedule_interval = 10
enable_tag = False
categories = {}
has_target = True
sub_index = 0
@classmethod
async def get_target_name(cls, client, _: "Target"):
return "MockPlatform"
def get_id(self, post: "RawPost") -> Any:
return post["id"]
def get_date(self, raw_post: "RawPost") -> float:
return raw_post["date"]
async def parse(self, raw_post: "RawPost") -> "Post":
return Post(
self,
raw_post["text"],
url="http://t.tt/" + str(self.get_id(raw_post)),
nickname="Mock",
)
@classmethod
async def get_sub_list(cls, _: "Target"):
if cls.sub_index == 0:
cls.sub_index += 1
return raw_post_list_1
else:
return raw_post_list_2
return MockPlatform
@pytest.fixture()
def mock_post(app: App, mock_platform):
from nonebot_bison.post import Post
from nonebot_bison.utils import ProcessContext
return Post(
mock_platform(ProcessContext(), AsyncClient()),
"text",
title="title",
images=["http://t.tt/1.jpg"],
timestamp=1234567890,
url="http://t.tt/1",
avatar="http://t.tt/avatar.jpg",
nickname="Mock",
description="description",
)
@pytest.mark.asyncio
async def test_theme_need_browser(app: App, mock_post):
from nonebot_bison.theme import Theme, theme_manager
class MockTheme(Theme):
name: str = "mock_theme"
need_browser: bool = False
async def render(self, post):
return []
theme = MockTheme()
theme_manager.register(theme)
mock_post.platform.default_theme = theme.name
await theme.do_render(mock_post)
assert not theme._browser_checked
theme.need_browser = True
await theme.do_render(mock_post)
assert theme._browser_checked
theme_manager.unregister(theme.name)
@pytest.mark.asyncio
async def test_theme_no_enable_use_browser(app: App, mock_post):
from nonebot_bison.plugin_config import plugin_config
plugin_config.bison_theme_use_browser = False
from nonebot_bison.theme import Theme, ThemeRenderUnsupportError, theme_manager
class MockTheme(Theme):
name: str = "mock_theme"
need_browser: bool = True
async def render(self, post):
return []
theme = MockTheme()
theme_manager.register(theme)
mock_post.platform.default_theme = theme.name
with pytest.raises(ThemeRenderUnsupportError, match="not support render"):
await theme.do_render(mock_post)
theme_manager.unregister(theme.name)
plugin_config.bison_theme_use_browser = True
@pytest.mark.asyncio
@flaky(max_runs=3, min_passes=1)
async def test_arknights_theme(app: App, mock_post):
from nonebot_plugin_saa import Image
from nonebot_bison.theme import theme_manager
from nonebot_bison.theme.themes.arknights import ArknightsTheme
arknights_theme = theme_manager["arknights"]
assert isinstance(arknights_theme, ArknightsTheme)
assert arknights_theme.name == "arknights"
res = await arknights_theme.render(mock_post)
assert len(res) == 1
assert isinstance(res[0], Image)
@pytest.mark.asyncio
async def test_basic_theme(app: App, mock_post):
from nonebot_plugin_saa import Text, Image
from nonebot_bison.theme import theme_manager
from nonebot_bison.theme.themes.basic import BasicTheme
basic_theme = theme_manager["basic"]
assert isinstance(basic_theme, BasicTheme)
assert basic_theme.name == "basic"
res = await basic_theme.render(mock_post)
assert len(res) == 2
assert res[0] == Text("title\n\ntext\n来源: Mock Platform Mock\n详情: http://t.tt/1")
assert isinstance(res[1], Image)
@pytest.mark.asyncio
async def test_brief_theme(app: App, mock_post):
from nonebot_plugin_saa import Text, Image
from nonebot_bison.theme import theme_manager
from nonebot_bison.theme.themes.brief import BriefTheme
brief_theme = theme_manager["brief"]
assert isinstance(brief_theme, BriefTheme)
assert brief_theme.name == "brief"
res = await brief_theme.render(mock_post)
assert len(res) == 2
assert res[0] == Text("title\n\n来源: Mock Platform Mock\n详情: http://t.tt/1")
assert isinstance(res[1], Image)
@pytest.mark.render
@pytest.mark.asyncio
@flaky(max_runs=3, min_passes=1)
async def test_ceobecanteen_theme(app: App, mock_post):
from nonebot_plugin_saa import Text, Image
from nonebot_bison.theme import theme_manager
from nonebot_bison.theme.themes.ceobe_canteen import CeobeCanteenTheme
ceobecanteen_theme = theme_manager["ceobecanteen"]
assert isinstance(ceobecanteen_theme, CeobeCanteenTheme)
assert ceobecanteen_theme.name == "ceobecanteen"
res = await ceobecanteen_theme.render(mock_post)
assert len(res) == 3
assert isinstance(res[0], Image)
assert isinstance(res[2], Image)
assert res[1] == Text("来源: Mock Platform Mock\n详情: http://t.tt/1")
@pytest.mark.render
@pytest.mark.asyncio
@flaky(max_runs=3, min_passes=1)
async def test_ht2i_theme(app: App, mock_post):
from nonebot_plugin_saa import Text, Image
from nonebot_bison.theme import theme_manager
from nonebot_bison.theme.themes.ht2i import Ht2iTheme
ht2i_theme = theme_manager["ht2i"]
assert isinstance(ht2i_theme, Ht2iTheme)
assert ht2i_theme.name == "ht2i"
res = await ht2i_theme.render(mock_post)
assert len(res) == 3
assert isinstance(res[0], Image)
assert isinstance(res[2], Image)
assert res[1] == Text("详情: http://t.tt/1")