diff --git a/zhenxun/builtin_plugins/admin/plugin_switch/_data_source.py b/zhenxun/builtin_plugins/admin/plugin_switch/_data_source.py index b5c991bb..f79bc838 100644 --- a/zhenxun/builtin_plugins/admin/plugin_switch/_data_source.py +++ b/zhenxun/builtin_plugins/admin/plugin_switch/_data_source.py @@ -211,12 +211,13 @@ class PluginManage: if status: for module in module_list: group.block_plugin = group.block_plugin.replace( - f"{module},", "" + f"<{module},", "" ) else: module_list = await PluginInfo.filter( plugin_type=PluginType.NORMAL ).values_list("module", flat=True) + module_list = [f"<{module}" for module in module_list] group.block_plugin = ",".join(module_list) + "," # type: ignore await group.save(update_fields=["block_plugin"]) return f'成功将此群组所有功能状态修改为: {"开启" if status else "关闭"}' @@ -413,7 +414,7 @@ class PluginManage: 参数: task_name: 被动技能名称 group_id: 群组Id - status: 状态 + status: 状态,为True时是关闭 is_all: 所有群被动 返回: @@ -426,6 +427,7 @@ class PluginManage: group, _ = await GroupConsole.get_or_create( group_id=group_id, channel_id__isnull=True ) + modules = [f"<{module}" for module in modules] if status: group.block_task = ",".join(modules) + "," # type: ignore else: @@ -434,16 +436,12 @@ class PluginManage: await group.save(update_fields=["block_task"]) return f"已成功{status_str}全部被动技能!" elif task := await TaskInfo.get_or_none(name=task_name): - group, _ = await GroupConsole.get_or_create( - group_id=group_id, channel_id__isnull=True - ) if status: - group.block_task += f"{task.module}," - elif f"super:{task.module}," in group.block_task: + await GroupConsole.set_block_task(group_id, task.module) + elif await GroupConsole.is_superuser_block_task(group_id, task.module): return f"{status_str} {task_name} 被动技能失败,当前群组该被动已被管理员禁用" # noqa: E501 else: - group.block_task = group.block_task.replace(f"{task.module},", "") - await group.save(update_fields=["block_task"]) + await GroupConsole.set_unblock_task(group_id, task.module) return f"已成功{status_str} {task_name} 被动技能!" return "没有找到这个被动技能喔..." @@ -469,20 +467,13 @@ class PluginManage: name=plugin_name, load_status=True, plugin_type__not=PluginType.PARENT ) if plugin: - group, _ = await GroupConsole.get_or_create( - group_id=group_id, channel_id__isnull=True - ) status_str = "开启" if status else "关闭" if status: - if plugin.module in group.block_plugin: - group.block_plugin = group.block_plugin.replace( - f"{plugin.module},", "" - ) - await group.save(update_fields=["block_plugin"]) + if await GroupConsole.is_normal_block_plugin(group_id, plugin.module): + await GroupConsole.set_unblock_plugin(group_id, plugin.module) return f"已成功{status_str} {plugin.name} 功能!" - elif plugin.module not in group.block_plugin: - group.block_plugin += f"{plugin.module}," - await group.save(update_fields=["block_plugin"]) + elif not await GroupConsole.is_normal_block_plugin(group_id, plugin.module): + await GroupConsole.set_block_plugin(group_id, plugin.module) return f"已成功{status_str} {plugin.name} 功能!" return f"该功能已经{status_str}了喔,不要重复{status_str}..." return "没有找到这个功能喔..." @@ -504,14 +495,10 @@ class PluginManage: if not (task := await TaskInfo.get_or_none(name=task_name)): return "没有找到这个功能喔..." if group_id: - group, _ = await GroupConsole.get_or_create( - group_id=group_id, channel_id__isnull=True - ) if status: - group.block_task = group.block_task.replace(f"super:{task.module},", "") + await GroupConsole.set_unblock_task(group_id, task.module, True) else: - group.block_task += f"super:{task.module}," - await group.save(update_fields=["block_task"]) + await GroupConsole.set_block_task(group_id, task.module, True) status_str = "开启" if status else "关闭" return f"已成功将群组 {group_id} 被动技能 {task_name} {status_str}!" return "没有找到这个群组喔..." @@ -538,17 +525,12 @@ class PluginManage: ) if plugin: if group_id: - if group := await GroupConsole.get_or_none( - group_id=group_id, channel_id__isnull=True + if not await GroupConsole.is_superuser_block_plugin( + group_id, plugin.module ): - if f"super:{plugin.module}," not in group.block_plugin: - group.block_plugin += f"super:{plugin.module}," - await group.save(update_fields=["block_plugin"]) - return ( - f"已成功关闭群组 {group.group_name} 的 {plugin_name} 功能!" - ) - return "此群组该功能已被超级用户关闭,不要重复关闭..." - return "群组信息未更新,请先更新群组信息..." + await GroupConsole.set_block_plugin(group_id, plugin.module, True) + return f"已成功关闭群组 {group_id} 的 {plugin_name} 功能!" + return "此群组该功能已被超级用户关闭,不要重复关闭..." plugin.block_type = block_type plugin.status = not bool(block_type) await plugin.save(update_fields=["status", "block_type"]) @@ -584,19 +566,12 @@ class PluginManage: ) if plugin: if group_id: - if group := await GroupConsole.get_or_none( - group_id=group_id, channel_id__isnull=True + if await GroupConsole.is_superuser_block_plugin( + group_id, plugin.module ): - if f"super:{plugin.module}," in group.block_plugin: - group.block_plugin = group.block_plugin.replace( - f"super:{plugin.module},", "" - ) - await group.save(update_fields=["block_plugin"]) - return ( - f"已成功开启群组 {group.group_name} 的 {plugin_name} 功能!" - ) - return "此群组该功能已被超级用户开启,不要重复开启..." - return "群组信息未更新,请先更新群组信息..." + await GroupConsole.set_unblock_plugin(group_id, plugin.module, True) + return f"已成功开启群组 {group_id} 的 {plugin_name} 功能!" + return "此群组该功能已被超级用户开启,不要重复开启..." plugin.block_type = block_type plugin.status = not bool(block_type) await plugin.save(update_fields=["status", "block_type"]) diff --git a/zhenxun/builtin_plugins/hooks/_auth_checker.py b/zhenxun/builtin_plugins/hooks/_auth_checker.py index 687fc44d..e12eb0ad 100644 --- a/zhenxun/builtin_plugins/hooks/_auth_checker.py +++ b/zhenxun/builtin_plugins/hooks/_auth_checker.py @@ -319,8 +319,8 @@ class AuthChecker: is_poke = isinstance(event, PokeNotifyEvent) if group_id: sid = group_id or user_id - if await GroupConsole.is_super_block_plugin( - group_id, plugin.module, channel_id + if await GroupConsole.is_superuser_block_plugin( + group_id, plugin.module ): """超级用户群组插件状态""" if self.is_send_limit_message(plugin, sid) and not is_poke: @@ -334,9 +334,7 @@ class AuthChecker: session=session, ) raise IgnoredException("超级管理员禁用了该群此功能...") - if await GroupConsole.is_block_plugin( - group_id, plugin.module, channel_id - ): + if await GroupConsole.is_normal_block_plugin(group_id, plugin.module): """群组插件状态""" if self.is_send_limit_message(plugin, sid) and not is_poke: self._flmt_s.start_cd(group_id or user_id) diff --git a/zhenxun/builtin_plugins/scripts.py b/zhenxun/builtin_plugins/scripts.py index 3059f870..56c4d918 100644 --- a/zhenxun/builtin_plugins/scripts.py +++ b/zhenxun/builtin_plugins/scripts.py @@ -1,13 +1,15 @@ from asyncio.exceptions import TimeoutError import nonebot +import aiofiles import ujson as json from nonebot.drivers import Driver from nonebot_plugin_apscheduler import scheduler -from zhenxun.configs.path_config import TEXT_PATH from zhenxun.services.log import logger from zhenxun.utils.http_utils import AsyncHttpx +from zhenxun.configs.path_config import TEXT_PATH +from zhenxun.models.group_console import GroupConsole driver: Driver = nonebot.get_driver() @@ -19,8 +21,8 @@ async def update_city(): 这里直接更新,避免插件内代码重复 """ china_city = TEXT_PATH / "china_city.json" - data = {} if not china_city.exists(): + data = {} try: logger.debug("开始更新城市列表...") res = await AsyncHttpx.get( @@ -38,7 +40,7 @@ async def update_city(): city_data = json.loads(res.text) for city in city_data.keys(): data[provinces_data[province]].append(city_data[city]) - with open(china_city, "w", encoding="utf8") as f: + async with aiofiles.open(china_city, "w", encoding="utf8") as f: json.dump(data, f, indent=4, ensure_ascii=False) logger.info("自动更新城市列表完成.....") except TimeoutError as e: @@ -46,7 +48,7 @@ async def update_city(): except ValueError as e: logger.warning("自动城市列表失败.....", e=e) except Exception as e: - logger.error(f"自动城市列表未知错误", e=e) + logger.error("自动城市列表未知错误", e=e) # 自动更新城市列表 @@ -57,3 +59,27 @@ async def update_city(): ) async def _(): await update_city() + + +@driver.on_startup +async def _(): + """开启/禁用插件格式修改""" + _, is_create = await GroupConsole.get_or_create(group_id=133133133) + """标记""" + if is_create: + data_list = [] + for group in await GroupConsole.all(): + if group.block_plugin: + if modules := group.block_plugin.split(",")[:-1]: + if block_plugin := [ + f"<{module}" for module in modules if not module.startswith("<") + ]: + group.block_plugin = ",".join(block_plugin) + "," + if group.block_task: + if modules := group.block_task.split(",")[:-1]: + if block_task := [ + f"<{module}" for module in modules if not module.startswith("<") + ]: + group.block_task = ",".join(block_task) + "," + data_list.append(group) + await GroupConsole.bulk_update(data_list, ["block_plugin", "block_task"], 10) diff --git a/zhenxun/models/group_console.py b/zhenxun/models/group_console.py index 8c64d2a4..6f3ca49f 100644 --- a/zhenxun/models/group_console.py +++ b/zhenxun/models/group_console.py @@ -9,7 +9,6 @@ from zhenxun.services.db_context import Model class GroupConsole(Model): - id = fields.IntField(pk=True, generated=True, auto_increment=True) """自增id""" group_id = fields.CharField(255, description="群组id") @@ -34,8 +33,12 @@ class GroupConsole(Model): """群认证标记""" block_plugin = fields.TextField(default="", description="禁用插件") """禁用插件""" + superuser_block_plugin = fields.TextField( + default="", description="超级用户禁用插件" + ) block_task = fields.TextField(default="", description="禁用插件") """禁用插件""" + superuser_block_task = fields.TextField(default="", description="超级用户禁用被动") platform = fields.CharField(255, default="qq", description="所属平台") """所属平台""" @@ -53,6 +56,7 @@ class GroupConsole(Model): if modules := await TaskInfo.filter(default_status=False).values_list( "module", flat=True ): + modules = [f"<{module}" for module in modules] group.block_task = ",".join(modules) + "," # type: ignore await group.save(using_db=using_db, update_fields=["block_task"]) return group @@ -73,6 +77,7 @@ class GroupConsole(Model): "module", flat=True ) ): + modules = [f"<{module}" for module in modules] group.block_task = ",".join(modules) + "," # type: ignore await group.save(using_db=using_db, update_fields=["block_task"]) return group, is_create @@ -93,6 +98,7 @@ class GroupConsole(Model): "module", flat=True ) ): + modules = [f"<{module}" for module in modules] group.block_task = ",".join(modules) + "," # type: ignore await group.save(using_db=using_db, update_fields=["block_task"]) return group, is_create @@ -127,27 +133,94 @@ class GroupConsole(Model): return group.is_super if (group := await cls.get_group(group_id)) else False @classmethod - async def is_super_block_plugin( - cls, group_id: str, module: str, channel_id: str | None = None - ) -> bool: + async def is_superuser_block_plugin(cls, group_id: str, module: str) -> bool: """查看群组是否超级用户禁用功能 参数: group_id: 群组id module: 模块名称 - channel_id: 频道id 返回: bool: 是否禁用被动 """ return await cls.exists( group_id=group_id, - channel_id=channel_id, - block_plugin__contains=f"super:{module},", + superuser_block_plugin__contains=f"<{module},", ) @classmethod - async def is_block_plugin( + async def is_block_plugin(cls, group_id: str, module: str) -> bool: + """查看群组是否禁用插件 + + 参数: + group_id: 群组id + plugin: 插件名称 + + 返回: + bool: 是否禁用插件 + """ + return await cls.exists( + group_id=group_id, block_plugin__contains=f"<{module}," + ) or await cls.exists( + group_id=group_id, superuser_block_plugin__contains=f"<{module}," + ) + + @classmethod + async def set_block_plugin( + cls, + group_id: str, + module: str, + is_superuser: bool = False, + platform: str | None = None, + ): + """禁用群组插件 + + 参数: + group_id: 群组id + task: 任务模块 + is_superuser: 是否为超级用户 + platform: 平台 + """ + group, _ = await cls.get_or_create( + group_id=group_id, defaults={"platform": platform} + ) + if is_superuser: + if f"<{module}," not in group.superuser_block_plugin: + group.superuser_block_plugin += f"<{module}," + elif f"<{module}," not in group.block_plugin: + group.block_plugin += f"<{module}," + await group.save(update_fields=["block_plugin", "superuser_block_plugin"]) + + @classmethod + async def set_unblock_plugin( + cls, + group_id: str, + module: str, + is_superuser: bool = False, + platform: str | None = None, + ): + """禁用群组插件 + + 参数: + group_id: 群组id + task: 任务模块 + is_superuser: 是否为超级用户 + platform: 平台 + """ + group, _ = await cls.get_or_create( + group_id=group_id, defaults={"platform": platform} + ) + if is_superuser: + if f"<{module}," in group.superuser_block_plugin: + group.superuser_block_plugin = group.superuser_block_plugin.replace( + f"<{module},", "" + ) + elif f"<{module}," in group.block_plugin: + group.block_plugin = group.block_plugin.replace(f"<{module},", "") + await group.save(update_fields=["block_plugin", "superuser_block_plugin"]) + + @classmethod + async def is_normal_block_plugin( cls, group_id: str, module: str, channel_id: str | None = None ) -> bool: """查看群组是否禁用功能 @@ -163,7 +236,23 @@ class GroupConsole(Model): return await cls.exists( group_id=group_id, channel_id=channel_id, - block_plugin__contains=f"{module},", + block_plugin__contains=f"<{module},", + ) + + @classmethod + async def is_superuser_block_task(cls, group_id: str, task: str) -> bool: + """查看群组是否超级用户禁用被动 + + 参数: + group_id: 群组id + task: 模块名称 + + 返回: + bool: 是否禁用被动 + """ + return await cls.exists( + group_id=group_id, + superuser_block_task__contains=f"<{task},", ) @classmethod @@ -184,12 +273,79 @@ class GroupConsole(Model): return await cls.exists( group_id=group_id, channel_id__isnull=True, - block_task__contains=f"{task},", + block_task__contains=f"<{task},", + ) or await cls.exists( + group_id=group_id, + channel_id__isnull=True, + superuser_block_task__contains=f"<{task},", ) return await cls.exists( - group_id=group_id, channel_id=channel_id, block_task__contains=f"{task}," + group_id=group_id, channel_id=channel_id, block_task__contains=f"<{task}," + ) or await cls.exists( + group_id=group_id, + channel_id__isnull=True, + superuser_block_task__contains=f"<{task},", ) + @classmethod + async def set_block_task( + cls, + group_id: str, + task: str, + is_superuser: bool = False, + platform: str | None = None, + ): + """禁用群组插件 + + 参数: + group_id: 群组id + task: 任务模块 + is_superuser: 是否为超级用户 + platform: 平台 + """ + group, _ = await cls.get_or_create( + group_id=group_id, defaults={"platform": platform} + ) + if is_superuser: + if f"<{task}," not in group.superuser_block_task: + group.superuser_block_task += f"<{task}," + elif f"<{task}," not in group.block_task: + group.block_task += f"<{task}," + await group.save(update_fields=["block_task", "superuser_block_task"]) + + @classmethod + async def set_unblock_task( + cls, + group_id: str, + task: str, + is_superuser: bool = False, + platform: str | None = None, + ): + """禁用群组插件 + + 参数: + group_id: 群组id + task: 任务模块 + is_superuser: 是否为超级用户 + platform: 平台 + """ + group, _ = await cls.get_or_create( + group_id=group_id, defaults={"platform": platform} + ) + if is_superuser: + if f"<{task}," in group.superuser_block_task: + group.superuser_block_task = group.superuser_block_task.replace( + f"<{task},", "" + ) + elif f"<{task}," in group.block_task: + group.block_task = group.block_task.replace(f"<{task},", "") + await group.save(update_fields=["block_task", "superuser_block_task"]) + @classmethod def _run_script(cls): - return [] + return [ + "ALTER TABLE group_console ADD superuser_block_plugin" + " character varying(255) NOT NULL DEFAULT '';", + "ALTER TABLE group_console ADD superuser_block_task" + " character varying(255) NOT NULL DEFAULT '';", + ] diff --git a/zhenxun/models/group_info.py b/zhenxun/models/group_info.py index 8183bf16..9b8e3065 100644 --- a/zhenxun/models/group_info.py +++ b/zhenxun/models/group_info.py @@ -23,7 +23,7 @@ class GroupInfo(Model): platform = fields.CharField(255, default="qq", description="所属平台") """所属平台""" - class Meta: + class Meta: # type: ignore table = "group_info" table_description = "群聊信息表" @@ -40,12 +40,81 @@ class GroupInfo(Model): """ return await cls.exists(group_id=group_id, block_task__contains=f"{task},") + @classmethod + async def is_block_plugin(cls, group_id: str, module: str) -> bool: + """查看群组是否禁用插件 + + 参数: + group_id: 群组id + plugin: 插件名称 + + 返回: + bool: 是否禁用插件 + """ + return await cls.exists( + group_id=group_id, block_plugin__contains=f"{module}," + ) or await cls.exists( + group_id=group_id, superuser_block_plugin__contains=f"{module}," + ) + + @classmethod + async def set_block_plugin( + cls, + group_id: str, + module: str, + is_superuser: bool = False, + platform: str | None = None, + ): + """禁用群组插件 + + 参数: + group_id: 群组id + task: 任务模块 + """ + group, _ = await cls.get_or_create( + group_id=group_id, defaults={"platform": platform} + ) + if is_superuser: + if "module," not in group.superuser_block_plugin: + group.superuser_block_plugin += f"{module}," + elif "module," not in group.block_plugin: + group.block_plugin += f"{module}," + await group.save(update_fields=["block_plugin", "superuser_block_plugin"]) + + @classmethod + async def set_unblock_plugin( + cls, + group_id: str, + module: str, + is_superuser: bool = False, + platform: str | None = None, + ): + """禁用群组插件 + + 参数: + group_id: 群组id + task: 任务模块 + """ + group, _ = await cls.get_or_create( + group_id=group_id, defaults={"platform": platform} + ) + if is_superuser: + if "module," in group.superuser_block_plugin: + group.superuser_block_plugin = group.superuser_block_plugin.replace( + f"{module},", "" + ) + elif "module," in group.block_plugin: + group.block_plugin = group.block_plugin.replace(f"{module},", "") + await group.save(update_fields=["block_plugin", "superuser_block_plugin"]) + @classmethod def _run_script(cls): return [ - "ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;", # group_info表添加一个group_flag + "ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;", + # group_info表添加一个group_flag "ALTER TABLE group_info ALTER COLUMN group_id TYPE character varying(255);", "ALTER TABLE group_info ADD block_plugin Text NOT NULL DEFAULT '';", "ALTER TABLE group_info ADD block_task Text NOT NULL DEFAULT '';", - "ALTER TABLE group_info ADD platform character varying(255) NOT NULL DEFAULT 'qq';", + "ALTER TABLE group_info ADD platform character varying(255) NOT NULL" + " DEFAULT 'qq';", ]