Files
zhenxun_bot/zhenxun/builtin_plugins/hooks/chkdsk_hook.py
T

134 lines
4.4 KiB
Python
Raw Normal View History

2024-02-25 03:18:34 +08:00
from collections import defaultdict
import time
2024-02-25 03:18:34 +08:00
2024-08-24 13:25:34 +08:00
from nonebot.adapters import Event
from nonebot.adapters.onebot.v11 import Bot
from nonebot.exception import IgnoredException
from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor
from nonebot.typing import T_State
from nonebot_plugin_alconna import At
2024-02-25 03:18:34 +08:00
from nonebot_plugin_session import EventSession
from zhenxun.configs.config import Config
from zhenxun.models.ban_console import BanConsole
from zhenxun.services.log import logger
2024-02-25 03:18:34 +08:00
from zhenxun.utils.enum import PluginType
2024-08-11 15:57:33 +08:00
from zhenxun.utils.message import MessageUtils
2024-02-25 03:18:34 +08:00
2026-04-26 15:50:15 +08:00
from .auth.context import resolve_actor_user_id, resolve_event_group_id
2024-02-25 03:18:34 +08:00
class BanCheckLimiter:
"""
恶意命令触发检测
"""
def __init__(self, default_check_time: float = 5, default_count: int = 4):
self.mint = defaultdict(int)
self.mtime = defaultdict(float)
self.default_check_time = default_check_time
self.default_count = default_count
2026-04-26 15:50:15 +08:00
def configure(self, check_time: float, count: int) -> None:
self.default_check_time = check_time
self.default_count = count
def add(self, key: str | float):
2024-02-25 03:18:34 +08:00
if self.mint[key] == 1:
self.mtime[key] = time.time()
self.mint[key] += 1
def check(self, key: str | float) -> bool:
2024-02-25 03:18:34 +08:00
if time.time() - self.mtime[key] > self.default_check_time:
2025-10-09 08:46:08 +08:00
return self._extracted_from_check_3(key, False)
2024-02-25 03:18:34 +08:00
if (
self.mint[key] >= self.default_count
and time.time() - self.mtime[key] < self.default_check_time
):
2025-10-09 08:46:08 +08:00
return self._extracted_from_check_3(key, True)
2024-02-25 03:18:34 +08:00
return False
2025-10-09 08:46:08 +08:00
# TODO Rename this here and in `check`
def _extracted_from_check_3(self, key, arg1):
self.mtime[key] = time.time()
self.mint[key] = 0
return arg1
2024-02-25 03:18:34 +08:00
_blmt = BanCheckLimiter(
2026-04-26 15:50:15 +08:00
5,
4,
2024-02-25 03:18:34 +08:00
)
2026-04-26 15:50:15 +08:00
def _get_positive_config(key: str, cast_type: type[int] | type[float]) -> int | float:
value = Config.get_config("hook", key)
try:
parsed_value = cast_type(value)
except (TypeError, ValueError) as e:
raise ValueError(f"模块: [hook], 配置项: [{key}] 不是有效数字") from e
if parsed_value <= 0:
raise ValueError(f"模块: [hook], 配置项: [{key}] 为空或小于0")
return parsed_value
2024-02-25 03:18:34 +08:00
# 恶意触发命令检测
@run_preprocessor
2024-08-24 13:25:34 +08:00
async def _(
matcher: Matcher, bot: Bot, session: EventSession, state: T_State, event: Event
):
2026-04-18 23:42:10 +08:00
# 提前判断 notice 类型,直接跳过
if matcher.type == "notice":
return
# 提前判断插件类型,跳过不需要检测的插件
2024-02-25 03:18:34 +08:00
if plugin := matcher.plugin:
2026-04-18 23:42:10 +08:00
if metadata := plugin.metadata:
extra = metadata.extra
if extra.get("plugin_type") in [
PluginType.HIDDEN,
PluginType.DEPENDANT,
PluginType.ADMIN,
PluginType.SUPERUSER,
]:
return
2024-08-07 23:31:25 +08:00
module = plugin.module_name
2026-04-18 23:42:10 +08:00
else:
2024-08-24 13:25:34 +08:00
return
2026-04-18 23:42:10 +08:00
2026-04-26 15:50:15 +08:00
user_id = resolve_actor_user_id(event, session.id1)
group_id = resolve_event_group_id(event, session.id3 or session.id2)
malicious_check_time = float(_get_positive_config("MALICIOUS_CHECK_TIME", float))
malicious_ban_count = int(_get_positive_config("MALICIOUS_BAN_COUNT", int))
malicious_ban_time = int(_get_positive_config("MALICIOUS_BAN_TIME", int))
_blmt.configure(malicious_check_time, malicious_ban_count)
2025-10-09 08:46:08 +08:00
if user_id and module:
if _blmt.check(f"{user_id}__{module}"):
await BanConsole.ban(
user_id,
group_id,
9,
"恶意触发命令检测",
malicious_ban_time * 60,
bot.self_id,
)
logger.info(
f"触发了恶意触发检测: {matcher.plugin_name}",
"HOOK",
session=session,
)
await MessageUtils.build_message(
[
At(flag="user", target=user_id),
"检测到恶意触发命令,您将被封禁 30 分钟",
]
).send()
logger.debug(
f"触发了恶意触发检测: {matcher.plugin_name}",
"HOOK",
session=session,
)
raise IgnoredException("检测到恶意触发命令")
_blmt.add(f"{user_id}__{module}")