mirror of
https://github.com/TriM-Organization/LiteyukiBot-TriM.git
synced 2024-11-28 16:24:51 +08:00
feat: 更清晰的目录结构,新的markdown构建
This commit is contained in:
parent
65dcf36fe7
commit
15a329029d
@ -9,12 +9,12 @@ from nonebot.exception import MockApiException
|
|||||||
from nonebot.internal.matcher import Matcher
|
from nonebot.internal.matcher import Matcher
|
||||||
from nonebot.permission import SUPERUSER
|
from nonebot.permission import SUPERUSER
|
||||||
|
|
||||||
from liteyuki.utils.config import get_config, load_from_yaml
|
from liteyuki.utils.base.config import get_config, load_from_yaml
|
||||||
from liteyuki.utils.data_manager import StoredConfig, TempConfig, common_db
|
from liteyuki.utils.base.data_manager import StoredConfig, TempConfig, common_db
|
||||||
from liteyuki.utils.language import get_user_lang
|
from liteyuki.utils.base.language import get_user_lang
|
||||||
from liteyuki.utils.ly_typing import T_Bot, T_MessageEvent
|
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent
|
||||||
from liteyuki.utils.message import Markdown as md, broadcast_to_superusers
|
from liteyuki.utils.message import *
|
||||||
from liteyuki.utils.reloader import Reloader
|
from liteyuki.utils.base.reloader import Reloader
|
||||||
from .api import update_liteyuki
|
from .api import update_liteyuki
|
||||||
|
|
||||||
require("nonebot_plugin_alconna"), require("nonebot_plugin_apscheduler")
|
require("nonebot_plugin_alconna"), require("nonebot_plugin_apscheduler")
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import os.path
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
import nonebot.plugin
|
import nonebot.plugin
|
||||||
|
|
||||||
from liteyuki.utils import init_log
|
from liteyuki.utils import init_log
|
||||||
from liteyuki.utils.data_manager import InstalledPlugin, plugin_db
|
from liteyuki.utils.base.data_manager import InstalledPlugin, plugin_db
|
||||||
from liteyuki.utils.resource import load_resource_from_dir, load_resources
|
from liteyuki.utils.base.resource import load_resources
|
||||||
from liteyuki.utils.tools import check_for_package
|
from liteyuki.utils.message.tools import check_for_package
|
||||||
|
|
||||||
load_resources()
|
load_resources()
|
||||||
init_log()
|
init_log()
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import json
|
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
import nonebot
|
import nonebot
|
||||||
@ -7,13 +6,12 @@ from cpuinfo import get_cpu_info
|
|||||||
from nonebot import on_command
|
from nonebot import on_command
|
||||||
from nonebot.adapters.onebot.v11 import MessageSegment
|
from nonebot.adapters.onebot.v11 import MessageSegment
|
||||||
from nonebot.permission import SUPERUSER
|
from nonebot.permission import SUPERUSER
|
||||||
from playwright.async_api import async_playwright
|
|
||||||
from liteyuki.utils import __NAME__, __VERSION__, load_from_yaml
|
from liteyuki.utils import __NAME__, __VERSION__, load_from_yaml
|
||||||
from liteyuki.utils.htmlrender import template2image
|
from liteyuki.utils.message.html_tool import template2image
|
||||||
from liteyuki.utils.language import Language, get_default_lang, get_user_lang
|
from liteyuki.utils.base.language import Language, get_default_lang, get_user_lang
|
||||||
from liteyuki.utils.ly_typing import T_Bot, T_MessageEvent
|
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent
|
||||||
from liteyuki.utils.resource import get_path
|
from liteyuki.utils.base.resource import get_path
|
||||||
from liteyuki.utils.tools import convert_size
|
from liteyuki.utils.message.tools import convert_size
|
||||||
|
|
||||||
stats = on_command("status", aliases={"状态"}, priority=5, permission=SUPERUSER)
|
stats = on_command("status", aliases={"状态"}, priority=5, permission=SUPERUSER)
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@ import nonebot
|
|||||||
from nonebot import on_message, require
|
from nonebot import on_message, require
|
||||||
from nonebot.plugin import PluginMetadata
|
from nonebot.plugin import PluginMetadata
|
||||||
|
|
||||||
from liteyuki.utils.data import Database, LiteModel
|
from liteyuki.utils.base.data import Database, LiteModel
|
||||||
from liteyuki.utils.ly_typing import T_Bot, T_MessageEvent
|
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent
|
||||||
from liteyuki.utils.message import Markdown as md
|
from liteyuki.utils.message.message import MarkdownMessage as md
|
||||||
|
|
||||||
require("nonebot_plugin_alconna")
|
require("nonebot_plugin_alconna")
|
||||||
from nonebot_plugin_alconna import on_alconna
|
from nonebot_plugin_alconna import on_alconna
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import nonebot
|
|
||||||
from nonebot import on_command
|
from nonebot import on_command
|
||||||
from nonebot.params import CommandArg
|
from nonebot.params import CommandArg
|
||||||
from nonebot.permission import SUPERUSER
|
from nonebot.permission import SUPERUSER
|
||||||
from nonebot.plugin import PluginMetadata
|
from nonebot.plugin import PluginMetadata
|
||||||
|
|
||||||
from liteyuki.utils.ly_typing import T_Bot, T_MessageEvent, v11
|
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent, v11
|
||||||
from liteyuki.utils.message import Markdown as md
|
from liteyuki.utils.message.message import MarkdownMessage as md, broadcast_to_superusers
|
||||||
|
|
||||||
md_test = on_command("mdts", aliases={"会话md"}, permission=SUPERUSER)
|
md_test = on_command("mdts", permission=SUPERUSER)
|
||||||
|
btn_test = on_command("btnts", permission=SUPERUSER)
|
||||||
|
|
||||||
placeholder = {
|
placeholder = {
|
||||||
"[": "[",
|
"[": "[",
|
||||||
@ -28,6 +28,15 @@ async def _(bot: T_Bot, event: T_MessageEvent, arg: v11.Message = CommandArg()):
|
|||||||
session_id=event.user_id if event.message_type == "private" else event.group_id
|
session_id=event.user_id if event.message_type == "private" else event.group_id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@btn_test.handle()
|
||||||
|
async def _(bot: T_Bot, event: T_MessageEvent, arg: v11.Message = CommandArg()):
|
||||||
|
await md.send_btn(
|
||||||
|
str(arg),
|
||||||
|
bot,
|
||||||
|
message_type=event.message_type,
|
||||||
|
session_id=event.user_id if event.message_type == "private" else event.group_id
|
||||||
|
)
|
||||||
|
|
||||||
__author__ = "snowykami"
|
__author__ = "snowykami"
|
||||||
__plugin_meta__ = PluginMetadata(
|
__plugin_meta__ = PluginMetadata(
|
||||||
name="轻雪Markdown测试",
|
name="轻雪Markdown测试",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import random
|
import random
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from liteyuki.utils.message import Markdown as md
|
from liteyuki.utils.message.message import MarkdownMessage as md
|
||||||
|
|
||||||
|
|
||||||
class Dot(BaseModel):
|
class Dot(BaseModel):
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from nonebot import require
|
from nonebot import require
|
||||||
|
|
||||||
from ...utils.ly_typing import T_Bot, T_MessageEvent
|
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent
|
||||||
from ...utils.message import Markdown as md
|
from liteyuki.utils.message.message import MarkdownMessage as md
|
||||||
|
|
||||||
require("nonebot_plugin_alconna")
|
require("nonebot_plugin_alconna")
|
||||||
from .game import Minesweeper
|
from .game import Minesweeper
|
||||||
|
@ -4,9 +4,9 @@ from typing import Optional
|
|||||||
import aiofiles
|
import aiofiles
|
||||||
import nonebot.plugin
|
import nonebot.plugin
|
||||||
|
|
||||||
from liteyuki.utils.data import LiteModel
|
from liteyuki.utils.base.data import LiteModel
|
||||||
from liteyuki.utils.data_manager import GlobalPlugin, Group, User, group_db, plugin_db, user_db
|
from liteyuki.utils.base.data_manager import GlobalPlugin, Group, User, group_db, plugin_db, user_db
|
||||||
from liteyuki.utils.ly_typing import T_MessageEvent
|
from liteyuki.utils.base.ly_typing import T_MessageEvent
|
||||||
|
|
||||||
|
|
||||||
class PluginTag(LiteModel):
|
class PluginTag(LiteModel):
|
||||||
|
@ -12,12 +12,12 @@ from nonebot.internal.matcher import Matcher
|
|||||||
from nonebot.message import run_preprocessor
|
from nonebot.message import run_preprocessor
|
||||||
from nonebot.permission import SUPERUSER
|
from nonebot.permission import SUPERUSER
|
||||||
from nonebot.plugin import Plugin
|
from nonebot.plugin import Plugin
|
||||||
from liteyuki.utils.data_manager import InstalledPlugin
|
from liteyuki.utils.base.data_manager import InstalledPlugin
|
||||||
from liteyuki.utils.language import get_user_lang
|
from liteyuki.utils.base.language import get_user_lang
|
||||||
from liteyuki.utils.ly_typing import T_Bot
|
from liteyuki.utils.base.ly_typing import T_Bot
|
||||||
from liteyuki.utils.message import Markdown as md
|
from liteyuki.utils.message.message import MarkdownMessage as md
|
||||||
from liteyuki.utils.permission import GROUP_ADMIN, GROUP_OWNER
|
from liteyuki.utils.base.permission import GROUP_ADMIN, GROUP_OWNER
|
||||||
from liteyuki.utils.tools import clamp
|
from liteyuki.utils.message.tools import clamp
|
||||||
from .common import *
|
from .common import *
|
||||||
|
|
||||||
require("nonebot_plugin_alconna")
|
require("nonebot_plugin_alconna")
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
# 轻雪资源包管理器
|
# 轻雪资源包管理器
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import nonebot
|
|
||||||
import yaml
|
import yaml
|
||||||
from nonebot import require
|
from nonebot import require
|
||||||
from nonebot.permission import SUPERUSER
|
from nonebot.permission import SUPERUSER
|
||||||
|
|
||||||
from liteyuki.utils.config import get_config
|
from liteyuki.utils.base.language import get_user_lang
|
||||||
from liteyuki.utils.language import get_user_lang
|
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent
|
||||||
from liteyuki.utils.ly_typing import T_Bot, T_MessageEvent
|
from liteyuki.utils.message.message import MarkdownMessage as md
|
||||||
from liteyuki.utils.message import Markdown as md
|
from liteyuki.utils.base.resource import (ResourceMetadata, add_resource_pack, change_priority, check_exist, check_status, get_loaded_resource_packs, get_resource_metadata, load_resources, remove_resource_pack)
|
||||||
from liteyuki.utils.resource import (ResourceMetadata, add_resource_pack, change_priority, check_exist, check_status, get_loaded_resource_packs, get_resource_metadata, load_resources, remove_resource_pack)
|
|
||||||
|
|
||||||
require("nonebot_plugin_alconna")
|
require("nonebot_plugin_alconna")
|
||||||
from nonebot_plugin_alconna import Alconna, Args, on_alconna, Arparma, Subcommand
|
from nonebot_plugin_alconna import Alconna, Args, on_alconna, Arparma, Subcommand
|
||||||
|
@ -3,11 +3,11 @@ from typing import Optional
|
|||||||
import pytz
|
import pytz
|
||||||
from nonebot import require
|
from nonebot import require
|
||||||
|
|
||||||
from liteyuki.utils.data import LiteModel
|
from liteyuki.utils.base.data import LiteModel
|
||||||
from liteyuki.utils.data_manager import User, user_db
|
from liteyuki.utils.base.data_manager import User, user_db
|
||||||
from liteyuki.utils.language import Language, get_all_lang, get_user_lang
|
from liteyuki.utils.base.language import Language, get_all_lang, get_user_lang
|
||||||
from liteyuki.utils.ly_typing import T_Bot, T_MessageEvent
|
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent
|
||||||
from liteyuki.utils.message import Markdown as md
|
from liteyuki.utils.message.message import MarkdownMessage as md
|
||||||
from .const import representative_timezones_list
|
from .const import representative_timezones_list
|
||||||
|
|
||||||
require("nonebot_plugin_alconna")
|
require("nonebot_plugin_alconna")
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from nonebot import on_command
|
from liteyuki.utils.base.data import LiteModel
|
||||||
from liteyuki.utils.data import LiteModel
|
|
||||||
|
|
||||||
|
|
||||||
class Location(LiteModel):
|
class Location(LiteModel):
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
from nonebot import require
|
from nonebot import require
|
||||||
from jieba import lcut
|
|
||||||
|
|
||||||
from liteyuki.utils.ly_typing import T_MessageEvent
|
from liteyuki.utils.base.ly_typing import T_MessageEvent
|
||||||
|
|
||||||
require("nonebot_plugin_alconna")
|
require("nonebot_plugin_alconna")
|
||||||
from nonebot_plugin_alconna import on_alconna, Alconna, Subcommand, Args, MultiVar, Arparma
|
from nonebot_plugin_alconna import on_alconna, Alconna, Args, MultiVar, Arparma
|
||||||
|
|
||||||
|
|
||||||
@on_alconna(
|
@on_alconna(
|
||||||
|
@ -10,9 +10,9 @@ __VERSION__ = "6.2.8" # 60201
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from liteyuki.utils.config import load_from_yaml, config
|
from liteyuki.utils.base.config import load_from_yaml, config
|
||||||
from .log import init_log
|
from liteyuki.utils.base.log import init_log
|
||||||
from .data_manager import auto_migrate
|
from liteyuki.utils.base.data_manager import auto_migrate
|
||||||
|
|
||||||
major, minor, patch = map(int, __VERSION__.split("."))
|
major, minor, patch = map(int, __VERSION__.split("."))
|
||||||
__VERSION_I__ = major * 10000 + minor * 100 + patch
|
__VERSION_I__ = major * 10000 + minor * 100 + patch
|
||||||
|
@ -4,9 +4,9 @@ import nonebot
|
|||||||
import yaml
|
import yaml
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from liteyuki.utils.data_manager import StoredConfig, common_db
|
from .data_manager import StoredConfig, common_db
|
||||||
from liteyuki.utils.ly_typing import T_Bot
|
from .ly_typing import T_Bot
|
||||||
from liteyuki.utils.tools import random_hex_string
|
from ..message.tools import random_hex_string
|
||||||
|
|
||||||
config = {} # 全局配置,确保加载后读取
|
config = {} # 全局配置,确保加载后读取
|
||||||
|
|
@ -2,7 +2,7 @@ import os
|
|||||||
|
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
|
|
||||||
from liteyuki.utils.data import LiteModel, Database as DB
|
from .data import LiteModel, Database as DB
|
||||||
|
|
||||||
DATA_PATH = "data/liteyuki"
|
DATA_PATH = "data/liteyuki"
|
||||||
|
|
@ -2,13 +2,13 @@ import sys
|
|||||||
import loguru
|
import loguru
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from .config import load_from_yaml
|
from .config import load_from_yaml
|
||||||
from .language import Language, get_default_lang
|
from .language import get_default_lang
|
||||||
|
|
||||||
logger = loguru.logger
|
logger = loguru.logger
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
# avoid sphinx autodoc resolve annotation failed
|
# avoid sphinx autodoc resolve annotation failed
|
||||||
# because loguru module do not have `Logger` class actually
|
# because loguru module do not have `Logger` class actually
|
||||||
from loguru import Logger, Record
|
from loguru import Record
|
||||||
|
|
||||||
|
|
||||||
def default_filter(record: "Record"):
|
def default_filter(record: "Record"):
|
@ -8,8 +8,8 @@ import psutil
|
|||||||
import requests
|
import requests
|
||||||
from aiohttp import FormData
|
from aiohttp import FormData
|
||||||
|
|
||||||
from . import __VERSION_I__, __VERSION__, __NAME__
|
from .. import __VERSION_I__, __VERSION__, __NAME__
|
||||||
from .config import config, load_from_yaml
|
from .config import load_from_yaml
|
||||||
|
|
||||||
|
|
||||||
class LiteyukiAPI:
|
class LiteyukiAPI:
|
@ -1,7 +1,5 @@
|
|||||||
from nonebot.adapters.onebot import v11
|
from nonebot.adapters.onebot import v11
|
||||||
|
|
||||||
from liteyuki.utils.ly_typing import T_GroupMessageEvent, T_MessageEvent
|
|
||||||
|
|
||||||
GROUP_ADMIN = v11.GROUP_ADMIN
|
GROUP_ADMIN = v11.GROUP_ADMIN
|
||||||
GROUP_OWNER = v11.GROUP_OWNER
|
GROUP_OWNER = v11.GROUP_OWNER
|
||||||
|
|
@ -42,7 +42,7 @@ def load_resource_from_dir(path: str):
|
|||||||
metadata["path"] = path
|
metadata["path"] = path
|
||||||
metadata["folder"] = os.path.basename(path)
|
metadata["folder"] = os.path.basename(path)
|
||||||
if os.path.exists(os.path.join(path, "lang")):
|
if os.path.exists(os.path.join(path, "lang")):
|
||||||
from liteyuki.utils.language import load_from_dir
|
from liteyuki.utils.base.language import load_from_dir
|
||||||
load_from_dir(os.path.join(path, "lang"))
|
load_from_dir(os.path.join(path, "lang"))
|
||||||
_loaded_resource_packs.insert(0, ResourceMetadata(**metadata))
|
_loaded_resource_packs.insert(0, ResourceMetadata(**metadata))
|
||||||
|
|
0
liteyuki/utils/message/__init__.py
Normal file
0
liteyuki/utils/message/__init__.py
Normal file
186
liteyuki/utils/message/markdown.py
Normal file
186
liteyuki/utils/message/markdown.py
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
import base64
|
||||||
|
from io import BytesIO
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
from ..base.config import get_config
|
||||||
|
from ..base.ly_typing import T_Bot
|
||||||
|
|
||||||
|
|
||||||
|
def markdown_escape(text: str) -> str:
|
||||||
|
"""
|
||||||
|
转义Markdown特殊字符
|
||||||
|
Args:
|
||||||
|
text: str: 文本
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: 转义后文本
|
||||||
|
"""
|
||||||
|
text = text.replace("\n", r"\n").replace('"', r'\\\"')
|
||||||
|
spacial_chars = r"\`*_{}[]()#+-.!"
|
||||||
|
for char in spacial_chars:
|
||||||
|
text = text.replace(char, "\\" + char)
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def escape_decorator(func):
|
||||||
|
def wrapper(text: str):
|
||||||
|
return func(markdown_escape(text))
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
class MarkdownComponent:
|
||||||
|
@staticmethod
|
||||||
|
@escape_decorator
|
||||||
|
def heading(text: str, level: int = 1) -> str:
|
||||||
|
"""标题"""
|
||||||
|
assert 1 <= level <= 6, "标题级别应在 1-6 之间"
|
||||||
|
return f"{'#' * level} {text}"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@escape_decorator
|
||||||
|
def bold(text: str) -> str:
|
||||||
|
"""粗体"""
|
||||||
|
return f"**{text}**"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@escape_decorator
|
||||||
|
def italic(text: str) -> str:
|
||||||
|
"""斜体"""
|
||||||
|
return f"*{text}*"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@escape_decorator
|
||||||
|
def strike(text: str) -> str:
|
||||||
|
"""删除线"""
|
||||||
|
return f"~~{text}~~"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@escape_decorator
|
||||||
|
def code(text: str) -> str:
|
||||||
|
"""行内代码"""
|
||||||
|
return f"`{text}`"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@escape_decorator
|
||||||
|
def code_block(text: str, language: str = "") -> str:
|
||||||
|
"""代码块"""
|
||||||
|
return f"```{language}\n{text}\n```"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@escape_decorator
|
||||||
|
def quote(text: str) -> str:
|
||||||
|
"""引用"""
|
||||||
|
return f"> {text}"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@escape_decorator
|
||||||
|
def link(text: str, url: str, symbol: bool = True) -> str:
|
||||||
|
"""
|
||||||
|
链接
|
||||||
|
|
||||||
|
Args:
|
||||||
|
text: 链接文本
|
||||||
|
url: 链接地址
|
||||||
|
symbol: 是否显示链接图标, mqqapi请使用False
|
||||||
|
"""
|
||||||
|
return f"[{'🔗' if symbol else ''}{text}]({quote(url)})"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@escape_decorator
|
||||||
|
def image(url: str, *, size: tuple[int, int]) -> str:
|
||||||
|
"""
|
||||||
|
图片,本地图片不建议直接使用
|
||||||
|
Args:
|
||||||
|
url: 图片链接
|
||||||
|
size: 图片大小
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
markdown格式的图片
|
||||||
|
"""
|
||||||
|
return f"![image #{size[0]}px #{size[1]}px]({url})"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@escape_decorator
|
||||||
|
async def auto_image(image: str | bytes, bot: T_Bot) -> str:
|
||||||
|
"""
|
||||||
|
自动获取图片大小
|
||||||
|
Args:
|
||||||
|
image: 本地图片路径 | 图片url http/file | 图片bytes
|
||||||
|
bot: bot对象,用于上传图片到图床
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
markdown格式的图片
|
||||||
|
"""
|
||||||
|
if isinstance(image, bytes):
|
||||||
|
# 传入为二进制图片
|
||||||
|
image_obj = Image.open(BytesIO(image))
|
||||||
|
base64_string = base64.b64encode(image_obj.tobytes()).decode("utf-8")
|
||||||
|
url = await bot.call_api("upload_image", file=f"base64://{base64_string}")
|
||||||
|
size = image_obj.size
|
||||||
|
elif isinstance(image, str):
|
||||||
|
# 传入链接或本地路径
|
||||||
|
if image.startswith("http"):
|
||||||
|
# 网络请求
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get(image) as resp:
|
||||||
|
image_data = await resp.read()
|
||||||
|
url = image
|
||||||
|
size = Image.open(BytesIO(image_data)).size
|
||||||
|
|
||||||
|
else:
|
||||||
|
# 本地路径/file://
|
||||||
|
image_obj = Image.open(image.replace("file://", ""))
|
||||||
|
base64_string = base64.b64encode(image_obj.tobytes()).decode("utf-8")
|
||||||
|
url = await bot.call_api("upload_image", file=f"base64://{base64_string}")
|
||||||
|
size = image_obj.size
|
||||||
|
else:
|
||||||
|
raise ValueError("图片类型错误")
|
||||||
|
|
||||||
|
return MarkdownComponent.image(url, size=size)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@escape_decorator
|
||||||
|
def table(data: list[list[any]]) -> str:
|
||||||
|
"""
|
||||||
|
表格
|
||||||
|
Args:
|
||||||
|
data: 表格数据,二维列表
|
||||||
|
Returns:
|
||||||
|
markdown格式的表格
|
||||||
|
"""
|
||||||
|
# 表头
|
||||||
|
table = "|".join(map(str, data[0])) + "\n"
|
||||||
|
table += "|".join([":-:" for _ in range(len(data[0]))]) + "\n"
|
||||||
|
# 表内容
|
||||||
|
for row in data[1:]:
|
||||||
|
table += "|".join(map(str, row)) + "\n"
|
||||||
|
return table
|
||||||
|
|
||||||
|
|
||||||
|
class Mqqapi:
|
||||||
|
@staticmethod
|
||||||
|
@escape_decorator
|
||||||
|
def cmd(text: str, cmd: str, enter: bool = True, reply: bool = False, use_cmd_start: bool = True) -> str:
|
||||||
|
"""
|
||||||
|
生成点击回调文本
|
||||||
|
Args:
|
||||||
|
text: 显示内容
|
||||||
|
cmd: 命令
|
||||||
|
enter: 是否自动发送
|
||||||
|
reply: 是否回复
|
||||||
|
use_cmd_start: 是否使用配置的命令前缀
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
[text](mqqapi://) markdown格式的可点击回调文本,类似于链接
|
||||||
|
"""
|
||||||
|
|
||||||
|
if use_cmd_start:
|
||||||
|
command_start = get_config("command_start", [])
|
||||||
|
if command_start:
|
||||||
|
# 若命令前缀不为空,则使用配置的第一个命令前缀
|
||||||
|
cmd = f"{command_start[0]}{cmd}"
|
||||||
|
return f"[{text}](mqqapi://aio/inlinecmd?command={quote(cmd)}&reply={str(reply).lower()}&enter={str(enter).lower()})"
|
@ -1,4 +1,3 @@
|
|||||||
import asyncio
|
|
||||||
import base64
|
import base64
|
||||||
import io
|
import io
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
@ -8,12 +7,14 @@ from PIL import Image
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
import nonebot
|
import nonebot
|
||||||
from nonebot import require
|
from nonebot import require
|
||||||
from nonebot.adapters.onebot import v11, v12
|
from nonebot.adapters.onebot import v11
|
||||||
from typing import Any
|
from typing import Any, Type
|
||||||
|
|
||||||
from . import load_from_yaml
|
from nonebot.internal.adapter import MessageSegment
|
||||||
from .ly_api import liteyuki_api
|
from nonebot.internal.adapter.message import TM
|
||||||
from .ly_typing import T_Bot, T_Message, T_MessageEvent
|
|
||||||
|
from .. import load_from_yaml
|
||||||
|
from ..base.ly_typing import T_Bot, T_Message, T_MessageEvent
|
||||||
|
|
||||||
require("nonebot_plugin_htmlrender")
|
require("nonebot_plugin_htmlrender")
|
||||||
from nonebot_plugin_htmlrender import md_to_pic
|
from nonebot_plugin_htmlrender import md_to_pic
|
||||||
@ -28,12 +29,12 @@ async def broadcast_to_superusers(message: str | T_Message, markdown: bool = Fal
|
|||||||
for bot in nonebot.get_bots().values():
|
for bot in nonebot.get_bots().values():
|
||||||
for user_id in config.get("superusers", []):
|
for user_id in config.get("superusers", []):
|
||||||
if markdown:
|
if markdown:
|
||||||
await Markdown.send_md(message, bot, message_type="private", session_id=user_id)
|
await MarkdownMessage.send_md(message, bot, message_type="private", session_id=user_id)
|
||||||
else:
|
else:
|
||||||
await bot.send_private_msg(user_id=user_id, message=message)
|
await bot.send_private_msg(user_id=user_id, message=message)
|
||||||
|
|
||||||
|
|
||||||
class Markdown:
|
class MarkdownMessage:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def send_md(
|
async def send_md(
|
||||||
markdown: str,
|
markdown: str,
|
||||||
@ -158,8 +159,8 @@ class Markdown:
|
|||||||
if method == 2:
|
if method == 2:
|
||||||
base64_string = base64.b64encode(image).decode("utf-8")
|
base64_string = base64.b64encode(image).decode("utf-8")
|
||||||
data = await bot.call_api("upload_image", file=f"base64://{base64_string}")
|
data = await bot.call_api("upload_image", file=f"base64://{base64_string}")
|
||||||
await Markdown.send_md(Markdown.image(data, Image.open(io.BytesIO(image)).size), bot, event=event, message_type=message_type,
|
await MarkdownMessage.send_md(MarkdownMessage.image(data, Image.open(io.BytesIO(image)).size), bot, event=event, message_type=message_type,
|
||||||
session_id=session_id, **kwargs)
|
session_id=session_id, **kwargs)
|
||||||
|
|
||||||
# 其他实现端方案
|
# 其他实现端方案
|
||||||
else:
|
else:
|
||||||
@ -171,8 +172,8 @@ class Markdown:
|
|||||||
))["message_id"]
|
))["message_id"]
|
||||||
image_url = (await bot.get_msg(message_id=image_message_id))["message"][0]["data"]["url"]
|
image_url = (await bot.get_msg(message_id=image_message_id))["message"][0]["data"]["url"]
|
||||||
image_size = Image.open(io.BytesIO(image)).size
|
image_size = Image.open(io.BytesIO(image)).size
|
||||||
image_md = Markdown.image(image_url, image_size)
|
image_md = MarkdownMessage.image(image_url, image_size)
|
||||||
return await Markdown.send_md(image_md, bot, message_type=message_type, session_id=session_id, event=event, **kwargs)
|
return await MarkdownMessage.send_md(image_md, bot, message_type=message_type, session_id=session_id, event=event, **kwargs)
|
||||||
|
|
||||||
if data is None:
|
if data is None:
|
||||||
data = await bot.send_msg(
|
data = await bot.send_msg(
|
||||||
@ -251,7 +252,7 @@ class Markdown:
|
|||||||
async with aiohttp.ClientSession() as session:
|
async with aiohttp.ClientSession() as session:
|
||||||
async with session.get(url) as resp:
|
async with session.get(url) as resp:
|
||||||
image = Image.open(io.BytesIO(await resp.read()))
|
image = Image.open(io.BytesIO(await resp.read()))
|
||||||
return Markdown.image(url, image.size)
|
return MarkdownMessage.image(url, image.size)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
nonebot.logger.error(f"get image error: {e}")
|
nonebot.logger.error(f"get image error: {e}")
|
||||||
return "[Image Error]"
|
return "[Image Error]"
|
||||||
@ -270,58 +271,3 @@ class Markdown:
|
|||||||
for char in chars:
|
for char in chars:
|
||||||
text = text.replace(char, f"\\\\{char}")
|
text = text.replace(char, f"\\\\{char}")
|
||||||
return text
|
return text
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def H1(text: str, end="\n") -> str:
|
|
||||||
"""H1标题"""
|
|
||||||
return f"# {text}{end}"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def H2(text: str, end="\n") -> str:
|
|
||||||
"""H2标题"""
|
|
||||||
return f"## {text}{end}"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def H3(text: str, end="\n") -> str:
|
|
||||||
"""H3标题"""
|
|
||||||
return f"### {text}{end}"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def H4(text: str, end="\n") -> str:
|
|
||||||
"""H4标题"""
|
|
||||||
return f"#### {text}{end}"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def H5(text: str, end="\n") -> str:
|
|
||||||
"""H5标题"""
|
|
||||||
return f"##### {text}{end}"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def H6(text: str, end="\n") -> str:
|
|
||||||
"""H6标题"""
|
|
||||||
return f"###### {text}{end}"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def Bold(text: str) -> str:
|
|
||||||
"""加粗"""
|
|
||||||
return f"**{text}**"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def Italic(text: str) -> str:
|
|
||||||
"""斜体"""
|
|
||||||
return f"*{text}*"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def BoldItalic(text: str) -> str:
|
|
||||||
"""粗斜体"""
|
|
||||||
return f"***{text}***"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def Underline(text: str) -> str:
|
|
||||||
"""下划线"""
|
|
||||||
return f"__{text}__"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def Strike(text: str) -> str:
|
|
||||||
"""删除线"""
|
|
||||||
return f"~~{text}~~"
|
|
8
main.py
8
main.py
@ -1,12 +1,10 @@
|
|||||||
import os.path
|
|
||||||
|
|
||||||
import nonebot
|
import nonebot
|
||||||
from nonebot.adapters.onebot import v11, v12
|
from nonebot.adapters.onebot import v11, v12
|
||||||
|
|
||||||
from liteyuki.utils import init
|
from liteyuki.utils import init
|
||||||
from liteyuki.utils.config import load_from_yaml
|
from liteyuki.utils.base.config import load_from_yaml
|
||||||
from liteyuki.utils.data_manager import StoredConfig, common_db
|
from liteyuki.utils.base.data_manager import StoredConfig, common_db
|
||||||
from liteyuki.utils.ly_api import liteyuki_api
|
from liteyuki.utils.base.ly_api import liteyuki_api
|
||||||
|
|
||||||
init()
|
init()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user