diff --git a/zhenxun/builtin_plugins/platform/qq/group_handle/__init__.py b/zhenxun/builtin_plugins/platform/qq/group_handle/__init__.py index 4a88919e..f4c28f04 100644 --- a/zhenxun/builtin_plugins/platform/qq/group_handle/__init__.py +++ b/zhenxun/builtin_plugins/platform/qq/group_handle/__init__.py @@ -1,4 +1,4 @@ -from nonebot import on_notice, on_request +from nonebot import on_notice from nonebot.adapters import Bot from nonebot.adapters.onebot.v11 import ( GroupDecreaseNoticeEvent, @@ -14,9 +14,10 @@ from nonebot_plugin_uninfo import Uninfo from zhenxun.builtin_plugins.platform.qq.exception import ForceAddGroupError from zhenxun.configs.config import BotConfig, Config from zhenxun.configs.utils import PluginExtraData, RegisterConfig, Task +from zhenxun.models.event_log import EventLog from zhenxun.models.group_console import GroupConsole from zhenxun.utils.common_utils import CommonUtils -from zhenxun.utils.enum import PluginType +from zhenxun.utils.enum import EventLogType, PluginType from zhenxun.utils.platform import PlatformUtils from zhenxun.utils.rules import notice_rule @@ -106,8 +107,6 @@ group_decrease_handle = on_notice( rule=notice_rule([GroupMemberDecreaseEvent, GroupDecreaseNoticeEvent]), ) """群员减少处理""" -add_group = on_request(priority=1, block=False) -"""加群同意请求""" @group_increase_handle.handle() @@ -142,7 +141,20 @@ async def _( if event.sub_type == "kick_me": """踢出Bot""" await GroupManager.kick_bot(bot, group_id, str(event.operator_id)) + await EventLog.create( + user_id=user_id, group_id=group_id, event_type=EventLogType.KICK_BOT + ) elif event.sub_type in ["leave", "kick"]: + if event.sub_type == "leave": + """主动退群""" + await EventLog.create( + user_id=user_id, group_id=group_id, event_type=EventLogType.LEAVE_MEMBER + ) + else: + """被踢出群""" + await EventLog.create( + user_id=user_id, group_id=group_id, event_type=EventLogType.KICK_MEMBER + ) result = await GroupManager.run_user( bot, user_id, group_id, str(event.operator_id), event.sub_type ) diff --git a/zhenxun/builtin_plugins/record_request.py b/zhenxun/builtin_plugins/record_request.py index d4b0c694..12533c95 100644 --- a/zhenxun/builtin_plugins/record_request.py +++ b/zhenxun/builtin_plugins/record_request.py @@ -17,11 +17,12 @@ from nonebot_plugin_session import EventSession from zhenxun.configs.config import BotConfig, Config from zhenxun.configs.utils import PluginExtraData, RegisterConfig +from zhenxun.models.event_log import EventLog from zhenxun.models.fg_request import FgRequest from zhenxun.models.friend_user import FriendUser from zhenxun.models.group_console import GroupConsole from zhenxun.services.log import logger -from zhenxun.utils.enum import PluginType, RequestHandleType, RequestType +from zhenxun.utils.enum import EventLogType, PluginType, RequestHandleType, RequestType from zhenxun.utils.platform import PlatformUtils base_config = Config.get("invite_manager") @@ -112,21 +113,27 @@ async def _(bot: v12Bot | v11Bot, event: FriendRequestEvent, session: EventSessi nickname=nickname, comment=comment, ) - await PlatformUtils.send_superuser( + results = await PlatformUtils.send_superuser( bot, f"*****一份好友申请*****\n" f"ID: {f.id}\n" f"昵称:{nickname}({event.user_id})\n" f"自动同意:{'√' if base_config.get('AUTO_ADD_FRIEND') else '×'}\n" - f"日期:{str(datetime.now()).split('.')[0]}\n" + f"日期:{datetime.now().replace(microsecond=0)}\n" f"备注:{event.comment}", ) + if message_ids := [ + r[1].msg_ids[0]["message_id"] for r in results if r and r[1].msg_ids + ]: + f.message_ids = ",".join(message_ids) + await f.save(update_fields=["message_ids"]) else: logger.debug("好友请求五分钟内重复, 已忽略", "好友请求", target=event.user_id) @group_req.handle() async def _(bot: v12Bot | v11Bot, event: GroupRequestEvent, session: EventSession): + # sourcery skip: low-code-quality if event.sub_type != "invite": return if str(event.user_id) in bot.config.superusers or base_config.get("AUTO_ADD_GROUP"): @@ -186,7 +193,7 @@ async def _(bot: v12Bot | v11Bot, event: GroupRequestEvent, session: EventSessio group_id=str(event.group_id), handle_type=RequestHandleType.APPROVE, ) - await PlatformUtils.send_superuser( + results = await PlatformUtils.send_superuser( bot, f"*****一份入群申请*****\n" f"ID:{f.id}\n" @@ -230,13 +237,27 @@ async def _(bot: v12Bot | v11Bot, event: GroupRequestEvent, session: EventSessio nickname=nickname, group_id=str(event.group_id), ) - await PlatformUtils.send_superuser( + kick_count = await EventLog.filter( + group_id=str(event.group_id), event_type=EventLogType.KICK_BOT + ).count() + kick_message = ( + f"\n该群累计踢出{BotConfig.self_nickname} <{kick_count}>次" + if kick_count + else "" + ) + results = await PlatformUtils.send_superuser( bot, f"*****一份入群申请*****\n" f"ID:{f.id}\n" f"申请人:{nickname}({event.user_id})\n群聊:" - f"{event.group_id}\n邀请日期:{datetime.now().replace(microsecond=0)}", + f"{event.group_id}\n邀请日期:{datetime.now().replace(microsecond=0)}" + f"{kick_message}", ) + if message_ids := [ + r[1].msg_ids[0]["message_id"] for r in results if r and r[1].msg_ids + ]: + f.message_ids = ",".join(message_ids) + await f.save(update_fields=["message_ids"]) else: logger.debug( "群聊请求五分钟内重复, 已忽略", diff --git a/zhenxun/builtin_plugins/superuser/request_manage.py b/zhenxun/builtin_plugins/superuser/request_manage.py index 23b235bf..f2e12b3f 100644 --- a/zhenxun/builtin_plugins/superuser/request_manage.py +++ b/zhenxun/builtin_plugins/superuser/request_manage.py @@ -2,7 +2,7 @@ from io import BytesIO from arclet.alconna import Args, Option from arclet.alconna.typing import CommandMeta -from nonebot.adapters import Bot +from nonebot.adapters import Bot, Event from nonebot.permission import SUPERUSER from nonebot.plugin import PluginMetadata from nonebot.rule import to_me @@ -10,10 +10,13 @@ from nonebot_plugin_alconna import ( Alconna, AlconnaQuery, Arparma, + Match, Query, + Reply, on_alconna, store_true, ) +from nonebot_plugin_alconna.uniseg.tools import reply_fetch from nonebot_plugin_session import EventSession from zhenxun.configs.config import BotConfig @@ -54,7 +57,7 @@ __plugin_meta__ = PluginMetadata( _req_matcher = on_alconna( Alconna( "请求处理", - Args["handle", ["-fa", "-fr", "-fi", "-ga", "-gr", "-gi"]]["id", int], + Args["handle", ["-fa", "-fr", "-fi", "-ga", "-gr", "-gi"]]["id?", int], meta=CommandMeta( description="好友/群组请求处理", usage=usage, @@ -125,32 +128,48 @@ for r in reg_arg_list: @_req_matcher.handle() async def _( bot: Bot, + event: Event, session: EventSession, handle: str, - id: int, + id: Match[int], arparma: Arparma, ): + reply: Reply | None = None type_dict = { "a": RequestHandleType.APPROVE, "r": RequestHandleType.REFUSED, "i": RequestHandleType.IGNORE, } + if not id.available: + reply = await reply_fetch(event, bot) + if not reply: + await MessageUtils.build_message("请引用消息处理或添加处理Id.").finish() + handle_id = id.result + if reply: + db_data = await FgRequest.get_or_none(message_ids__contains=reply.id) + if not db_data: + await MessageUtils.build_message( + "未发现此消息的Id,请使用Id进行处理..." + ).finish(reply_to=True) + handle_id = db_data.id req = None handle_type = type_dict[handle[-1]] try: if handle_type == RequestHandleType.APPROVE: - req = await FgRequest.approve(bot, id) + req = await FgRequest.approve(bot, handle_id) if handle_type == RequestHandleType.REFUSED: - req = await FgRequest.refused(bot, id) + req = await FgRequest.refused(bot, handle_id) if handle_type == RequestHandleType.IGNORE: - req = await FgRequest.ignore(id) + req = await FgRequest.ignore(handle_id) except NotFoundError: await MessageUtils.build_message("未发现此id的请求...").finish(reply_to=True) except Exception: await MessageUtils.build_message("其他错误, 可能flag已失效...").finish( reply_to=True ) - logger.info("处理请求", arparma.header_result, session=session) + logger.info( + f"处理请求 Id: {req.id if req else ''}", arparma.header_result, session=session + ) await MessageUtils.build_message("成功处理请求!").send(reply_to=True) if req and handle_type == RequestHandleType.APPROVE: await bot.send_private_msg( diff --git a/zhenxun/models/event_log.py b/zhenxun/models/event_log.py new file mode 100644 index 00000000..6737f619 --- /dev/null +++ b/zhenxun/models/event_log.py @@ -0,0 +1,21 @@ +from tortoise import fields + +from zhenxun.services.db_context import Model +from zhenxun.utils.enum import EventLogType + + +class EventLog(Model): + id = fields.IntField(pk=True, generated=True, auto_increment=True) + """自增id""" + user_id = fields.CharField(255, description="用户id") + """用户id""" + group_id = fields.CharField(255, description="群组id") + """群组id""" + event_type = fields.CharEnumField(EventLogType, default=None, description="类型") + """类型""" + create_time = fields.DatetimeField(auto_now_add=True, description="创建时间") + """创建时间""" + + class Meta: # pyright: ignore [reportIncompatibleVariableOverride] + table = "event_log" + table_description = "各种请求通知记录表" diff --git a/zhenxun/models/fg_request.py b/zhenxun/models/fg_request.py index 4aee1d73..a3691161 100644 --- a/zhenxun/models/fg_request.py +++ b/zhenxun/models/fg_request.py @@ -5,6 +5,7 @@ from tortoise import fields from zhenxun.models.group_console import GroupConsole from zhenxun.services.db_context import Model +from zhenxun.utils.common_utils import SqlUtils from zhenxun.utils.enum import RequestHandleType, RequestType from zhenxun.utils.exception import NotFoundError @@ -34,6 +35,8 @@ class FgRequest(Model): RequestHandleType, null=True, description="处理类型" ) """处理类型""" + message_ids = fields.CharField(max_length=255, null=True, description="消息id列表") + """消息id列表""" class Meta: # pyright: ignore [reportIncompatibleVariableOverride] table = "fg_request" @@ -129,3 +132,9 @@ class FgRequest(Model): approve=handle_type == RequestHandleType.APPROVE, ) return req + + @classmethod + async def _run_script(cls): + return [ + SqlUtils.add_column("fg_request", "message_ids", "character varying(255)") + ] diff --git a/zhenxun/utils/enum.py b/zhenxun/utils/enum.py index 91834ec2..df399d6e 100644 --- a/zhenxun/utils/enum.py +++ b/zhenxun/utils/enum.py @@ -14,6 +14,19 @@ class BankHandleType(StrEnum): """利息""" +class EventLogType(StrEnum): + GROUP_MEMBER_INCREASE = "GROUP_MEMBER_INCREASE" + """群成员增加""" + GROUP_MEMBER_DECREASE = "GROUP_MEMBER_DECREASE" + """群成员减少""" + KICK_MEMBER = "KICK_MEMBER" + """踢出群成员""" + KICK_BOT = "KICK_BOT" + """踢出Bot""" + LEAVE_MEMBER = "LEAVE_MEMBER" + """主动退群""" + + class GoldHandle(StrEnum): """ 金币处理 diff --git a/zhenxun/utils/platform.py b/zhenxun/utils/platform.py index 6d379131..6a13293a 100644 --- a/zhenxun/utils/platform.py +++ b/zhenxun/utils/platform.py @@ -83,7 +83,7 @@ class PlatformUtils: bot: Bot, message: UniMessage | str, superuser_id: str | None = None, - ) -> Receipt | None: + ) -> list[tuple[str, Receipt]]: """发送消息给超级用户 参数: @@ -97,15 +97,33 @@ class PlatformUtils: 返回: Receipt | None: Receipt """ - if not superuser_id: - if platform := cls.get_platform(bot): - if platform_superusers := BotConfig.get_superuser(platform): - superuser_id = random.choice(platform_superusers) - else: - raise NotFindSuperuser() + superuser_ids = [] + if superuser_id: + superuser_ids.append(superuser_id) + elif platform := cls.get_platform(bot): + if platform_superusers := BotConfig.get_superuser(platform): + superuser_ids = platform_superusers + else: + raise NotFindSuperuser() if isinstance(message, str): message = MessageUtils.build_message(message) - return await cls.send_message(bot, superuser_id, None, message) + result = [] + for superuser_id in superuser_ids: + try: + result.append( + ( + superuser_id, + await cls.send_message(bot, superuser_id, None, message), + ) + ) + except Exception as e: + logger.error( + "发送消息给超级用户失败", + "PlatformUtils:send_superuser", + target=superuser_id, + e=e, + ) + return result @classmethod async def get_group_member_list(cls, bot: Bot, group_id: str) -> list[UserData]: