nonebot2/nonebot/adapters/ding/message.py

156 lines
4.7 KiB
Python
Raw Normal View History

2020-12-30 20:08:22 +08:00
from copy import copy
2020-12-06 02:30:19 +08:00
from typing import Any, Dict, Union, Iterable
2020-12-30 20:08:22 +08:00
from nonebot.typing import overrides
from nonebot.adapters import Message as BaseMessage, MessageSegment as BaseMessageSegment
2020-12-03 00:59:32 +08:00
class MessageSegment(BaseMessageSegment):
"""
钉钉 协议 MessageSegment 适配具体方法参考协议消息段类型或源码
"""
2020-12-30 20:08:22 +08:00
@overrides(BaseMessageSegment)
2020-12-30 00:36:29 +08:00
def __init__(self, type_: str, data: Dict[str, Any]) -> None:
2020-12-03 00:59:32 +08:00
super().__init__(type=type_, data=data)
2020-12-30 20:08:22 +08:00
@overrides(BaseMessageSegment)
2020-12-03 00:59:32 +08:00
def __str__(self):
if self.type == "text":
2020-12-30 00:36:29 +08:00
return str(self.data["content"])
elif self.type == "markdown":
return str(self.data["text"])
2020-12-03 00:59:32 +08:00
return ""
2020-12-30 20:08:22 +08:00
@overrides(BaseMessageSegment)
2020-12-03 00:59:32 +08:00
def __add__(self, other) -> "Message":
return Message(self) + other
2020-12-30 20:08:22 +08:00
@overrides(BaseMessageSegment)
def __radd__(self, other) -> "Message":
return Message(other) + self
2020-12-30 20:08:22 +08:00
@overrides(BaseMessageSegment)
def is_text(self) -> bool:
return self.type == "text"
2020-12-30 00:36:29 +08:00
@staticmethod
def atAll() -> "MessageSegment":
return MessageSegment("at", {"isAtAll": True})
2020-12-03 00:59:32 +08:00
2020-12-30 00:36:29 +08:00
@staticmethod
def atMobiles(*mobileNumber: str) -> "MessageSegment":
return MessageSegment("at", {"atMobiles": list(mobileNumber)})
2020-12-03 00:59:32 +08:00
@staticmethod
2020-12-30 00:36:29 +08:00
def text(text: str) -> "MessageSegment":
return MessageSegment("text", {"content": text})
2020-12-03 00:59:32 +08:00
@staticmethod
def image(picURL: str) -> "MessageSegment":
return MessageSegment("image", {"picURL": picURL})
@staticmethod
def extension(dict_: dict) -> "MessageSegment":
""""标记 text 文本的 extension 属性,需要与 text 消息段相加。
"""
return MessageSegment("extension", dict_)
2020-12-03 00:59:32 +08:00
@staticmethod
def markdown(title: str, text: str) -> "MessageSegment":
2020-12-30 00:36:29 +08:00
return MessageSegment(
"markdown",
{
2020-12-03 00:59:32 +08:00
"title": title,
"text": text,
},
2020-12-30 00:36:29 +08:00
)
2020-12-03 00:59:32 +08:00
@staticmethod
def actionCardSingleBtn(title: str, text: str, singleTitle: str,
singleURL) -> "MessageSegment":
2020-12-03 00:59:32 +08:00
return MessageSegment(
"actionCard", {
2020-12-30 00:36:29 +08:00
"title": title,
"text": text,
"singleTitle": singleTitle,
"singleURL": singleURL
2020-12-03 00:59:32 +08:00
})
@staticmethod
2020-12-30 00:36:29 +08:00
def actionCardMultiBtns(
2020-12-03 00:59:32 +08:00
title: str,
text: str,
btns: list,
2020-12-03 00:59:32 +08:00
hideAvatar: bool = False,
btnOrientation: str = '1',
) -> "MessageSegment":
"""
:参数:
* ``btnOrientation``: 0按钮竖直排列 1按钮横向排列
* ``btns``: [{ "title": title, "actionURL": actionURL }, ...]
"""
return MessageSegment(
"actionCard", {
2020-12-30 00:36:29 +08:00
"title": title,
"text": text,
"hideAvatar": "1" if hideAvatar else "0",
"btnOrientation": btnOrientation,
"btns": btns
2020-12-03 00:59:32 +08:00
})
@staticmethod
def feedCard(links: list) -> "MessageSegment":
2020-12-03 00:59:32 +08:00
"""
:参数:
* ``links``: [{ "title": xxx, "messageURL": xxx, "picURL": xxx }, ...]
"""
2020-12-30 00:36:29 +08:00
return MessageSegment("feedCard", {"links": links})
2020-12-03 00:59:32 +08:00
@staticmethod
def raw(data) -> "MessageSegment":
return MessageSegment('raw', data)
def to_dict(self) -> dict:
# 让用户可以直接发送原始的消息格式
if self.type == "raw":
return copy(self.data)
# 不属于消息内容,只是作为消息段的辅助
if self.type in ["at", "extension"]:
return {self.type: copy(self.data)}
return {"msgtype": self.type, self.type: copy(self.data)}
2020-12-03 00:59:32 +08:00
class Message(BaseMessage):
"""
钉钉 协议 Message 适配
"""
@staticmethod
2020-12-30 20:08:22 +08:00
@overrides(BaseMessage)
2020-12-30 00:36:29 +08:00
def _construct(msg: Union[str, dict, list]) -> Iterable[MessageSegment]:
2020-12-03 00:59:32 +08:00
if isinstance(msg, dict):
yield MessageSegment(msg["type"], msg.get("data") or {})
elif isinstance(msg, list):
for seg in msg:
yield MessageSegment(seg["type"], seg.get("data") or {})
elif isinstance(msg, str):
2020-12-03 18:47:58 +08:00
yield MessageSegment.text(msg)
2020-12-30 00:36:29 +08:00
def _produce(self) -> dict:
data = {}
for segment in self:
# text 可以和 text 合并
if segment.type == "text" and data.get("msgtype") == 'text':
2020-12-30 00:36:29 +08:00
data.setdefault("text", {})
data["text"]["content"] = data["text"].setdefault(
"content", "") + segment.data["content"]
else:
data.update(segment.to_dict())
2020-12-30 00:36:29 +08:00
return data