From a2d6c7f951d25061e55d074740ed7f4c655b5c72 Mon Sep 17 00:00:00 2001 From: HibiKier <775757368@qq.com> Date: Thu, 29 Feb 2024 03:07:31 +0800 Subject: [PATCH] =?UTF-8?q?perf=F0=9F=91=8C:=20=E5=B9=BF=E6=92=AD=E4=B8=8E?= =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=8F=92=E4=BB=B6/=E8=A2=AB=E5=8A=A8?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/plugin_switch/__init__.py | 113 ++++++++----- .../admin/plugin_switch/_data_source.py | 112 ++++++++++++- .../admin/plugin_switch/command.py | 17 ++ zhenxun/builtin_plugins/scheduler/morning.py | 91 ++++++++--- .../superuser/broadcast/__init__.py | 8 +- .../superuser/broadcast/_data_source.py | 74 ++------- zhenxun/models/group_console.py | 6 + zhenxun/utils/platform.py | 150 +++++++++++++++++- 8 files changed, 433 insertions(+), 138 deletions(-) diff --git a/zhenxun/builtin_plugins/admin/plugin_switch/__init__.py b/zhenxun/builtin_plugins/admin/plugin_switch/__init__.py index 1165dead..59295c44 100644 --- a/zhenxun/builtin_plugins/admin/plugin_switch/__init__.py +++ b/zhenxun/builtin_plugins/admin/plugin_switch/__init__.py @@ -1,6 +1,6 @@ from nonebot.adapters import Bot from nonebot.plugin import PluginMetadata -from nonebot_plugin_alconna import Arparma, Match +from nonebot_plugin_alconna import AlconnaQuery, Arparma, Match, Query from nonebot_plugin_saa import Image, Text from nonebot_plugin_session import EventSession @@ -21,14 +21,16 @@ __plugin_meta__ = PluginMetadata( usage=""" 普通管理员 格式: - 开启/关闭[功能名称] : 开关功能 - 群被动状态 : 查看被动技能开关状态 - 醒来 : 结束休眠 - 休息吧 : 群组休眠, 不会再响应命令 + 开启/关闭[功能名称] : 开关功能 + 开启/关闭群被动[被动名称] : 群被动开关 + 群被动状态 : 查看被动技能开关状态 + 醒来 : 结束休眠 + 休息吧 : 群组休眠, 不会再响应命令 示例: 开启签到 : 开启签到 关闭签到 : 关闭签到 + 开启群被动早晚安 : 关闭被动任务早晚安 超级管理员额外命令 格式: @@ -61,26 +63,21 @@ __plugin_meta__ = PluginMetadata( @_status_matcher.assign("$main") -async def _(bot: Bot, session: EventSession, arparma: Arparma): +async def _( + bot: Bot, + session: EventSession, + arparma: Arparma, + task: Query[bool] = AlconnaQuery("task.value", False), +): image = None - if session.id1 in bot.config.superusers: + if task.result: + image = await build_task(session.id3 or session.id2) + elif session.id1 in bot.config.superusers: image = await build_plugin() if image: await Image(image.pic2bytes()).send(reply=True) logger.info( - f"查看功能列表", - arparma.header_result, - session=session, - ) - - -@_status_matcher.assign("task") -async def _(bot: Bot, session: EventSession, arparma: Arparma): - image = None - if image := await build_task(session.id3 or session.id2): - await Image(image.pic2bytes()).send(reply=True) - logger.info( - f"查看被动列表", + f"查看{'功能' if arparma.find('task') else '被动'}列表", arparma.header_result, session=session, ) @@ -93,21 +90,35 @@ async def _( arparma: Arparma, name: str, group: Match[str], + task: Query[bool] = AlconnaQuery("task.value", False), ): if gid := session.id3 or session.id2: - result = await PluginManage.block_group_plugin(name, gid) + if task.result: + result = await PluginManage.unblock_group_task(name, gid) + else: + result = await PluginManage.block_group_plugin(name, gid) await Text(result).send(reply=True) logger.info(f"开启功能 {name}", arparma.header_result, session=session) elif session.id1 in bot.config.superusers: group_id = group.result if group.available else None - result = await PluginManage.superuser_block(name, None, group_id) - await Text(result).send(reply=True) - logger.info( - f"超级用户开启功能 {name}", - arparma.header_result, - session=session, - target=group_id, - ) + if task.result: + result = await PluginManage.superuser_task_handle(name, group_id, True) + await Text(result).send(reply=True) + logger.info( + f"超级用户开启被动技能 {name}", + arparma.header_result, + session=session, + target=group_id, + ) + else: + result = await PluginManage.superuser_block(name, None, group_id) + await Text(result).send(reply=True) + logger.info( + f"超级用户开启功能 {name}", + arparma.header_result, + session=session, + target=group_id, + ) @_status_matcher.assign("close") @@ -118,27 +129,41 @@ async def _( name: str, block_type: Match[str], group: Match[str], + task: Query[bool] = AlconnaQuery("task.value", False), ): if gid := session.id3 or session.id2: - result = await PluginManage.unblock_group_plugin(name, gid) + if task.result: + result = await PluginManage.block_group_task(name, gid) + else: + result = await PluginManage.unblock_group_plugin(name, gid) await Text(result).send(reply=True) logger.info(f"关闭功能 {name}", arparma.header_result, session=session) elif session.id1 in bot.config.superusers: group_id = group.result if group.available else None - _type = BlockType.ALL - if block_type.available: - if block_type.result in ["p", "private"]: - _type = BlockType.PRIVATE - elif block_type.result in ["g", "group"]: - _type = BlockType.GROUP - result = await PluginManage.superuser_block(name, _type, group_id) - await Text(result).send(reply=True) - logger.info( - f"超级用户关闭功能 {name}, 禁用类型: {_type}", - arparma.header_result, - session=session, - target=group_id, - ) + if task.result: + result = await PluginManage.superuser_task_handle(name, group_id, False) + await Text(result).send(reply=True) + logger.info( + f"超级用户关闭被动技能 {name}", + arparma.header_result, + session=session, + target=group_id, + ) + else: + _type = BlockType.ALL + if block_type.available: + if block_type.result in ["p", "private"]: + _type = BlockType.PRIVATE + elif block_type.result in ["g", "group"]: + _type = BlockType.GROUP + result = await PluginManage.superuser_block(name, _type, group_id) + await Text(result).send(reply=True) + logger.info( + f"超级用户关闭功能 {name}, 禁用类型: {_type}", + arparma.header_result, + session=session, + target=group_id, + ) @_group_status_matcher.handle() diff --git a/zhenxun/builtin_plugins/admin/plugin_switch/_data_source.py b/zhenxun/builtin_plugins/admin/plugin_switch/_data_source.py index b88cd607..5894cfbc 100644 --- a/zhenxun/builtin_plugins/admin/plugin_switch/_data_source.py +++ b/zhenxun/builtin_plugins/admin/plugin_switch/_data_source.py @@ -104,7 +104,9 @@ async def build_task(group_id: str | None) -> BuildImage: column_name = ["ID", "模块", "名称", "群组状态", "全局状态", "运行时间"] group = None if group_id: - group = await GroupConsole.get_or_none(group_id=group_id) + group = await GroupConsole.get_or_none( + group_id=group_id, channel_id__isnull=True + ) if not group: raise GroupInfoNotFound() else: @@ -145,17 +147,23 @@ class PluginManage: @classmethod async def is_wake(cls, group_id: str) -> bool: - if c := await GroupConsole.get_or_none(group_id=group_id): + if c := await GroupConsole.get_or_none( + group_id=group_id, channel_id__isnull=True + ): return c.status return False @classmethod async def sleep(cls, group_id: str): - await GroupConsole.filter(group_id=group_id).update(status=False) + await GroupConsole.filter(group_id=group_id, channel_id__isnull=True).update( + status=False + ) @classmethod async def wake(cls, group_id: str): - await GroupConsole.filter(group_id=group_id).update(status=True) + await GroupConsole.filter(group_id=group_id, channel_id__isnull=True).update( + status=True + ) @classmethod async def block(cls, module: str): @@ -178,6 +186,32 @@ class PluginManage: """ return await cls._change_group_plugin(plugin_name, group_id, True) + @classmethod + async def unblock_group_task(cls, task_name: str, group_id: str) -> str: + """启用被动技能 + + 参数: + task_name: 被动技能名称 + group_id: 群组id + + 返回: + str: 返回信息 + """ + return await cls._change_group_task(task_name, group_id, False) + + @classmethod + async def block_group_task(cls, task_name: str, group_id: str) -> str: + """禁用被动技能 + + 参数: + task_name: 被动技能名称 + group_id: 群组id + + 返回: + str: 返回信息 + """ + return await cls._change_group_task(task_name, group_id, True) + @classmethod async def unblock_group_plugin(cls, plugin_name: str, group_id: str) -> str: """启用群组插件 @@ -191,6 +225,33 @@ class PluginManage: """ return await cls._change_group_plugin(plugin_name, group_id, False) + @classmethod + async def _change_group_task( + cls, task_name: str, group_id: str, status: bool + ) -> str: + """改变群组被动技能状态 + + 参数: + task_name: 被动技能名称 + group_id: 群组Id + status: 状态 + + 返回: + str: 返回信息 + """ + if task := await TaskInfo.get_or_none(name=task_name): + status_str = "关闭" if status else "开启" + group, _ = await GroupConsole.get_or_create( + group_id=group_id, channel_id__isnull=True + ) + if status: + group.block_task += f"{task.module}," + else: + group.block_task = group.block_task.replace(f"{task.module},", "") + await group.save(update_fields=["block_task"]) + return f"已成功{status_str} {task_name} 被动技能!" + return "没有找到这个被动技能喔..." + @classmethod async def _change_group_plugin( cls, plugin_name: str, group_id: str, status: bool @@ -212,7 +273,9 @@ class PluginManage: plugin = await PluginInfo.get_or_none(name=plugin_name) status_str = "开启" if status else "关闭" if plugin: - group, _ = await GroupConsole.get_or_create(group_id=group_id) + group, _ = await GroupConsole.get_or_create( + group_id=group_id, channel_id__isnull=True + ) if status: if plugin.module in group.block_plugin: group.block_plugin = group.block_plugin.replace( @@ -228,11 +291,44 @@ class PluginManage: return f"该功能已经{status_str}了喔,不要重复{status_str}..." return "没有找到这个功能喔..." + @classmethod + async def superuser_task_handle( + cls, task_name: str, group_id: str | None, status: bool + ) -> str: + """超级用户禁用被动技能 + + 参数: + task_name: 被动技能名称 + group_id: 群组id + status: 状态 + + 返回: + str: 返回信息 + """ + if task := await TaskInfo.get_or_none(name=task_name): + status_str = "开启" if status else "关闭" + 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},", "" + ) + else: + group.block_task += f"super:{task.module}," + await group.save(update_fields=["block_task"]) + else: + task.status = status + await task.save(update_fields=["status"]) + return f"已成功将被动技能 {task_name} 全局{status_str}!" + return "没有找到这个功能喔..." + @classmethod async def superuser_block( cls, plugin_name: str, block_type: BlockType | None, group_id: str | None ) -> str: - """超级用户禁用 + """超级用户禁用插件 参数: plugin_name: 插件名称 @@ -248,7 +344,9 @@ class PluginManage: plugin = await PluginInfo.get_or_none(name=plugin_name) if plugin: if group_id: - if group := await GroupConsole.get_or_none(group_id=group_id): + if group := await GroupConsole.get_or_none( + group_id=group_id, channel_id__isnull=True + ): if f"super:{plugin.module}," not in group.block_plugin: group.block_plugin += f"super:{plugin.module}," await group.save(update_fields=["block_plugin"]) diff --git a/zhenxun/builtin_plugins/admin/plugin_switch/command.py b/zhenxun/builtin_plugins/admin/plugin_switch/command.py index 41e1811a..f1323227 100644 --- a/zhenxun/builtin_plugins/admin/plugin_switch/command.py +++ b/zhenxun/builtin_plugins/admin/plugin_switch/command.py @@ -63,6 +63,15 @@ _status_matcher.shortcut( prefix=True, ) + +_status_matcher.shortcut( + r"开启群被动(?P.+)", + command="switch", + arguments=["open", "{name}", "--task"], + prefix=True, +) + + _status_matcher.shortcut( r"开启(?P.+)", command="switch", @@ -70,6 +79,13 @@ _status_matcher.shortcut( prefix=True, ) +_status_matcher.shortcut( + r"关闭群被动(?P.+)", + command="switch", + arguments=["close", "{name}", "--task"], + prefix=True, +) + _status_matcher.shortcut( r"关闭(?P.+)", command="switch", @@ -77,6 +93,7 @@ _status_matcher.shortcut( prefix=True, ) + _group_status_matcher.shortcut( r"醒来", command="group-status", diff --git a/zhenxun/builtin_plugins/scheduler/morning.py b/zhenxun/builtin_plugins/scheduler/morning.py index 62964462..6ed2ff1c 100644 --- a/zhenxun/builtin_plugins/scheduler/morning.py +++ b/zhenxun/builtin_plugins/scheduler/morning.py @@ -1,28 +1,75 @@ +import nonebot +from nonebot.plugin import PluginMetadata from nonebot_plugin_apscheduler import scheduler +from nonebot_plugin_saa import Image -# TODO: 消息发送 +from zhenxun.configs.config import NICKNAME +from zhenxun.configs.path_config import IMAGE_PATH +from zhenxun.configs.utils import PluginExtraData, Task +from zhenxun.models.group_console import GroupConsole +from zhenxun.models.task_info import TaskInfo +from zhenxun.services.log import logger +from zhenxun.utils.enum import PluginType +from zhenxun.utils.platform import broadcast_group -# # 早上好 -# @scheduler.scheduled_job( -# "cron", -# hour=6, -# minute=1, -# ) -# async def _(): -# img = image(IMAGE_PATH / "zhenxun" / "zao.jpg") -# await broadcast_group("[[_task|zwa]]早上好" + img, log_cmd="被动早晚安") -# logger.info("每日早安发送...") +__plugin_meta__ = PluginMetadata( + name="早晚安被动技能", + description="早晚安被动技能", + usage="", + extra=PluginExtraData( + author="HibiKier", + version="0.1", + plugin_type=PluginType.HIDDEN, + tasks=[ + Task(module="group_welcome", name="进群欢迎"), + Task(module="refund_group_remind", name="退群提醒"), + ], + ).dict(), +) + +driver = nonebot.get_driver() + + +@driver.on_startup +async def _(): + if not await TaskInfo.exists(module="morning_goodnight"): + await TaskInfo.create( + module="morning_goodnight", + name="早晚安", + status=True, + ) + + +async def check(group_id: str, channel_id: str | None) -> bool: + task = await TaskInfo.get_or_none(module="morning_goodnight") + if not task or not task.status: + return False + return await GroupConsole.is_block_task(group_id, "morning_goodnight") + + +# 早上好 +@scheduler.scheduled_job( + "cron", + hour=6, + minute=1, +) +async def _(): + img = Image(IMAGE_PATH / "zhenxun" / "zao.jpg") + await broadcast_group("早上好" + img, log_cmd="被动早晚安", check_func=check) + logger.info("每日早安发送...") # # 睡觉了 -# @scheduler.scheduled_job( -# "cron", -# hour=23, -# minute=59, -# ) -# async def _(): -# img = image(IMAGE_PATH / "zhenxun" / "sleep.jpg") -# await broadcast_group( -# f"[[_task|zwa]]{NICKNAME}要睡觉了,你们也要早点睡呀" + img, log_cmd="被动早晚安" -# ) -# logger.info("每日晚安发送...") +@scheduler.scheduled_job( + "cron", + hour=23, + minute=59, +) +async def _(): + img = Image(IMAGE_PATH / "zhenxun" / "sleep.jpg") + await broadcast_group( + f"{NICKNAME}要睡觉了,你们也要早点睡呀" + img, + log_cmd="被动早晚安", + check_func=check, + ) + logger.info("每日晚安发送...") diff --git a/zhenxun/builtin_plugins/superuser/broadcast/__init__.py b/zhenxun/builtin_plugins/superuser/broadcast/__init__.py index 271652a7..9b823f54 100644 --- a/zhenxun/builtin_plugins/superuser/broadcast/__init__.py +++ b/zhenxun/builtin_plugins/superuser/broadcast/__init__.py @@ -5,6 +5,7 @@ from nonebot.adapters import Bot from nonebot.params import Command from nonebot.permission import SUPERUSER from nonebot.plugin import PluginMetadata +from nonebot_plugin_alconna import Text as alcText from nonebot_plugin_alconna import UniMsg from nonebot_plugin_saa import Text from nonebot_plugin_session import EventSession @@ -51,8 +52,11 @@ async def _( message: UniMsg, command: Annotated[tuple[str, ...], Command()], ): - message[0].text = message[0].text.replace(command[0], "").strip() - # await Text("正在发送..请等一下哦!").send() + for msg in message: + if isinstance(msg, alcText) and msg.text.strip().startswith(command[0]): + msg.text = msg.text.replace(command[0], "", 1).strip() + break + await Text("正在发送..请等一下哦!").send() count, error_count = await BroadcastManage.send(bot, message, session) result = f"成功广播 {count} 个群组" if error_count: diff --git a/zhenxun/builtin_plugins/superuser/broadcast/_data_source.py b/zhenxun/builtin_plugins/superuser/broadcast/_data_source.py index 1833aae3..4781aff3 100644 --- a/zhenxun/builtin_plugins/superuser/broadcast/_data_source.py +++ b/zhenxun/builtin_plugins/superuser/broadcast/_data_source.py @@ -9,23 +9,13 @@ from nonebot_plugin_alconna import UniMsg from nonebot_plugin_saa import ( Image, MessageFactory, - TargetDoDoChannel, - TargetQQGroup, Text, ) from nonebot_plugin_session import EventSession -from pydantic import BaseModel from zhenxun.models.group_console import GroupConsole from zhenxun.services.log import logger - - -class GroupChannel(BaseModel): - - group_id: str - """群组id""" - channel_id: str | None = None - """频道id""" +from zhenxun.utils.platform import PlatformManage class BroadcastManage: @@ -50,24 +40,27 @@ class BroadcastManage: message_list.append(Image(msg.url)) elif isinstance(msg, alc.Text): message_list.append(Text(msg.text)) - if group_list := await cls.__get_group_list(bot): + group_list, _ = await PlatformManage.get_group_list(bot) + if group_list: error_count = 0 for group in group_list: try: if not await GroupConsole.is_block_task( group.group_id, "broadcast", group.channel_id ): - if isinstance(bot, (v11Bot, v12Bot)): - target = TargetQQGroup(group_id=int(group.group_id)) - elif isinstance(bot, DodoBot): - target = TargetDoDoChannel(channel_id=group.channel_id) # type: ignore - await MessageFactory(message_list).send_to(target, bot) - logger.debug( - "发送成功", - "广播", - session=session, - target=f"{group.group_id}:{group.channel_id}", + target = PlatformManage.get_target( + bot, group.group_id, group.channel_id ) + if target: + await MessageFactory(message_list).send_to(target, bot) + logger.debug( + "发送成功", + "广播", + session=session, + target=f"{group.group_id}:{group.channel_id}", + ) + else: + logger.warning("target为空", "广播", session=session) except Exception as e: error_count += 1 logger.error( @@ -79,40 +72,3 @@ class BroadcastManage: ) return len(group_list) - error_count, error_count return 0, 0 - - @classmethod - async def __get_group_list(cls, bot: Bot) -> list[GroupChannel]: - """获取群组id列表 - - 参数: - bot: Bot - - 返回: - list[str]: 群组id列表 - """ - if isinstance(bot, (v11Bot, v12Bot)): - group_list = await bot.get_group_list() - return [GroupChannel(group_id=str(g["group_id"])) for g in group_list] - if isinstance(bot, DodoBot): - island_list = await bot.get_island_list() - source_id_list = [ - g.island_source_id for g in island_list if g.island_source_id - ] - channel_id_list = [] - for id in source_id_list: - channel_list = await bot.get_channel_list(island_source_id=id) - channel_id_list += [ - GroupChannel(group_id=id, channel_id=c.channel_id) - for c in channel_list - ] - return channel_id_list - if isinstance(bot, KaiheilaBot): - # TODO: kaiheila获取群组列表 - pass - # group_list = await bot.guild_list() - # if group_list.guilds: - # return [g.open_id for g in group_list.guilds if g.open_id] - if isinstance(bot, DiscordBot): - # TODO: discord获取群组列表 - pass - return [] diff --git a/zhenxun/models/group_console.py b/zhenxun/models/group_console.py index 0e8858de..d5946396 100644 --- a/zhenxun/models/group_console.py +++ b/zhenxun/models/group_console.py @@ -108,6 +108,12 @@ class GroupConsole(Model): 返回: bool: 是否禁用被动 """ + if not channel_id: + return await cls.exists( + group_id=group_id, + channel_id__isnull=True, + block_task__contains=f"{task},", + ) return await cls.exists( group_id=group_id, channel_id=channel_id, block_task__contains=f"{task}," ) diff --git a/zhenxun/utils/platform.py b/zhenxun/utils/platform.py index fc18a5f6..fb34e81f 100644 --- a/zhenxun/utils/platform.py +++ b/zhenxun/utils/platform.py @@ -1,9 +1,20 @@ +from typing import Awaitable, Callable, Literal, Set + +import nonebot from nonebot.adapters import Bot from nonebot.adapters.discord import Bot as DiscordBot from nonebot.adapters.dodo import Bot as DodoBot from nonebot.adapters.kaiheila import Bot as KaiheilaBot from nonebot.adapters.onebot.v11 import Bot as v11Bot from nonebot.adapters.onebot.v12 import Bot as v12Bot +from nonebot.utils import is_coroutine_callable +from nonebot_plugin_saa import ( + MessageFactory, + TargetDoDoChannel, + TargetKaiheilaChannel, + TargetQQGroup, + Text, +) from zhenxun.models.friend_user import FriendUser from zhenxun.models.group_console import GroupConsole @@ -23,7 +34,7 @@ class PlatformManage: int: 更新个数 """ create_list = [] - group_list, platform = await cls.__get_group_list(bot) + group_list, platform = await cls.get_group_list(bot) if group_list: exists_group_list = await GroupConsole.all().values_list( "group_id", "channel_id" @@ -42,7 +53,25 @@ class PlatformManage: return len(create_list) @classmethod - async def __get_group_list(cls, bot: Bot) -> tuple[list[GroupConsole], str]: + def get_platform(cls, bot: Bot) -> str | None: + """获取平台 + + 参数: + bot: Bot + + 返回: + str | None: 平台 + """ + if isinstance(bot, (v11Bot, v12Bot)): + return "qq" + if isinstance(bot, DodoBot): + return "dodo" + if isinstance(bot, KaiheilaBot): + return "kaiheila" + return None + + @classmethod + async def get_group_list(cls, bot: Bot) -> tuple[list[GroupConsole], str]: """获取群组列表 参数: @@ -121,7 +150,7 @@ class PlatformManage: int: 更新个数 """ create_list = [] - friend_list, platform = await cls.__get_friend_list(bot) + friend_list, platform = await cls.get_friend_list(bot) if friend_list: user_id_list = await FriendUser.all().values_list("user_id", flat=True) for friend in friend_list: @@ -133,7 +162,7 @@ class PlatformManage: return len(create_list) @classmethod - async def __get_friend_list(cls, bot: Bot) -> tuple[list[FriendUser], str]: + async def get_friend_list(cls, bot: Bot) -> tuple[list[FriendUser], str]: """获取好友列表 参数: @@ -167,3 +196,116 @@ class PlatformManage: # TODO: discord好友列表 pass return [], "" + + @classmethod + def get_target(cls, bot: Bot, group_id: str | None, channel_id: str | None): + """获取发生Target + + 参数: + bot: Bot + group_id: 群组id + channel_id: 频道id + + 返回: + target: 对应平台Target + """ + target = None + if isinstance(bot, (v11Bot, v12Bot)): + if group_id: + target = TargetQQGroup(group_id=int(group_id)) + if channel_id: + if isinstance(bot, DodoBot): + target = TargetDoDoChannel(channel_id=channel_id) + elif isinstance(bot, KaiheilaBot): + target = TargetKaiheilaChannel(channel_id=channel_id) + return target + + +async def broadcast_group( + message: str | MessageFactory, + bot: Bot | list[Bot] | None = None, + bot_id: str | Set[str] | None = None, + ignore_group: Set[int] | None = None, + check_func: Callable[[str, str | None], Awaitable] | None = None, + log_cmd: str | None = None, + platform: Literal["qq", "dodo", "kaiheila"] | None = None, +): + """获取所有Bot或指定Bot对象广播群聊 + + Args: + message: 广播消息内容 + bot: 指定bot对象. + bot_id: 指定bot id. + ignore_group: 忽略群聊列表. + check_func: 发送前对群聊检测方法,判断是否发送. + log_cmd: 日志标记. + platform: 指定平台 + """ + if platform and platform not in ["qq", "dodo", "kaiheila"]: + raise ValueError("指定平台不支持") + if not message: + raise ValueError("群聊广播消息不能为空") + bot_dict = nonebot.get_bots() + bot_list: list[Bot] = [] + if bot: + if isinstance(bot, list): + bot_list = bot + else: + bot_list.append(bot) + elif bot_id: + _bot_id_list = bot_id + if isinstance(bot_id, str): + _bot_id_list = [bot_id] + for id_ in _bot_id_list: + if bot_id in bot_dict: + bot_list.append(bot_dict[bot_id]) + else: + logger.warning(f"Bot:{id_} 对象未连接或不存在") + else: + bot_list = list(bot_dict.values()) + _used_group = [] + for _bot in bot_list: + try: + if platform and platform != PlatformManage.get_platform(_bot): + continue + group_list, _ = await PlatformManage.get_group_list(_bot) + if group_list: + for group in group_list: + key = f"{group.group_id}:{group.channel_id}" + try: + if ( + ignore_group + and ( + group.group_id in ignore_group + or group.channel_id in ignore_group + ) + ) or key in _used_group: + continue + is_continue = False + if check_func: + if is_coroutine_callable(check_func): + is_continue = not await check_func( + group.group_id, group.channel_id + ) + else: + is_continue = not check_func( + group.group_id, group.channel_id + ) + if is_continue: + continue + target = PlatformManage.get_target( + _bot, group.group_id, group.channel_id + ) + if target: + _used_group.append(key) + message_list = message + if isinstance(message, str): + message_list = MessageFactory([Text(message)]) + await MessageFactory(message_list).send_to(target, _bot) + logger.debug("发送成功", log_cmd, target=key) + else: + logger.warning("target为空", log_cmd, target=key) + except Exception as e: + logger.error("发送失败", log_cmd, target=key, e=e) + except Exception as e: + logger.error(f"Bot: {_bot.self_id} 获取群聊列表失败", command=log_cmd, e=e)