2020-12-06 02:30:19 +08:00
|
|
|
|
from typing import Any, Dict, Union, Iterable
|
|
|
|
|
|
2020-12-07 00:06:09 +08:00
|
|
|
|
from nonebot.adapters import Message as BaseMessage, MessageSegment as BaseMessageSegment
|
2020-12-06 02:30:19 +08:00
|
|
|
|
|
2020-12-03 00:59:32 +08:00
|
|
|
|
|
|
|
|
|
class MessageSegment(BaseMessageSegment):
|
|
|
|
|
"""
|
|
|
|
|
钉钉 协议 MessageSegment 适配。具体方法参考协议消息段类型或源码。
|
|
|
|
|
"""
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
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 ""
|
|
|
|
|
|
|
|
|
|
def __add__(self, other) -> "Message":
|
|
|
|
|
return Message(self) + other
|
|
|
|
|
|
2020-12-29 12:12:35 +08:00
|
|
|
|
def __radd__(self, other) -> "Message":
|
|
|
|
|
return Message(other) + self
|
|
|
|
|
|
|
|
|
|
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 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, btnTitle: str,
|
|
|
|
|
btnUrl) -> "MessageSegment":
|
|
|
|
|
return MessageSegment(
|
|
|
|
|
"actionCard", {
|
2020-12-30 00:36:29 +08:00
|
|
|
|
"title": title,
|
|
|
|
|
"text": text,
|
|
|
|
|
"singleTitle": btnTitle,
|
|
|
|
|
"singleURL": btnUrl
|
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 = [],
|
|
|
|
|
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
|
2020-12-30 00:36:29 +08:00
|
|
|
|
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 empty() -> "MessageSegment":
|
|
|
|
|
"""不想回复消息到群里"""
|
2020-12-30 00:36:29 +08:00
|
|
|
|
return MessageSegment("empty", {})
|
2020-12-03 00:59:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Message(BaseMessage):
|
|
|
|
|
"""
|
|
|
|
|
钉钉 协议 Message 适配。
|
|
|
|
|
"""
|
|
|
|
|
|
2020-12-29 12:12:35 +08:00
|
|
|
|
@classmethod
|
|
|
|
|
def _validate(cls, value):
|
|
|
|
|
return cls(value)
|
|
|
|
|
|
2020-12-03 00:59:32 +08:00
|
|
|
|
@staticmethod
|
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:
|
|
|
|
|
if segment.type == "text":
|
|
|
|
|
data["msgtype"] = "text"
|
|
|
|
|
data.setdefault("text", {})
|
|
|
|
|
data["text"]["content"] = data["text"].setdefault(
|
|
|
|
|
"content", "") + segment.data["content"]
|
|
|
|
|
elif segment.type == "markdown":
|
|
|
|
|
data["msgtype"] = "markdown"
|
|
|
|
|
data.setdefault("markdown", {})
|
|
|
|
|
data["markdown"]["text"] = data["markdown"].setdefault(
|
|
|
|
|
"content", "") + segment.data["content"]
|
|
|
|
|
elif segment.type == "empty":
|
|
|
|
|
data["msgtype"] = "empty"
|
|
|
|
|
elif segment.type == "at" and "atMobiles" in segment.data:
|
|
|
|
|
data.setdefault("at", {})
|
|
|
|
|
data["at"]["atMobiles"] = data["at"].setdefault(
|
|
|
|
|
"atMobiles", []) + segment.data["atMobiles"]
|
|
|
|
|
elif segment.data:
|
|
|
|
|
data.setdefault(segment.type, {})
|
|
|
|
|
data[segment.type].update(segment.data)
|
|
|
|
|
return data
|