mirror of
https://github.com/LiteyukiStudio/LiteyukiBot.git
synced 2024-11-14 13:47:24 +08:00
✨ 初步对Uninfo的支持
This commit is contained in:
parent
ab89cd1c72
commit
86e50e369b
@ -1,357 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
|
||||||
|
|
||||||
@Time : 2024/8/19 上午6:23
|
|
||||||
@Author : snowykami
|
|
||||||
@Email : snowykami@outlook.com
|
|
||||||
@File : mkdoc.py
|
|
||||||
@Software: PyCharm
|
|
||||||
"""
|
|
||||||
|
|
||||||
import ast
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
from typing import Any
|
|
||||||
from enum import Enum
|
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
NO_TYPE_ANY = "Any"
|
|
||||||
NO_TYPE_HINT = "NoTypeHint"
|
|
||||||
|
|
||||||
|
|
||||||
class DefType(Enum):
|
|
||||||
FUNCTION = "function"
|
|
||||||
METHOD = "method"
|
|
||||||
STATIC_METHOD = "staticmethod"
|
|
||||||
CLASS_METHOD = "classmethod"
|
|
||||||
PROPERTY = "property"
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionInfo(BaseModel):
|
|
||||||
name: str
|
|
||||||
args: list[tuple[str, str]]
|
|
||||||
return_type: str
|
|
||||||
docstring: str
|
|
||||||
source_code: str = ""
|
|
||||||
|
|
||||||
type: DefType
|
|
||||||
"""若为类中def,则有"""
|
|
||||||
is_async: bool
|
|
||||||
|
|
||||||
|
|
||||||
class AttributeInfo(BaseModel):
|
|
||||||
name: str
|
|
||||||
type: str
|
|
||||||
value: Any = None
|
|
||||||
docstring: str = ""
|
|
||||||
|
|
||||||
|
|
||||||
class ClassInfo(BaseModel):
|
|
||||||
name: str
|
|
||||||
docstring: str
|
|
||||||
methods: list[FunctionInfo]
|
|
||||||
attributes: list[AttributeInfo]
|
|
||||||
inherit: list[str]
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleInfo(BaseModel):
|
|
||||||
module_path: str
|
|
||||||
"""点分割模块路径 例如 liteyuki.bot"""
|
|
||||||
|
|
||||||
functions: list[FunctionInfo]
|
|
||||||
classes: list[ClassInfo]
|
|
||||||
attributes: list[AttributeInfo]
|
|
||||||
docstring: str
|
|
||||||
|
|
||||||
|
|
||||||
def get_relative_path(base_path: str, target_path: str) -> str:
|
|
||||||
"""
|
|
||||||
获取相对路径
|
|
||||||
Args:
|
|
||||||
base_path: 基础路径
|
|
||||||
target_path: 目标路径
|
|
||||||
"""
|
|
||||||
return os.path.relpath(target_path, base_path)
|
|
||||||
|
|
||||||
|
|
||||||
def write_to_files(file_data: dict[str, str]):
|
|
||||||
"""
|
|
||||||
输出文件
|
|
||||||
Args:
|
|
||||||
file_data: 文件数据 相对路径
|
|
||||||
"""
|
|
||||||
|
|
||||||
for rp, data in file_data.items():
|
|
||||||
|
|
||||||
if not os.path.exists(os.path.dirname(rp)):
|
|
||||||
os.makedirs(os.path.dirname(rp))
|
|
||||||
with open(rp, 'w', encoding='utf-8') as f:
|
|
||||||
f.write(data)
|
|
||||||
|
|
||||||
|
|
||||||
def get_file_list(module_folder: str):
|
|
||||||
file_list = []
|
|
||||||
for root, dirs, files in os.walk(module_folder):
|
|
||||||
for file in files:
|
|
||||||
if file.endswith((".py", ".pyi")):
|
|
||||||
file_list.append(os.path.join(root, file))
|
|
||||||
return file_list
|
|
||||||
|
|
||||||
|
|
||||||
def get_module_info_normal(file_path: str, ignore_private: bool = True) -> ModuleInfo:
|
|
||||||
"""
|
|
||||||
获取函数和类
|
|
||||||
Args:
|
|
||||||
file_path: Python 文件路径
|
|
||||||
ignore_private: 忽略私有函数和类
|
|
||||||
Returns:
|
|
||||||
模块信息
|
|
||||||
"""
|
|
||||||
|
|
||||||
with open(file_path, 'r', encoding='utf-8') as file:
|
|
||||||
file_content = file.read()
|
|
||||||
tree = ast.parse(file_content)
|
|
||||||
|
|
||||||
dot_sep_module_path = file_path.replace(os.sep, '.').replace(".py", "").replace(".pyi", "")
|
|
||||||
module_docstring = ast.get_docstring(tree)
|
|
||||||
|
|
||||||
module_info = ModuleInfo(
|
|
||||||
module_path=dot_sep_module_path,
|
|
||||||
functions=[],
|
|
||||||
classes=[],
|
|
||||||
attributes=[],
|
|
||||||
docstring=module_docstring if module_docstring else ""
|
|
||||||
)
|
|
||||||
|
|
||||||
for node in ast.walk(tree):
|
|
||||||
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
||||||
# 模块函数 且不在类中 若ignore_private=True则忽略私有函数
|
|
||||||
if not any(isinstance(parent, ast.ClassDef) for parent in ast.iter_child_nodes(node)) and (not ignore_private or not node.name.startswith('_')):
|
|
||||||
|
|
||||||
# 判断第一个参数是否为self或cls,后期用其他办法优化
|
|
||||||
if node.args.args:
|
|
||||||
first_arg = node.args.args[0]
|
|
||||||
if first_arg.arg in ("self", "cls"):
|
|
||||||
continue
|
|
||||||
|
|
||||||
function_docstring = ast.get_docstring(node)
|
|
||||||
|
|
||||||
func_info = FunctionInfo(
|
|
||||||
name=node.name,
|
|
||||||
args=[(arg.arg, ast.unparse(arg.annotation) if arg.annotation else NO_TYPE_ANY) for arg in node.args.args],
|
|
||||||
return_type=ast.unparse(node.returns) if node.returns else "None",
|
|
||||||
docstring=function_docstring if function_docstring else "",
|
|
||||||
type=DefType.FUNCTION,
|
|
||||||
is_async=isinstance(node, ast.AsyncFunctionDef),
|
|
||||||
source_code=ast.unparse(node)
|
|
||||||
)
|
|
||||||
module_info.functions.append(func_info)
|
|
||||||
|
|
||||||
elif isinstance(node, ast.ClassDef):
|
|
||||||
# 模块类
|
|
||||||
class_docstring = ast.get_docstring(node)
|
|
||||||
|
|
||||||
class_info = ClassInfo(
|
|
||||||
name=node.name,
|
|
||||||
docstring=class_docstring if class_docstring else "",
|
|
||||||
methods=[],
|
|
||||||
attributes=[],
|
|
||||||
inherit=[ast.unparse(base) for base in node.bases]
|
|
||||||
)
|
|
||||||
|
|
||||||
for class_node in node.body:
|
|
||||||
# methods [instance, static, class, property],保留__init__方法
|
|
||||||
if isinstance(class_node, ast.FunctionDef) and (not ignore_private or not class_node.name.startswith('_') or class_node.name == "__init__"):
|
|
||||||
method_docstring = ast.get_docstring(class_node)
|
|
||||||
def_type = DefType.METHOD
|
|
||||||
if class_node.decorator_list:
|
|
||||||
if any(isinstance(decorator, ast.Name) and decorator.id == "staticmethod" for decorator in class_node.decorator_list):
|
|
||||||
def_type = DefType.STATIC_METHOD
|
|
||||||
elif any(isinstance(decorator, ast.Name) and decorator.id == "classmethod" for decorator in class_node.decorator_list):
|
|
||||||
def_type = DefType.CLASS_METHOD
|
|
||||||
elif any(isinstance(decorator, ast.Name) and decorator.id == "property" for decorator in class_node.decorator_list):
|
|
||||||
def_type = DefType.PROPERTY
|
|
||||||
class_info.methods.append(FunctionInfo(
|
|
||||||
name=class_node.name,
|
|
||||||
args=[(arg.arg, ast.unparse(arg.annotation) if arg.annotation else NO_TYPE_ANY) for arg in class_node.args.args],
|
|
||||||
return_type=ast.unparse(class_node.returns) if class_node.returns else "None",
|
|
||||||
docstring=method_docstring if method_docstring else "",
|
|
||||||
type=def_type,
|
|
||||||
is_async=isinstance(class_node, ast.AsyncFunctionDef),
|
|
||||||
source_code=ast.unparse(class_node)
|
|
||||||
))
|
|
||||||
# attributes
|
|
||||||
elif isinstance(class_node, ast.Assign):
|
|
||||||
for target in class_node.targets:
|
|
||||||
if isinstance(target, ast.Name):
|
|
||||||
class_info.attributes.append(AttributeInfo(
|
|
||||||
name=target.id,
|
|
||||||
type=ast.unparse(class_node.value)
|
|
||||||
))
|
|
||||||
module_info.classes.append(class_info)
|
|
||||||
|
|
||||||
elif isinstance(node, ast.Assign):
|
|
||||||
# 检查是否在类或函数中
|
|
||||||
if not any(isinstance(parent, (ast.ClassDef, ast.FunctionDef)) for parent in ast.iter_child_nodes(node)):
|
|
||||||
# 模块属性变量
|
|
||||||
for target in node.targets:
|
|
||||||
if isinstance(target, ast.Name) and (not ignore_private or not target.id.startswith('_')):
|
|
||||||
attr_type = NO_TYPE_HINT
|
|
||||||
if isinstance(node.value, ast.AnnAssign) and node.value.annotation:
|
|
||||||
attr_type = ast.unparse(node.value.annotation)
|
|
||||||
module_info.attributes.append(AttributeInfo(
|
|
||||||
name=target.id,
|
|
||||||
type=attr_type,
|
|
||||||
value=ast.unparse(node.value) if node.value else None
|
|
||||||
))
|
|
||||||
|
|
||||||
return module_info
|
|
||||||
|
|
||||||
|
|
||||||
def generate_markdown(module_info: ModuleInfo, front_matter=None, lang: str = "zh-CN") -> str:
|
|
||||||
"""
|
|
||||||
生成模块的Markdown
|
|
||||||
你可在此自定义生成的Markdown格式
|
|
||||||
Args:
|
|
||||||
module_info: 模块信息
|
|
||||||
front_matter: 自定义选项title, index, icon, category
|
|
||||||
lang: 语言
|
|
||||||
Returns:
|
|
||||||
Markdown 字符串
|
|
||||||
"""
|
|
||||||
|
|
||||||
content = ""
|
|
||||||
|
|
||||||
front_matter = "---\n" + "\n".join([f"{k}: {v}" for k, v in front_matter.items()]) + "\n---\n\n"
|
|
||||||
|
|
||||||
content += front_matter
|
|
||||||
|
|
||||||
# 模块函数
|
|
||||||
for func in module_info.functions:
|
|
||||||
args_with_type = [f"{arg[0]}: {arg[1]}" if arg[1] else arg[0] for arg in func.args]
|
|
||||||
content += f"### ***{'async ' if func.is_async else ''}def*** `{func.name}({', '.join(args_with_type)}) -> {func.return_type}`\n\n"
|
|
||||||
|
|
||||||
func.docstring = func.docstring.replace("\n", "\n\n")
|
|
||||||
content += f"{func.docstring}\n\n"
|
|
||||||
|
|
||||||
# 函数源代码可展开区域
|
|
||||||
content += f"<details>\n<summary>源代码</summary>\n\n```python\n{func.source_code}\n```\n</details>\n\n"
|
|
||||||
|
|
||||||
# 类
|
|
||||||
for cls in module_info.classes:
|
|
||||||
if cls.inherit:
|
|
||||||
inherit = f"({', '.join(cls.inherit)})" if cls.inherit else ""
|
|
||||||
content += f"### ***class*** `{cls.name}{inherit}`\n\n"
|
|
||||||
else:
|
|
||||||
content += f"### ***class*** `{cls.name}`\n\n"
|
|
||||||
|
|
||||||
cls.docstring = cls.docstring.replace("\n", "\n\n")
|
|
||||||
content += f"{cls.docstring}\n\n"
|
|
||||||
for method in cls.methods:
|
|
||||||
# 类函数
|
|
||||||
|
|
||||||
if method.type != DefType.METHOD:
|
|
||||||
args_with_type = [f"{arg[0]}: {arg[1]}" if arg[1] else arg[0] for arg in method.args]
|
|
||||||
content += f"###   ***@{method.type.value}***\n"
|
|
||||||
else:
|
|
||||||
# self不加类型提示
|
|
||||||
args_with_type = [f"{arg[0]}: {arg[1]}" if arg[1] and arg[0] != "self" else arg[0] for arg in method.args]
|
|
||||||
content += f"###   ***{'async ' if method.is_async else ''}def*** `{method.name}({', '.join(args_with_type)}) -> {method.return_type}`\n\n"
|
|
||||||
|
|
||||||
method.docstring = method.docstring.replace("\n", "\n\n")
|
|
||||||
content += f" {method.docstring}\n\n"
|
|
||||||
# 函数源代码可展开区域
|
|
||||||
|
|
||||||
if lang == "zh-CN":
|
|
||||||
TEXT_SOURCE_CODE = "源代码"
|
|
||||||
else:
|
|
||||||
TEXT_SOURCE_CODE = "Source Code"
|
|
||||||
|
|
||||||
content += f"<details>\n<summary>{TEXT_SOURCE_CODE}</summary>\n\n```python\n{method.source_code}\n```\n</details>\n\n"
|
|
||||||
for attr in cls.attributes:
|
|
||||||
content += f"###   ***attr*** `{attr.name}: {attr.type}`\n\n"
|
|
||||||
|
|
||||||
# 模块属性
|
|
||||||
for attr in module_info.attributes:
|
|
||||||
if attr.type == NO_TYPE_HINT:
|
|
||||||
content += f"### ***var*** `{attr.name} = {attr.value}`\n\n"
|
|
||||||
else:
|
|
||||||
content += f"### ***var*** `{attr.name}: {attr.type} = {attr.value}`\n\n"
|
|
||||||
|
|
||||||
attr.docstring = attr.docstring.replace("\n", "\n\n")
|
|
||||||
content += f"{attr.docstring}\n\n"
|
|
||||||
|
|
||||||
return content
|
|
||||||
|
|
||||||
|
|
||||||
def generate_docs(module_folder: str, output_dir: str, with_top: bool = False, lang: str = "zh-CN", ignored_paths=None):
|
|
||||||
"""
|
|
||||||
生成文档
|
|
||||||
Args:
|
|
||||||
module_folder: 模块文件夹
|
|
||||||
output_dir: 输出文件夹
|
|
||||||
with_top: 是否包含顶层文件夹 False时例如docs/api/module_a, docs/api/module_b, True时例如docs/api/module/module_a.md, docs/api/module/module_b.md
|
|
||||||
ignored_paths: 忽略的路径
|
|
||||||
lang: 语言
|
|
||||||
"""
|
|
||||||
if ignored_paths is None:
|
|
||||||
ignored_paths = []
|
|
||||||
file_data: dict[str, str] = {} # 路径 -> 字串
|
|
||||||
|
|
||||||
file_list = get_file_list(module_folder)
|
|
||||||
|
|
||||||
# 清理输出目录
|
|
||||||
shutil.rmtree(output_dir, ignore_errors=True)
|
|
||||||
os.mkdir(output_dir)
|
|
||||||
|
|
||||||
replace_data = {
|
|
||||||
"__init__": "README",
|
|
||||||
".py" : ".md",
|
|
||||||
}
|
|
||||||
|
|
||||||
for pyfile_path in file_list:
|
|
||||||
if any(ignored_path.replace("\\", "/") in pyfile_path.replace("\\", "/") for ignored_path in ignored_paths):
|
|
||||||
continue
|
|
||||||
|
|
||||||
no_module_name_pyfile_path = get_relative_path(module_folder, pyfile_path) # 去头路径
|
|
||||||
|
|
||||||
# markdown相对路径
|
|
||||||
rel_md_path = pyfile_path if with_top else no_module_name_pyfile_path
|
|
||||||
for rk, rv in replace_data.items():
|
|
||||||
rel_md_path = rel_md_path.replace(rk, rv)
|
|
||||||
|
|
||||||
abs_md_path = os.path.join(output_dir, rel_md_path)
|
|
||||||
|
|
||||||
# 获取模块信息
|
|
||||||
module_info = get_module_info_normal(pyfile_path)
|
|
||||||
|
|
||||||
# 生成markdown
|
|
||||||
|
|
||||||
if "README" in abs_md_path:
|
|
||||||
front_matter = {
|
|
||||||
"title" : module_info.module_path.replace(".__init__", "").replace("_", "\\n"),
|
|
||||||
"index" : "true",
|
|
||||||
"icon" : "laptop-code",
|
|
||||||
"category": "API"
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
front_matter = {
|
|
||||||
"title" : module_info.module_path.replace("_", "\\n"),
|
|
||||||
"order" : "1",
|
|
||||||
"icon" : "laptop-code",
|
|
||||||
"category": "API"
|
|
||||||
}
|
|
||||||
|
|
||||||
md_content = generate_markdown(module_info, front_matter)
|
|
||||||
print(f"Generate {pyfile_path} -> {abs_md_path}")
|
|
||||||
file_data[abs_md_path] = md_content
|
|
||||||
|
|
||||||
write_to_files(file_data)
|
|
||||||
|
|
||||||
|
|
||||||
# 入口脚本
|
|
||||||
if __name__ == '__main__':
|
|
||||||
# 这里填入你的模块路径
|
|
||||||
generate_docs('liteyuki', 'docs/dev/api', with_top=False, ignored_paths=["liteyuki/plugins"], lang="zh-CN")
|
|
||||||
generate_docs('liteyuki', 'docs/en/dev/api', with_top=False, ignored_paths=["liteyuki/plugins"], lang="en")
|
|
@ -9,6 +9,8 @@ from magicoca import Chan, select
|
|||||||
|
|
||||||
from liteyuki.log import logger
|
from liteyuki.log import logger
|
||||||
|
|
||||||
|
from .models import *
|
||||||
|
|
||||||
|
|
||||||
def message_handler_thread(i_chans: Iterable[Chan[Any]]):
|
def message_handler_thread(i_chans: Iterable[Chan[Any]]):
|
||||||
"""
|
"""
|
||||||
@ -18,4 +20,4 @@ def message_handler_thread(i_chans: Iterable[Chan[Any]]):
|
|||||||
"""
|
"""
|
||||||
for msg in select(*i_chans):
|
for msg in select(*i_chans):
|
||||||
logger.debug(f"Recv from anybot {msg}")
|
logger.debug(f"Recv from anybot {msg}")
|
||||||
logger.info(f"Recv from anybot {msg}")
|
logger.info(f"Recv from anybot {msg}")
|
||||||
|
@ -1,5 +1,49 @@
|
|||||||
|
"""
|
||||||
|
本模块使用了[nonebot-plugin-uninfo](https://github.com/RF-Tar-Railt/nonebot-plugin-uninfo)的部分模型定义
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 RF-Tar-Railt
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Any
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class SceneType(int, Enum):
|
||||||
|
PRIVATE = 0
|
||||||
|
"""私聊场景"""
|
||||||
|
GROUP = 1
|
||||||
|
"""群聊场景"""
|
||||||
|
GUILD = 2
|
||||||
|
"""频道场景"""
|
||||||
|
CHANNEL_TEXT = 3
|
||||||
|
"""子频道文本场景"""
|
||||||
|
CHANNEL_CATEGORY = 4
|
||||||
|
"""频道分类场景"""
|
||||||
|
CHANNEL_VOICE = 5
|
||||||
|
"""子频道语音场景"""
|
||||||
|
|
||||||
|
|
||||||
class User(BaseModel):
|
class User(BaseModel):
|
||||||
"""
|
"""
|
||||||
用户信息
|
用户信息
|
||||||
@ -9,10 +53,13 @@ class User(BaseModel):
|
|||||||
nick: 用户昵称
|
nick: 用户昵称
|
||||||
avatar: 用户头像图链接
|
avatar: 用户头像图链接
|
||||||
"""
|
"""
|
||||||
|
|
||||||
id: str
|
id: str
|
||||||
name: str | None
|
name: str | None = None
|
||||||
nick: str | None
|
nick: str | None = None
|
||||||
avatar: str | None
|
avatar: str | None = None
|
||||||
|
gender: str | None = None
|
||||||
|
|
||||||
|
|
||||||
class Scene(BaseModel):
|
class Scene(BaseModel):
|
||||||
"""
|
"""
|
||||||
@ -24,11 +71,28 @@ class Scene(BaseModel):
|
|||||||
avatar: 场景头像图链接
|
avatar: 场景头像图链接
|
||||||
parent: 父场景
|
parent: 父场景
|
||||||
"""
|
"""
|
||||||
|
|
||||||
id: str
|
id: str
|
||||||
type: str
|
type: SceneType
|
||||||
name: str | None
|
name: str | None = None
|
||||||
avatar: str | None
|
avatar: str | None = None
|
||||||
parent: "Scene | None"
|
parent: "Scene | None" = None
|
||||||
|
|
||||||
|
|
||||||
|
class Role(BaseModel):
|
||||||
|
id: str
|
||||||
|
level: int | None = None
|
||||||
|
name: str | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class Member(BaseModel):
|
||||||
|
user: User
|
||||||
|
nickname: str | None = None
|
||||||
|
role: Role | None = None
|
||||||
|
|
||||||
|
mute: bool | None = None
|
||||||
|
joined_at: datetime | None = None
|
||||||
|
|
||||||
|
|
||||||
class Session(BaseModel):
|
class Session(BaseModel):
|
||||||
"""
|
"""
|
||||||
@ -41,11 +105,43 @@ class Session(BaseModel):
|
|||||||
user: 用户信息
|
user: 用户信息
|
||||||
member: 成员信息,仅频道及群聊有效
|
member: 成员信息,仅频道及群聊有效
|
||||||
operator: 操作者信息,仅频道及群聊有效
|
operator: 操作者信息,仅频道及群聊有效
|
||||||
|
|
||||||
|
session_id: 会话ID,精确到会话,用于快速标识会话,通常为{适配器范围}:{群聊ID(公共)/用户ID(群聊)}
|
||||||
|
target_id: 目标ID,精确到用户,用于快速标识会话,通常为{适配器范围}:{群聊ID}:{用户ID}(仅公共) 或 {适配器范围}:{用户ID}(仅私聊)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self_id: str
|
self_id: str
|
||||||
adapter: str
|
adapter: str
|
||||||
scope: str
|
scope: str
|
||||||
scene: Scene
|
scene: Scene
|
||||||
user: User
|
user: User
|
||||||
member: "Member | None"
|
member: "Member | None" = None
|
||||||
operator: "Member | None"
|
operator: "Member | None" = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def session_id(self):
|
||||||
|
if self.scope == SceneType.PRIVATE:
|
||||||
|
return f"{self.scope}:{self.user.id}"
|
||||||
|
elif self.scope in (
|
||||||
|
SceneType.GROUP,
|
||||||
|
SceneType.GUILD,
|
||||||
|
SceneType.CHANNEL_TEXT,
|
||||||
|
SceneType.CHANNEL_VOICE,
|
||||||
|
SceneType.CHANNEL_CATEGORY,
|
||||||
|
):
|
||||||
|
return f"{self.scope}:{self.scene.id}"
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid SceneType")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_id(self):
|
||||||
|
if self.scope == SceneType.PRIVATE:
|
||||||
|
return f"{self.scope}:{self.user.id}"
|
||||||
|
elif self.scope in (
|
||||||
|
SceneType.GROUP,
|
||||||
|
SceneType.GUILD,
|
||||||
|
SceneType.CHANNEL_TEXT,
|
||||||
|
SceneType.CHANNEL_VOICE,
|
||||||
|
SceneType.CHANNEL_CATEGORY,
|
||||||
|
):
|
||||||
|
return f"{self.scope}:{self.scene.id}:{self.user.id}"
|
||||||
|
52
pdm.lock
52
pdm.lock
@ -5,7 +5,7 @@
|
|||||||
groups = ["default", "dev"]
|
groups = ["default", "dev"]
|
||||||
strategy = ["inherit_metadata"]
|
strategy = ["inherit_metadata"]
|
||||||
lock_version = "4.5.0"
|
lock_version = "4.5.0"
|
||||||
content_hash = "sha256:b79773f31b417a430bc17fa770a0ff937c3ed0a3d1ac18950fdf4d5c405a28af"
|
content_hash = "sha256:4ccaad15580313d375bbd9032a7e564dd2304d2140cb93756d1ca40aaf5838d6"
|
||||||
|
|
||||||
[[metadata.targets]]
|
[[metadata.targets]]
|
||||||
requires_python = ">=3.10"
|
requires_python = ">=3.10"
|
||||||
@ -89,7 +89,7 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "croterline"
|
name = "croterline"
|
||||||
version = "1.0.9"
|
version = "1.0.10"
|
||||||
requires_python = ">=3.10"
|
requires_python = ">=3.10"
|
||||||
summary = "Default template for PDM package"
|
summary = "Default template for PDM package"
|
||||||
groups = ["default"]
|
groups = ["default"]
|
||||||
@ -97,8 +97,8 @@ dependencies = [
|
|||||||
"magicoca>=1.0.6",
|
"magicoca>=1.0.6",
|
||||||
]
|
]
|
||||||
files = [
|
files = [
|
||||||
{file = "croterline-1.0.9-py3-none-any.whl", hash = "sha256:d2d62bd8038ea0a845175b4a2ac127e4c4fcdb8dab5d4a04804c8af0a30986eb"},
|
{file = "croterline-1.0.10-py3-none-any.whl", hash = "sha256:c1248ddec86fcf9b6c2ca0607a4bed64d8a1693a02d9fa047eb529b6619e30f0"},
|
||||||
{file = "croterline-1.0.9.tar.gz", hash = "sha256:417a3aa2b18ee362f6b22939d918db378dceb1992b0231f3b80cbbdde4cb2f0a"},
|
{file = "croterline-1.0.10.tar.gz", hash = "sha256:d55eb981a12c894cbd37004725c52b29eb323551d3a045d2eb9b5328422a145a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -142,13 +142,13 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "magicoca"
|
name = "magicoca"
|
||||||
version = "1.0.6"
|
version = "1.0.7"
|
||||||
requires_python = ">=3.10"
|
requires_python = ">=3.10"
|
||||||
summary = "A communication library for Python"
|
summary = "A communication library for Python"
|
||||||
groups = ["default"]
|
groups = ["default"]
|
||||||
files = [
|
files = [
|
||||||
{file = "magicoca-1.0.6-py3-none-any.whl", hash = "sha256:3c62d6c3e87b3b5a13e0fd5b5fb674374355326684ab4421f2ac8a4c5127455e"},
|
{file = "magicoca-1.0.7-py3-none-any.whl", hash = "sha256:1a39966fd7038f3c8751b060b4098409798fe1c5a30497c83c7d8ea641dba91a"},
|
||||||
{file = "magicoca-1.0.6.tar.gz", hash = "sha256:e32ec57d67e64232dc7681c5095166e6a0ee3d27048d7115aa2b09ce4e7d9ff6"},
|
{file = "magicoca-1.0.7.tar.gz", hash = "sha256:89f2be0f9c92db2cdd50e0095c3edd0482ce082717e88adc02054a0d67a9820e"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -443,29 +443,29 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uv"
|
name = "uv"
|
||||||
version = "0.4.24"
|
version = "0.4.25"
|
||||||
requires_python = ">=3.8"
|
requires_python = ">=3.8"
|
||||||
summary = "An extremely fast Python package and project manager, written in Rust."
|
summary = "An extremely fast Python package and project manager, written in Rust."
|
||||||
groups = ["dev"]
|
groups = ["dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "uv-0.4.24-py3-none-linux_armv6l.whl", hash = "sha256:bbc24b232c5e874741d863c5bec2257533db86f91381f1a101872028a0502ec9"},
|
{file = "uv-0.4.25-py3-none-linux_armv6l.whl", hash = "sha256:94fb2b454afa6bdfeeea4b4581c878944ca9cf3a13712e6762f245f5fbaaf952"},
|
||||||
{file = "uv-0.4.24-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8d467d4c4746127b2121d6f67686957a2b5431935d26767aa02fa4516694293"},
|
{file = "uv-0.4.25-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a7c3a18c20ddb527d296d1222bddf42b78031c50b5b4609d426569b5fb61f5b0"},
|
||||||
{file = "uv-0.4.24-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7d076875e9fa4d8cda44d3e51c9b47efc578db830535c62f25884772bfa265bc"},
|
{file = "uv-0.4.25-py3-none-macosx_11_0_arm64.whl", hash = "sha256:18100f0f36419a154306ed6211e3490bf18384cdf3f1a0950848bf64b62fa251"},
|
||||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:c40f75df1f2c45a7f67fcc69d80231760f6a017b7c8e889a16e21348651a34d7"},
|
{file = "uv-0.4.25-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:6e981b1465e30102e41946adede9cb08051a5d70c6daf09f91a7ea84f0b75c08"},
|
||||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b459913d8ba6edba2c4b299e87fccfbd7fca4b2e2abe5fd4fa0da56147e19fc8"},
|
{file = "uv-0.4.25-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:578ae385fad6bd6f3868828e33d54994c716b315b1bc49106ec1f54c640837e4"},
|
||||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e3ce0350e74b3dba6854789dd253faeab2fdf8e84f2671b68573070bb40ff17"},
|
{file = "uv-0.4.25-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d29a78f011ecc2f31c13605acb6574c2894c06d258b0f8d0dbb899986800450"},
|
||||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d274f7ddc013697fb52962632bc7e77889a6ec87d2cd12316d218686cfece3d4"},
|
{file = "uv-0.4.25-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ec181be2bda10651a3558156409ac481549983e0276d0e3645e3b1464e7f8715"},
|
||||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ef6914a7294ac7df5bd15b21652cbe61d1c12a0f29a94d178dce6192f858092"},
|
{file = "uv-0.4.25-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50c7d0d9e7f392f81b13bf3b7e37768d1486f2fc9d533a54982aa0ed11e4db23"},
|
||||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d8e5f66a8756d4908121cb59189e6f9992fdbd0f9c26a5a30a069b94f8acab3"},
|
{file = "uv-0.4.25-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2fc35b5273f1e018aecd66b70e0fd7d2eb6698853dde3e2fc644e7ebf9f825b1"},
|
||||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a3ea6780e3451c81ce1635656abcd8a47e43f1b0f02542c433b4b6dd459df8e"},
|
{file = "uv-0.4.25-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7022a71ff63a3838796f40e954b76bf7820fc27e96fe002c537e75ff8e34f1d"},
|
||||||
{file = "uv-0.4.24-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:beaff8fdaad3bcd781a8d28b60843b8d1cd2a04229847dc314c1bb7e0bb39ca2"},
|
{file = "uv-0.4.25-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:e02afb0f6d4b58718347f7d7cfa5a801e985ce42181ba971ed85ef149f6658ca"},
|
||||||
{file = "uv-0.4.24-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:70a76cb5b8a459d6f6931becf2b5689599382c2512341d566ce335b8304c44e8"},
|
{file = "uv-0.4.25-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:3d7680795ea78cdbabbcce73d039b2651cf1fa635ddc1aa3082660f6d6255c50"},
|
||||||
{file = "uv-0.4.24-py3-none-musllinux_1_1_i686.whl", hash = "sha256:29c514752873c1be259afd82b975e528ec6783564a306fd24deee0cccb2dc566"},
|
{file = "uv-0.4.25-py3-none-musllinux_1_1_i686.whl", hash = "sha256:aae9dcafd20d5ba978c8a4939ab942e8e2e155c109e9945207fbbd81d2892c9e"},
|
||||||
{file = "uv-0.4.24-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:c03a411f1b86ce7de25d6271d90358ba2d33e87b4922dc5378c4c07674909363"},
|
{file = "uv-0.4.25-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:4c55040e67470f2b73e95e432aba06f103a0b348ea0b9c6689b1029c8d9e89fd"},
|
||||||
{file = "uv-0.4.24-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:a03bc4b2ca2236eece97fffb8b5605b7a2248cd8a4b9a9c67955ad08756a1ceb"},
|
{file = "uv-0.4.25-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:bdbfd0c476b9e80a3f89af96aed6dd7d2782646311317a9c72614ccce99bb2ad"},
|
||||||
{file = "uv-0.4.24-py3-none-win32.whl", hash = "sha256:a97c347af12deb687c09fed82dc829efd6e5fbc4d76a38e98b2eaa2b065e4cfe"},
|
{file = "uv-0.4.25-py3-none-win32.whl", hash = "sha256:7d266e02fefef930609328c31c075084295c3cb472bab3f69549fad4fd9d82b3"},
|
||||||
{file = "uv-0.4.24-py3-none-win_amd64.whl", hash = "sha256:ec0570f5e2e4dbfd83a89e9a55d5f033050d749f684bd0e7d4c327fd49f89b12"},
|
{file = "uv-0.4.25-py3-none-win_amd64.whl", hash = "sha256:be2a4fc4fcade9ea5e67e51738c95644360d6e59b6394b74fc579fb617f902f7"},
|
||||||
{file = "uv-0.4.24.tar.gz", hash = "sha256:f71a00f10cfa15b4f4f0184a67da19f35c48683bba9bb49cebe9c206f1b2bc1f"},
|
{file = "uv-0.4.25.tar.gz", hash = "sha256:d39077cdfe3246885fcdf32e7066ae731a166101d063629f9cea08738f79e6a3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -13,7 +13,15 @@ from croterline.process import get_ctx
|
|||||||
from nonebot.adapters.onebot.v11 import MessageEvent
|
from nonebot.adapters.onebot.v11 import MessageEvent
|
||||||
from nonebot.plugin import PluginMetadata
|
from nonebot.plugin import PluginMetadata
|
||||||
from nonebot.log import logger
|
from nonebot.log import logger
|
||||||
from nonebot import on_message
|
from nonebot import on_message, require
|
||||||
|
from nonebot.adapters import Bot
|
||||||
|
|
||||||
|
from liteyuki.session import Session, SceneType
|
||||||
|
|
||||||
|
require("nonebot_plugin_uninfo")
|
||||||
|
|
||||||
|
from nonebot_plugin_uninfo import get_session, Role, ROLE_LEVEL
|
||||||
|
|
||||||
|
|
||||||
__plugin_meta__ = PluginMetadata(
|
__plugin_meta__ = PluginMetadata(
|
||||||
name="轻雪push",
|
name="轻雪push",
|
||||||
@ -22,12 +30,15 @@ __plugin_meta__ = PluginMetadata(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ctx = get_ctx()
|
ctx = get_ctx()
|
||||||
|
|
||||||
@on_message(block=False, priority=100).handle()
|
|
||||||
async def _(event: MessageEvent):
|
@on_message(block=False, priority=0).handle()
|
||||||
|
async def _(bot: Bot, event: MessageEvent):
|
||||||
|
session = await get_session(bot, event)
|
||||||
|
print("Role", session.member.role)
|
||||||
|
new_session = Session(**session.dump())
|
||||||
|
|
||||||
|
logger.debug("SESSION", new_session)
|
||||||
logger.debug("Pushing message to Liteyuki")
|
logger.debug("Pushing message to Liteyuki")
|
||||||
ctx.sub_chan << event.raw_message
|
ctx.sub_chan << event.raw_message
|
||||||
logger.debug("Pushed message to Liteyuki")
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user