feat✨: 更新内置插件

This commit is contained in:
HibiKier
2024-02-25 03:18:34 +08:00
parent 131200a28e
commit eb0572ea77
83 changed files with 7588 additions and 450 deletions
+165
View File
@@ -0,0 +1,165 @@
import nonebot
from arclet.alconna import Args, Option
from nonebot.plugin import PluginMetadata
from nonebot_plugin_alconna import Alconna, Arparma, on_alconna
from nonebot_plugin_alconna.matcher import AlconnaMatcher
from nonebot_plugin_saa import Image, Text
from nonebot_plugin_session import EventSession
from zhenxun.configs.config import Config
from zhenxun.configs.path_config import DATA_PATH, IMAGE_PATH
from zhenxun.configs.utils import PluginExtraData, RegisterConfig
from zhenxun.models.plugin_info import PluginInfo
from zhenxun.models.task_info import TaskInfo
from zhenxun.services.log import logger
from zhenxun.utils.enum import PluginType
from zhenxun.utils.exception import EmptyError
from zhenxun.utils.image_utils import (
BuildImage,
build_sort_image,
group_image,
text2image,
)
from zhenxun.utils.rules import admin_check, ensure_group
base_config = Config.get("admin_bot_manage")
__plugin_meta__ = PluginMetadata(
name="群组管理员帮助",
description="管理员帮助列表",
usage="""
管理员帮助
""".strip(),
extra=PluginExtraData(
author="HibiKier",
version="0.1",
plugin_type=PluginType.ADMIN,
admin_level=1,
).dict(),
)
_matcher = on_alconna(
Alconna("管理员帮助"),
rule=admin_check(1) & ensure_group,
priority=5,
block=True,
)
ADMIN_HELP_IMAGE = IMAGE_PATH / "ADMIN_HELP.png"
if ADMIN_HELP_IMAGE.exists():
ADMIN_HELP_IMAGE.unlink()
async def build_help() -> BuildImage:
"""构造管理员帮助图片
异常:
EmptyError: 管理员帮助为空
返回:
BuildImage: 管理员帮助图片
"""
plugin_list = await PluginInfo.filter(
plugin_type__in=[PluginType.ADMIN, PluginType.SUPER_AND_ADMIN]
).all()
data_list = []
for plugin in plugin_list:
if _plugin := nonebot.get_plugin_by_module_name(plugin.module_path):
if _plugin.metadata:
data_list.append({"plugin": plugin, "metadata": _plugin.metadata})
font = BuildImage.load_font("HYWenHei-85W.ttf", 20)
image_list = []
for data in data_list:
plugin = data["plugin"]
metadata = data["metadata"]
try:
usage = None
description = None
if metadata.usage:
usage = await text2image(
metadata.usage,
padding=5,
color=(255, 255, 255),
font_color=(0, 0, 0),
)
if metadata.description:
description = await text2image(
metadata.description,
padding=5,
color=(255, 255, 255),
font_color=(0, 0, 0),
)
width = 0
height = 100
if usage:
width = usage.width
height += usage.height
if description and description.width > width:
width = description.width
height += description.height
font_width, font_height = BuildImage.get_text_size(
plugin.name + f"[{plugin.level}]", font
)
if font_width > width:
width = font_width
A = BuildImage(width + 30, height + 120, "#EAEDF2")
await A.text((15, 10), plugin.name + f"[{plugin.level}]")
await A.text((15, 70), "简介:")
if not description:
description = BuildImage(A.width - 30, 30, (255, 255, 255))
await description.circle_corner(10)
await A.paste(description, (15, 100))
if not usage:
usage = BuildImage(A.width - 30, 30, (255, 255, 255))
await usage.circle_corner(10)
await A.text((15, description.height + 115), "用法:")
await A.paste(usage, (15, description.height + 145))
await A.circle_corner(10)
image_list.append(A)
except Exception as e:
logger.warning(
f"获取群管理员插件 {plugin.module}: {plugin.name} 设置失败...",
"管理员帮助",
e=e,
)
if task_list := await TaskInfo.all():
task_str = "\n".join([task.name for task in task_list])
task_str = "通过 开启/关闭 来控制群被动\n----------\n" + task_str
task_image = await text2image(task_str, padding=5, color=(255, 255, 255))
await task_image.circle_corner(10)
A = BuildImage(task_image.width + 50, task_image.height + 85, "#EAEDF2")
await A.text((25, 10), "被动技能")
await A.paste(task_image, (25, 50))
await A.circle_corner(10)
image_list.append(A)
if not image_list:
raise EmptyError()
image_group, _ = group_image(image_list)
A = await build_sort_image(image_group, color=(255, 255, 255), padding_top=160)
text = await BuildImage.build_text_image(
"群管理员帮助",
size=40,
)
tip = await BuildImage.build_text_image(
"注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数", size=25, font_color="red"
)
await A.paste(text, (50, 30))
await A.paste(tip, (50, 90))
await A.save(ADMIN_HELP_IMAGE)
return BuildImage(1, 1)
@_matcher.handle()
async def _(
session: EventSession,
matcher: AlconnaMatcher,
arparma: Arparma,
):
if not ADMIN_HELP_IMAGE.exists():
try:
await build_help()
except EmptyError:
await Text("管理员帮助为空").finish(reply=True)
await Image(ADMIN_HELP_IMAGE).send()
logger.info("查看管理员帮助", arparma.header_result, session=session)
+11 -11
View File
@@ -9,11 +9,6 @@ from zhenxun.models.level_user import LevelUser
from zhenxun.services.log import logger
from zhenxun.utils.enum import PluginType
__zx_plugin_name__ = "群管理员变动监测 [Hidden]"
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_meta__ = PluginMetadata(
name="群管理员变动监测",
description="检测群管理员变动, 添加与删除管理员默认权限, 当配置项 ADMIN_DEFAULT_AUTH 为空时, 不会添加管理员权限",
@@ -40,20 +35,25 @@ async def _(event: GroupAdminNoticeEvent):
admin_default_auth = base_config.get("ADMIN_DEFAULT_AUTH")
if admin_default_auth is not None:
await LevelUser.set_level(
event.user_id,
event.group_id,
str(event.user_id),
str(event.group_id),
admin_default_auth,
)
logger.info(
f"成为管理员,添加权限: {admin_default_auth}",
"群管理员变动监测",
event.user_id,
event.group_id,
session=event.user_id,
group_id=event.group_id,
)
else:
logger.warning(
f"配置项 MODULE: [<u><y>admin_bot_manage</y></u>] | KEY: [<u><y>ADMIN_DEFAULT_AUTH</y></u>] 为空"
)
elif event.sub_type == "unset":
await LevelUser.delete_level(event.user_id, event.group_id)
logger.info("撤销群管理员, 取消权限等级", "群管理员变动监测", event.user_id, event.group_id)
await LevelUser.delete_level(str(event.user_id), str(event.group_id))
logger.info(
"撤销群管理员, 取消权限等级",
"群管理员变动监测",
session=event.user_id,
group_id=event.group_id,
)
@@ -0,0 +1,196 @@
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,
At,
Match,
Option,
Subcommand,
on_alconna,
store_true,
)
from nonebot_plugin_saa import Image, Mention, MessageFactory, Text
from nonebot_plugin_session import EventSession
from zhenxun.configs.config import Config
from zhenxun.configs.utils import PluginExtraData, RegisterConfig
from zhenxun.services.log import logger
from zhenxun.utils.enum import PluginType
from zhenxun.utils.rules import admin_check
from ._data_source import BanManage
base_config = Config.get("ban")
__plugin_meta__ = PluginMetadata(
name="封禁用户/群组",
description="你被逮捕了!丢进小黑屋!封禁用户以及群组,屏蔽消息",
usage="""
.ban [at] ?[小时] ?[分钟]
.unban
示例:.ban @user
示例:.ban @user 6
示例:.ban @user 3 10
示例:.unban @user
""".strip(),
extra=PluginExtraData(
author="HibiKier",
version="0.1",
plugin_type=PluginType.SUPER_AND_ADMIN,
admin_level=base_config.get("BAN_LEVEL", 5),
configs=[
RegisterConfig(
key="BAN_LEVEL",
value=5,
help="ban/unban所需要的管理员权限等级",
default_value=5,
type=int,
)
],
).dict(),
)
_matcher = on_alconna(
Alconna(
"ban-console",
Subcommand(
"ban",
Args["user?", [str, At]]["duration?", int],
Option("-g|--group", Args["group_id", str]),
),
Subcommand(
"unban",
Args["user?", [str, At]],
Option("-g|--group", Args["group_id", str]),
),
),
rule=admin_check("ban", "BAN_LEVEL"),
priority=5,
block=True,
)
_status_matcher = on_alconna(
Alconna(
"ban-status",
Option("-u|--user", Args["user_id", str]),
Option("-g|--group", Args["group_id", str]),
),
permission=SUPERUSER,
priority=1,
block=True,
)
# TODO: shortcut
@_status_matcher.handle()
async def _(
bot: Bot,
session: EventSession,
arparma: Arparma,
user_id: Match[str],
group_id: Match[str],
):
_user_id = user_id.result if user_id.available else None
_group_id = group_id.result if group_id.available else None
if image := await BanManage.build_ban_image(_user_id, _group_id):
await Image(image.pic2bs4()).finish(reply=True)
else:
await Text("数据为空捏...").finish(reply=True)
@_matcher.assign("ban")
async def _(
bot: Bot,
session: EventSession,
arparma: Arparma,
user: Match[str | At],
duration: Match[int],
group_id: Match[str],
):
user_id = None
if user.available:
if isinstance(user.result, At):
user_id = user.result.target
else:
user_id = user.result
_duration = duration.result * 60 if duration.available else -1
if gid := session.id3 or session.id2:
if group_id.available:
gid = group_id.result
await BanManage.ban(
user_id, gid, _duration, session, session.id1 in bot.config.superusers
)
logger.info(
f"管理员Ban",
arparma.header_result,
session=session,
target=f"{gid}:{user_id}",
)
await MessageFactory(
[
Text("对 "),
Mention(user_id), # type: ignore
Text(f" 狠狠惩戒了一番,一脚踢进了小黑屋!"),
]
).finish(reply=True)
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, _duration, session, True)
logger.info(
f"超级用户Ban",
arparma.header_result,
session=session,
target=f"{_group_id}:{user_id}",
)
at_msg = user_id if user_id else f"群组:{_group_id}"
await Text(f"对 {at_msg} 狠狠惩戒了一番,一脚踢进了小黑屋!").finish(reply=True)
@_matcher.assign("unban")
async def _(
bot: Bot,
session: EventSession,
arparma: Arparma,
user: Match[str | At],
group_id: Match[str],
):
user_id = None
if user.available:
if isinstance(user.result, At):
user_id = user.result.target
else:
user_id = user.result
if gid := session.id3 or session.id2:
if group_id.available:
gid = group_id.result
await BanManage.unban(
user_id, gid, session, session.id1 in bot.config.superusers
)
logger.info(
f"管理员UnBan",
arparma.header_result,
session=session,
target=f"{gid}:{user_id}",
)
await MessageFactory(
[
Text("将 "),
Mention(user_id), # type: ignore
Text(f" 从黑屋中拉了出来并急救了一下!"),
]
).finish(reply=True)
elif session.id1 in bot.config.superusers:
_group_id = group_id.result if group_id.available else None
await BanManage.unban(user_id, _group_id, session, True)
logger.info(
f"超级用户UnBan",
arparma.header_result,
session=session,
target=f"{_group_id}:{user_id}",
)
at_msg = user_id if user_id else f"群组:{_group_id}"
await Text(f"对 {at_msg} 从黑屋中拉了出来并急救了一下!").finish(reply=True)
@@ -0,0 +1,120 @@
import time
from nonebot_plugin_session import EventSession
from zhenxun.models.ban_console import BanConsole
from zhenxun.models.level_user import LevelUser
from zhenxun.utils.image_utils import ImageTemplate
class BanManage:
@classmethod
async def build_ban_image(cls, user_id: str | None, group_id: str | None):
data_list = None
if not user_id and not group_id:
data_list = await BanConsole.all()
elif user_id:
if group_id:
data_list = await BanConsole.filter(
user_id=user_id, group_id=group_id
).all()
else:
data_list = await BanConsole.filter(
user_id=user_id, group_id__isnull=True
).all()
else:
if group_id:
data_list = await BanConsole.filter(
user_id__isnull=True, group_id=group_id
).all()
if not data_list:
return None
column_name = [
"ID",
"用户ID",
"群组ID",
"BAN LEVEL",
"剩余时长(分钟)",
"操作员ID",
]
row_data = []
for data in data_list:
duration = int((data.ban_time + data.duration - time.time()) / 60)
if duration < 0:
duration = 0
row_data.append(
[
data.id,
data.user_id,
data.group_id,
data.ban_level,
duration,
data.operator,
]
)
return await ImageTemplate.table_page(
"Ban / UnBan 列表", "在黑屋中狠狠调教!", column_name, row_data
)
@classmethod
async def is_ban(cls, user_id: str, group_id: str | None):
"""判断用户是否被ban
参数:
user_id: 用户id
返回:
bool: 是否被ban
"""
return await BanConsole.is_ban(user_id, group_id)
@classmethod
async def unban(
cls,
user_id: str | None,
group_id: str | None,
session: EventSession,
is_superuser: bool = False,
) -> bool:
"""ban掉目标用户
参数:
user_id: 用户id
group_id: 群组id
session: Session
is_superuser: 是否为超级用户操作
返回:
bool: 是否unban成功
"""
user_level = 9999
if not is_superuser and user_id and session.id1:
user_level = await LevelUser.get_user_level(session.id1, group_id)
if await BanConsole.check_ban_level(user_id, group_id, user_level):
await BanConsole.unban(user_id, group_id)
return True
return False
@classmethod
async def ban(
cls,
user_id: str | None,
group_id: str | None,
duration: int,
session: EventSession,
is_superuser: bool,
):
"""ban掉目标用户
参数:
user_id: 用户id
group_id: 群组id
duration: 时长,秒
session: Session
is_superuser: 是否为超级用户操作
"""
level = 9999
if not is_superuser and user_id and session.id1:
level = await LevelUser.get_user_level(session.id1, group_id)
await BanConsole.ban(user_id, group_id, level, duration, session.id1)
@@ -0,0 +1,63 @@
from nonebot import on_notice
from nonebot.adapters import Bot
from nonebot.adapters.onebot.v11 import GroupIncreaseNoticeEvent
from nonebot.plugin import PluginMetadata
from nonebot_plugin_alconna import Alconna, Arparma, on_alconna
from nonebot_plugin_saa import Text
from nonebot_plugin_session import EventSession
from zhenxun.configs.utils import PluginExtraData
from zhenxun.services.log import logger
from zhenxun.utils.enum import PluginType
from zhenxun.utils.rules import admin_check, ensure_group
from ._data_source import MemberUpdateManage
__plugin_meta__ = PluginMetadata(
name="更新群组成员列表",
description="更新群组成员列表",
usage="""
更新群组成员的基本信息
指令:
更新群组成员信息
""".strip(),
extra=PluginExtraData(
author="HibiKier",
version="0.1",
plugin_type=PluginType.SUPER_AND_ADMIN,
admin_level=1,
).dict(),
)
_matcher = on_alconna(
Alconna("更新群组成员信息"),
rule=admin_check(1) & ensure_group,
priority=5,
block=True,
)
@_matcher.handle()
async def _(bot: Bot, session: EventSession, arparma: Arparma):
if gid := session.id3 or session.id2:
logger.info("更新群组成员信息", arparma.header_result, session=session)
await MemberUpdateManage.update(bot, gid)
await Text("已经成功更新了群组成员信息!").finish(reply=True)
await Text("群组id为空...").send()
_notice = on_notice(priority=1, block=False)
@_notice.handle()
async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
# TODO: 其他适配器的加群自动更新群组成员信息
if str(event.user_id) == bot.self_id:
await MemberUpdateManage.update(bot, str(event.group_id))
logger.info(
"{NICKNAME}加入群聊更新群组信息",
"更新群组成员列表",
session=event.user_id,
group_id=event.group_id,
)
@@ -0,0 +1,177 @@
import time
from datetime import datetime, timedelta, timezone
from nonebot.adapters import Bot
from nonebot.adapters.discord import Bot as DiscordBot
from nonebot.adapters.dodo import Bot as DodoBot
from nonebot.adapters.dodo.models import MemberInfo
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 zhenxun.configs.config import Config
from zhenxun.models.group_member_info import GroupInfoUser
from zhenxun.models.level_user import LevelUser
from zhenxun.services.log import logger
class MemberUpdateManage:
@classmethod
async def update(cls, bot: Bot, group_id: str):
if isinstance(bot, v11Bot):
await cls.v11(bot, group_id)
elif isinstance(bot, v12Bot):
await cls.v12(bot, group_id)
elif isinstance(bot, KaiheilaBot):
await cls.kaiheila(bot, group_id)
elif isinstance(bot, DodoBot):
await cls.dodo(bot, group_id)
elif isinstance(bot, DiscordBot):
await cls.discord(bot, group_id)
@classmethod
async def discord(cls, bot: DiscordBot, group_id: str):
# TODO: discord更新群组成员信息
pass
@classmethod
async def dodo(cls, bot: DodoBot, group_id: str):
page_size = 100
result_size = 100
max_id = 0
exist_member_list = []
group_member_list: list[MemberInfo] = []
while result_size == page_size:
group_member_data = await bot.get_member_list(
island_source_id=group_id, page_size=page_size
)
result_size = len(group_member_data.list)
group_member_list += group_member_data.list
max_id = group_member_data.max_id
if group_member_list:
for user in group_member_list:
exist_member_list.append(user.dodo_source_id)
await GroupInfoUser.update_or_create(
user_id=user.dodo_source_id,
group_id=group_id,
defaults={
"user_name": user.nick_name or user.personal_nick_name,
"user_join_time": user.join_time,
"platform": "dodo",
},
)
if delete_member_list := list(
set(exist_member_list).difference(
set(await GroupInfoUser.get_group_member_id_list(group_id))
)
):
await GroupInfoUser.filter(
user_id__in=delete_member_list, group_id=group_id
).delete()
logger.info(
f"删除已退群用户",
"更新群组成员信息",
group_id=group_id,
platform="dodo",
)
@classmethod
async def kaiheila(cls, bot: KaiheilaBot, group_id: str):
# TODO: kaiheila 更新群组成员信息
pass
@classmethod
async def v11(cls, bot: v11Bot, group_id: str):
exist_member_list = []
default_auth = Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH")
group_member_list = await bot.get_group_member_list(group_id=int(group_id))
for user_info in group_member_list:
user_id = user_info["user_id"]
nickname = user_info["card"] or user_info["nickname"]
role = user_info["role"]
if default_auth:
if role in ["owner", "admin"] and not LevelUser.is_group_flag(
str(user_id), group_id
):
await LevelUser.set_level(user_id, group_id, default_auth)
if str(user_id) in bot.config.superusers:
await LevelUser.set_level(str(user_id), group_id, 9)
join_time = datetime.strptime(
time.strftime(
"%Y-%m-%d %H:%M:%S", time.localtime(user_info["join_time"])
),
"%Y-%m-%d %H:%M:%S",
)
await GroupInfoUser.update_or_create(
user_id=str(user_id),
group_id=group_id,
defaults={
"user_name": nickname,
"user_join_time": join_time.replace(
tzinfo=timezone(timedelta(hours=8))
),
"platform": "qq",
},
)
exist_member_list.append(str(user_id))
logger.debug(
"更新成功", "更新群组成员信息", session=user_id, group_id=group_id
)
if delete_member_list := list(
set(exist_member_list).difference(
set(await GroupInfoUser.get_group_member_id_list(group_id))
)
):
await GroupInfoUser.filter(
user_id__in=delete_member_list, group_id=group_id
).delete()
logger.info(
f"删除已退群用户", "更新群组成员信息", group_id=group_id, platform="qq"
)
@classmethod
async def v12(cls, bot: v12Bot, group_id: str):
# TODO: v12更新群组成员信息
pass
# exist_member_list = []
# default_auth = Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH")
# group_member_list: list[GetGroupMemberInfoResp] = await bot.get_group_member_list(
# group_id=group_id
# )
# for user_info in group_member_list:
# user_id = user_info.user_id
# nickname = user_info.user_displayname or user_info.user_name
# role = user_info["role"]
# if default_auth:
# if role in ["owner", "admin"] and not LevelUser.is_group_flag(
# str(user_id), group_id
# ):
# await LevelUser.set_level(user_id, group_id, default_auth)
# if str(user_id) in bot.config.superusers:
# await LevelUser.set_level(str(user_id), group_id, 9)
# join_time = datetime.strptime(
# time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(user_info["join_time"])),
# "%Y-%m-%d %H:%M:%S",
# )
# await GroupInfoUser.update_or_create(
# user_id=str(user_id),
# group_id=group_id,
# defaults={
# "user_name": nickname,
# "user_join_time": join_time.replace(
# tzinfo=timezone(timedelta(hours=8))
# ),
# },
# )
# exist_member_list.append(str(user_id))
# logger.debug("更新成功", "更新群组成员信息", session=user_id, group_id=group_id)
# if delete_member_list := list(
# set(exist_member_list).difference(
# set(await GroupInfoUser.get_group_member_id_list(group_id))
# )
# ):
# await GroupInfoUser.filter(
# user_id__in=delete_member_list, group_id=group_id
# ).delete()
# logger.info(f"删除已退群用户", "更新群组成员信息", group_id=group_id)
@@ -0,0 +1,162 @@
from nonebot.adapters import Bot
from nonebot.plugin import PluginMetadata
from nonebot_plugin_alconna import (
Alconna,
Args,
Arparma,
Match,
Option,
Subcommand,
on_alconna,
store_true,
)
from nonebot_plugin_saa import Image, Text
from nonebot_plugin_session import EventSession
from requests import session
from zhenxun.configs.config import Config
from zhenxun.configs.utils import PluginExtraData, RegisterConfig
from zhenxun.services.log import logger
from zhenxun.utils.enum import BlockType, PluginType
from zhenxun.utils.rules import admin_check, ensure_group
from ._data_source import PluginManage, build_plugin, build_task
base_config = Config.get("admin_bot_manage")
__plugin_meta__ = PluginMetadata(
name="功能开关",
description="对群组内的功能限制,超级用户可以对群组以及全局的功能被动开关限制",
usage="""
开启/关闭[功能]
群被动状态
开启全部被动
关闭全部被动
醒来/休息吧
""".strip(),
extra=PluginExtraData(
author="HibiKier",
version="0.1",
plugin_type=PluginType.SUPER_AND_ADMIN,
admin_level=base_config.get("CHANGE_GROUP_SWITCH_LEVEL", 2),
configs=[
RegisterConfig(
key="CHANGE_GROUP_SWITCH_LEVEL",
value=2,
help="开关群功能权限",
default_value=2,
type=int,
)
],
).dict(),
)
_status_matcher = on_alconna(
Alconna(
"switch",
Option("-t|--task", action=store_true, help_text="被动技能"),
Subcommand(
"open",
Args["name", str],
Option(
"-g|--group",
Args["group_id", str],
),
),
Subcommand(
"close",
Args["name", str],
Option(
"-t|--type",
Args["block_type", ["all", "a", "private", "p", "group", "g"]],
),
Option(
"-g|--group",
Args["group_id", str],
),
),
),
rule=admin_check("admin_bot_manage", "CHANGE_GROUP_SWITCH_LEVEL"),
priority=5,
block=True,
)
# TODO: shortcut
_group_status_matcher = on_alconna(
Alconna("group-status", Args["status", ["sleep", "wake"]]),
rule=admin_check("admin_bot_manage", "CHANGE_GROUP_SWITCH_LEVEL") & ensure_group,
priority=5,
block=True,
)
@_status_matcher.assign("$main")
async def _(bot: Bot, session: EventSession, arparma: Arparma):
image = None
if arparma.find("task"):
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.pic2bs4()).send(reply=True)
logger.info(
f"查看{'被动' if arparma.find('task') else '功能'}列表",
arparma.header_result,
session=session,
)
@_status_matcher.assign("open")
async def _(
bot: Bot,
session: EventSession,
arparma: Arparma,
name: str,
group: Match[str],
):
if gid := session.id3 or session.id2:
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:
result = await PluginManage.superuser_block(name, None, group.result)
await Text(result).send(reply=True)
logger.info(
f"超级用户开启功能 {name}",
arparma.header_result,
session=session,
target=group.result,
)
@_status_matcher.assign("close")
async def _(
bot: Bot,
session: EventSession,
arparma: Arparma,
name: str,
block_type: Match[str],
group: Match[str],
):
if gid := session.id3 or session.id2:
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:
_type = BlockType.ALL
if block_type.available:
if block_type.result in ["p", "private"]:
_type = BlockType.FRIEND
elif block_type.result in ["g", "group"]:
_type = BlockType.GROUP
result = await PluginManage.superuser_block(name, _type, group.result)
await Text(result).send(reply=True)
logger.info(
f"超级用户关闭功能 {name}, 禁用类型: {_type}",
arparma.header_result,
session=session,
target=group.result,
)
@@ -0,0 +1,244 @@
from zhenxun.models.group_console import GroupConsole
from zhenxun.models.plugin_info import PluginInfo
from zhenxun.models.task_info import TaskInfo
from zhenxun.utils.enum import BlockType, PluginType
from zhenxun.utils.exception import GroupInfoNotFound
from zhenxun.utils.image_utils import BuildImage, ImageTemplate, RowStyle
def plugin_row_style(column: str, text: str) -> RowStyle:
"""被动技能文本风格
参数:
column: 表头
text: 文本内容
返回:
RowStyle: RowStyle
"""
style = RowStyle()
if column == "全局状态":
if text == "开启":
style.font_color = "#67C23A"
else:
style.font_color = "#F56C6C"
if column == "加载状态":
if text == "SUCCESS":
style.font_color = "#67C23A"
else:
style.font_color = "#F56C6C"
return style
async def build_plugin() -> BuildImage:
column_name = [
"ID",
"模块",
"名称",
"全局状态",
"禁用类型",
"加载状态",
"菜单分类",
"作者",
"版本",
"金币花费",
]
plugin_list = await PluginInfo.filter(plugin_type__not=PluginType.HIDDEN).all()
column_data = []
for plugin in plugin_list:
column_data.append(
[
plugin.id,
plugin.module,
plugin.name,
"开启" if plugin.status else "关闭",
plugin.block_type,
"SUCCESS" if plugin.load_status else "ERROR",
plugin.menu_type,
plugin.author,
plugin.version,
plugin.cost_gold,
]
)
return await ImageTemplate.table_page(
"Plugin",
"插件状态",
column_name,
column_data,
text_style=plugin_row_style,
)
def task_row_style(column: str, text: str) -> RowStyle:
"""被动技能文本风格
参数:
column: 表头
text: 文本内容
返回:
RowStyle: RowStyle
"""
style = RowStyle()
if column in ["群组状态", "全局状态"]:
if text == "开启":
style.font_color = "#67C23A"
else:
style.font_color = "#F56C6C"
return style
async def build_task(group_id: str | None) -> BuildImage:
"""构造被动技能状态图片
参数:
group_id: 群组id
异常:
GroupInfoNotFound: 未找到群组
返回:
BuildImage: 被动技能状态图片
"""
task_list = await TaskInfo.all()
column_name = ["ID", "模块", "名称", "群组状态", "全局状态", "运行时间"]
group = None
if group_id:
group = await GroupConsole.get_or_none(group_id=group_id)
if not group:
raise GroupInfoNotFound()
else:
column_name.remove("群组状态")
column_data = []
for task in task_list:
if group:
column_data.append(
[
task.id,
task.module,
task.name,
"开启" if task.module not in group.block_task else "关闭",
"开启" if task.status else "关闭",
task.run_time,
]
)
else:
column_data.append(
[
task.id,
task.module,
task.name,
"开启" if task.status else "关闭",
task.run_time,
]
)
return await ImageTemplate.table_page(
"Task",
"被动技能状态",
column_name,
column_data,
text_style=task_row_style,
)
class PluginManage:
@classmethod
async def block(cls, module: str):
await PluginInfo.filter(module=module).update(status=False)
@classmethod
async def unblock(cls, module: str):
await PluginInfo.filter(module=module).update(status=True)
@classmethod
async def block_group_plugin(cls, plugin_name: str, group_id: str) -> str:
"""禁用群组插件
参数:
plugin_name: 插件名称
group_id: 群组id
返回:
str: 返回信息
"""
return await cls._change_group_plugin(plugin_name, group_id, True)
@classmethod
async def unblock_group_plugin(cls, plugin_name: str, group_id: str) -> str:
"""启用群组插件
参数:
plugin_name: 插件名称
group_id: 群组id
返回:
str: 返回信息
"""
return await cls._change_group_plugin(plugin_name, group_id, False)
@classmethod
async def _change_group_plugin(
cls, plugin_name: str, group_id: str, status: bool
) -> str:
"""修改群组插件状态
参数:
plugin_name: 插件名称
group_id: 群组id
status: 插件状态
返回:
str: 返回信息
"""
status_str = "开启" if status else "关闭"
if plugin := await PluginInfo.get_or_none(name=plugin_name):
group, _ = await GroupConsole.get_or_create(group_id=group_id)
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"])
return f"已成功{status_str} {plugin_name} 功能!"
else:
if plugin.module not in group.block_plugin:
group.block_plugin += f"{plugin.module},"
await group.save(update_fields=["block_plugin"])
return f"已成功{status_str} {plugin_name} 功能!"
return f"该功能已经{status_str}了喔,不要重复{status_str}..."
return "没有找到这个功能喔..."
@classmethod
async def superuser_block(
cls, plugin_name: str, block_type: BlockType | None, group_id: str | None
) -> str:
"""超级用户禁用
参数:
plugin_name: 插件名称
block_type: 禁用类型
group_id: 群组id
返回:
str: 返回信息
"""
if plugin := await PluginInfo.get_or_none(name=plugin_name):
if group_id:
if group := await GroupConsole.get_or_none(group_id=group_id):
if f"super:{plugin_name}," not in group.block_plugin:
group.block_plugin += f"super:{plugin_name},"
await group.save(update_fields=["block_plugin"])
return (
f"已成功关闭群组 {group.group_name} 的 {plugin_name} 功能!"
)
return "此群组该功能已被超级用户关闭,不要重复关闭..."
return "群组信息未更新,请先更新群组信息..."
plugin.block_type = block_type
plugin.status = not bool(block_type)
await plugin.save(update_fields=["status", "block_type"])
if not block_type:
return f"已成功将 {plugin_name} 全局启用!"
else:
return f"已成功将 {plugin_name} 全局关闭!"
return "没有找到这个功能喔..."
@@ -1,26 +1,22 @@
import os
import shutil
from typing import Dict
from typing import Annotated, Dict
import ujson as json
from arclet.alconna import Args, Option
from nonebot import on_command
from nonebot.params import Command
from nonebot.plugin import PluginMetadata
from nonebot_plugin_alconna import (
Alconna,
AlconnaMatch,
Arparma,
Match,
on_alconna,
store_true,
)
from nonebot_plugin_alconna.matcher import AlconnaMatcher
from nonebot_plugin_saa import Text
from nonebot_plugin_alconna import Image
from nonebot_plugin_alconna import Text as alcText
from nonebot_plugin_alconna import UniMsg
from nonebot_plugin_session import EventSession
from zhenxun.configs.config import Config
from zhenxun.configs.path_config import DATA_PATH
from zhenxun.configs.utils import PluginCdBlock, PluginExtraData, RegisterConfig
from zhenxun.configs.utils import PluginExtraData, RegisterConfig
from zhenxun.services.log import logger
from zhenxun.utils.enum import PluginType
from zhenxun.utils.http_utils import AsyncHttpx
from zhenxun.utils.rules import admin_check, ensure_group
base_config = Config.get("admin_bot_manage")
@@ -48,18 +44,15 @@ __plugin_meta__ = PluginMetadata(
).dict(),
)
_matcher = on_alconna(
Alconna(
"设置欢迎消息",
Args["message", str],
Option("-at", action=store_true, help_text="是否at新入群用户"),
),
_matcher = on_command(
"设置欢迎消息",
rule=admin_check("admin_bot_manage", "SET_GROUP_WELCOME_MESSAGE_LEVEL")
& ensure_group,
priority=5,
block=True,
)
BASE_PATH = DATA_PATH / "welcome_message"
BASE_PATH.mkdir(parents=True, exist_ok=True)
@@ -86,31 +79,43 @@ if old_file.exists():
@_matcher.handle()
async def _(
session: EventSession,
matcher: AlconnaMatcher,
arparma: Arparma,
message: str,
message: UniMsg,
command: Annotated[tuple[str, ...], Command()],
):
file = (
BASE_PATH
/ f"{session.platform or session.bot_type}"
/ f"{session.id2}"
/ "text.json"
)
path = BASE_PATH / f"{session.platform or session.bot_type}" / f"{session.id2}"
if session.id3:
file = (
path = (
BASE_PATH
/ f"{session.platform or session.bot_type}"
/ f"{session.id3}"
/ f"{session.id2}"
/ "text.json"
)
file = path / "text.json"
idx = 0
text = ""
for f in os.listdir(path):
(path / f).unlink()
message[0].text = message[0].text.replace(command[0], "").strip()
for msg in message:
if isinstance(msg, alcText):
text += msg.text
elif isinstance(msg, Image):
if msg.url:
text += f"[image:{idx}]"
await AsyncHttpx.download_file(msg.url, path / f"{idx}.png")
idx += 1
else:
logger.debug("图片 URL 为空...", command[0])
if not file.exists():
file.parent.mkdir(exist_ok=True, parents=True)
is_at = "-at" in message
text = text.replace("-at", "")
json.dump(
{"at": arparma.find("at"), "message": message},
{"at": is_at, "message": text},
file.open("w"),
ensure_ascii=False,
indent=4,
)
logger.info(f"设置群欢迎消息成功: {message}", arparma.header_result, session=session)
await Text(f"设置欢迎消息成功: \n{message}").send()
uni_msg = alcText("设置欢迎消息成功: \n") + message
await uni_msg.send()
logger.info(f"设置群欢迎消息成功: {text}", command[0], session=session)