Skip to content

Commit c65a142

Browse files
committed
✨ support adapter WXMP
1 parent 5e75d51 commit c65a142

File tree

9 files changed

+213
-30
lines changed

9 files changed

+213
-30
lines changed

example/bot.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
# driver.register_adapter(SatoriAdapter)
1212

1313
# nonebot.require("nonebot_plugin_alconna")
14-
nonebot.load_plugins("plugins")
14+
# nonebot.load_plugins("plugins")
15+
nonebot.load_plugin("plugins.demo1")
1516

1617

1718
async def _():

pdm.lock

Lines changed: 38 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ dependencies = [
1414
"nonebot-plugin-waiter>=0.6.0",
1515
]
1616
dynamic = ["version"]
17-
requires-python = ">=3.9"
17+
requires-python = ">=3.11"
1818
readme = "README.md"
1919
license = {text = "MIT"}
2020
keywords = [
@@ -69,6 +69,8 @@ dev = [
6969
"nonebot-plugin-localstore>=0.7.1",
7070
"pyyaml>=6.0.1",
7171
"fix-future-annotations>=0.5.0",
72+
"nonebot-adapter-heybox>=0.1.1; python_version >= \"3.11\"",
73+
"nonebot-adapter-wxmp>=0.1.4; python_version >= \"3.10\"",
7274
]
7375
[tool.pdm.build]
7476
includes = ["src/nonebot_plugin_alconna"]

src/nonebot_plugin_alconna/uniseg/adapters/qq/exporter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ async def send_to(self, target: Union[Target, Event], bot: Bot, message: Message
356356
message = message.exclude("mention_channel", "mention_user", "mention_everyone", "reference")
357357
return await bot.send(event=target, message=message, **kwargs)
358358

359-
if target.extra.get("qq.reply_seq"):
359+
if target.extra.get("qq.reply_seq") is not None:
360360
target.extra["qq.reply_seq"] += 1
361361

362362
if target.channel:
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from nonebot_plugin_alconna.uniseg.loader import BaseLoader
2+
from nonebot_plugin_alconna.uniseg.constraint import SupportAdapter
3+
4+
5+
class Loader(BaseLoader):
6+
def get_adapter(self) -> SupportAdapter:
7+
return SupportAdapter.wxmp
8+
9+
def get_builder(self):
10+
from .builder import WXMPMessageBuilder
11+
12+
return WXMPMessageBuilder()
13+
14+
def get_exporter(self):
15+
from .exporter import WXMPMessageExporter
16+
17+
return WXMPMessageExporter()
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from nonebot.adapters.wxmp.message import MessageSegment
2+
from nonebot.adapters.wxmp.message import Text as TextSegment
3+
from nonebot.adapters.wxmp.message import Emjoy as EmojiSegment
4+
from nonebot.adapters.wxmp.message import Image as ImageSegment
5+
from nonebot.adapters.wxmp.message import Video as VideoSegment
6+
from nonebot.adapters.wxmp.message import Voice as VoiceSegment
7+
from nonebot.adapters.wxmp.message import Location as LocationSegment
8+
from nonebot.adapters.wxmp.message import Miniprogrampage as MiniProgramSegment
9+
10+
from nonebot_plugin_alconna.uniseg.constraint import SupportAdapter
11+
from nonebot_plugin_alconna.uniseg.builder import MessageBuilder, build
12+
from nonebot_plugin_alconna.uniseg.segment import Text, Audio, Emoji, Hyper, Image, Other, Video
13+
14+
15+
class WXMPMessageBuilder(MessageBuilder[MessageSegment]):
16+
@classmethod
17+
def get_adapter(cls) -> SupportAdapter:
18+
return SupportAdapter.wxmp
19+
20+
@build("text")
21+
def build_text(self, seg: TextSegment):
22+
return Text(seg.data["text"])
23+
24+
@build("image")
25+
def build_image(self, seg: ImageSegment):
26+
return Image(id=seg.data["media_id"], url=str(seg.data["file_url"]))
27+
28+
@build("miniprogrampage")
29+
def build_miniprogrampage(self, seg: MiniProgramSegment):
30+
return Hyper("json", content={**seg.data})
31+
32+
@build("video")
33+
def build_video(self, seg: VideoSegment):
34+
return Video(id=seg.data["media_id"])
35+
36+
@build("voice")
37+
def build_voice(self, seg: VoiceSegment):
38+
return Audio(id=seg.data["media_id"])
39+
40+
@build("location")
41+
def build_location(self, seg: LocationSegment):
42+
return Other(seg)
43+
44+
@build("emjoy")
45+
def build_emoji(self, seg: EmojiSegment):
46+
t = seg.data["emjoy"]
47+
return Emoji(t.value, t.name)
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from pathlib import Path
2+
from typing import Union
3+
4+
from tarina import lang
5+
from nonebot.adapters import Bot, Event
6+
from nonebot.adapters.wxmp import Bot as WXMPBot
7+
from nonebot.adapters.wxmp.event import MessageEvent
8+
from nonebot.adapters.wxmp.event import Event as WXMPEvent
9+
from nonebot.adapters.wxmp.message import Message, EmjoyType, MessageSegment
10+
11+
from nonebot_plugin_alconna.uniseg.constraint import SupportScope, SerializeFailed
12+
from nonebot_plugin_alconna.uniseg.segment import Text, Audio, Emoji, Hyper, Image, Video, Voice
13+
from nonebot_plugin_alconna.uniseg.exporter import Target, SupportAdapter, MessageExporter, export
14+
15+
16+
class WXMPMessageExporter(MessageExporter[Message]):
17+
def get_message_type(self):
18+
return Message
19+
20+
@classmethod
21+
def get_adapter(cls) -> SupportAdapter:
22+
return SupportAdapter.wxmp
23+
24+
def get_target(self, event: Event, bot: Union[Bot, None] = None) -> Target:
25+
assert isinstance(event, WXMPEvent)
26+
return Target(
27+
event.get_user_id(),
28+
private=True,
29+
adapter=self.get_adapter(),
30+
self_id=bot.self_id if bot else None,
31+
scope=SupportScope.wechat_oap,
32+
)
33+
34+
def get_message_id(self, event: Event) -> str:
35+
assert isinstance(event, MessageEvent)
36+
return str(event.message_id)
37+
38+
@export
39+
async def text(self, seg: Text, bot: Union[Bot, None]) -> "MessageSegment":
40+
if not seg.styles:
41+
return MessageSegment.text(seg.text)
42+
style = seg.extract_most_style()
43+
if style == "link":
44+
title = desc = url = seg.text
45+
if getattr(seg, "_children", []):
46+
title = desc = seg._children[0].text # type: ignore
47+
return MessageSegment.link(title, desc, url)
48+
return MessageSegment.text(seg.text)
49+
50+
@export
51+
async def media(self, seg: Union[Image, Voice, Video, Audio], bot: Union[Bot, None]) -> "MessageSegment":
52+
name = seg.__class__.__name__.lower()
53+
methods = {
54+
"image": MessageSegment.image,
55+
"voice": MessageSegment.voice,
56+
"video": MessageSegment.video,
57+
"audio": MessageSegment.voice,
58+
}
59+
if seg.id:
60+
return methods[name](media_id=seg.id)
61+
if seg.raw:
62+
if name in ("voice", "audio"):
63+
return MessageSegment.voice(file=seg.raw_bytes, format=seg.mimetype)
64+
return methods[name](file=seg.raw_bytes)
65+
if seg.path:
66+
return methods[name](file_path=Path(seg.path))
67+
if seg.url and name == "image":
68+
return MessageSegment.image(file_url=seg.url) # type: ignore
69+
raise SerializeFailed(lang.require("nbp-uniseg", "invalid_segment").format(type=name, seg=seg))
70+
71+
@export
72+
async def emoji(self, seg: Emoji, bot: Union[Bot, None]) -> "MessageSegment":
73+
t = EmjoyType(seg.name)
74+
return MessageSegment.emjoy(t)
75+
76+
@export
77+
async def hyper(self, seg: Hyper, bot: Union[Bot, None]) -> "MessageSegment":
78+
if isinstance(seg.content, dict):
79+
return MessageSegment.miniprogrampage(**seg.content)
80+
raise SerializeFailed(lang.require("nbp-uniseg", "invalid_segment").format(type="hyper", seg=seg))
81+
82+
async def send_to(self, target: Union[Target, Event], bot: Bot, message: Message, **kwargs):
83+
assert isinstance(bot, WXMPBot)
84+
85+
if isinstance(target, Event):
86+
return await bot.send(target, message, **kwargs) # type: ignore
87+
return await bot.send_custom_message(user_id=target.id, message=message)

src/nonebot_plugin_alconna/uniseg/constraint.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class SupportAdapter(str, Enum):
1717
dodo = "DoDo"
1818
feishu = "Feishu"
1919
github = "GitHub"
20+
heybox = "Heybox"
2021
kritor = "Kritor"
2122
kook = "Kaiheila"
2223
mail = "Mail"
@@ -30,6 +31,7 @@ class SupportAdapter(str, Enum):
3031
satori = "Satori"
3132
telegram = "Telegram"
3233
tail_chat = "Tailchat"
34+
wxmp = "WXMP"
3335

3436
nonebug = "fake"
3537

@@ -47,6 +49,7 @@ class SupportScope(str, Enum):
4749
discord = "Discord"
4850
feishu = "Feishu"
4951
dodo = "DoDo"
52+
heybox = "Heybox"
5053
kook = "Kaiheila"
5154
mail = "Mail"
5255
minecraft = "Minecraft"
@@ -96,6 +99,7 @@ def ensure_satori(platform: str):
9699
"kook": SupportScope.kook,
97100
"dingtalk": SupportScope.ding,
98101
"mail": SupportScope.mail,
102+
"heybox": SupportScope.heybox,
99103
}.get(platform, SupportScope.satori_other)
100104

101105

@@ -108,6 +112,7 @@ class SupportAdapterModule(str, Enum):
108112
dodo = "nonebot.adapters.dodo"
109113
feishu = "nonebot.adapters.feishu"
110114
github = "nonebot.adapters.github"
115+
heybox = "nonebot.adapters.heybox"
111116
kritor = "nonebot.adapters.kritor"
112117
kook = "nonebot.adapters.kaiheila"
113118
mail = "nonebot.adapters.mail"
@@ -121,6 +126,7 @@ class SupportAdapterModule(str, Enum):
121126
satori = "nonebot.adapters.satori"
122127
telegram = "nonebot.adapters.telegram"
123128
tail_chat = "nonebot_adapter_tailchat"
129+
wxmp = "nonebot.adapters.wxmp"
124130

125131

126132
UNISEG_MESSAGE: Literal["_alc_uniseg_message"] = "_alc_uniseg_message"

src/nonebot_plugin_alconna/uniseg/target.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -439,14 +439,14 @@ async def select_wechat(target: "Target", bot: Bot):
439439
return False
440440
if bot.adapter.get_name() != SupportAdapter.onebot12:
441441
return False
442-
return not hasattr(bot, "platform") or bot.platform == "wechat"
442+
return hasattr(bot, "platform") and bot.platform == "wechat"
443443

444444

445445
@_register(SupportScope.wechat_oap)
446446
async def select_wechat_oap(target: "Target", bot: Bot):
447447
if target.channel:
448448
return False
449-
if bot.adapter.get_name() != SupportAdapter.satori:
449+
if bot.adapter.get_name() not in {SupportAdapter.wxmp, SupportAdapter.satori}:
450450
return False
451451
return not hasattr(bot, "platform") or bot.platform == "wechat-official"
452452

@@ -457,7 +457,7 @@ async def select_wecom(target: "Target", bot: Bot):
457457
return False
458458
if bot.adapter.get_name() != SupportAdapter.satori:
459459
return False
460-
return not hasattr(bot, "platform") or bot.platform == "wecom"
460+
return hasattr(bot, "platform") and bot.platform == "wecom"
461461

462462

463463
@_register(SupportScope.tail_chat)
@@ -474,3 +474,12 @@ async def select_mail(target: "Target", bot: Bot):
474474
if bot.adapter.get_name() not in {SupportAdapter.mail, SupportAdapter.satori}:
475475
return False
476476
return not hasattr(bot, "platform") or bot.platform == "mail"
477+
478+
479+
@_register(SupportScope.heybox)
480+
async def select_heybox(target: "Target", bot: Bot):
481+
if not target.channel:
482+
return False
483+
if bot.adapter.get_name() not in {SupportAdapter.heybox, SupportAdapter.satori}:
484+
return False
485+
return not hasattr(bot, "platform") or bot.platform == "heybox"

0 commit comments

Comments
 (0)