zhenxun_bot/zhenxun/builtin_plugins/admin/ban/__init__.py

335 lines
11 KiB
Python
Raw Normal View History

2024-02-25 03:18:34 +08:00
from arclet.alconna import Args
from nonebot.adapters import Bot
from nonebot.permission import SUPERUSER
from nonebot.plugin import PluginMetadata
from nonebot_plugin_alconna import (
Alconna,
Arparma,
2024-02-25 03:18:34 +08:00
At,
Match,
Option,
on_alconna,
store_true,
)
from nonebot_plugin_session import EventSession
2024-02-25 03:18:34 +08:00
from zhenxun.configs.config import BotConfig, Config
2025-06-09 14:40:19 +08:00
from zhenxun.configs.utils import (
AICallableParam,
AICallableProperties,
AICallableTag,
PluginExtraData,
RegisterConfig,
)
2024-02-25 03:18:34 +08:00
from zhenxun.services.log import logger
from zhenxun.utils.enum import PluginType
from zhenxun.utils.message import MessageUtils
from zhenxun.utils.rules import admin_check
2024-02-25 03:18:34 +08:00
2025-06-09 14:40:19 +08:00
from ._data_source import BanManage, call_ban
2024-02-25 03:18:34 +08:00
base_config = Config.get("ban")
__plugin_meta__ = PluginMetadata(
2024-05-15 23:24:35 +08:00
name="Ban",
2024-02-25 03:18:34 +08:00
description="你被逮捕了!丢进小黑屋!封禁用户以及群组,屏蔽消息",
usage="""
2024-02-27 02:30:01 +08:00
普通管理员
格式:
ban [At用户] ?[-t [时长(分钟)]] ?[-r [理由]]
2024-02-27 02:30:01 +08:00
示例:
2024-08-04 18:49:39 +08:00
ban @用户 : 永久拉黑用户
ban @用户 -t 100 : 拉黑用户100分钟
ban @用户 -t 10 -r : 拉黑用户10分钟并携带理由
2024-08-04 18:49:39 +08:00
unban @用户 : 从小黑屋中拉出来
2024-05-15 23:24:35 +08:00
""".strip(),
extra=PluginExtraData(
author="HibiKier",
version="0.1",
plugin_type=PluginType.SUPER_AND_ADMIN,
superuser_help="""
超级管理员额外命令
2024-02-27 02:30:01 +08:00
格式:
ban [At用户/用户Id] ?[-t [时长]] ?[-r [理由]]
2024-10-05 19:07:18 +08:00
unban --id [idx] : 通过id来进行unban操作
2024-02-27 02:30:01 +08:00
ban列表: 获取所有Ban数据
2024-08-04 18:49:39 +08:00
2024-02-27 02:30:01 +08:00
群组ban列表: 获取群组Ban数据
用户ban列表: 获取用户Ban数据
2024-08-04 18:49:39 +08:00
ban列表 -u [用户Id]: 查找指定用户ban数据
ban列表 -g [群组Id]: 查找指定群组ban数据
示例:
ban列表 -u 123456789 : 查找用户123456789的ban数据
ban列表 -g 123456789 : 查找群组123456789的ban数据
2024-02-27 02:30:01 +08:00
私聊下:
示例:
2024-08-04 18:49:39 +08:00
ban 123456789 : 永久拉黑用户123456789
ban 123456789 -r : 永久拉黑用户123456789并携带理由
2024-08-04 18:49:39 +08:00
ban 123456789 -t 100 : 拉黑用户123456789 100分钟
2024-02-27 02:30:01 +08:00
2024-08-04 18:49:39 +08:00
ban -g 999999 : 拉黑群组为999999的群组
ban -g 999999 -t 100 : 拉黑群组为999999的群组 100分钟
ban -g 999999 -r : 永久拉黑群组为999999的群组并携带理由
2024-02-27 02:30:01 +08:00
unban 123456789 : 从小黑屋中拉出来
unban -g 999999 : 将群组9999999从小黑屋中拉出来
2024-05-15 23:24:35 +08:00
""",
2024-02-25 03:18:34 +08:00
admin_level=base_config.get("BAN_LEVEL", 5),
configs=[
RegisterConfig(
key="BAN_LEVEL",
value=5,
help="ban/unban所需要的管理员权限等级",
default_value=5,
type=int,
)
],
2025-06-09 14:40:19 +08:00
smart_tools=[
AICallableTag(
name="call_ban",
:sparkles: 引入缓存机制 (#1889) * 添加全局cache * ✨ 构建缓存,hook使用缓存 * :sparkles: 新增数据库Model方法监控 * :sparkles: 数据库添加semaphore锁 * :adhesive_bandage: 优化webapi返回数据 * :sparkles: 添加增量缓存与缓存过期 * :art: 优化检测代码结构 * :zap: 优化hook权限检测性能 * :bug: 添加新异常判断跳过权限检测 * :sparkles: 添加插件limit缓存 * :art: 代码格式优化 * :bug: 修复代码导入 * :bug: 修复刷新时检查 * :alien: Rename exception for missing database URL in initialization * :wheelchair: Update default database URL to SQLite in configuration * :wrench: Update tortoise-orm and aiocache dependencies restrictions; add optional redis and asyncpg support * :bug: 修复ban检测 * :bug: 修复所有插件关闭时缓存更新 * :bug: 尝试迁移至aiocache * :bug: 完善aiocache缓存 * :zap: 代码性能优化 * :bug: 移除获取封禁缓存时的日志记录 * :bug: 修复缓存类型声明,优化封禁用户处理逻辑 * :bug: 优化LevelUser权限更新逻辑及数据库迁移 * :sparkles: cache支持redis连接 * :rotating_light: auto fix by pre-commit hooks * :zap: :增强获取群组的安全性和准确性。同时,优化了缓存管理中的相关逻辑,确保缓存操作的一致性。 * ✨ feat(auth_limit): 将插件初始化逻辑的启动装饰器更改为优先级管理器 * 🔧 修复日志记录级别 * 🔧 更新数据库连接字符串 * 🔧 更新数据库连接字符串为内存数据库,并优化权限检查逻辑 * ✨ feat(cache): 增加缓存功能配置项,并新增数据访问层以支持缓存逻辑 * :recycle: 重构cache * ✨ feat(cache): 增强缓存管理,新增缓存字典和缓存列表功能,支持过期时间管理 * 🔧 修复Notebook类中的viewport高度设置,将其从1000调整为10 * ✨ 更新插件管理逻辑,替换缓存服务为CacheRoot并优化缓存失效处理 * ✨ 更新RegisterConfig类中的type字段 * ✨ 修复清理重复记录逻辑,确保检查记录的id属性有效性 * :zap: 超级无敌大优化,解决延迟与卡死问题 * ✨ 更新封禁功能,增加封禁时长参数和描述,优化插件信息返回结构 * ✨ 更新zhenxun_help.py中的viewport高度,将其从453调整为10,以优化页面显示效果 * ✨ 优化插件分类逻辑,增加插件ID排序,并更新插件信息返回结构 --------- Co-authored-by: BalconyJH <balconyjh@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-07-14 22:35:29 +08:00
description="如果你讨厌某个人(好感度过低并让你感到困扰,或者多次辱骂你),调用此方法进行封禁,调用该方法后要告知用户被封禁和原因",
2025-06-09 14:40:19 +08:00
parameters=AICallableParam(
type="object",
properties={
"user_id": AICallableProperties(
type="string", description="用户的id"
),
"reason": AICallableProperties(
type="string", description="封禁理由"
),
:sparkles: 引入缓存机制 (#1889) * 添加全局cache * ✨ 构建缓存,hook使用缓存 * :sparkles: 新增数据库Model方法监控 * :sparkles: 数据库添加semaphore锁 * :adhesive_bandage: 优化webapi返回数据 * :sparkles: 添加增量缓存与缓存过期 * :art: 优化检测代码结构 * :zap: 优化hook权限检测性能 * :bug: 添加新异常判断跳过权限检测 * :sparkles: 添加插件limit缓存 * :art: 代码格式优化 * :bug: 修复代码导入 * :bug: 修复刷新时检查 * :alien: Rename exception for missing database URL in initialization * :wheelchair: Update default database URL to SQLite in configuration * :wrench: Update tortoise-orm and aiocache dependencies restrictions; add optional redis and asyncpg support * :bug: 修复ban检测 * :bug: 修复所有插件关闭时缓存更新 * :bug: 尝试迁移至aiocache * :bug: 完善aiocache缓存 * :zap: 代码性能优化 * :bug: 移除获取封禁缓存时的日志记录 * :bug: 修复缓存类型声明,优化封禁用户处理逻辑 * :bug: 优化LevelUser权限更新逻辑及数据库迁移 * :sparkles: cache支持redis连接 * :rotating_light: auto fix by pre-commit hooks * :zap: :增强获取群组的安全性和准确性。同时,优化了缓存管理中的相关逻辑,确保缓存操作的一致性。 * ✨ feat(auth_limit): 将插件初始化逻辑的启动装饰器更改为优先级管理器 * 🔧 修复日志记录级别 * 🔧 更新数据库连接字符串 * 🔧 更新数据库连接字符串为内存数据库,并优化权限检查逻辑 * ✨ feat(cache): 增加缓存功能配置项,并新增数据访问层以支持缓存逻辑 * :recycle: 重构cache * ✨ feat(cache): 增强缓存管理,新增缓存字典和缓存列表功能,支持过期时间管理 * 🔧 修复Notebook类中的viewport高度设置,将其从1000调整为10 * ✨ 更新插件管理逻辑,替换缓存服务为CacheRoot并优化缓存失效处理 * ✨ 更新RegisterConfig类中的type字段 * ✨ 修复清理重复记录逻辑,确保检查记录的id属性有效性 * :zap: 超级无敌大优化,解决延迟与卡死问题 * ✨ 更新封禁功能,增加封禁时长参数和描述,优化插件信息返回结构 * ✨ 更新zhenxun_help.py中的viewport高度,将其从453调整为10,以优化页面显示效果 * ✨ 优化插件分类逻辑,增加插件ID排序,并更新插件信息返回结构 --------- Co-authored-by: BalconyJH <balconyjh@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-07-14 22:35:29 +08:00
"duration": AICallableProperties(
type="integer",
description="封禁时长选择的值只能是1-360单位为分钟如果频繁触发按情况增加",
),
2025-06-09 14:40:19 +08:00
},
required=["user_id"],
),
func=call_ban,
)
],
).to_dict(),
2024-02-25 03:18:34 +08:00
)
2024-02-27 02:30:01 +08:00
_ban_matcher = on_alconna(
Alconna(
"ban",
2024-08-04 18:49:39 +08:00
Args["user?", [str, At]],
Option("-r|--reason", Args["reason", str]),
2024-02-27 02:30:01 +08:00
Option("-g|--group", Args["group_id", str]),
2024-08-04 18:49:39 +08:00
Option("-t|--time", Args["duration", int]),
2024-02-27 02:30:01 +08:00
),
rule=admin_check("ban", "BAN_LEVEL"),
priority=5,
block=True,
)
_unban_matcher = on_alconna(
2024-02-25 03:18:34 +08:00
Alconna(
2024-02-27 02:30:01 +08:00
"unban",
Args["user?", [str, At]],
Option("-g|--group", Args["group_id", str]),
2024-10-05 19:07:18 +08:00
Option("--id", Args["idx", int]),
2024-02-25 03:18:34 +08:00
),
rule=admin_check("ban", "BAN_LEVEL"),
priority=5,
block=True,
)
_status_matcher = on_alconna(
Alconna(
2024-08-04 18:49:39 +08:00
"ban列表",
Option("-u", Args["user_id", str], help_text="查找用户"),
Option("-g", Args["group_id", str], help_text="查找群组"),
Option("--user", action=store_true, help_text="过滤用户"),
Option("--group", action=store_true, help_text="过滤群组"),
2024-02-25 03:18:34 +08:00
),
permission=SUPERUSER,
priority=1,
block=True,
)
2024-02-27 02:30:01 +08:00
_status_matcher.shortcut(
"用户ban列表",
2024-08-04 18:49:39 +08:00
command="ban列表",
2024-02-27 02:30:01 +08:00
arguments=["--user"],
prefix=True,
)
_status_matcher.shortcut(
"群组ban列表",
2024-08-04 18:49:39 +08:00
command="ban列表",
2024-02-27 02:30:01 +08:00
arguments=["--group"],
prefix=True,
)
2024-02-25 03:18:34 +08:00
@_status_matcher.handle()
async def _(
arparma: Arparma,
user_id: Match[str],
group_id: Match[str],
):
2024-02-27 02:30:01 +08:00
filter_type = None
if arparma.find("user"):
filter_type = "user"
if arparma.find("group"):
filter_type = "group"
2024-02-25 03:18:34 +08:00
_user_id = user_id.result if user_id.available else None
_group_id = group_id.result if group_id.available else None
2024-08-04 18:49:39 +08:00
if image := await BanManage.build_ban_image(filter_type, _user_id, _group_id):
2024-08-10 02:25:04 +08:00
await MessageUtils.build_message(image).finish(reply_to=True)
2024-02-25 03:18:34 +08:00
else:
2024-08-10 02:25:04 +08:00
await MessageUtils.build_message("数据为空捏...").finish(reply_to=True)
2024-02-25 03:18:34 +08:00
2024-02-27 02:30:01 +08:00
@_ban_matcher.handle()
2024-02-25 03:18:34 +08:00
async def _(
bot: Bot,
session: EventSession,
arparma: Arparma,
user: Match[str | At],
reason: Match[str],
2024-02-25 03:18:34 +08:00
duration: Match[int],
group_id: Match[str],
):
user_id = ""
if not session.id1:
await MessageUtils.build_message("用户id为空...").finish(reply_to=True)
2024-02-25 03:18:34 +08:00
if user.available:
if isinstance(user.result, At):
user_id = user.result.target
else:
2024-08-04 18:49:39 +08:00
if session.id1 not in bot.config.superusers:
2024-08-10 02:25:04 +08:00
await MessageUtils.build_message("权限不足捏...").finish(reply_to=True)
2024-02-25 03:18:34 +08:00
user_id = user.result
_duration = duration.result * 60 if duration.available else -1
_duration_text = f"{duration.result} 分钟" if duration.available else " 到世界湮灭"
ban_reason = reason.result if reason.available else None
2024-08-04 18:49:39 +08:00
if (gid := session.id3 or session.id2) and not group_id.available:
if not user_id or (
user_id == bot.self_id and session.id1 not in bot.config.superusers
):
_duration = 0.5
await MessageUtils.build_message("倒反天罡,小小管理速速退下!").send()
await BanManage.ban(session.id1, gid, ban_reason, 30, session, True)
_duration_text = "半 分钟"
logger.info(
f"尝试ban {BotConfig.self_nickname} 反被拿下",
arparma.header_result,
session=session,
)
await MessageUtils.build_message(
[
"",
At(flag="user", target=session.id1),
" 狠狠惩戒了一番,一脚踢进了小黑屋!"
f" 在里面乖乖呆 {_duration_text}吧!",
]
).finish(reply_to=True)
2024-02-25 03:18:34 +08:00
await BanManage.ban(
user_id,
gid,
ban_reason,
_duration,
session,
session.id1 in bot.config.superusers,
2024-02-25 03:18:34 +08:00
)
logger.info(
"管理员Ban",
2024-02-25 03:18:34 +08:00
arparma.header_result,
session=session,
target=f"{gid}:{user_id}",
)
2024-08-10 02:25:04 +08:00
await MessageUtils.build_message(
2024-02-25 03:18:34 +08:00
[
2024-08-10 02:25:04 +08:00
"",
(
At(flag="user", target=user_id)
if isinstance(user.result, At)
else user_id
), # type: ignore
" 狠狠惩戒了一番,一脚踢进了小黑屋!",
f" 在里面乖乖呆 {_duration_text} 吧!",
2024-02-25 03:18:34 +08:00
]
2024-08-10 02:25:04 +08:00
).finish(reply_to=True)
2024-02-25 03:18:34 +08:00
elif session.id1 in bot.config.superusers:
_group_id = group_id.result if group_id.available else None
await BanManage.ban(user_id, _group_id, ban_reason, _duration, session, True)
2024-02-25 03:18:34 +08:00
logger.info(
"超级用户Ban",
2024-02-25 03:18:34 +08:00
arparma.header_result,
session=session,
target=f"{_group_id}:{user_id}",
)
at_msg = user_id or f"群组:{_group_id}"
2024-08-10 02:25:04 +08:00
await MessageUtils.build_message(
f"{at_msg} 狠狠惩戒了一番,一脚踢进了小黑屋!"
).finish(reply_to=True)
2024-02-25 03:18:34 +08:00
2024-02-27 02:30:01 +08:00
@_unban_matcher.handle()
2024-02-25 03:18:34 +08:00
async def _(
bot: Bot,
session: EventSession,
arparma: Arparma,
user: Match[str | At],
group_id: Match[str],
2024-10-05 19:07:18 +08:00
idx: Match[int],
2024-02-25 03:18:34 +08:00
):
user_id = ""
2024-10-05 19:07:18 +08:00
_idx = idx.result if idx.available else None
2024-02-25 03:18:34 +08:00
if user.available:
if isinstance(user.result, At):
user_id = user.result.target
else:
2024-08-04 18:49:39 +08:00
if session.id1 not in bot.config.superusers:
2024-08-10 02:25:04 +08:00
await MessageUtils.build_message("权限不足捏...").finish(reply_to=True)
2024-02-25 03:18:34 +08:00
user_id = user.result
if gid := session.id3 or session.id2:
if group_id.available:
gid = group_id.result
2024-10-05 19:07:18 +08:00
is_unban, result = await BanManage.unban(
user_id, gid, session, _idx, session.id1 in bot.config.superusers
)
if not is_unban:
await MessageUtils.build_message(result).finish(reply_to=True)
logger.info(
"管理员UnBan",
arparma.header_result,
session=session,
target=f"{gid}:{result}",
)
await MessageUtils.build_message(
[
"",
(
At(flag="user", target=user_id)
if isinstance(user.result, At)
else result
),
2024-10-05 19:07:18 +08:00
" 从黑屋中拉了出来并急救了一下!",
]
).finish(reply_to=True)
2024-02-25 03:18:34 +08:00
elif session.id1 in bot.config.superusers:
_group_id = group_id.result if group_id.available else None
2024-10-05 19:07:18 +08:00
is_unban, result = await BanManage.unban(
user_id, _group_id, session, _idx, True
)
if not is_unban:
await MessageUtils.build_message(result).finish(reply_to=True)
logger.info(
"超级用户UnBan",
arparma.header_result,
session=session,
target=f"{_group_id}:{user_id}",
)
at_msg = user_id or f"群组:{result}"
await MessageUtils.build_message(
f"{at_msg} 从黑屋中拉了出来并急救了一下!"
).finish(reply_to=True)