mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-14 21:52:56 +08:00
feat(admin): 增加封禁用户理由并优化相关逻辑 (#1992)
Some checks failed
检查bot是否运行正常 / bot check (push) Has been cancelled
CodeQL Code Security Analysis / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Has been cancelled
CodeQL Code Security Analysis / Analyze (${{ matrix.language }}) (none, python) (push) Has been cancelled
Sequential Lint and Type Check / ruff-call (push) Has been cancelled
Release Drafter / Update Release Draft (push) Has been cancelled
Force Sync to Aliyun / sync (push) Has been cancelled
Update Version / update-version (push) Has been cancelled
Sequential Lint and Type Check / pyright-call (push) Has been cancelled
Some checks failed
检查bot是否运行正常 / bot check (push) Has been cancelled
CodeQL Code Security Analysis / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Has been cancelled
CodeQL Code Security Analysis / Analyze (${{ matrix.language }}) (none, python) (push) Has been cancelled
Sequential Lint and Type Check / ruff-call (push) Has been cancelled
Release Drafter / Update Release Draft (push) Has been cancelled
Force Sync to Aliyun / sync (push) Has been cancelled
Update Version / update-version (push) Has been cancelled
Sequential Lint and Type Check / pyright-call (push) Has been cancelled
* feat(admin): 增加封禁用户理由并优化相关逻辑
- 在 ban 命令中添加了 -r 或 --reason 选项,用于指定封禁理由
- 优化了 ban 命令的参数解析和处理逻辑
- 更新了数据库模型,增加了 ban_reason 字段用于存储封禁理由
- 修复了部分逻辑错误,如永久封禁的处理方式
* 🚨 auto fix by pre-commit hooks
* refactor(ban): 优化 ban 命令和相关功能
- 修复 ban 命令中的 reason 参数可选标记
- 完善恶意触发检测和用户昵称违规的禁言信息
- 统一禁言操作的参数顺序,提高代码可读性
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
c571bfb133
commit
59d72c3b3d
@ -36,11 +36,12 @@ __plugin_meta__ = PluginMetadata(
|
|||||||
usage="""
|
usage="""
|
||||||
普通管理员
|
普通管理员
|
||||||
格式:
|
格式:
|
||||||
ban [At用户] ?[-t [时长(分钟)]]
|
ban [At用户] ?[-t [时长(分钟)]] ?[-r [理由]]
|
||||||
|
|
||||||
示例:
|
示例:
|
||||||
ban @用户 : 永久拉黑用户
|
ban @用户 : 永久拉黑用户
|
||||||
ban @用户 -t 100 : 拉黑用户100分钟
|
ban @用户 -t 100 : 拉黑用户100分钟
|
||||||
|
ban @用户 -t 10 -r 坏 : 拉黑用户10分钟并携带理由
|
||||||
unban @用户 : 从小黑屋中拉出来
|
unban @用户 : 从小黑屋中拉出来
|
||||||
""".strip(),
|
""".strip(),
|
||||||
extra=PluginExtraData(
|
extra=PluginExtraData(
|
||||||
@ -50,7 +51,7 @@ __plugin_meta__ = PluginMetadata(
|
|||||||
superuser_help="""
|
superuser_help="""
|
||||||
超级管理员额外命令
|
超级管理员额外命令
|
||||||
格式:
|
格式:
|
||||||
ban [At用户/用户Id] ?[-t [时长]]
|
ban [At用户/用户Id] ?[-t [时长]] ?[-r [理由]]
|
||||||
unban --id [idx] : 通过id来进行unban操作
|
unban --id [idx] : 通过id来进行unban操作
|
||||||
ban列表: 获取所有Ban数据
|
ban列表: 获取所有Ban数据
|
||||||
|
|
||||||
@ -66,10 +67,13 @@ __plugin_meta__ = PluginMetadata(
|
|||||||
私聊下:
|
私聊下:
|
||||||
示例:
|
示例:
|
||||||
ban 123456789 : 永久拉黑用户123456789
|
ban 123456789 : 永久拉黑用户123456789
|
||||||
|
ban 123456789 -r 坏 : 永久拉黑用户123456789并携带理由
|
||||||
ban 123456789 -t 100 : 拉黑用户123456789 100分钟
|
ban 123456789 -t 100 : 拉黑用户123456789 100分钟
|
||||||
|
|
||||||
ban -g 999999 : 拉黑群组为999999的群组
|
ban -g 999999 : 拉黑群组为999999的群组
|
||||||
ban -g 999999 -t 100 : 拉黑群组为999999的群组 100分钟
|
ban -g 999999 -t 100 : 拉黑群组为999999的群组 100分钟
|
||||||
|
ban -g 999999 -r 坏 : 永久拉黑群组为999999的群组并携带理由
|
||||||
|
|
||||||
|
|
||||||
unban 123456789 : 从小黑屋中拉出来
|
unban 123456789 : 从小黑屋中拉出来
|
||||||
unban -g 999999 : 将群组9999999从小黑屋中拉出来
|
unban -g 999999 : 将群组9999999从小黑屋中拉出来
|
||||||
@ -94,6 +98,9 @@ __plugin_meta__ = PluginMetadata(
|
|||||||
"user_id": AICallableProperties(
|
"user_id": AICallableProperties(
|
||||||
type="string", description="用户的id"
|
type="string", description="用户的id"
|
||||||
),
|
),
|
||||||
|
"reason": AICallableProperties(
|
||||||
|
type="string", description="封禁理由"
|
||||||
|
),
|
||||||
"duration": AICallableProperties(
|
"duration": AICallableProperties(
|
||||||
type="integer",
|
type="integer",
|
||||||
description="封禁时长(选择的值只能是1-360),单位为分钟,如果频繁触发,按情况增加",
|
description="封禁时长(选择的值只能是1-360),单位为分钟,如果频繁触发,按情况增加",
|
||||||
@ -112,6 +119,7 @@ _ban_matcher = on_alconna(
|
|||||||
Alconna(
|
Alconna(
|
||||||
"ban",
|
"ban",
|
||||||
Args["user?", [str, At]],
|
Args["user?", [str, At]],
|
||||||
|
Option("-r|--reason", Args["reason", str]),
|
||||||
Option("-g|--group", Args["group_id", str]),
|
Option("-g|--group", Args["group_id", str]),
|
||||||
Option("-t|--time", Args["duration", int]),
|
Option("-t|--time", Args["duration", int]),
|
||||||
),
|
),
|
||||||
@ -185,6 +193,7 @@ async def _(
|
|||||||
session: EventSession,
|
session: EventSession,
|
||||||
arparma: Arparma,
|
arparma: Arparma,
|
||||||
user: Match[str | At],
|
user: Match[str | At],
|
||||||
|
reason: Match[str],
|
||||||
duration: Match[int],
|
duration: Match[int],
|
||||||
group_id: Match[str],
|
group_id: Match[str],
|
||||||
):
|
):
|
||||||
@ -200,13 +209,14 @@ async def _(
|
|||||||
user_id = user.result
|
user_id = user.result
|
||||||
_duration = duration.result * 60 if duration.available else -1
|
_duration = duration.result * 60 if duration.available else -1
|
||||||
_duration_text = f"{duration.result} 分钟" if duration.available else " 到世界湮灭"
|
_duration_text = f"{duration.result} 分钟" if duration.available else " 到世界湮灭"
|
||||||
|
ban_reason = reason.result if reason.available else None
|
||||||
if (gid := session.id3 or session.id2) and not group_id.available:
|
if (gid := session.id3 or session.id2) and not group_id.available:
|
||||||
if not user_id or (
|
if not user_id or (
|
||||||
user_id == bot.self_id and session.id1 not in bot.config.superusers
|
user_id == bot.self_id and session.id1 not in bot.config.superusers
|
||||||
):
|
):
|
||||||
_duration = 0.5
|
_duration = 0.5
|
||||||
await MessageUtils.build_message("倒反天罡,小小管理速速退下!").send()
|
await MessageUtils.build_message("倒反天罡,小小管理速速退下!").send()
|
||||||
await BanManage.ban(session.id1, gid, 30, session, True)
|
await BanManage.ban(session.id1, gid, ban_reason, 30, session, True)
|
||||||
_duration_text = "半 分钟"
|
_duration_text = "半 分钟"
|
||||||
logger.info(
|
logger.info(
|
||||||
f"尝试ban {BotConfig.self_nickname} 反被拿下",
|
f"尝试ban {BotConfig.self_nickname} 反被拿下",
|
||||||
@ -222,7 +232,12 @@ async def _(
|
|||||||
]
|
]
|
||||||
).finish(reply_to=True)
|
).finish(reply_to=True)
|
||||||
await BanManage.ban(
|
await BanManage.ban(
|
||||||
user_id, gid, _duration, session, session.id1 in bot.config.superusers
|
user_id,
|
||||||
|
gid,
|
||||||
|
ban_reason,
|
||||||
|
_duration,
|
||||||
|
session,
|
||||||
|
session.id1 in bot.config.superusers,
|
||||||
)
|
)
|
||||||
logger.info(
|
logger.info(
|
||||||
"管理员Ban",
|
"管理员Ban",
|
||||||
@ -244,7 +259,7 @@ async def _(
|
|||||||
).finish(reply_to=True)
|
).finish(reply_to=True)
|
||||||
elif session.id1 in bot.config.superusers:
|
elif session.id1 in bot.config.superusers:
|
||||||
_group_id = group_id.result if group_id.available else None
|
_group_id = group_id.result if group_id.available else None
|
||||||
await BanManage.ban(user_id, _group_id, _duration, session, True)
|
await BanManage.ban(user_id, _group_id, ban_reason, _duration, session, True)
|
||||||
logger.info(
|
logger.info(
|
||||||
"超级用户Ban",
|
"超级用户Ban",
|
||||||
arparma.header_result,
|
arparma.header_result,
|
||||||
@ -296,7 +311,7 @@ async def _(
|
|||||||
At(flag="user", target=user_id)
|
At(flag="user", target=user_id)
|
||||||
if isinstance(user.result, At)
|
if isinstance(user.result, At)
|
||||||
else result
|
else result
|
||||||
), # type: ignore
|
),
|
||||||
" 从黑屋中拉了出来并急救了一下!",
|
" 从黑屋中拉了出来并急救了一下!",
|
||||||
]
|
]
|
||||||
).finish(reply_to=True)
|
).finish(reply_to=True)
|
||||||
|
|||||||
@ -9,13 +9,13 @@ from zhenxun.services.log import logger
|
|||||||
from zhenxun.utils.image_utils import BuildImage, ImageTemplate
|
from zhenxun.utils.image_utils import BuildImage, ImageTemplate
|
||||||
|
|
||||||
|
|
||||||
async def call_ban(user_id: str, duration: int = 1):
|
async def call_ban(user_id: str, reason: str | None = None, duration: int = 1):
|
||||||
"""调用ban
|
"""调用ban
|
||||||
|
|
||||||
参数:
|
参数:
|
||||||
user_id: 用户id
|
user_id: 用户id
|
||||||
"""
|
"""
|
||||||
await BanConsole.ban(user_id, None, 9, duration * 60)
|
await BanConsole.ban(user_id, None, 9, reason, duration * 60)
|
||||||
logger.info("被讨厌了,已将用户加入黑名单...", "ban", session=user_id)
|
logger.info("被讨厌了,已将用户加入黑名单...", "ban", session=user_id)
|
||||||
|
|
||||||
|
|
||||||
@ -55,20 +55,23 @@ class BanManage:
|
|||||||
"用户ID",
|
"用户ID",
|
||||||
"群组ID",
|
"群组ID",
|
||||||
"BAN LEVEL",
|
"BAN LEVEL",
|
||||||
|
"封禁原因",
|
||||||
"剩余时长(分钟)",
|
"剩余时长(分钟)",
|
||||||
"操作员ID",
|
"操作员ID",
|
||||||
]
|
]
|
||||||
row_data = []
|
row_data = []
|
||||||
for data in data_list:
|
for data in data_list:
|
||||||
duration = int((data.ban_time + data.duration - time.time()) / 60)
|
if data.duration == -1:
|
||||||
if data.duration < 0:
|
|
||||||
duration = "∞"
|
duration = "∞"
|
||||||
|
else:
|
||||||
|
duration = int((data.ban_time + data.duration - time.time()) / 60)
|
||||||
row_data.append(
|
row_data.append(
|
||||||
[
|
[
|
||||||
data.id,
|
data.id,
|
||||||
data.user_id,
|
data.user_id,
|
||||||
data.group_id,
|
data.group_id,
|
||||||
data.ban_level,
|
data.ban_level,
|
||||||
|
data.ban_reason,
|
||||||
duration,
|
duration,
|
||||||
data.operator,
|
data.operator,
|
||||||
]
|
]
|
||||||
@ -120,10 +123,15 @@ class BanManage:
|
|||||||
if ban_data.ban_level > user_level:
|
if ban_data.ban_level > user_level:
|
||||||
return False, "unBan权限等级不足捏..."
|
return False, "unBan权限等级不足捏..."
|
||||||
await ban_data.delete()
|
await ban_data.delete()
|
||||||
return True, str(ban_data.user_id or ban_data.group_id)
|
return (
|
||||||
|
True,
|
||||||
|
f"用户 {ban_data.user_id}"
|
||||||
|
if ban_data.user_id
|
||||||
|
else f"群组 {ban_data.group_id}",
|
||||||
|
)
|
||||||
elif await BanConsole.check_ban_level(user_id, group_id, user_level):
|
elif await BanConsole.check_ban_level(user_id, group_id, user_level):
|
||||||
await BanConsole.unban(user_id, group_id)
|
await BanConsole.unban(user_id, group_id)
|
||||||
return True, str(group_id)
|
return True, f"群组 {group_id}"
|
||||||
return False, "该用户/群组不在黑名单中不足捏..."
|
return False, "该用户/群组不在黑名单中不足捏..."
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -131,6 +139,7 @@ class BanManage:
|
|||||||
cls,
|
cls,
|
||||||
user_id: str | None,
|
user_id: str | None,
|
||||||
group_id: str | None,
|
group_id: str | None,
|
||||||
|
reason: str | None,
|
||||||
duration: int,
|
duration: int,
|
||||||
session: EventSession,
|
session: EventSession,
|
||||||
is_superuser: bool,
|
is_superuser: bool,
|
||||||
@ -140,6 +149,7 @@ class BanManage:
|
|||||||
参数:
|
参数:
|
||||||
user_id: 用户id
|
user_id: 用户id
|
||||||
group_id: 群组id
|
group_id: 群组id
|
||||||
|
reason: 理由
|
||||||
duration: 时长,秒
|
duration: 时长,秒
|
||||||
session: Session
|
session: Session
|
||||||
is_superuser: 是否为超级用户操作
|
is_superuser: 是否为超级用户操作
|
||||||
@ -147,4 +157,4 @@ class BanManage:
|
|||||||
level = 9999
|
level = 9999
|
||||||
if not is_superuser and user_id and session.id1:
|
if not is_superuser and user_id and session.id1:
|
||||||
level = await LevelUser.get_user_level(session.id1, group_id)
|
level = await LevelUser.get_user_level(session.id1, group_id)
|
||||||
await BanConsole.ban(user_id, group_id, level, duration, session.id1)
|
await BanConsole.ban(user_id, group_id, level, reason, duration, session.id1)
|
||||||
|
|||||||
@ -27,7 +27,7 @@ Config.add_plugin_config(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def calculate_ban_time(ban_record: BanConsole | None) -> int:
|
async def calculate_ban_time(ban_record: BanConsole | None) -> int:
|
||||||
"""根据ban记录计算剩余ban时间
|
"""根据ban记录计算剩余ban时间
|
||||||
|
|
||||||
参数:
|
参数:
|
||||||
@ -43,7 +43,10 @@ def calculate_ban_time(ban_record: BanConsole | None) -> int:
|
|||||||
return -1
|
return -1
|
||||||
|
|
||||||
_time = time.time() - (ban_record.ban_time + ban_record.duration)
|
_time = time.time() - (ban_record.ban_time + ban_record.duration)
|
||||||
return 0 if _time > 0 else int(abs(_time))
|
if _time < 0:
|
||||||
|
return int(abs(_time))
|
||||||
|
await ban_record.delete()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
async def is_ban(user_id: str | None, group_id: str | None) -> int:
|
async def is_ban(user_id: str | None, group_id: str | None) -> int:
|
||||||
@ -113,7 +116,7 @@ async def is_ban(user_id: str | None, group_id: str | None) -> int:
|
|||||||
for result in results:
|
for result in results:
|
||||||
if result.duration > 0 or result.duration == -1:
|
if result.duration > 0 or result.duration == -1:
|
||||||
# 直接计算ban时间,避免再次查询数据库
|
# 直接计算ban时间,避免再次查询数据库
|
||||||
ban_time = calculate_ban_time(result)
|
ban_time = await calculate_ban_time(result)
|
||||||
if ban_time == -1 or ban_time > max_ban_time:
|
if ban_time == -1 or ban_time > max_ban_time:
|
||||||
max_ban_time = ban_time
|
max_ban_time = ban_time
|
||||||
|
|
||||||
|
|||||||
@ -92,7 +92,12 @@ async def _(
|
|||||||
if module:
|
if module:
|
||||||
if _blmt.check(f"{user_id}__{module}"):
|
if _blmt.check(f"{user_id}__{module}"):
|
||||||
await BanConsole.ban(
|
await BanConsole.ban(
|
||||||
user_id, group_id, 9, malicious_ban_time * 60, bot.self_id
|
user_id,
|
||||||
|
group_id,
|
||||||
|
9,
|
||||||
|
"恶意触发命令检测",
|
||||||
|
malicious_ban_time * 60,
|
||||||
|
bot.self_id,
|
||||||
)
|
)
|
||||||
logger.info(
|
logger.info(
|
||||||
f"触发了恶意触发检测: {matcher.plugin_name}",
|
f"触发了恶意触发检测: {matcher.plugin_name}",
|
||||||
|
|||||||
@ -275,7 +275,9 @@ async def _(bot: Bot, session: Uninfo):
|
|||||||
await GroupInfoUser.set_user_nickname(session.user.id, group_id, "")
|
await GroupInfoUser.set_user_nickname(session.user.id, group_id, "")
|
||||||
else:
|
else:
|
||||||
await FriendUser.set_user_nickname(session.user.id, "")
|
await FriendUser.set_user_nickname(session.user.id, "")
|
||||||
await BanConsole.ban(session.user.id, group_id, 9, 60, bot.self_id)
|
await BanConsole.ban(
|
||||||
|
session.user.id, group_id, 9, "用户昵称违规", 60, bot.self_id
|
||||||
|
)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
await MessageUtils.build_message("你在做梦吗?你没有昵称啊").finish(
|
await MessageUtils.build_message("你在做梦吗?你没有昵称啊").finish(
|
||||||
|
|||||||
@ -21,6 +21,8 @@ class BanConsole(Model):
|
|||||||
"""使用ban命令的用户等级"""
|
"""使用ban命令的用户等级"""
|
||||||
ban_time = fields.BigIntField()
|
ban_time = fields.BigIntField()
|
||||||
"""ban开始的时间"""
|
"""ban开始的时间"""
|
||||||
|
ban_reason = fields.TextField(null=True, default=None)
|
||||||
|
"""ban的理由"""
|
||||||
duration = fields.BigIntField()
|
duration = fields.BigIntField()
|
||||||
"""ban时长"""
|
"""ban时长"""
|
||||||
operator = fields.CharField(255)
|
operator = fields.CharField(255)
|
||||||
@ -107,7 +109,9 @@ class BanConsole(Model):
|
|||||||
if user.duration == -1:
|
if user.duration == -1:
|
||||||
return -1
|
return -1
|
||||||
_time = time.time() - (user.ban_time + user.duration)
|
_time = time.time() - (user.ban_time + user.duration)
|
||||||
return 0 if _time > 0 else int(time.time() - user.ban_time - user.duration)
|
if _time < 0:
|
||||||
|
return int(time.time() - user.ban_time - user.duration)
|
||||||
|
await user.delete()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -133,6 +137,7 @@ class BanConsole(Model):
|
|||||||
user_id: str | None,
|
user_id: str | None,
|
||||||
group_id: str | None,
|
group_id: str | None,
|
||||||
ban_level: int,
|
ban_level: int,
|
||||||
|
reason: str | None,
|
||||||
duration: int,
|
duration: int,
|
||||||
operator: str | None = None,
|
operator: str | None = None,
|
||||||
):
|
):
|
||||||
@ -157,6 +162,7 @@ class BanConsole(Model):
|
|||||||
group_id=group_id,
|
group_id=group_id,
|
||||||
ban_level=ban_level,
|
ban_level=ban_level,
|
||||||
ban_time=int(time.time()),
|
ban_time=int(time.time()),
|
||||||
|
ban_reason=reason,
|
||||||
duration=duration,
|
duration=duration,
|
||||||
operator=operator or 0,
|
operator=operator or 0,
|
||||||
)
|
)
|
||||||
@ -206,4 +212,5 @@ class BanConsole(Model):
|
|||||||
return [
|
return [
|
||||||
"CREATE INDEX idx_ban_console_user_id ON ban_console(user_id);",
|
"CREATE INDEX idx_ban_console_user_id ON ban_console(user_id);",
|
||||||
"CREATE INDEX idx_ban_console_group_id ON ban_console(group_id);",
|
"CREATE INDEX idx_ban_console_group_id ON ban_console(group_id);",
|
||||||
|
"ALTER TABLE ban_console ADD COLUMN ban_reason TEXT DEFAULT NULL;",
|
||||||
]
|
]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user