Skip to content

Commit

Permalink
Update to 2.1.0: fix some bugs, add new features, modify definitions.
Browse files Browse the repository at this point in the history
1. Add a function which can format cq string to message array.
2. Add new apis: event(), msg_text()
3. Modify some object typing and definitions.
  • Loading branch information
aicorein committed Mar 4, 2024
1 parent 1652079 commit dd2ceb0
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 62 deletions.
10 changes: 8 additions & 2 deletions melobot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@
RespEvent,
RWController,
bot,
event,
finish,
get_twin_event,
msg_text,
send,
send_hup,
send_reply,
session,
to_cq_arr,
)
from .types import (
BotChecker,
Expand All @@ -50,8 +53,8 @@
PrivateMsgLvl,
RegexMatch,
StartMatch,
clear_cq,
cooldown,
get_cq_text,
get_id,
lock,
semaphore,
Expand All @@ -76,6 +79,7 @@ def get_metainfo() -> MetaInfo:
"get_metainfo",
"AttrSessionRule",
"session",
"to_cq_arr",
"MetaEvent",
"MsgEvent",
"NoticeEvent",
Expand All @@ -86,6 +90,8 @@ def get_metainfo() -> MetaInfo:
"RespEvent",
"RWController",
"bot",
"event",
"msg_text",
"finish",
"get_twin_event",
"send",
Expand All @@ -112,7 +118,7 @@ def get_metainfo() -> MetaInfo:
"PrivateMsgLvl",
"RegexMatch",
"StartMatch",
"clear_cq",
"get_cq_text",
"cooldown",
"get_id",
"lock",
Expand Down
2 changes: 1 addition & 1 deletion melobot/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

class MetaInfo:
def __init__(self) -> None:
self.VER = "2.0.2"
self.VER = "2.1.0"
self.PROJ_NAME = "MeloBot"
self.PROJ_DESC = "A qbot module with friendly interface, session control and plugin-supported."
self.PROJ_SRC = "https://github.com/aicorein/melobot"
Expand Down
13 changes: 11 additions & 2 deletions melobot/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
from .action import *
from .base import RWController, get_twin_event
from .base import RWController, get_twin_event, to_cq_arr
from .bot import BOT_PROXY as bot
from .event import MetaEvent, MsgEvent, NoticeEvent, RequestEvent, RespEvent
from .ipc import PluginBus, PluginStore
from .plugin import Plugin
from .session import SESSION_LOCAL as session
from .session import AttrSessionRule, BotSession, finish, send, send_hup, send_reply
from .session import (
AttrSessionRule,
BotSession,
event,
finish,
msg_text,
send,
send_hup,
send_reply,
)
14 changes: 7 additions & 7 deletions melobot/models/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
# cq 编码相关
"cq_escape",
"cq_anti_escape",
"to_cq_str_format",
"to_cq_str_action",
# 消息发送、处理相关
"msg_action",
"forward_msg_action",
Expand Down Expand Up @@ -117,7 +117,7 @@ def cq_anti_escape(text: str) -> str:
)


