Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/nonebot_plugin_alconna/builtins/uniseg/music_share.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,14 @@ async def music_export(exporter: MessageExporter, seg: MusicShare, bot: Bot | No
if exporter.get_adapter() is SupportAdapter.onebot11:
from nonebot.adapters.onebot.v11.message import MessageSegment

platform = {
platforms = {
MusicShareKind.NeteaseCloudMusic: "163",
MusicShareKind.QQMusic: "qq",
MusicShareKind.MiguMusic: "migu",
MusicShareKind.KugouMusic: "kugou",
MusicShareKind.KuwoMusic: "kuwo",
}.get(seg.kind, "qq")
}
platform = platforms.get(seg.kind, "qq")

if seg.id:
return MessageSegment.music(platform, int(seg.id))
Expand All @@ -154,7 +155,11 @@ async def music_export(exporter: MessageExporter, seg: MusicShare, bot: Bot | No
content=seg.content or seg.summary or "",
img_url=seg.thumbnail or "",
)
res.data["subtype"] = platform
if seg.kind in platforms:
res.data["type"] = platform
else:
# 保留自定义音乐消息原有的 QQ subtype。
res.data["subtype"] = platform
return res

if exporter.get_adapter() is SupportAdapter.qq:
Expand Down
133 changes: 133 additions & 0 deletions tests/test_music_share.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import pytest
from nonebot import get_adapter
from nonebot.adapters.onebot.v11 import Adapter, Bot, Message, MessageSegment
from nonebug import App

from tests.fake import fake_group_message_event_v11

MUSIC_PLATFORMS = [
("NeteaseCloudMusic", "163"),
("QQMusic", "qq"),
("MiguMusic", "migu"),
("KugouMusic", "kugou"),
("KuwoMusic", "kuwo"),
]


@pytest.fixture
def music_metadata() -> dict[str, str]:
return {
"title": "示例歌曲",
"content": "示例歌手 | 示例专辑",
"url": "https://example.com/song",
"audio": "https://example.com/song.mp3",
"thumbnail": "https://example.com/cover.jpg",
}


@pytest.fixture
def music_data(music_metadata: dict[str, str]) -> dict[str, str]:
return {
"url": music_metadata["url"],
"audio": music_metadata["audio"],
"title": music_metadata["title"],
"content": music_metadata["content"],
"image": music_metadata["thumbnail"],
}


@pytest.mark.asyncio()
@pytest.mark.parametrize(("kind", "platform"), MUSIC_PLATFORMS)
@pytest.mark.parametrize("song_id", [None, ""])
async def test_onebot_music_share_without_id(
app: App,
kind: str,
platform: str,
song_id: str | None,
music_metadata: dict[str, str],
music_data: dict[str, str],
):
from nonebot_plugin_alconna import UniMessage
from nonebot_plugin_alconna.builtins.uniseg.music_share import MusicShare, MusicShareKind

card = MusicShare(kind=MusicShareKind(kind), id=song_id, **music_metadata)
message = await UniMessage(card).export(adapter="OneBot V11", fallback=False)

assert message == Message(MessageSegment("music", {"type": platform, **music_data}))


@pytest.mark.asyncio()
@pytest.mark.parametrize(("kind", "platform"), [*MUSIC_PLATFORMS, ("Custom", "qq")])
async def test_onebot_music_share_with_id(app: App, kind: str, platform: str, music_metadata: dict[str, str]):
from nonebot_plugin_alconna import UniMessage
from nonebot_plugin_alconna.builtins.uniseg.music_share import MusicShare, MusicShareKind

card = MusicShare(kind=MusicShareKind(kind), id="123", **music_metadata)
message = await UniMessage(card).export(adapter="OneBot V11", fallback=False)

assert message == Message(MessageSegment.music(platform, 123))


@pytest.mark.asyncio()
@pytest.mark.parametrize("kind", ["Custom", "custom", "Unknown"])
async def test_onebot_custom_music_share(
app: App, kind: str, music_metadata: dict[str, str], music_data: dict[str, str]
):
from nonebot_plugin_alconna import UniMessage
from nonebot_plugin_alconna.builtins.uniseg.music_share import MusicShare, MusicShareKind

card = MusicShare(kind=MusicShareKind(kind), **music_metadata)
message = await UniMessage(card).export(adapter="OneBot V11", fallback=False)

assert message == Message(MessageSegment("music", {"type": "custom", "subtype": "qq", **music_data}))


def test_music_share_requires_kind(app: App, music_metadata: dict[str, str]):
from nonebot_plugin_alconna.builtins.uniseg.music_share import MusicShare

with pytest.raises(TypeError, match="kind"):
MusicShare(**music_metadata)


@pytest.mark.asyncio()
@pytest.mark.parametrize(("url", "audio"), [(None, "https://example.com/song.mp3"), ("https://example.com/song", None)])
async def test_onebot_music_share_metadata_fallback(app: App, url: str | None, audio: str | None):
from nonebot_plugin_alconna import UniMessage
from nonebot_plugin_alconna.builtins.uniseg.music_share import MusicShare, MusicShareKind

card = MusicShare(kind=MusicShareKind.KuwoMusic, url=url, audio=audio, summary="示例摘要")
message = await UniMessage(card).export(adapter="OneBot V11", fallback=False)

assert message == Message(
MessageSegment(
"music",
{
"type": "kuwo",
"url": url or audio,
"audio": audio or url,
"title": "",
"content": "示例摘要",
"image": "",
},
)
)


@pytest.mark.asyncio()
async def test_onebot_music_share_finish(app: App, music_metadata: dict[str, str], music_data: dict[str, str]):
from nonebot_plugin_alconna import UniMessage, on_alconna
from nonebot_plugin_alconna.builtins.uniseg.music_share import MusicShare, MusicShareKind

card = MusicShare(kind=MusicShareKind.KuwoMusic, **music_metadata)
matcher = on_alconna("music")

@matcher.handle()
async def _():
await matcher.finish(UniMessage([card]))

async with app.test_matcher(matcher) as ctx:
bot = ctx.create_bot(base=Bot, adapter=get_adapter(Adapter))
event = fake_group_message_event_v11(message=Message("music"), user_id=123)
ctx.receive_event(bot, event)
ctx.should_call_send(event, Message(MessageSegment("music", {"type": "kuwo", **music_data})))
ctx.should_finished()