Files
HeXi/hexi/plugins/nonebot_plugin_group_tools/handlers/management/ban.py
T
sansenhoshiandClaude 9371a28e35 refactor: restructure plugins per MTSS standard, consolidate assets to res/
Per docs/plugin-audit-report.md (plugins normalized to
Trigger(handlers) → Service(services) → Model(repository/models) + utils):

- Split monolithic __init__.py into handlers/services/utils across
  dailywife, deer_pipe, dice, galgame_card, helldivers_tools,
  huoziyinshua, learning_chat, makeaquote, mc_server_status,
  ncm_saying, picfinder_take, picstatus, random_jm_code, regif,
  steam_info, video_analysis, group_tools
- Move static assets under res/: deer_pipe font/img, makeaquote font,
  helldivers img/templates, huoziyinshua HuoZiYinShua
- Add config.py + register_config_items to ncm_saying, random_jm_code,
  group_tools; learning_chat unified config bridge
- Remove deprecated: voice_trans plugin, bf_bot/test.py, dead code in
  dailywife/deer_pipe, empty dirs, debug scripts under helldivers temp
- Disable brash_general_supercredits_tools (stub comment only)
- bot.py: optional stdout/stderr redirect to log file for Web log viewer,
  force ANSI colorize on non-TTY sinks
- Move runtime data (jm_code.json) out of plugin dir into hexi/data
- Docs: plugin-audit-report.md; README reflects removed plugins

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-03 00:44:38 +08:00

146 lines
5.0 KiB
Python

"""群管理工具 —— 禁言相关。"""
from __future__ import annotations
import math
import random
from nonebot import logger, on_fullmatch, on_message, on_regex, on_startswith, require
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent
from nonebot.rule import Rule, is_type
from nonebot_plugin_alconna import UniMessage
from hexi.plugins.nonebot_plugin_hexi_core.custom_utils import check_manage
from ...services.moderation import group_silence, member_silence, silence
from ...utils.message import get_at_id, has_at_all
from ...utils.permissions import check_perm
from ...utils.text import parse_seconds, strip_prefix
require("nonebot_plugin_alconna")
def _is_ban_cmd(event: GroupMessageEvent) -> bool:
text = event.message.extract_plain_text()
return text.startswith("禁言") and not text.startswith("禁言一下")
ban_user = on_message(rule=Rule(_is_ban_cmd) & is_type(GroupMessageEvent), block=True)
ban_member = on_startswith(("来发口球", "塞口球", "禁言一下"))
one_for_one = on_startswith("极限一换一")
cancel_ban = on_startswith(("解除口球", "取消口球", "摘口球", "脱口球", "取消禁言", "解除禁言", "解禁"))
ban_all = on_fullmatch(("全员口球", "全员禁言"))
cancel_ban_all = on_fullmatch(("取消全员口球", "取消全员禁言", "解除全员口球", "解除全员禁言"))
sleep_8h = on_fullmatch(("睡眠套餐", "休眠套餐", "精致睡眠", "来一份精致睡眠套餐"))
tea = on_regex(r"(来|來)(.*(份|个)(.*)(睡|茶)(.*))套餐")
@ban_user.handle()
async def ban_user_handle(bot: Bot, ev: GroupMessageEvent):
if not await check_perm(bot, ev, silent=True):
return
msg = ev.message.extract_plain_text().removeprefix("禁言").strip()
at_seg = next(
(seg for seg in ev.message if seg.type == "at" and seg.data.get("qq") != "all"),
None,
)
if not at_seg:
return
try:
uid = int(at_seg.data["qq"])
minutes = 1 if not msg else int(msg)
await bot.set_group_ban(group_id=ev.group_id, user_id=uid, duration=minutes * 60)
await UniMessage.text("我好了").send()
except Exception as ex:
logger.error(ex)
@ban_member.handle()
async def ban_member_handle(bot: Bot, ev: GroupMessageEvent):
uid = ev.user_id
gid = ev.group_id
duration_text = strip_prefix(
ev.message.extract_plain_text(), ("来发口球", "塞口球", "禁言一下")
)
if not duration_text:
duration_text = "30"
if has_at_all(ev):
await group_silence(bot, ev, gid, True)
return
sid = get_at_id(ev) or uid
await member_silence(bot, ev, uid, sid, gid, duration_text, silent=False)
@one_for_one.handle()
async def one_for_one_handle(bot: Bot, ev: GroupMessageEvent):
uid = ev.user_id
gid = ev.group_id
duration_text = strip_prefix(ev.message.extract_plain_text(), ("极限一换一",))
if has_at_all(ev):
await UniMessage.text("人干事?").send(at_sender=True)
await member_silence(bot, ev, uid, uid, gid, "180", silent=False)
return
seconds = parse_seconds(duration_text)
if seconds is None:
await UniMessage.text("请输入正确时长~").send(at_sender=True)
return
if seconds > 30:
await UniMessage.text("时长不可大于30秒哟~").send(at_sender=True)
return
sid = get_at_id(ev) or uid
await member_silence(bot, ev, uid, sid, gid, str(seconds), silent=True)
await member_silence(bot, ev, uid, uid, gid, str(seconds), silent=True)
await (
UniMessage.at(user_id=str(uid))
.text("成功一换一")
.at(user_id=str(sid))
.text(f"{seconds}秒~")
.send()
)
@cancel_ban.handle()
async def cancel_ban_handle(bot: Bot, ev: GroupMessageEvent):
if not await check_manage(bot, ev):
await UniMessage.text("权限不足").send()
return
uid = ev.user_id
gid = ev.group_id
if has_at_all(ev):
await group_silence(bot, ev, gid, False)
return
sid = get_at_id(ev)
if sid is None:
await UniMessage.text("请@需要摘口球的群员哦w").send()
return
await member_silence(bot, ev, uid, sid, gid, "0", silent=False)
@ban_all.handle()
async def ban_all_handle(bot: Bot, ev: GroupMessageEvent):
if not await check_manage(bot, ev):
await UniMessage.text("权限不足").send()
return
await group_silence(bot, ev, ev.group_id, True)
@cancel_ban_all.handle()
async def cancel_ban_all_handle(bot: Bot, ev: GroupMessageEvent):
if not await check_manage(bot, ev):
await UniMessage.text("权限不足").send()
return
await group_silence(bot, ev, ev.group_id, False)
@sleep_8h.handle()
async def sleep_8h_handle(bot: Bot, ev: MessageEvent):
await silence(bot, ev, 8 * 60 * 60)
@tea.handle()
async def tea_handle(bot: Bot, ev: MessageEvent):
base = 0 if "午" in ev.plain_text else 5 * 60 * 60
length = len(ev.plain_text)
sleep_time = base + round(math.sqrt(length) * 60 * 30 + 60 * random.randint(-15, 15))
await silence(bot, ev, sleep_time)