Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] 消息转发支持来自所有人 #63

Merged
merged 4 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ repos:
hooks:
- id: isort
name: isort (python)
- repo: https://github.com/PyCQA/bandit
rev: 1.7.7
hooks:
- id: bandit
args: ['-c', 'pyproject.toml']

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ python3 -m wechatter
| --- | --- | --- | --- |
| `message_forwarding_enabled` | | 功能开关,是否开启消息转发 | 默认为 `False` |
| `message_forwarding_rule_list` | | 消息规则列表,每个规则包含三个字段:`from_list`、`to_person_list` 和 `to_group_list` | |
| | `from_list` | 消息转发来源列表,即消息发送者 | 可以填多个用户名称或群名称 |
| | `from_list` | 消息转发来源列表,即消息发送者 | 可以填多个用户名称或群名称,若要转发所有消息则使用 `["%ALL"]` |
| | `from_list_exclude` | 消息转发来源排除列表,不转发此列表的用户和群 | 只在 `from_list` 为 `["%ALL"]` 时生效 |
| | `to_person_list` | 消息转发目标用户列表,即消息接收用户 | 可以填多个用户名称或为空列表 |
| | `to_group_list` | 消息转发目标群列表,即消息接收群 | 可以填多个群名称或为空列表 |

Expand All @@ -189,7 +190,6 @@ python3 -m wechatter
| `all_task_cron_enabled` | 所有定时任务的总开关 | 默认为 `True` |
| `task_cron_list` | 定时任务列表,每个任务包含四个字段:`task`、`enabled`、`cron` 和 `commands` | |

