屏蔽官方机器人功能

pull/38/head
UnCLAS-Prommer 2025-06-24 11:40:15 +08:00
parent 5034039d10
commit 77ff2ff257
6 changed files with 81 additions and 6 deletions

3
.gitignore vendored
View File

@ -271,4 +271,5 @@ $RECYCLE.BIN/
config.toml
config.toml.back
test
test
data/qq_bot.json

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

View File

@ -61,6 +61,9 @@ class ChatConfig(ConfigBase):
ban_user_id: list[int] = field(default_factory=[])
"""被封禁的用户ID列表封禁后将无法与其进行交互"""
ban_qq_bot: bool = False
"""是否屏蔽QQ官方机器人若为True则所有QQ官方机器人将无法与MaiMCore进行交互"""
enable_poke: bool = True
"""是否启用戳一戳功能"""

View File

@ -27,6 +27,8 @@ from .utils import (
get_self_info,
get_stranger_info,
get_message_detail,
read_bot_id,
update_bot_id,
)
from .response_pool import get_response
@ -38,6 +40,7 @@ class RecvHandler:
self.server_connection: Server.ServerConnection = None
self.interval = global_config.napcat_server.heartbeat_interval
self._interval_checking = False
self.bot_id_list: Dict[int, bool] = {}
async def handle_meta_event(self, message: dict) -> None:
event_type = message.get("meta_event_type")
@ -69,7 +72,7 @@ class RecvHandler:
logger.debug("心跳正常")
await asyncio.sleep(self.interval)
def check_allow_to_chat(self, user_id: int, group_id: Optional[int]) -> bool:
async def check_allow_to_chat(self, user_id: int, group_id: Optional[int]) -> bool:
# sourcery skip: hoist-statement-from-if, merge-else-if-into-elif
"""
检查是否允许聊天
@ -79,7 +82,32 @@ class RecvHandler:
Returns:
bool: 是否允许聊天
"""
user_id = str(user_id)
logger.debug(f"群聊id: {group_id}, 用户id: {user_id}")
if global_config.chat.ban_qq_bot and group_id:
logger.debug("开始判断是否为机器人")
if not self.bot_id_list:
self.bot_id_list = read_bot_id()
if user_id in self.bot_id_list:
if self.bot_id_list[user_id]:
logger.warning("QQ官方机器人消息拦截已启用消息被丢弃")
return False
else:
member_info = await get_member_info(self.server_connection, group_id, user_id)
if member_info:
is_bot = member_info.get("is_robot")
if is_bot is None:
logger.warning("无法获取用户是否为机器人,默认为不是但是不进行更新")
else:
if is_bot:
logger.warning("QQ官方机器人消息拦截已启用消息被丢弃新机器人加入拦截名单")
self.bot_id_list[user_id] = True
update_bot_id(self.bot_id_list)
return False
else:
self.bot_id_list[user_id] = False
update_bot_id(self.bot_id_list)
logger.debug("开始检查聊天白名单/黑名单")
if group_id:
if global_config.chat.group_list_type == "whitelist" and group_id not in global_config.chat.group_list:
logger.warning("群聊不在聊天白名单中,消息被丢弃")
@ -122,7 +150,7 @@ class RecvHandler:
if sub_type == MessageType.Private.friend:
sender_info: dict = raw_message.get("sender")
if not self.check_allow_to_chat(sender_info.get("user_id"), None):
if not await self.check_allow_to_chat(sender_info.get("user_id"), None):
return None
# 发送者用户信息
@ -181,7 +209,7 @@ class RecvHandler:
if sub_type == MessageType.Group.normal:
sender_info: dict = raw_message.get("sender")
if not self.check_allow_to_chat(sender_info.get("user_id"), raw_message.get("group_id")):
if not await self.check_allow_to_chat(sender_info.get("user_id"), raw_message.get("group_id")):
return None
# 发送者用户信息
@ -485,7 +513,7 @@ class RecvHandler:
group_id = raw_message.get("group_id")
user_id = raw_message.get("user_id")
if not self.check_allow_to_chat(user_id, group_id):
if not await self.check_allow_to_chat(user_id, group_id):
logger.warning("notice消息被丢弃")
return None

View File

@ -7,9 +7,10 @@ from .response_pool import get_response
import urllib3
import ssl
from pathlib import Path
from PIL import Image
import io
import os
class SSLAdapter(urllib3.PoolManager):
@ -88,6 +89,7 @@ async def get_image_base64(url: str) -> str:
def convert_image_to_gif(image_base64: str) -> str:
# sourcery skip: extract-method
"""
将Base64编码的图片转换为GIF格式
Parameters:
@ -192,3 +194,43 @@ async def get_message_detail(websocket: Server.ServerConnection, message_id: str
return None
logger.debug(response)
return response.get("data")
def update_bot_id(data: dict) -> None:
"""
更新用户是否为机器人的字典到根目录下的data文件夹中的qq_bot.json
Parameters:
data: dict: 包含需要更新的信息
"""
json_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "qq_bot.json")
try:
with open(json_path, "w", encoding="utf-8") as json_file:
json.dump(data, json_file, ensure_ascii=False, indent=4)
logger.info(f"ID字典已更新到文件: {json_path}")
except Exception as e:
logger.error(f"更新ID字典失败: {e}")
def read_bot_id() -> dict:
"""
从根目录下的data文件夹中的文件读取机器人ID
Returns:
list: 读取的机器人ID信息
"""
json_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "qq_bot.json")
try:
with open(json_path, "r", encoding="utf-8") as json_file:
data = json.load(json_file)
logger.info(f"已读取机器人ID信息: {data}")
return data
except FileNotFoundError:
logger.warning(f"文件未找到: {json_path},正在自动创建文件")
json_path = Path(os.path.dirname(os.path.dirname(__file__))) / "data" / "qq_bot.json"
# 确保父目录存在
json_path.parent.mkdir(parents=True, exist_ok=True)
# 创建空文件
json_path.touch(exist_ok=True)
return {}
except Exception as e:
logger.error(f"读取机器人ID失败: {e}")
return {}

View File

@ -24,6 +24,7 @@ private_list = [] # 私聊名单
# 当private_list_type为whitelist时只有私聊名单中的用户可以聊天
# 当private_list_type为blacklist时私聊名单中的任何用户无法聊天
ban_user_id = [] # 全局禁止名单(全局禁止名单中的用户无法进行任何聊天)
ban_qq_bot = false # 是否屏蔽QQ官方机器人
enable_poke = true # 是否启用戳一戳功能
[voice] # 发送语音设置