Skip to content

Commit 97645da

Browse files
committed
🍻 format spec for UniMessage and Segment
1 parent 0c20be9 commit 97645da

File tree

4 files changed

+31
-6
lines changed

4 files changed

+31
-6
lines changed

src/nonebot_plugin_alconna/uniseg/adapters/onebot11/builder.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ def get_adapter(cls) -> SupportAdapter:
1616

1717
@build("at")
1818
def at(self, seg: MessageSegment):
19-
if seg.data["qq"] != "all":
20-
return At("user", str(seg.data["qq"]))
21-
return AtAll()
19+
if seg.data["qq"] == "all":
20+
return AtAll()
21+
if int(seg.data["qq"]) == 0:
22+
return AtAll()
23+
return At("user", str(seg.data["qq"]))
2224

2325
@build("face")
2426
def face(self, seg: MessageSegment):

src/nonebot_plugin_alconna/uniseg/message.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,11 @@ def __str__(self) -> str:
626626
def __repr__(self) -> str:
627627
return "[" + ", ".join(repr(seg) for seg in self) + "]"
628628

629+
def __format__(self, format_spec):
630+
if format_spec in ("#", "*"):
631+
return "".join(format(seg, format_spec) for seg in self)
632+
return format(self.__str__(), format_spec)
633+
629634
@classmethod
630635
def template(cls, format_string: str | UniMessage) -> UniMessageTemplate:
631636
"""创建消息模板。

src/nonebot_plugin_alconna/uniseg/segment.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ class Segment:
5353
def __str__(self):
5454
return f"[{self.__class__.__name__.lower()}]"
5555

56+
def __format__(self, format_spec):
57+
if format_spec == "*":
58+
if not isinstance(self, Text):
59+
attrs = ",".join(f"{k}={v}" for k, v in self.data.items() if v is not None)
60+
return f"[{self.__class__.__name__.lower()}:{attrs}]"
61+
return self.__str__()
62+
if format_spec == "#":
63+
return self.__rich__() if isinstance(self, Text) else self.__str__()
64+
return format(self.__str__(), format_spec)
65+
5666
@overload
5767
def __add__(self: TS, item: str) -> "UniMessage[Union[TS, Text]]": ...
5868

@@ -161,15 +171,16 @@ def load(cls, data: dict) -> Self:
161171
"underline": "4",
162172
"flash": "5",
163173
"blink": "5",
164-
"rapid": "6",
165174
"sparkle": "5",
175+
"rapid": "6",
166176
"code": "7",
167177
"inverse": "7",
168178
"spoiler": "8",
169179
"invisible": "8",
170180
"strikethrough": "9",
171181
"delete": "9",
172182
"cross": "9",
183+
"normal": "22",
173184
"black": "30",
174185
"red": "31",
175186
"green": "32",
@@ -350,7 +361,8 @@ def __rich__(self):
350361
result.append(text[:left])
351362
for scale in scales:
352363
prefix = ";".join(f"{STYLE_TYPE_MAP[style]}" for style in styles[scale])
353-
result.append(f"\033[{prefix}m{text[scale[0] : scale[1]]}\033[0m")
364+
result.append(f"\033[{prefix}m{text[scale[0] : scale[1]]}")
365+
result.append("\033[0m")
354366
right = scales[-1][1]
355367
result.append(text[right:])
356368
return "".join(result)

tests/test_uniseg.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
from tests.fake import fake_group_message_event_v11
1010

1111

12+
def ansi(*code) -> str:
13+
codes = ";".join(str(c) for c in code)
14+
return f"\033[{codes}m"
15+
16+
1217
def test_uniseg():
1318
from nonebot_plugin_alconna.uniseg import FallbackSegment
1419
from nonebot_plugin_alconna import Text, Other, Video, Segment, select
@@ -28,7 +33,7 @@ def test_uniseg():
2833
Text("man").italic(0, 1),
2934
]
3035
assert text1.replace("o", "e") == Text("helle werld man").color("red", 0, -3).italic(3, -2)
31-
36+
assert f"{text1:#}" == f"{ansi(31)}hel{ansi(31, 3)}lo world {ansi(3)}m{ansi(0)}an"
3237
pat = select(Text)
3338
assert pat.first.validate(Text("foobar")).value() == Text("foobar")
3439
assert pat.first.validate(Video(url="foobar")(Text("foobar"))).value() == Text("foobar")
@@ -60,6 +65,7 @@ def test_unimsg():
6065
"At(flag='channel', target='456', display=None), "
6166
"At(flag='role', target='789', display=None)]"
6267
)
68+
assert f"{msg1:*}" == "[at:flag=user,target=123][at:flag=channel,target=456][at:flag=role,target=789]"
6369
assert msg1.select(At).filter(lambda x: x.flag == "user") == UniMessage.at("123")
6470
assert msg1.select(At).map(lambda x: x.target) == ["123", "456", "789"]
6571
assert UniMessage.text("123").at("456").export_sync(adapter="OneBot V11") == MessageSegment.text(

0 commit comments

Comments
 (0)