feat: 添加shortcut和usage

This commit is contained in:
HibiKier 2024-02-27 16:12:56 +08:00
parent 499e51e996
commit 993ff81130
8 changed files with 255 additions and 65 deletions

View File

@ -25,9 +25,20 @@ from zhenxun.utils.enum import PluginType
from zhenxun.utils.image_utils import ImageTemplate
__plugin_meta__ = PluginMetadata(
name="消息统计查询",
name="消息统计",
description="消息统计查询",
usage="",
usage="""
格式:
消息排行 ?[type [,,,]] ?[--des]
快捷:
[,,,]消息排行
示例:
消息排行 : 所有记录排行
日消息排行 : 今日记录排行
消息排行 --des : 逆序周记录排行
""".strip(),
extra=PluginExtraData(
author="HibiKier",
version="0.1",
@ -36,7 +47,6 @@ __plugin_meta__ = PluginMetadata(
).dict(),
)
# TODO: shortcut
_matcher = on_alconna(
Alconna(
@ -51,7 +61,7 @@ _matcher = on_alconna(
_matcher.shortcut(
r"(?P<type>.+)?消息排行",
command="消息排行",
arguments=["type", "{type}"],
arguments=["{type}"],
prefix=True,
)

View File

@ -54,7 +54,7 @@ class HelpImageBuild:
self._sort_data[menu_type] = []
self._sort_data[menu_type].append(plugin)
async def build_image(self, group_id: int | None):
async def build_image(self, group_id: str | None):
if group_id:
help_image = GROUP_HELP_PATH / f"{group_id}.png"
else:
@ -68,7 +68,7 @@ class HelpImageBuild:
img = await self.build_pil_image(group_id)
await img.save(help_image)
async def build_html_image(self, group_id: int | None) -> bytes:
async def build_html_image(self, group_id: str | None) -> bytes:
from nonebot_plugin_htmlrender import template_to_pic
await self.sort_type()
@ -133,7 +133,7 @@ class HelpImageBuild:
)
return pic
async def build_pil_image(self, group_id: int | None) -> BuildImage:
async def build_pil_image(self, group_id: str | None) -> BuildImage:
"""构造帮助图片
参数:

View File

@ -77,7 +77,7 @@ async def _(matcher: Matcher, bot: Bot, session: EventSession, state: T_State):
raise ValueError("模块: [hook], 配置项: [MALICIOUS_BAN_TIME] 为空或小于0")
if user_id:
command = state["_prefix"]["raw_command"]
if state["_alc_result"]:
if state.get("_alc_result"):
command = state["_alc_result"].source.command
if command:
if _blmt.check(f"{user_id}__{command}"):

View File

@ -25,7 +25,8 @@ __plugin_meta__ = PluginMetadata(
usage="""
每日签到
会影响色图概率和开箱次数以及签到的随机道具获取
指令
指令:
签到
我的签到
好感度排行
* 签到时有 3% 概率 * 2 *
@ -88,7 +89,19 @@ _sign_matcher = on_alconna(
block=True,
)
# TODO: shortcut
_sign_matcher.shortcut(
"我的签到",
command="签到",
arguments=["--my"],
prefix=True,
)
_sign_matcher.shortcut(
"好感度排行",
command="签到",
arguments=["--list"],
prefix=True,
)
@_sign_matcher.assign("$main")

View File

@ -107,6 +107,7 @@ class BroadcastManage:
]
return channel_id_list
if isinstance(bot, KaiheilaBot):
# TODO: kaiheila获取群组列表
pass
# group_list = await bot.guild_list()
# if group_list.guilds:

View File

@ -1,18 +1,9 @@
from nonebot import on_command
from nonebot.permission import SUPERUSER
from nonebot.plugin import PluginMetadata
from nonebot.rule import to_me
from nonebot_plugin_alconna import (
Alconna,
AlconnaQuery,
Args,
Arparma,
Match,
Option,
Query,
on_alconna,
store_true,
)
from nonebot_plugin_saa import Text
from nonebot_plugin_alconna import UniMsg
from nonebot_plugin_saa import Image, Text
from nonebot_plugin_session import EventSession
from tortoise import Tortoise
@ -20,6 +11,7 @@ from zhenxun.configs.utils import PluginExtraData
from zhenxun.services.db_context import TestSQL
from zhenxun.services.log import logger
from zhenxun.utils.enum import PluginType
from zhenxun.utils.image_utils import ImageTemplate
__plugin_meta__ = PluginMetadata(
name="数据库操作",
@ -35,44 +27,59 @@ __plugin_meta__ = PluginMetadata(
).dict(),
)
_matcher = on_alconna(
Alconna(
_matcher = on_command(
"exec",
Args["sql?", str],
Option("-l|--list", action=store_true, help_text="查看数据表"),
),
rule=to_me(),
permission=SUPERUSER,
priority=1,
block=True,
)
_table_matcher = on_command(
"查看所有表",
rule=to_me(),
permission=SUPERUSER,
priority=1,
block=True,
)
SELECT_TABLE_SQL = """
select a.tablename as name,d.description as desc from pg_tables a
left join pg_class c on relname=tablename
left join pg_description d on oid=objoid and objsubid=0 where a.schemaname = 'public'
"""
@_matcher.handle()
async def _(
sql: Match[str],
session: EventSession,
arparma: Arparma,
query_list: Query[bool] = AlconnaQuery("list.value", False),
):
db = Tortoise.get_connection("default")
if query_list.result:
query = await db.execute_query_dict(
"select tablename from pg_tables where schemaname = 'public'"
)
msg = "数据库中的所有表名:\n"
for tablename in query:
msg += str(tablename["tablename"]) + "\n"
logger.info("查看数据库所有表", arparma.header_result, session=session)
await Text(msg[:-1]).finish()
else:
if not sql.available:
await Text("必须带有需要执行的 SQL 语句...").finish()
sql_text = sql.result
async def _(session: EventSession, message: UniMsg):
sql_text = message.extract_plain_text().strip()
if sql_text.startswith("exec"):
sql_text = sql_text[4:]
logger.info(f"执行SQL语句: {sql_text}", "exec", session=session)
try:
if not sql_text.lower().startswith("select"):
await TestSQL.raw(sql_text)
await Text("执行 SQL 语句成功!").finish()
else:
db = Tortoise.get_connection("default")
res = await db.execute_query_dict(sql_text)
# TODO: Alconna空格sql无法接收
except Exception as e:
logger.error("执行 SQL 语句失败...", session=session, e=e)
await Text(f"执行 SQL 语句失败... {type(e)}").finish()
await Text("执行 SQL 语句成功!").finish()
@_table_matcher.handle()
async def _(session: EventSession):
try:
db = Tortoise.get_connection("default")
query = await db.execute_query_dict(SELECT_TABLE_SQL)
column_name = ["表名", "简介"]
data_list = []
for table in query:
data_list.append([table["name"], table["desc"]])
logger.info("查看数据库所有表", "查看所有表", session=session)
table = await ImageTemplate.table_page("数据库表", "", column_name, data_list)
await Image(table.pic2bs4()).send()
except Exception as e:
logger.error("获取表数据失败...", session=session, e=e)
await Text(f"获取表数据失败... {type(e)}").send()

View File

@ -30,13 +30,25 @@ __plugin_meta__ = PluginMetadata(
群权限 | 群白名单 | 退出群 操作
退群添加/删除群白名单添加/删除群认证当在群组中这五个命令且没有指定群号时默认指定当前群组
指令:
退群 ?[group_id]
修改群权限 [group_id] [等级]
修改群权限 [等级]: 该命令仅在群组时生效默认修改当前群组
添加群白名单 ?*[group_id]
删除群白名单 ?*[group_id]
添加群认证 ?*[group_id]
删除群认证 ?*[group_id]
格式:
group-manage modify-level [权限等级] ?[群组Id] : 修改群权限
group-manage super-handle [群组Id] [--del 删除操作] : 添加/删除群白名单
group-manage auth-handle [群组Id] [--del 删除操作] : 添加/删除群认证
group-manage del-group [群组Id] : 退出指定群
快捷:
group-manage modify-level : 修改群权限
group-manage super-handle : 添加/删除群白名单
group-manage auth-handle : 添加/删除群认证
group-manage del-group : 退群
示例:
修改群权限 7 : 在群组中修改当前群组权限为7
group-manage modify-level 7 : 在群组中修改当前群组权限为7
group-manage modify-level 7 1234556 : 修改 123456 群组的权限等级为7
添加/删除群白名单 1234567 : 添加/删除 1234567 为群白名单
添加/删除群认证 1234567 : 添加/删除 1234567 为群认证
退群 12344566 : 退出指定群组
""".strip(),
extra=PluginExtraData(
author="HibiKier",
@ -62,7 +74,7 @@ _matcher = on_alconna(
"auth-handle",
Option("--del", action=store_true, help_text="删除"),
Args["group_id", int],
help_text="添加群白名单",
help_text="添加/删除群认证",
),
Subcommand("del-group", Args["group_id", int], help_text="退出群组"),
),
@ -71,7 +83,47 @@ _matcher = on_alconna(
block=True,
)
# TODO: shortcut
_matcher.shortcut(
"修改群权限",
command="group-manage",
arguments=["modify-level", "{%0}"],
prefix=True,
)
_matcher.shortcut(
"添加群白名单",
command="group-manage",
arguments=["super-handle", "{%0}"],
prefix=True,
)
_matcher.shortcut(
"删除群白名单",
command="group-manage",
arguments=["super-handle", "{%0}", "--del"],
prefix=True,
)
_matcher.shortcut(
"添加群认证",
command="group-manage",
arguments=["auth-handle", "{%0}"],
prefix=True,
)
_matcher.shortcut(
"删除群认证",
command="group-manage",
arguments=["auth-handle", "{%0}", "--del"],
prefix=True,
)
_matcher.shortcut(
"退群",
command="group-manage",
arguments=["del-group", "{%0}"],
prefix=True,
)
def CheckGroupId():

View File

@ -1,9 +1,9 @@
from email.mime import image
import random
from io import BytesIO
from pathlib import Path
from typing import Any, Callable
from typing import Any, Callable, Dict
from nonebot.plugin import PluginMetadata
from fastapi import background
from PIL.ImageFont import FreeTypeFont
from pydantic import BaseModel
@ -25,13 +25,60 @@ class RowStyle(BaseModel):
class ImageTemplate:
color_list = ["#C2CEFE", "#FFA94C", "#3FE6A0", "#D1D4F5"]
@classmethod
async def hl_page(
cls,
head_text: str,
items: Dict[str, str],
row_space: int = 10,
padding: int = 30,
) -> BuildImage:
font = BuildImage.load_font("HYWenHei-85W.ttf", 20)
width, height = BuildImage.get_text_size(head_text, font)
for title, item in items.items():
title_width, title_height = await cls.__get_text_size(title, font)
it_width, it_height = await cls.__get_text_size(item, font)
width = max([width, title_width, it_width])
height += title_height + it_height
width = max([width + padding * 2 + 100, 300])
height = max([height + padding * 2 + 150, 100])
A = BuildImage(width + padding * 2, height + padding * 2, color="#FAF9FE")
top_head = BuildImage(width, 100, color="#FFFFFF", font_size=40)
await top_head.line((0, 1, width, 1), "#C2CEFE", 2)
await top_head.text((15, 20), "签到", "#9FA3B2", "center")
await top_head.circle_corner()
await A.paste(top_head, (0, 20), "width")
_min_width = top_head.width - 60
cur_h = top_head.height + 35 + row_space * len(items)
for title, item in items.items():
title_width, title_height = BuildImage.get_text_size(title, font)
title_background = BuildImage(
title_width + 6, title_height + 10, font=font, color="#C1CDFF"
)
await title_background.text((3, 5), title)
await title_background.circle_corner(5)
_text_width, _text_height = await cls.__get_text_size(item, font)
_width = max([title_background.width, _text_width, _min_width])
text_image = await cls.__build_text_image(
item, _width, _text_height, font, color="#FDFCFA"
)
B = BuildImage(_width + 20, title_height + text_image.height + 40)
await B.paste(title_background, (10, 10))
await B.paste(text_image, (10, 20 + title_background.height))
await B.line((0, 0, 0, B.height), random.choice(cls.color_list))
await A.paste(B, (0, cur_h), "width")
cur_h += B.height + row_space
return A
@classmethod
async def table_page(
cls,
head_text: str,
tip_text: str | None,
column_name: list[str],
data_list: list[list[str]],
data_list: list[list[str | tuple[Path | BuildImage, int, int]]],
row_space: int = 35,
column_space: int = 30,
padding: int = 5,
@ -71,7 +118,7 @@ class ImageTemplate:
async def table(
cls,
column_name: list[str],
data_list: list[list[str | tuple[Path, int, int]]],
data_list: list[list[str | tuple[Path | BuildImage, int, int]]],
row_space: int = 25,
column_space: int = 10,
padding: int = 5,
@ -154,3 +201,63 @@ class ImageTemplate:
return await BuildImage.auto_paste(
column_image_list, len(column_image_list), column_space
)
@classmethod
async def __build_text_image(
cls,
text: str,
width: int,
height: int,
font: FreeTypeFont,
font_color: str | tuple[int, int, int] = (0, 0, 0),
color: str | tuple[int, int, int] = (255, 255, 255),
) -> BuildImage:
"""文本转图片
参数:
text: 文本
width: 宽度
height: 长度
font: 字体
font_color: 文本颜色
color: 背景颜色
返回:
BuildImage: 文本转图片
"""
_, h = BuildImage.get_text_size("A", font)
A = BuildImage(width, height, color=color)
cur_h = 0
for s in text.split("\n"):
text_image = await BuildImage.build_text_image(
s, font, font_color=font_color
)
await A.paste(text_image, (0, cur_h))
cur_h += h
return A
@classmethod
async def __get_text_size(
cls,
text: str,
font: FreeTypeFont,
) -> tuple[int, int]:
"""获取文本所占大小
参数:
text: 文本
font: 字体
返回:
tuple[int, int]: ,
"""
width = 0
height = 0
_, h = BuildImage.get_text_size("A", font)
image_list = []
for s in text.split("\n"):
s = s.strip() or "A"
w, _ = BuildImage.get_text_size(s, font)
width = width if width > w else w
height += h
return width, height