Skip to content

Commit

Permalink
feat: 支持 wechatbot-webhook 至 v2.6.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Cassius0924 committed Mar 4, 2024
1 parent b6235b2 commit 01afb46
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 31 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ python3 -m wechatter
| 配置项 | 解释 | 备注 |
| --- | --- | --- |
| `command_prefix` | 机器人命令前缀 | 默认为 `/` ,可以设置为`>>``!` 等任意字符 |
| `need_mentioned` | 群聊中的命令是否需要@机器人 | 默认为 `True` |
| `need_mentioned` | 群聊中的命令是否需要@机器人 | 默认为 `False` |

### ⚙️ LLM 配置

Expand Down
39 changes: 22 additions & 17 deletions wechatter/app/routers/wechat.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from fastapi import APIRouter, Form, UploadFile
from loguru import logger

from wechatter.bot import BotInfo
# from wechatter.bot import BotInfo
from wechatter.commands import commands, quoted_handlers
from wechatter.config import config
from wechatter.database import (
Expand All @@ -22,25 +22,34 @@

router = APIRouter()

# 传入命令字典,构造消息处理器
message_handler = MessageHandler(
commands=commands, quoted_handlers=quoted_handlers, games=games
)


@router.post(config["wx_webhook_recv_api_path"])
async def recv_wechat_msg(
type: str = Form(),
content: Union[UploadFile, str] = Form(),
source: str = Form(),
is_mentioned: str = Form(alias="isMentioned"),
is_system_event: str = Form(alias="isSystemEvent"),
is_from_self: str = Form(alias="isMsgFromSelf"),
):
"""
接收Docker转发过来的消息的接口
用于接收 wxBotWebhook 转发过来的消息的接口
"""

# 更新机器人信息(id和name)
BotInfo.update_from_source(source)
# BotInfo.update_from_source(source)

if type == "unknown":
logger.info(f"收到未知消息:{content}")
return

# 判断是否是系统事件
if is_system_event == "1":
logger.warning(f"收到系统事件:{content}")
if type in ["system_event_login", "system_event_logout", "system_event_error"]:
logger.info(f"收到系统事件:{type}")
handle_system_event(content)
return

Expand All @@ -51,29 +60,25 @@ async def recv_wechat_msg(

# 解析命令
# 构造消息对象
message = Message.from_api_msg(
message_obj = Message.from_api_msg(
type=type,
content=content,
source=source,
is_mentioned=is_mentioned,
is_from_self=is_from_self,
)
# 向群组表中添加该群组
add_group(message.group)
add_group(message_obj.group)
# 向用户表中添加该用户
add_person(message.person)
add_person(message_obj.person)
# 向消息表中添加该消息
message.id = add_message(message)
# TODO: 添加自己发送的消息,等待 wechatbot-webhook 支持
message_obj.id = add_message(message_obj)

# DEBUG
print(str(message))
print(str(message_obj))

# 传入命令字典,构造消息处理器
message_handler = MessageHandler(
commands=commands, quoted_handlers=quoted_handlers, games=games
)
# 用户发来的消息均送给消息解析器处理
message_handler.handle_message(message)
message_handler.handle_message(message_obj)

# 快捷回复
# return {"success": True, "data": {"type": "text", "content": "hello world!"}}
Expand Down
16 changes: 16 additions & 0 deletions wechatter/config/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,22 @@ def validate_config(config):
error_msg = f"配置参数错误:task_cron_list[{i}].commands[{i2}] 缺少必要字段 {field}"
logger.critical(error_msg)
raise ValueError(error_msg)
# 微信消息转发配置
ess_fields = ["from_list"]
for i, rule in enumerate(config["message_forwarding_rule_list"]):
for field in ess_fields:
if field not in rule:
error_msg = f"配置参数错误:message_forwarding_rule_list[{i}] 缺少必要字段 {field}"
logger.critical(error_msg)
raise ValueError(error_msg)

# 判断这个 rule 是否有 from_list_exclude 字段
if (
"from_list_exclude" in rule
and config["bot_name"] not in rule["from_list_exclude"]
):
# 加入机器人名字,防止机器人自己转发自己的消息,导致死循环刷屏
rule["from_list_exclude"].append(config["bot_name"])

# Discord 消息转发配置
ess_fields = ["from_list", "webhook_url"]
Expand Down
6 changes: 3 additions & 3 deletions wechatter/message/message_forwarder.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,14 @@ def reply_wechat_forwarded_message(message_obj: Message):
回复转发消息
:param message_obj: 消息对象
"""
assert message_obj.forwarded_source
name, is_group = message_obj.forwarded_source
assert message_obj.forwarded_source_name
name, is_group = message_obj.forwarded_source_name
sender.send_msg(
name,
message_obj.pure_content,
is_group=is_group,
)
logger.info(f"回复 {message_obj.forwarded_source} 的转发消息")
logger.info(f"回复 {message_obj.forwarded_source_name} 的转发消息")

def remind_official_account_article(self, message_obj: Message):
"""
Expand Down
8 changes: 6 additions & 2 deletions wechatter/message/message_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def handle_message(self, message_obj: Message):
# 尝试进行消息转发
message_forwarder.forwarding_to_wechat(message_obj)
# 尝试进行转发消息的回复
if message_obj.forwarded_source:
if message_obj.forwarded_source_name:
message_forwarder.reply_wechat_forwarded_message(message_obj)
return

Expand All @@ -74,7 +74,11 @@ def handle_message(self, message_obj: Message):
):
message_forwarder.forwarding_to_discord(message_obj)

to = SendTo(person=message_obj.person, group=message_obj.group)
# 判断是否是自己的消息,是则需要将 to 设置为对方
if message_obj.is_from_self:
to = SendTo(person=message_obj.receiver, group=message_obj.group)
else:
to = SendTo(person=message_obj.person, group=message_obj.group)

# 解析命令
content = message_obj.content
Expand Down
33 changes: 30 additions & 3 deletions wechatter/models/wechat/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ class MessageType(enum.Enum):
file = "file"
urlLink = "urlLink"
friendship = "friendship"
system_event_login = "system_event_login"
system_event_logout = "system_event_logout"
system_event_error = "system_event_error"
system_event_push_notify = "system_event_push_notify"
unknown = "unknown"


class MessageSenderType(enum.Enum):
Expand All @@ -47,8 +52,10 @@ class Message(BaseModel):
type: MessageType
person: Person
group: Optional[Group] = None
receiver: Optional[Person] = None
content: str
is_mentioned: bool = False
is_from_self: bool = False
id: Optional[int] = None

@classmethod
Expand All @@ -58,13 +65,15 @@ def from_api_msg(
content: str,
source: str,
is_mentioned: str,
is_from_self: str = 0,
):
"""
从API接口创建消息对象
:param type: 消息类型
:param content: 消息内容
:param source: 消息来源
:param is_mentioned: 是否@机器人
:param is_from_self: 是否是自己发送的消息
:return: 消息对象
"""
try:
Expand Down Expand Up @@ -112,16 +121,34 @@ def from_api_msg(
admin_id_list=payload.get("adminIdList", []),
member_list=payload.get("memberList", []),
)

_receiver = None
if source_json.get("to"):
to_payload = source_json.get("to").get("payload", {})
_receiver = Person(
id=to_payload.get("id", ""),
name=to_payload.get("name", ""),
alias=to_payload.get("alias", ""),
gender="unknown",
is_star=to_payload.get("star", ""),
is_friend=to_payload.get("friend", ""),
)

_content = content.replace("\u2005", " ", 1)
_is_mentioned = False
if is_mentioned == "1":
_is_mentioned = True
_is_from_self = False
if is_from_self == "1":
_is_from_self = True
return cls(
type=type,
person=_person,
group=_group,
receiver=_receiver,
content=_content,
is_mentioned=is_mentioned,
is_mentioned=_is_mentioned,
is_from_self=_is_from_self,
)

@computed_field
Expand Down Expand Up @@ -190,10 +217,10 @@ def pure_content(self) -> str:

@computed_field
@cached_property
def forwarded_source(self) -> Optional[Tuple[str, bool]]:
def forwarded_source_name(self) -> Optional[Tuple[str, bool]]:
"""
获取转发消息的来源的名字
:return: 消息来源的名字和是否为群的元组(source, is_group)
:return: 消息来源的名字和是否为群的元组(source_name, is_group)
"""
if self.is_quoted:
# 先尝试匹配群消息
Expand Down
7 changes: 4 additions & 3 deletions wechatter/models/wechat/person.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import enum
from typing import Optional

from pydantic import BaseModel

Expand All @@ -22,9 +23,9 @@ class Person(BaseModel):
name: str
alias: str
gender: Gender
signature: str
province: str
city: str
signature: Optional[str] = None
province: Optional[str] = None
city: Optional[str] = None
# phone_list: List[str]
is_star: bool
is_friend: bool
Expand Down
7 changes: 5 additions & 2 deletions wechatter/sender/sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from wechatter.config import config
from wechatter.models.wechat import QuotedResponse, SendTo
from wechatter.sender.quotable import make_quotable
from wechatter.utils.url_joiner import join_urls


# 对retry装饰器重新包装,增加日志输出
Expand Down Expand Up @@ -99,10 +100,12 @@ def _post_request(


URL = (
f"{config['wx_webhook_base_api']}/webhook/msg/v2?token={config['wx_webhook_token']}"
join_urls(config["wx_webhook_base_api"], "webhook/msg/v2")
+ f"?token={config['wx_webhook_token']}"
)
V1_URL = (
f"{config['wx_webhook_base_api']}/webhook/msg?token={config['wx_webhook_token']}"
join_urls(config["wx_webhook_base_api"], "webhook/msg")
+ f"?token={config['wx_webhook_token']}"
)

MSG_TYPE = ["text", "fileUrl", "localfile"]
Expand Down

0 comments on commit 01afb46

Please sign in to comment.