[//]: # (引导用户查看定时任务配置详细docs/task_cron_config_detail)
关于定时任务配置详细请参阅[定时任务配置详细](docs/task_cron_config_detail.md)。

### ⚙️ Custom Command Key 配置
Expand Down
12 changes: 8 additions & 4 deletions config.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,15 @@ github_webhook_receive_person_list: [ ]
github_webhook_receive_group_list: [ ]

# Message Forwarding:消息转发
message_forwarding_enabled: True
message_forwarding_enabled: False
message_forwarding_rule_list:
- from_list: [ "缘" ]
to_person_list: [ ]
to_group_list: [ "WeChatter" ]
- from_list: [ "%ALL" ]
from_list_exclude: [ "You" ]
to_person_list: [ "You" ]
to_group_list: [ ]
- from_list: [ "Jay", "Tom" ]
to_person_list: [ "Cassius" ]
to_group_list: [ "Team" ]

# Task Cron:定时任务
# 配置说明:https://github.com/Cassius0924/WeChatter/blob/master/docs/task_cron_config_detail.md
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ line_length = 88
multi_line_output = 3
include_trailing_comma = true
combine_as_imports = true


# bandit
[tool.bandit]
skips = ["B101"]
2 changes: 1 addition & 1 deletion wechatter/commands/_commands/trivia.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
desc="获取冷知识。",
)
def trivia_command_handler(to: Union[str, SendTo], message: str = "") -> None:
random_number = random.randint(1, 917)
random_number = random.randint(1, 917) # nosec
try:
response = get_request(
url=f"http://www.quzhishi.com/shiwangelengzhishi/{random_number}.html"
Expand Down
85 changes: 66 additions & 19 deletions wechatter/message/message_forwarder.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List
from typing import Dict, List

from loguru import logger

Expand All @@ -10,38 +10,85 @@
from wechatter.sender import sender


def _forwarding_by_rule(message_obj: Message, rule: Dict):
"""
根据规则转发消息
:param message_obj: 消息对象
:param rule: 规则
"""
# 应用 exclude 规则
# 开始转发消息
to_person_list = rule["to_person_list"]
if message_obj.sender_name in rule.get("from_list_exclude", []):
return
if to_person_list:
msg = _construct_forwarding_message(message_obj)
sender.mass_send_msg(to_person_list, msg, is_group=False)
logger.info(f"转发消息:{message_obj.sender_name} -> {to_person_list}")
to_group_list = rule["to_group_list"]
if to_group_list:
msg = _construct_forwarding_message(message_obj)
sender.mass_send_msg(to_group_list, msg, is_group=True)
logger.info(f"转发消息:{message_obj.sender_name} -> {to_group_list}")


class MessageForwarder:
"""
消息转发器类
"""

def __init__(self, rule_list: List):
self.rule_list = rule_list
"""
初始化
:param rule_list: 转发规则列表
"""
self.all_message_rule = {
"from_list_exclude": [],
"to_group_list": [],
"to_person_list": [],
}
self.specific_message_rules = {}

for rule in rule_list:
if "%ALL" in rule["from_list"]:
self.all_message_rule["from_list_exclude"].extend(
rule.get("from_list_exclude", [])
)
self.all_message_rule["to_group_list"].extend(
rule.get("to_group_list", [])
)
self.all_message_rule["to_person_list"].extend(
rule.get("to_person_list", [])
)
else:
for from_name in rule["from_list"]:
if from_name not in self.specific_message_rules:
self.specific_message_rules[from_name] = {
"to_group_list": [],
"to_person_list": [],
}
self.specific_message_rules[from_name]["to_group_list"].extend(
rule.get("to_group_list", [])
)
self.specific_message_rules[from_name]["to_person_list"].extend(
rule.get("to_person_list", [])
)

def forward_message(self, message_obj: Message):
def forwarding(self, message_obj: Message):
"""
消息转发
:param message_obj: 消息对象
"""
# TODO: 转发文件
from_name = message_obj.sender_name

# TODO: from_list 支持通配符
# 判断消息来源是否符合转发规则
if self.all_message_rule:
rule = self.all_message_rule
_forwarding_by_rule(message_obj, rule)

# 判断消息是否符合转发规则
for rule in self.rule_list:
# 判断消息来源是否符合转发规则
if from_name in rule["from_list"]:
# 构造转发消息
msg = _construct_forwarding_message(message_obj)
to_person_list = rule.get("to_person_list")
if to_person_list:
logger.info(f"转发消息:{from_name} -> {to_person_list}")
sender.mass_send_msg(to_person_list, msg, is_group=False)
to_group_list = rule.get("to_group_list")
if to_group_list:
logger.info(f"转发消息:{from_name} -> {to_group_list}")
sender.mass_send_msg(to_group_list, msg, is_group=True)
if message_obj.sender_name in self.specific_message_rules.keys():
rule = self.specific_message_rules[message_obj.sender_name]
_forwarding_by_rule(message_obj, rule)

@staticmethod
def reply_forwarded_message(message_obj: Message):
Expand Down
6 changes: 4 additions & 2 deletions wechatter/message/message_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ def _get_quoted_response(quotable_id: str) -> QuotedResponse:
return quoted_response


message_forwarder = MessageForwarder(config["message_forwarding_rule_list"])


class MessageHandler:
"""
消息处理器,用于处理用户发来的消息
Expand All @@ -94,8 +97,7 @@ def handle_message(self, message_obj: Message):
"""

if config["message_forwarding_enabled"]:
message_forwarder = MessageForwarder(config["message_forwarding_rule_list"])
message_forwarder.forward_message(message_obj)
message_forwarder.forwarding(message_obj)

if message_obj.forwarded_source:
message_forwarder.reply_forwarded_message(message_obj)
Expand Down
2 changes: 1 addition & 1 deletion wechatter/models/wechat/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def forwarded_source(self) -> Optional[Tuple[str, bool]]:
group_format = GROUP_FORWARDING_MESSAGE_FORMAT.replace("[", "\[").replace(
"]", "\]"
)
pattern = re.compile(f'{group_format % ("(.+)", "(.+)")}')
pattern = re.compile(f'{group_format % ("(.*)", "(.+)")}')
try:
# 将名字和该名字是否为群都返回,便于在回复时判断
return re.search(pattern, self.content).group(2), True
Expand Down
2 changes: 1 addition & 1 deletion wechatter/wechatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def main():

# 启动uvicorn
port = config["wechatter_port"]
uvicorn.run(app, host="0.0.0.0", port=port)
uvicorn.run(app, host="0.0.0.0", port=port) # nosec


if __name__ == "__main__":
Expand Down
Loading