def to_cq_str_format(action: "BotAction") -> "BotAction":
def to_cq_str_action(action: "BotAction") -> "BotAction":
"""
转化 action 携带的 message 字段转为 cq 字符串格式,并返回新的 action。
支持的 action 类型有:msg_action 和 forward_action
Expand Down Expand Up @@ -375,7 +375,7 @@ def custom_msg_node(
sendName: str,
sendId: int,
seq: str = None,
) -> Dict:
) -> MsgNodeDict:
"""
自定义消息节点构造方法。转化字符串、消息、消息段为消息节点
"""
Expand All @@ -402,7 +402,7 @@ def custom_msg_node(
return ret


def refer_msg_node(msgId: int) -> Dict:
def refer_msg_node(msgId: int) -> MsgNodeDict:
"""
引用消息节点构造方法
"""
Expand Down Expand Up @@ -471,7 +471,7 @@ def __init__(
self,
msgs: List[CQMsgDict],
isPrivate: bool,
userId: int,
userId: int = None,
groupId: int = None,
) -> None:
super().__init__()
Expand All @@ -494,7 +494,7 @@ def __init__(
def msg_action(
content: Union[str, CQMsgDict, List[CQMsgDict]],
isPrivate: bool,
userId: int,
userId: int = None,
groupId: int = None,
respWaited: bool = False,
triggerEvent: BotEvent = None,
Expand Down Expand Up @@ -547,7 +547,7 @@ def __init__(


def forward_msg_action(
msgNodes: Dict,
msgNodes: List[MsgNodeDict],
isPrivate: bool,
userId: int = None,
groupId: int = None,
Expand Down
49 changes: 48 additions & 1 deletion melobot/models/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import asyncio as aio
import time
import re
from contextlib import asynccontextmanager
from itertools import chain, zip_longest

from ..types.exceptions import *
from ..types.typing import *
Expand All @@ -13,6 +14,52 @@ def __new__(cls, *args, **kwargs):
return cls.__instance__


def to_cq_arr(s: str) -> dict:
"""
从 cq 消息字符串转换为 cq 消息段
"""

def replace_func(m) -> str:
s, e = m.regs[0]
cq_texts.append(m.string[s:e])
return "\u0000"

cq_regex = re.compile(r"\[CQ:.*?\]")
cq_texts = []
no_cq_str = cq_regex.sub(replace_func, s)
pure_texts = map(
lambda x: f"[CQ:text,text={x}]" if x != "" else x,
no_cq_str.split("\u0000"),
)
content: str = "".join(
chain.from_iterable(zip_longest(pure_texts, cq_texts, fillvalue=""))
)

cq_entity = content.split("]")[:-1]
content: list = []
for e in cq_entity:
_ = e.split(",")
cq_type = _[0][4:]
data = {}
for param_pair in _[1:]:
name, val = param_pair.split("=")
val = (
val.replace("&", "&")
.replace("[", "[")
.replace("]", "]")
.replace(",", ",")
)
if val.isdigit():
val = int(val)
try:
val = float(val)
except Exception:
pass
data[name] = val
content.append({"type": cq_type, "data": data})
return content


class AsyncTwinEvent(aio.Event):
"""
孪生 Event,会和绑定的一方时刻保持状态相反。
Expand Down
48 changes: 31 additions & 17 deletions melobot/models/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from ..types.models import BotEvent
from ..types.typing import *
from .base import to_cq_arr


class BotEventBuilder:
Expand Down Expand Up @@ -33,8 +34,8 @@ def __init__(self, rawEvent: dict) -> None:
self.id: int
self.sender: MsgEvent.Sender
self.group_id: Union[int, None]
# 使用 CQ 码编码非文本消息段
self.cq_content: str
# 使用 CQ 字符串编码的消息
self.raw_content: str
# array 格式表示所有类型消息段
self.content: dict
# 消息中所有文本消息段的合并字符串
Expand All @@ -57,8 +58,8 @@ def _init(self) -> None:

self._cq_regex = re.compile(r"\[CQ:.*?\]")
self.id = rawEvent["message_id"]
self.cq_content = rawEvent["raw_message"]
self.content = rawEvent["message"]
self.raw_content = rawEvent["raw_message"]
self.content = self._format_to_array(rawEvent["message"])
self.text = self._get_text(self.content)
self.font = rawEvent["font"]

Expand All @@ -77,24 +78,37 @@ def _init(self) -> None:
if self.is_group():
self.group_id = rawEvent["group_id"]

def _format_to_array(self, content: Union[dict, str]) -> dict:
if not isinstance(content, str):
return content
else:
return to_cq_arr(content)

def _get_text(self, content: Union[dict, str]) -> bool:
"""
获取消息中所有文本消息,返回合并字符串
"""
if isinstance(content, str):
return (
self._cq_regex.sub("", content)
.replace("&", "&")
.replace("[", "[")
.replace("]", "]")
.replace(",", ",")
)
text_list = []
for item in content:
if item["type"] == "text":
text_list.append(item["data"]["text"])
return "".join(text_list)

def cq_get(self, cq_type: str, param: str) -> Union[List[Union[int, float, str]], None]:
"""
从当前 event 中获取指定 cq 类消息的指定 param,以列表形式返回。
当没有对应类型的 cq 消息或者没有对应的 param,不会返回空列表,而是返回 None
"""
if isinstance(self.content, str):
pass
else:
text_list = []
for item in content:
if item["type"] == "text":
text_list.append(item["data"]["text"])
return "".join(text_list)
results = []
for item in self.content:
if item["type"] == cq_type:
val = item["data"].get(param)
if val is not None:
results.append(val)
return results if len(results) > 0 else None

def is_private(self) -> bool:
"""是否为私聊消息(注意群临时会话属于该类别)"""
Expand Down
Loading

0 comments on commit dd2ceb0

Please sign in to comment.