版本更新 (#1666)

* ✨ 父级插件加载

* ✅ 添加测试:更新与添加插件 (#1594)

* ✅ 测试更新与添加插件

* ✅ Sourcery建议

* 👷 添加pytest

* 🎨 优化代码

* 🐛 bug修复

* 🐛修复添加插件返回403的问题 (#1595)

* 完善测试方法
* vscode测试配置
* 重构插件安装过程

* 🎨 修改readme

* Update README.md

* 🐛 修改bug与版本锁定

* 🐛 修复超级用户对群组功能开关

* 🐛 修复插件商店检查插件更新问题 (#1597)

* 🐛 修复插件商店检查插件更新问题

* 🐛 恶意命令检测问题

* 🐛 增加插件状态检查 (#1598)

* ✅ 优化测试用例

* 🐛 更改插件更新与安装逻辑

* 🐛 修复更新群组成员信息

* 🎨 代码优化

* 🚀 更新Dockerfile (#1599)

* 🎨 更新requirements

* ➕ 添加依赖aiocache

* ⚡ 添加github镜像

* ✨ 添加仓库目录多获取渠道

* 🐛 修复测试用例

* ✨ 添加API缓存

* 🎨 采取Sourcery建议

* 🐛 文件下载逻辑修改

* 🎨 优化代码

* 🐛 修复插件开关有时出现错误

* ✨ 重构自检ui

* 🐛 自检html修正

* 修复签到逻辑bug,并使代码更灵活以适应签到好感度等级配置 (#1606)

* 修复签到功能已知问题

* 修复签到功能已知问题

* 修改参数名称

* 修改uid判断

---------

Co-authored-by: HibiKier <45528451+HibiKier@users.noreply.github.com>

* 🎨 代码结构优化

* 🐛 私聊时修改插件时删除私聊帮助

* 🐛 过滤父插件

* 🐛 修复自检在ARM上的问题 (#1607)

* 🐛 修复自检在ARM上的问题

* ✅ 优化测试

* ✨ 支持mysql,psql,sqlite随机函数

* 🔧 VSCode配置修改

* 🔧 VSCode配置修改

* ✨ 添加金币排行

Co-Authored-By: HibiKier <45528451+HibiKier@users.noreply.github.com>

* 📝 修改README

Co-Authored-By: HibiKier <45528451+HibiKier@users.noreply.github.com>

* 🔨 提取GitHub相关操作 (#1609)

* 🔨 提取GitHub相关操作

* 🔨 重构API策略

* ✨ 签到/金币排行限制最大数量 (#1616)

* ✨ 签到/金币排行限制最大数量

* 🐛 修复超级用户id获取问题

* 🐛 修复路径解压与挂载 (#1619)

* 🐛 修复功能少时zhenxun帮助图片排序问题 (#1620)

* 🐛 签到文本适应 (#1622)

* 🐛 好感度排行提供默认值 (#1624)

* 🎈 优先使用github api (#1625)

* ✨ 重构帮助,限制普通用户查询管理插件 (#1626)

* 🐛 修复群权限与插件等级匹配 (#1627)

* ✨ 当管理员尝试ban真寻时将被反杀 (#1628)

* ✨ 群组发言时间检测提供开关配置 (#1630)

* 🐳 chore: 支持自动修改版本号 (#1629)

* 🎈 perf(github_utils): 支持github url下载遍历 (#1632)

* 🎈 perf(github_utils): 支持github url下载遍历

* 🐞 fix(http_utils): 修复一些下载问题

* 🦄 refactor(http_utils): 部分重构

* chore(version): Update version to v0.2.2-e6f17c4

---------

Co-authored-by: AkashiCoin <AkashiCoin@users.noreply.github.com>

* 🧪 test(auto_update): 修复测试用例 (#1633)

* 🐛 修复商店商品为空时报错 (#1634)

* 🐛 修复群权限与插件等级匹配 (#1635)

* ✨ message_build支持AtAll (#1639)

* 🎈 perf: 使用commit号下载插件 (#1641)

* 🎈 perf: 使用commit号下载插件

* chore(version): Update version to v0.2.2-f9c7360

---------

Co-authored-by: AkashiCoin <AkashiCoin@users.noreply.github.com>

* 🐳 chore: 修改运行检查触发路径 (#1642)

* 🐳 chore: 修改运行检查触发路径

* 🐳 chore: 添加tests目录

* ✨ 重构qq群事件处理 (#1643)

* 🐛 签到名称自适应 (#1644)

* 🎨  更新README (#1645)

* 🐛 fix(http_utils): 流式下载Content-Length错误 (#1647)

* 🐛 修复群组中帮助功能状态显示问题 (#1650)

* 🐛 修复群欢迎消息设置 (#1651)

* 🐛 修复webui下载后首次启动错误 (#1652)

* 🐛 修复webui下载后首次启动错误

* chore(version): Update version to v0.2.2-4a8ef85

---------

Co-authored-by: HibiKier <HibiKier@users.noreply.github.com>

* ✨ 移除默认图片文件夹:爬 (#1653)

* ✨ 安装/移除插件提供插件安装/卸载方法用于插件初始化 (#1654)

* ✨ 新增超级用户与管理员帮助模板 (#1655)

* ✨ 新增个人信息命令 (#1657)

* ✨ 修改个人信息菜单名称 (#1658)

* ✨ 新增插件商店api (#1659)

* ✨ 新增插件商店api

* chore(version): Update version to v0.2.2-7e15f20

---------

Co-authored-by: HibiKier <HibiKier@users.noreply.github.com>

* ✨ 将cd,block,count限制复原配置文件 (#1662)

* 🎨 修改README (#1663)

* 🎨 修改版本号 (#1664)

* 🎨 修改requirements (#1665)

---------

Co-authored-by: AkashiCoin <l1040186796@gmail.com>
Co-authored-by: fanyinrumeng <42991257+fanyinrumeng@users.noreply.github.com>
Co-authored-by: AkashiCoin <i@loli.vet>
Co-authored-by: Elaga <1728903318@qq.com>
Co-authored-by: AkashiCoin <AkashiCoin@users.noreply.github.com>
Co-authored-by: HibiKier <HibiKier@users.noreply.github.com>
This commit is contained in:
HibiKier
2024-10-01 00:42:23 +08:00
committed by GitHub
co-authored by AkashiCoin HibiKier AkashiCoin fanyinrumeng AkashiCoin Elaga
parent daa40ae8b8
commit 4e33bf3a50
216 changed files with 10281 additions and 2538 deletions
-160
View File
@@ -1,160 +0,0 @@
import nonebot
from nonebot.plugin import PluginMetadata
from nonebot_plugin_alconna import Alconna, Arparma, on_alconna
from nonebot_plugin_alconna.matcher import AlconnaMatcher
from nonebot_plugin_session import EventSession
from zhenxun.configs.path_config import IMAGE_PATH
from zhenxun.configs.utils import PluginExtraData
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.message import MessageUtils
from zhenxun.utils.rules import admin_check, ensure_group
__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,
arparma: Arparma,
):
if not ADMIN_HELP_IMAGE.exists():
try:
await build_help()
except EmptyError:
await MessageUtils.build_message("管理员帮助为空").finish(reply_to=True)
await MessageUtils.build_message(ADMIN_HELP_IMAGE).send()
logger.info("查看管理员帮助", arparma.header_result, session=session)
@@ -0,0 +1,63 @@
from nonebot.plugin import PluginMetadata
from nonebot_plugin_session import EventSession
from nonebot_plugin_alconna import Alconna, Arparma, on_alconna
from zhenxun.services.log import logger
from zhenxun.configs.config import Config
from zhenxun.utils.enum import PluginType
from zhenxun.utils.exception import EmptyError
from zhenxun.utils.message import MessageUtils
from zhenxun.utils.rules import admin_check, ensure_group
from zhenxun.configs.utils import RegisterConfig, PluginExtraData
from .normal_help import build_help
from .config import ADMIN_HELP_IMAGE
from .html_help import build_html_help
__plugin_meta__ = PluginMetadata(
name="群组管理员帮助",
description="管理员帮助列表",
usage="""
管理员帮助
""".strip(),
extra=PluginExtraData(
author="HibiKier",
version="0.1",
plugin_type=PluginType.ADMIN,
admin_level=1,
configs=[
RegisterConfig(
key="type",
value="zhenxun",
help="管理员帮助样式,normal, zhenxun",
default_value="zhenxun",
)
],
).dict(),
)
_matcher = on_alconna(
Alconna("管理员帮助"),
rule=admin_check(1) & ensure_group,
priority=5,
block=True,
)
@_matcher.handle()
async def _(
session: EventSession,
arparma: Arparma,
):
if not ADMIN_HELP_IMAGE.exists():
try:
if Config.get_config("admin_help", "type") == "zhenxun":
await build_html_help()
else:
await build_help()
except EmptyError:
await MessageUtils.build_message("当前管理员帮助为空...").finish(
reply_to=True
)
await MessageUtils.build_message(ADMIN_HELP_IMAGE).send()
logger.info("查看管理员帮助", arparma.header_result, session=session)
@@ -0,0 +1,23 @@
from pydantic import BaseModel
from nonebot.plugin import PluginMetadata
from zhenxun.models.plugin_info import PluginInfo
from zhenxun.configs.path_config import IMAGE_PATH
ADMIN_HELP_IMAGE = IMAGE_PATH / "ADMIN_HELP.png"
if ADMIN_HELP_IMAGE.exists():
ADMIN_HELP_IMAGE.unlink()
class PluginData(BaseModel):
"""
插件信息
"""
plugin: PluginInfo
"""插件信息"""
metadata: PluginMetadata
"""元数据"""
class Config:
arbitrary_types_allowed = True
@@ -0,0 +1,55 @@
from nonebot_plugin_htmlrender import template_to_pic
from zhenxun.configs.config import BotConfig
from zhenxun.models.task_info import TaskInfo
from zhenxun.utils._build_image import BuildImage
from zhenxun.configs.path_config import TEMPLATE_PATH
from zhenxun.builtin_plugins.admin.admin_help.config import ADMIN_HELP_IMAGE
from .utils import get_plugins
async def get_task() -> dict[str, str] | None:
"""获取被动技能帮助"""
if task_list := await TaskInfo.all():
return {
"name": "被动技能",
"description": "控制群组中的被动技能状态",
"usage": "通过 开启/关闭群被动 来控制群被<br>----------<br>"
+ "<br>".join([task.name for task in task_list]),
}
return None
async def build_html_help():
"""构建帮助图片"""
plugins = await get_plugins()
plugin_list = [
{
"name": data.plugin.name,
"description": data.metadata.description.replace("\n", "<br>"),
"usage": data.metadata.usage.replace("\n", "<br>"),
}
for data in plugins
]
if task := await get_task():
plugin_list.append(task)
plugin_list.sort(key=lambda p: len(p["description"]) + len(p["usage"]))
pic = await template_to_pic(
template_path=str((TEMPLATE_PATH / "help").absolute()),
template_name="main.html",
templates={
"data": {
"plugin_list": plugin_list,
"nickname": BotConfig.self_nickname,
"help_name": "群管理员",
}
},
pages={
"viewport": {"width": 1024, "height": 1024},
"base_url": f"file://{TEMPLATE_PATH}",
},
wait=2,
)
result = await BuildImage.open(pic).resize(0.5)
await result.save(ADMIN_HELP_IMAGE)
@@ -0,0 +1,127 @@
from PIL.ImageFont import FreeTypeFont
from nonebot.plugin import PluginMetadata
from zhenxun.services.log import logger
from zhenxun.models.task_info import TaskInfo
from zhenxun.models.plugin_info import PluginInfo
from zhenxun.utils._build_image import BuildImage
from zhenxun.utils.image_utils import text2image, group_image, build_sort_image
from .utils import get_plugins
from .config import ADMIN_HELP_IMAGE
async def build_usage_des_image(
metadata: PluginMetadata,
) -> tuple[BuildImage | None, BuildImage | None]:
"""构建用法和描述图片
参数:
metadata: PluginMetadata
返回:
tuple[BuildImage | None, BuildImage | None]: 用法和描述图片
"""
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),
)
return usage, description
async def build_image(
plugin: PluginInfo, metadata: PluginMetadata, font: FreeTypeFont
) -> BuildImage:
"""构建帮助图片
参数:
plugin: PluginInfo
metadata: PluginMetadata
font: FreeTypeFont
返回:
BuildImage: 帮助图片
"""
usage, description = await build_usage_des_image(metadata)
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, _ = BuildImage.get_text_size(f"{plugin.name}[{plugin.level}]", font)
if font_width > width:
width = font_width
A = BuildImage(width + 30, height + 120, "#EAEDF2")
await A.text((15, 10), f"{plugin.name}[{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)
return A
async def build_help():
"""构造管理员帮助图片
返回:
BuildImage: 管理员帮助图片
"""
font = BuildImage.load_font("HYWenHei-85W.ttf", 20)
image_list = []
for data in await get_plugins():
plugin = data.plugin
metadata = data.metadata
try:
A = await build_image(plugin, metadata, font)
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)
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)
@@ -0,0 +1,22 @@
import nonebot
from zhenxun.utils.enum import PluginType
from zhenxun.utils.exception import EmptyError
from zhenxun.models.plugin_info import PluginInfo
from .config import PluginData
async def get_plugins() -> list[PluginData]:
"""获取插件数据"""
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(PluginData(plugin=plugin, metadata=_plugin.metadata))
if not data_list:
raise EmptyError()
return data_list
+54 -22
View File
@@ -2,23 +2,23 @@ from arclet.alconna import Args
from nonebot.adapters import Bot
from nonebot.permission import SUPERUSER
from nonebot.plugin import PluginMetadata
from nonebot_plugin_session import EventSession
from nonebot_plugin_alconna import (
Alconna,
Arparma,
At,
Match,
Option,
Alconna,
Arparma,
on_alconna,
store_true,
)
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.message import MessageUtils
from zhenxun.utils.rules import admin_check
from zhenxun.utils.message import MessageUtils
from zhenxun.configs.config import Config, BotConfig
from zhenxun.configs.utils import RegisterConfig, PluginExtraData
from ._data_source import BanManage
@@ -160,7 +160,9 @@ async def _(
duration: Match[int],
group_id: Match[str],
):
user_id = None
user_id = ""
if not session.id1:
await MessageUtils.build_message("用户id为空...").finish(reply_to=True)
if user.available:
if isinstance(user.result, At):
user_id = user.result.target
@@ -169,14 +171,35 @@ async def _(
await MessageUtils.build_message("权限不足捏...").finish(reply_to=True)
user_id = user.result
_duration = duration.result * 60 if duration.available else -1
_duration_text = f"{duration.result} 分钟" if duration.available else " 到世界湮灭"
if (gid := session.id3 or session.id2) and not group_id.available:
if group_id.available:
gid = group_id.result
if (
not user_id
or user_id == bot.self_id
and session.id1 not in bot.config.superusers
):
_duration = 0.5
await MessageUtils.build_message("倒反天罡,小小管理速速退下!").send()
await BanManage.ban(session.id1, gid, 30, session, True)
_duration_text = "半 分钟"
logger.info(
f"尝试ban {BotConfig.self_nickname} 反被拿下",
arparma.header_result,
session=session,
)
await MessageUtils.build_message(
[
"对 ",
At(flag="user", target=session.id1),
" 狠狠惩戒了一番,一脚踢进了小黑屋!"
f" 在里面乖乖呆 {_duration_text}吧!",
]
).finish(reply_to=True)
await BanManage.ban(
user_id, gid, _duration, session, session.id1 in bot.config.superusers
)
logger.info(
f"管理员Ban",
"管理员Ban",
arparma.header_result,
session=session,
target=f"{gid}:{user_id}",
@@ -184,20 +207,25 @@ async def _(
await MessageUtils.build_message(
[
"对 ",
At(flag="user", target=user_id) if isinstance(user.result, At) else user_id, # type: ignore
f" 狠狠惩戒了一番,一脚踢进了小黑屋!",
(
At(flag="user", target=user_id)
if isinstance(user.result, At)
else user_id
), # type: ignore
" 狠狠惩戒了一番,一脚踢进了小黑屋!",
f" 在里面乖乖呆 {_duration_text} 吧!",
]
).finish(reply_to=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",
"超级用户Ban",
arparma.header_result,
session=session,
target=f"{_group_id}:{user_id}",
)
at_msg = user_id if user_id else f"群组:{_group_id}"
at_msg = user_id or f"群组:{_group_id}"
await MessageUtils.build_message(
f"对 {at_msg} 狠狠惩戒了一番,一脚踢进了小黑屋!"
).finish(reply_to=True)
@@ -211,7 +239,7 @@ async def _(
user: Match[str | At],
group_id: Match[str],
):
user_id = None
user_id = ""
if user.available:
if isinstance(user.result, At):
user_id = user.result.target
@@ -228,7 +256,7 @@ async def _(
user_id, gid, session, session.id1 in bot.config.superusers
):
logger.info(
f"管理员UnBan",
"管理员UnBan",
arparma.header_result,
session=session,
target=f"{gid}:{user_id}",
@@ -236,28 +264,32 @@ async def _(
await MessageUtils.build_message(
[
"将 ",
At(flag="user", target=user_id) if isinstance(user.result, At) else u_d, # type: ignore
f" 从黑屋中拉了出来并急救了一下!",
(
At(flag="user", target=user_id)
if isinstance(user.result, At)
else u_d
), # type: ignore
" 从黑屋中拉了出来并急救了一下!",
]
).finish(reply_to=True)
else:
await MessageUtils.build_message(f"该用户不在黑名单中捏...").finish(
await MessageUtils.build_message("该用户不在黑名单中捏...").finish(
reply_to=True
)
elif session.id1 in bot.config.superusers:
_group_id = group_id.result if group_id.available else None
if await BanManage.unban(user_id, _group_id, session, True):
logger.info(
f"超级用户UnBan",
"超级用户UnBan",
arparma.header_result,
session=session,
target=f"{_group_id}:{user_id}",
)
at_msg = user_id if user_id else f"群组:{_group_id}"
at_msg = user_id or f"群组:{_group_id}"
await MessageUtils.build_message(
f"对 {at_msg} 从黑屋中拉了出来并急救了一下!"
).finish(reply_to=True)
else:
await MessageUtils.build_message(f"该用户不在黑名单中捏...").finish(
await MessageUtils.build_message("该用户不在黑名单中捏...").finish(
reply_to=True
)
@@ -3,13 +3,12 @@ from typing import Literal
from nonebot_plugin_session import EventSession
from zhenxun.models.ban_console import BanConsole
from zhenxun.models.level_user import LevelUser
from zhenxun.models.ban_console import BanConsole
from zhenxun.utils.image_utils import BuildImage, ImageTemplate
class BanManage:
@classmethod
async def build_ban_image(
cls,
@@ -19,6 +19,10 @@ class MemberUpdateManage:
@classmethod
async def update(cls, bot: Bot, group_id: str):
if not group_id:
return logger.warning(
f"bot: {bot.self_id},group_id为空,无法更新群成员信息..."
)
if isinstance(bot, v11Bot):
await cls.v11(bot, group_id)
elif isinstance(bot, v12Bot):
@@ -145,14 +149,18 @@ class MemberUpdateManage:
if delete_list:
await GroupInfoUser.filter(id__in=delete_list).delete()
logger.debug(f"删除重复数据 Ids: {delete_list}", "更新群组成员信息")
if delete_member_list := list(
set(exist_member_list).difference(set(db_user_uid))
):
if delete_member_list := [
uid for uid in db_user_uid if uid not in exist_member_list
]:
await GroupInfoUser.filter(
user_id__in=delete_member_list, group_id=group_id
).delete()
logger.info(
"删除已退群用户", "更新群组成员信息", group_id=group_id, platform="qq"
f"删除已退群用户 {len(delete_member_list)} 条",
"更新群组成员信息",
group_id=group_id,
platform="qq",
)
@classmethod
@@ -1,16 +1,16 @@
from nonebot.adapters import Bot
from nonebot.plugin import PluginMetadata
from nonebot_plugin_alconna import AlconnaQuery, Arparma, Match, Query
from nonebot_plugin_session import EventSession
from nonebot_plugin_alconna import Match, Query, Arparma, AlconnaQuery
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.configs.config import Config
from zhenxun.utils.message import MessageUtils
from zhenxun.utils.enum import BlockType, PluginType
from zhenxun.configs.utils import RegisterConfig, PluginExtraData
from ._data_source import PluginManage, build_plugin, build_task
from .command import _group_status_matcher, _status_matcher
from .command import _status_matcher, _group_status_matcher
from ._data_source import PluginManage, build_task, build_plugin, delete_help_image
base_config = Config.get("plugin_switch")
@@ -40,36 +40,35 @@ __plugin_meta__ = PluginMetadata(
version="0.1",
plugin_type=PluginType.SUPER_AND_ADMIN,
superuser_help="""
超级管理员额外命令
格式:
插件列表
开启/关闭[功能名称] ?[-t ["private", "p", "group", "g"](关闭类型)] ?[-g 群组Id]
格式:
插件列表
开启/关闭[功能名称] ?[-t ["private", "p", "group", "g"](关闭类型)] ?[-g 群组Id]
开启/关闭插件df[功能名称]: 开启/关闭指定插件进群默认状态
开启/关闭所有插件df: 开启/关闭所有插件进群默认状态
开启/关闭所有插件:
私聊中: 开启/关闭所有插件全局状态
群组中: 开启/关闭当前群组所有插件状态
开启/关闭插件df[功能名称]: 开启/关闭指定插件进群默认状态
开启/关闭所有插件df: 开启/关闭所有插件进群默认状态
开启/关闭所有插件:
私聊中: 开启/关闭所有插件全局状态
群组中: 开启/关闭当前群组所有插件状态
开启/关闭群被动[name] ?[-g [group_id]]
私聊中: 开启/关闭全局指定的被动状态
群组中: 开启/关闭当前群组指定的被动状态
示例:
关闭群被动早晚安
关闭群被动早晚安 -g 12355555
开启/关闭群被动[name] ?[-g [group_id]]
私聊中: 开启/关闭全局指定的被动状态
群组中: 开启/关闭当前群组指定的被动状态
示例:
关闭群被动早晚安
关闭群被动早晚安 -g 12355555
开启/关闭所有群被动 ?[-g [group_id]]
私聊中: 开启/关闭全局或指定群组被动状态
示例:
开启所有群被动: 开启全局所有被动
开启所有群被动 -g 12345678: 开启群组12345678所有被动
开启/关闭所有群被动 ?[-g [group_id]]
私聊中: 开启/关闭全局或指定群组被动状态
示例:
开启所有群被动: 开启全局所有被动
开启所有群被动 -g 12345678: 开启群组12345678所有被动
私聊下:
示例:
开启签到 : 全局开启签到
关闭签到 : 全局关闭签到
关闭签到 p : 全局私聊关闭签到
关闭签到 -g 12345678 : 关闭群组12345678的签到功能(普通管理员无法开启)
私聊下:
示例:
开启签到 : 全局开启签到
关闭签到 : 全局关闭签到
关闭签到 p : 全局私聊关闭签到
关闭签到 -g 12345678 : 关闭群组12345678的签到功能(普通管理员无法开启)
""",
admin_level=base_config.get("CHANGE_GROUP_SWITCH_LEVEL", 2),
configs=[
@@ -94,7 +93,7 @@ async def _(
if session.id1 in bot.config.superusers:
image = await build_plugin()
logger.info(
f"查看功能列表",
"查看功能列表",
arparma.header_result,
session=session,
)
@@ -117,43 +116,39 @@ async def _(
if not all.result and not plugin_name.available:
await MessageUtils.build_message("请输入功能名称").finish(reply_to=True)
name = plugin_name.result
gid = session.id3 or session.id2
if gid:
if gid := session.id3 or session.id2:
"""修改当前群组的数据"""
if task.result:
if all.result:
result = await PluginManage.unblock_group_all_task(gid)
logger.info(f"开启所有群组被动", arparma.header_result, session=session)
logger.info("开启所有群组被动", arparma.header_result, session=session)
else:
result = await PluginManage.unblock_group_task(name, gid)
logger.info(
f"开启群组被动 {name}", arparma.header_result, session=session
)
elif session.id1 in bot.config.superusers and default_status.result:
"""单个插件的进群默认修改"""
result = await PluginManage.set_default_status(name, True)
logger.info(
f"超级用户开启 {name} 功能进群默认开关",
arparma.header_result,
session=session,
)
elif all.result:
"""所有插件"""
result = await PluginManage.set_all_plugin_status(
True, default_status.result, gid
)
logger.info(
"开启群组中全部功能",
arparma.header_result,
session=session,
)
else:
if session.id1 in bot.config.superusers and default_status.result:
"""单个插件的进群默认修改"""
result = await PluginManage.set_default_status(name, True)
logger.info(
f"超级用户开启 {name} 功能进群默认开关",
arparma.header_result,
session=session,
)
else:
if all.result:
"""所有插件"""
result = await PluginManage.set_all_plugin_status(
True, default_status.result, gid
)
logger.info(
f"开启群组中全部功能",
arparma.header_result,
session=session,
)
else:
result = await PluginManage.unblock_group_plugin(name, gid)
logger.info(
f"开启功能 {name}", arparma.header_result, session=session
)
result = await PluginManage.unblock_group_plugin(name, gid)
logger.info(f"开启功能 {name}", arparma.header_result, session=session)
delete_help_image(gid)
await MessageUtils.build_message(result).finish(reply_to=True)
elif session.id1 in bot.config.superusers:
"""私聊"""
@@ -170,7 +165,8 @@ async def _(
True, default_status.result, group_id
)
logger.info(
f"超级用户开启全部功能全局开关 {f'指定群组: {group_id}' if group_id else ''}",
"超级用户开启全部功能全局开关"
f" {f'指定群组: {group_id}' if group_id else ''}",
arparma.header_result,
session=session,
)
@@ -204,16 +200,16 @@ async def _(
arparma.header_result,
session=session,
)
await MessageUtils.build_message(result).finish(reply_to=True)
else:
result = await PluginManage.superuser_block(name, None, group_id)
result = await PluginManage.superuser_unblock(name, None, group_id)
logger.info(
f"超级用户开启功能 {name}",
arparma.header_result,
session=session,
target=group_id,
)
await MessageUtils.build_message(result).finish(reply_to=True)
delete_help_image()
await MessageUtils.build_message(result).finish(reply_to=True)
@_status_matcher.assign("close")
@@ -231,43 +227,35 @@ async def _(
if not all.result and not plugin_name.available:
await MessageUtils.build_message("请输入功能名称").finish(reply_to=True)
name = plugin_name.result
gid = session.id3 or session.id2
if gid:
if gid := session.id3 or session.id2:
"""修改当前群组的数据"""
if task.result:
if all.result:
result = await PluginManage.block_group_all_task(gid)
logger.info(f"开启所有群组被动", arparma.header_result, session=session)
logger.info("开启所有群组被动", arparma.header_result, session=session)
else:
result = await PluginManage.block_group_task(name, gid)
logger.info(
f"关闭群组被动 {name}", arparma.header_result, session=session
)
elif session.id1 in bot.config.superusers and default_status.result:
"""单个插件的进群默认修改"""
result = await PluginManage.set_default_status(name, False)
logger.info(
f"超级用户开启 {name} 功能进群默认开关",
arparma.header_result,
session=session,
)
elif all.result:
"""所有插件"""
result = await PluginManage.set_all_plugin_status(
False, default_status.result, gid
)
logger.info("关闭群组中全部功能", arparma.header_result, session=session)
else:
if session.id1 in bot.config.superusers and default_status.result:
"""单个插件的进群默认修改"""
result = await PluginManage.set_default_status(name, False)
logger.info(
f"超级用户开启 {name} 功能进群默认开关",
arparma.header_result,
session=session,
)
else:
if all.result:
"""所有插件"""
result = await PluginManage.set_all_plugin_status(
False, default_status.result, gid
)
logger.info(
f"关闭群组中全部功能",
arparma.header_result,
session=session,
)
else:
result = await PluginManage.block_group_plugin(name, gid)
logger.info(
f"关闭功能 {name}", arparma.header_result, session=session
)
result = await PluginManage.block_group_plugin(name, gid)
logger.info(f"关闭功能 {name}", arparma.header_result, session=session)
delete_help_image(gid)
await MessageUtils.build_message(result).finish(reply_to=True)
elif session.id1 in bot.config.superusers:
group_id = group.result if group.available else None
@@ -283,7 +271,8 @@ async def _(
False, default_status.result, group_id
)
logger.info(
f"超级用户关闭全部功能全局开关 {f'指定群组: {group_id}' if group_id else ''}",
"超级用户关闭全部功能全局开关"
f" {f'指定群组: {group_id}' if group_id else ''}",
arparma.header_result,
session=session,
)
@@ -317,13 +306,13 @@ async def _(
arparma.header_result,
session=session,
)
await MessageUtils.build_message(result).finish(reply_to=True)
else:
_type = BlockType.ALL
if block_type.available:
if block_type.result in ["p", "private"]:
if block_type.result in ["p", "private"]:
if block_type.available:
_type = BlockType.PRIVATE
elif block_type.result in ["g", "group"]:
elif block_type.result in ["g", "group"]:
if block_type.available:
_type = BlockType.GROUP
result = await PluginManage.superuser_block(name, _type, group_id)
logger.info(
@@ -332,7 +321,8 @@ async def _(
session=session,
target=group_id,
)
await MessageUtils.build_message(result).finish(reply_to=True)
delete_help_image()
await MessageUtils.build_message(result).finish(reply_to=True)
@_group_status_matcher.handle()
@@ -362,11 +352,7 @@ async def _(
):
image = await build_task(session.id3 or session.id2)
if image:
logger.info(
f"查看群被动列表",
arparma.header_result,
session=session,
)
logger.info("查看群被动列表", arparma.header_result, session=session)
await MessageUtils.build_message(image).finish(reply_to=True)
else:
await MessageUtils.build_message("获取群被动任务失败...").finish(reply_to=True)
@@ -1,9 +1,27 @@
from zhenxun.models.group_console import GroupConsole
from zhenxun.models.plugin_info import PluginInfo
from zhenxun.models.task_info import TaskInfo
from zhenxun.models.plugin_info import PluginInfo
from zhenxun.utils.enum import BlockType, PluginType
from zhenxun.models.group_console import GroupConsole
from zhenxun.utils.exception import GroupInfoNotFound
from zhenxun.utils.image_utils import BuildImage, ImageTemplate, RowStyle
from zhenxun.configs.path_config import DATA_PATH, IMAGE_PATH
from zhenxun.utils.image_utils import RowStyle, BuildImage, ImageTemplate
HELP_FILE = IMAGE_PATH / "SIMPLE_HELP.png"
GROUP_HELP_PATH = DATA_PATH / "group_help"
def delete_help_image(gid: str | None = None):
"""删除帮助图片"""
if gid:
file = GROUP_HELP_PATH / f"{gid}.png"
if file.exists():
file.unlink()
else:
if HELP_FILE.exists():
HELP_FILE.unlink()
for file in GROUP_HELP_PATH.iterdir():
file.unlink()
def plugin_row_style(column: str, text: str) -> RowStyle:
@@ -17,16 +35,16 @@ def plugin_row_style(column: str, text: str) -> RowStyle:
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"
if (
column == "全局状态"
and text == "开启"
or column != "全局状态"
and column == "加载状态"
and text == "SUCCESS"
):
style.font_color = "#67C23A"
elif column in {"全局状态", "加载状态"}:
style.font_color = "#F56C6C"
return style
@@ -44,22 +62,21 @@ async def build_plugin() -> BuildImage:
"金币花费",
]
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,
]
)
column_data = [
[
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,
]
for plugin in plugin_list
]
return await ImageTemplate.table_page(
"Plugin",
"插件状态",
@@ -80,11 +97,8 @@ def task_row_style(column: str, text: str) -> RowStyle:
RowStyle: RowStyle
"""
style = RowStyle()
if column in ["群组状态", "全局状态"]:
if text == "开启":
style.font_color = "#67C23A"
else:
style.font_color = "#F56C6C"
if column in {"群组状态", "全局状态"}:
style.font_color = "#67C23A" if text == "开启" else "#F56C6C"
return style
@@ -144,7 +158,6 @@ async def build_task(group_id: str | None) -> BuildImage:
class PluginManage:
@classmethod
async def set_default_status(cls, plugin_name: str, status: bool) -> str:
"""设置插件进群默认状态
@@ -159,12 +172,15 @@ class PluginManage:
if plugin_name.isdigit():
plugin = await PluginInfo.get_or_none(id=int(plugin_name))
else:
plugin = await PluginInfo.get_or_none(name=plugin_name)
plugin = await PluginInfo.get_or_none(
name=plugin_name, load_status=True, plugin_type__not=PluginType.PARENT
)
if plugin:
plugin.default_status = status
await plugin.save(update_fields=["default_status"])
return f'成功将 {plugin.name} 进群默认状态修改为: {"开启" if status else "关闭"}'
return f"没有找到这个功能喔..."
status_text = "开启" if status else "关闭"
return f"成功将 {plugin.name} 进群默认状态修改为: {status_text}"
return "没有找到这个功能喔..."
@classmethod
async def set_all_plugin_status(
@@ -206,7 +222,7 @@ class PluginManage:
return f'成功将此群组所有功能状态修改为: {"开启" if status else "关闭"}'
return "获取群组失败..."
await PluginInfo.filter(plugin_type=PluginType.NORMAL).update(
status=status, block_type=BlockType.ALL if not status else None
status=status, block_type=None if status else BlockType.ALL
)
return f'成功将所有功能全局状态修改为: {"开启" if status else "关闭"}'
@@ -417,19 +433,18 @@ class PluginManage:
group.block_task = group.block_task.replace(f"{module},", "")
await group.save(update_fields=["block_task"])
return f"已成功{status_str}全部被动技能!"
else:
if 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},"
else:
if f"super:{task.module}," in group.block_task:
return f"{status_str} {task_name} 被动技能失败,当前群组该被动已被管理员禁用"
group.block_task = group.block_task.replace(f"{task.module},", "")
await group.save(update_fields=["block_task"])
return f"已成功{status_str} {task_name} 被动技能!"
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:
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"])
return f"已成功{status_str} {task_name} 被动技能!"
return "没有找到这个被动技能喔..."
@classmethod
@@ -450,12 +465,14 @@ class PluginManage:
if plugin_name.isdigit():
plugin = await PluginInfo.get_or_none(id=int(plugin_name))
else:
plugin = await PluginInfo.get_or_none(name=plugin_name)
status_str = "开启" if status else "关闭"
plugin = await PluginInfo.get_or_none(
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(
@@ -463,11 +480,10 @@ class PluginManage:
)
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} 功能!"
elif 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 "没有找到这个功能喔..."
@@ -485,22 +501,20 @@ class PluginManage:
返回:
str: 返回信息
"""
if task := await TaskInfo.get_or_none(name=task_name):
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},", "")
else:
group.block_task += f"super:{task.module},"
await group.save(update_fields=["block_task"])
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"])
return f"已成功将群组 {group_id} 被动技能 {task_name} {status_str}!"
return "没有找到这个群组喔..."
return "没有找到这个功能喔..."
return f"已成功将群组 {group_id} 被动技能 {task_name} {status_str}!"
return "没有找到这个群组喔..."
@classmethod
async def superuser_block(
@@ -519,7 +533,9 @@ class PluginManage:
if plugin_name.isdigit():
plugin = await PluginInfo.get_or_none(id=int(plugin_name))
else:
plugin = await PluginInfo.get_or_none(name=plugin_name)
plugin = await PluginInfo.get_or_none(
name=plugin_name, load_status=True, plugin_type__not=PluginType.PARENT
)
if plugin:
if group_id:
if group := await GroupConsole.get_or_none(
@@ -538,11 +554,58 @@ class PluginManage:
await plugin.save(update_fields=["status", "block_type"])
if not block_type:
return f"已成功将 {plugin.name} 全局启用!"
else:
if block_type == BlockType.ALL:
return f"已成功将 {plugin.name} 全局关闭!"
if block_type == BlockType.GROUP:
return f"已成功将 {plugin.name} 全局群组关闭!"
if block_type == BlockType.PRIVATE:
return f"已成功将 {plugin.name} 全局私聊关闭!"
if block_type == BlockType.ALL:
return f"已成功将 {plugin.name} 全局关闭!"
if block_type == BlockType.GROUP:
return f"已成功将 {plugin.name} 全局群组关闭!"
if block_type == BlockType.PRIVATE:
return f"已成功将 {plugin.name} 全局私聊关闭!"
return "没有找到这个功能喔..."
@classmethod
async def superuser_unblock(
cls, plugin_name: str, block_type: BlockType | None, group_id: str | None
) -> str:
"""超级用户开启插件
参数:
plugin_name: 插件名称
block_type: 禁用类型
group_id: 群组id
返回:
str: 返回信息
"""
if plugin_name.isdigit():
plugin = await PluginInfo.get_or_none(id=int(plugin_name))
else:
plugin = await PluginInfo.get_or_none(
name=plugin_name, load_status=True, plugin_type__not=PluginType.PARENT
)
if plugin:
if group_id:
if group := await GroupConsole.get_or_none(
group_id=group_id, channel_id__isnull=True
):
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 "群组信息未更新,请先更新群组信息..."
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} 全局启用!"
if block_type == BlockType.ALL:
return f"已成功将 {plugin.name} 全局开启!"
if block_type == BlockType.GROUP:
return f"已成功将 {plugin.name} 全局群组开启!"
if block_type == BlockType.PRIVATE:
return f"已成功将 {plugin.name} 全局私聊开启!"
return "没有找到这个功能喔..."
@@ -1,23 +1,21 @@
import os
import shutil
from typing import Annotated, Dict
from pathlib import Path
from typing import Annotated
import ujson as json
from nonebot import on_command
from nonebot.params import Command
from nonebot.plugin import PluginMetadata
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 nonebot_plugin_alconna import Text, Image, UniMsg
from zhenxun.configs.config import Config
from zhenxun.configs.path_config import DATA_PATH
from zhenxun.configs.utils import PluginExtraData, RegisterConfig
from zhenxun.services.log import logger
from zhenxun.configs.config import Config
from zhenxun.utils.enum import PluginType
from zhenxun.utils.http_utils import AsyncHttpx
from zhenxun.configs.path_config import DATA_PATH
from zhenxun.utils.rules import admin_check, ensure_group
from zhenxun.configs.utils import RegisterConfig, PluginExtraData
base_config = Config.get("admin_bot_manage")
@@ -25,7 +23,8 @@ __plugin_meta__ = PluginMetadata(
name="自定义群欢迎消息",
description="自定义群欢迎消息",
usage="""
设置欢迎消息 欢迎新人!
设置群欢迎消息,当消息中包含 -at 时会at入群用户
设置欢迎消息 欢迎新人![图片]
设置欢迎消息 欢迎你 -at
""".strip(),
extra=PluginExtraData(
@@ -61,7 +60,7 @@ BASE_PATH.mkdir(parents=True, exist_ok=True)
old_file = DATA_PATH / "custom_welcome_msg" / "custom_welcome_msg.json"
if old_file.exists():
try:
old_data: Dict[str, str] = json.load(old_file.open(encoding="utf8"))
old_data: dict[str, str] = json.load(old_file.open(encoding="utf8"))
for group_id, message in old_data.items():
file = BASE_PATH / "qq" / f"{group_id}" / "text.json"
file.parent.mkdir(parents=True, exist_ok=True)
@@ -74,15 +73,18 @@ if old_file.exists():
logger.debug("群欢迎消息数据迁移", group_id=group_id)
shutil.rmtree(old_file.parent.absolute())
except Exception as e:
pass
logger.error("群欢迎消息数据迁移失败...", e=e)
@_matcher.handle()
async def _(
session: EventSession,
message: UniMsg,
command: Annotated[tuple[str, ...], Command()],
):
def get_path(session: EventSession) -> Path:
"""根据Session获取存储路径
参数:
session: EventSession:
返回:
Path: 存储路径
"""
path = BASE_PATH / f"{session.platform or session.bot_type}" / f"{session.id2}"
if session.id3:
path = (
@@ -91,32 +93,53 @@ async def _(
/ f"{session.id3}"
/ f"{session.id2}"
)
file = path / "text.json"
path.mkdir(parents=True, exist_ok=True)
for f in path.iterdir():
f.unlink()
return path
async def save(path: Path, message: UniMsg) -> str:
"""保存群欢迎消息
参数:
path: 存储路径
message: 消息内容
返回:
str: 消息内容文本格式
"""
idx = 0
text = ""
for f in os.listdir(path):
(path / f).unlink()
message[0].text = message[0].text.replace(command[0], "").strip()
file = path / "text.json"
for msg in message:
if isinstance(msg, alcText):
if isinstance(msg, Text):
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
if 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", "")
logger.warning("图片 URL 为空...", "设置欢迎消息")
json.dump(
{"at": is_at, "message": text},
file.open("w"),
{"at": "-at" in text, "message": text.replace("-at", "", 1)},
file.open("w", encoding="utf-8"),
ensure_ascii=False,
indent=4,
)
uni_msg = alcText("设置欢迎消息成功: \n") + message
return text
@_matcher.handle()
async def _(
session: EventSession,
message: UniMsg,
command: Annotated[tuple[str, ...], Command()],
):
path = get_path(session)
message[0].text = message[0].text.replace(command[0], "").strip()
text = await save(path, message)
uni_msg = Text("设置欢迎消息成功: \n") + message
await uni_msg.send()
logger.info(f"设置群欢迎消息成功: {text}", command[0], session=session)