diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 00000000..217e5d92 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,24 @@ +name: Pre-commit checks + +on: [push, pull_request] + +jobs: + pre-commit: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.10' # 选择适合你的项目的 Python 版本 + + - name: Install dependencies + run: | + python -m pip install pdm + pdm install + + - name: Run pre-commit + run: pre-commit run --all-files diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index 2c9b2009..ffab609a 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -43,4 +43,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: Pytest-test-report - path: report \ No newline at end of file + path: report diff --git a/.gitignore b/.gitignore index dd66346a..a26b9f50 100644 --- a/.gitignore +++ b/.gitignore @@ -176,4 +176,4 @@ praises.json config/ # dev -.vscode/ \ No newline at end of file +.vscode/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..4d3c8a95 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,25 @@ +fail_fast: true +repos: + - repo: https://github.com/timothycrosley/isort + rev: 5.13.2 + hooks: + - id: isort + + # - repo: https://github.com/psf/black + # rev: 24.4.2 + # hooks: + # - id: black + # args: [--config=./pyproject.toml] + + # - repo: https://github.com/pre-commit/mirrors-mypy + # rev: v0.910 + # hooks: + # - id: mypy + + # - repo: https://github.com/pre-commit/pre-commit-hooks + # rev: v4.0.1 + # hooks: + # - id: trailing-whitespace + # - id: end-of-file-fixer + # - id: check-yaml + # - id: check-added-large-files \ No newline at end of file diff --git a/README.md b/README.md index 976621bf..ab8200c1 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,9 @@ _✨ 使用 OpenAI 标准格式 API 的聊天机器人插件 ✨_ ## 📖 介绍 -通过调用 OpenAI 标准格式 API(例如由 Azure OpenAI 驱动,GitHub Models 提供访问的生成式 AI 推理 API) 来实现聊天的插件。 -插件内置了猫娘小棉(Marsho)的人物设定,可以进行可爱的聊天! -*谁不喜欢回复消息快又可爱的猫娘呢?* +通过调用 OpenAI 标准格式 API(例如由 Azure OpenAI 驱动,GitHub Models 提供访问的生成式 AI 推理 API) 来实现聊天的插件。 +插件内置了猫娘小棉(Marsho)的人物设定,可以进行可爱的聊天! +*谁不喜欢回复消息快又可爱的猫娘呢?* **对 OneBot 以外的适配器与非 GitHub Models API的支持未经过完全验证。** [Melobot 实现](https://github.com/LiteyukiStudio/marshoai-melo) @@ -101,13 +101,13 @@ _✨ 使用 OpenAI 标准格式 API 的聊天机器人插件 ✨_ 当 nonebot 连接到支持的 OneBot v11 实现端时,可以接收头像双击戳一戳消息并进行响应。详见`MARSHOAI_POKE_SUFFIX`配置项。 ## 🛠️ 小棉工具 -小棉工具(MarshoTools)是`v0.5.0`版本的新增功能,支持加载外部函数库来为 Marsho 提供 Function Call 功能。[使用文档](./README_TOOLS.md) +小棉工具(MarshoTools)是`v0.5.0`版本的新增功能,支持加载外部函数库来为 Marsho 提供 Function Call 功能。[使用文档](./README_TOOLS.md) ## 👍 夸赞名单 夸赞名单存储于插件数据目录下的`praises.json`里(该目录路径会在 Bot 启动时输出到日志),当配置项为`true` -时发起一次聊天后自动生成,包含人物名字与人物优点两个基本数据。 -存储于其中的人物会被 Marsho “认识”和“喜欢”。 +时发起一次聊天后自动生成,包含人物名字与人物优点两个基本数据。 +存储于其中的人物会被 Marsho “认识”和“喜欢”。 其结构类似于: ```json @@ -176,10 +176,10 @@ _✨ 使用 OpenAI 标准格式 API 的聊天机器人插件 ✨_ ## ❤ 鸣谢&版权说明 本项目使用了以下项目的代码: -- [nonebot-plugin-latex](https://github.com/EillesWan/nonebot-plugin-latex) +- [nonebot-plugin-latex](https://github.com/EillesWan/nonebot-plugin-latex) "Marsho" logo 由 [@Asankilp](https://github.com/Asankilp) -绘制,基于 [CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) 许可下提供。 +绘制,基于 [CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) 许可下提供。 "nonebot-plugin-marshoai" 基于 [MIT](./LICENSE-MIT) 许可下提供。 部分指定的代码基于 [Mulan PSL v2](./LICENSE-MULAN) 许可下提供。 diff --git a/README_EN.md b/README_EN.md index 81de6d24..187785da 100644 --- a/README_EN.md +++ b/README_EN.md @@ -22,11 +22,11 @@ _✨ A chat bot plugin which use OpenAI standard API ✨_ ## 📖 Indroduction -A plugin made by call OpenAI standard API(Such as GitHub Models API) +A plugin made by call OpenAI standard API(Such as GitHub Models API) Plugin internally installed the catgirl character of Marsho, is able to have a cute conversation! -*Who don't like a cute catgirl with fast answer speed?* +*Who don't like a cute catgirl with fast answer speed?* **Support for adapters other than OneBot and non-Github Models APIs is not fully verified.** @@ -50,7 +50,7 @@ Plugin internally installed the catgirl character of Marsho, is able to have a c
Install with nb-cli - + Open shell under the root directory of nonebot2, input the command below. nb plugin install nonebot-plugin-marshoai @@ -59,7 +59,7 @@ Open shell under the root directory of nonebot2, input the command below.
Install with pack manager - + Open shell under the plugin directory of nonebot2, input corresponding command according to your pack manager.
@@ -108,7 +108,7 @@ When nonebot linked to OneBot v11 adapter, can recieve double click and response ## 🛠️ MarshoTools -MarshoTools is a feature added in `v0.5.0`, support loading external function library to provide Function Call for Marsho. [Documentation](./README_TOOLS_EN.md) +MarshoTools is a feature added in `v0.5.0`, support loading external function library to provide Function Call for Marsho. [Documentation](./README_TOOLS_EN.md) ## 👍 Praise list @@ -184,7 +184,7 @@ Add options in the `.env` file from the diagram below in nonebot2 project. ## ❤ Thanks&Copyright This project uses the following code from other projects: -- [nonebot-plugin-latex](https://github.com/EillesWan/nonebot-plugin-latex) +- [nonebot-plugin-latex](https://github.com/EillesWan/nonebot-plugin-latex) "Marsho" logo contributed by [@Asankilp](https://github.com/Asankilp), licensed under [CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) lisense. diff --git a/README_TOOLS.md b/README_TOOLS.md index f9a5e880..07ac2932 100644 --- a/README_TOOLS.md +++ b/README_TOOLS.md @@ -1,5 +1,5 @@ # 🛠️小棉工具 -小棉工具(MarshoTools)是一个简单的模块加载器,允许从插件数据目录下的`tools`目录内加载数个工具包与其中定义的函数,以供 AI 模型调用。 +小棉工具(MarshoTools)是一个简单的模块加载器,允许从插件数据目录下的`tools`目录内加载数个工具包与其中定义的函数,以供 AI 模型调用。 有关 Function Call 的更多信息,请参阅[OpenAI 官方文档](https://platform.openai.com/docs/guides/function-calling)。 ## ✍️ 编写工具 @@ -64,11 +64,11 @@ async def get_current_time(): } ] ``` -在这个文件中定义了两个已经编写好的函数,该定义文件将被输入到 AI 模型中,来让 AI 模型知道这些函数的存在与调用方法。 +在这个文件中定义了两个已经编写好的函数,该定义文件将被输入到 AI 模型中,来让 AI 模型知道这些函数的存在与调用方法。 **函数调用名称**的命名方式比较特别。以获取天气的函数为例,它的函数调用名称`marshoai-example__get_weather`包含三个信息: - 前面的**marshoai-example**即为该函数所在工具包的**包名**。 - 后面的**get_weather**是这个函数在代码里的名称。 -- 中间的两个下划线是用于分割这两个信息的分隔符。 +- 中间的两个下划线是用于分割这两个信息的分隔符。 使用这种命名方式,是为了兼容更多的 OpenAI 标准格式 API。因此,在给工具包和函数取名时,不要使用带有两个下划线的名称。 ### 测试函数 @@ -78,7 +78,7 @@ async def get_current_time(): > marsho 深圳天气怎么样 深圳的天气显示温度是114514°C,真是不可思议呢!这一定是个误报吧~(≧▽≦) 希望你那里有个好天气哦! > marsho 分别告诉我下北泽,杭州,苏州的天气 -下北泽、杭州和苏州的天气都显示温度为114514°C呢!这么奇怪的温度,一定是个误报吧~(≧▽≦) +下北泽、杭州和苏州的天气都显示温度为114514°C呢!这么奇怪的温度,一定是个误报吧~(≧▽≦) 如果要查看真实的天气情况,建议查看专业天气预报哦~ > marsho 现在几点了 diff --git a/nonebot_plugin_marshoai/__init__.py b/nonebot_plugin_marshoai/__init__.py index b92a6ba2..6fd58a4b 100644 --- a/nonebot_plugin_marshoai/__init__.py +++ b/nonebot_plugin_marshoai/__init__.py @@ -3,8 +3,8 @@ from nonebot.plugin import require require("nonebot_plugin_alconna") require("nonebot_plugin_localstore") -from nonebot import get_driver, logger import nonebot_plugin_localstore as store +from nonebot import get_driver, logger # from .hunyuan import * from .azure import * diff --git a/nonebot_plugin_marshoai/azure.py b/nonebot_plugin_marshoai/azure.py index 475a6012..895679e1 100644 --- a/nonebot_plugin_marshoai/azure.py +++ b/nonebot_plugin_marshoai/azure.py @@ -1,33 +1,23 @@ -import traceback import contextlib -from typing import Optional +import traceback from pathlib import Path +from typing import Optional -from arclet.alconna import Alconna, Args, AllParam -from azure.ai.inference.models import ( - UserMessage, - AssistantMessage, - ToolMessage, - TextContentItem, - ImageContentItem, - ImageUrl, - CompletionsFinishReason, - ChatCompletionsToolCall, -) +import nonebot_plugin_localstore as store +from arclet.alconna import Alconna, AllParam, Args +from azure.ai.inference.models import (AssistantMessage, + ChatCompletionsToolCall, + CompletionsFinishReason, + ImageContentItem, ImageUrl, + TextContentItem, ToolMessage, + UserMessage) from azure.core.credentials import AzureKeyCredential -from nonebot import on_command, on_message, logger, get_driver -from nonebot.adapters import Message, Event +from nonebot import get_driver, logger, on_command, on_message +from nonebot.adapters import Event, Message from nonebot.params import CommandArg from nonebot.permission import SUPERUSER from nonebot.rule import Rule, to_me -from nonebot_plugin_alconna import ( - on_alconna, - MsgTarget, - UniMessage, - UniMsg, -) -import nonebot_plugin_localstore as store - +from nonebot_plugin_alconna import MsgTarget, UniMessage, UniMsg, on_alconna from .metadata import metadata from .models import MarshoContext, MarshoTools @@ -203,7 +193,7 @@ async def marsho(target: MsgTarget, event: Event, text: Optional[UniMsg] = None) not text and event.get_message().extract_plain_text() != config.marshoai_default_name ): - text = event.get_message() + text = event.get_message() # type: ignore if not text: # 发送说明 await UniMessage(metadata.usage + "\n当前使用的模型:" + model_name).send() @@ -233,12 +223,12 @@ async def marsho(target: MsgTarget, event: Event, text: Optional[UniMsg] = None) for i in text: if i.type == "text": if is_support_image_model: - usermsg += [TextContentItem(text=i.data["text"] + nickname_prompt)] + usermsg += [TextContentItem(text=i.data["text"] + nickname_prompt)] # type: ignore else: - usermsg += str(i.data["text"] + nickname_prompt) + usermsg += str(i.data["text"] + nickname_prompt) # type: ignore elif i.type == "image": if is_support_image_model: - usermsg.append( + usermsg.append( # type: ignore ImageContentItem( image_url=ImageUrl( url=str(await get_image_b64(i.data["url"])) @@ -260,7 +250,7 @@ async def marsho(target: MsgTarget, event: Event, text: Optional[UniMsg] = None) response = await make_chat( client=client, model_name=model_name, - msg=context_msg + [UserMessage(content=usermsg)], + msg=context_msg + [UserMessage(content=usermsg)], # type: ignore tools=tools.get_tools_list(), ) # await UniMessage(str(response)).send() @@ -268,7 +258,7 @@ async def marsho(target: MsgTarget, event: Event, text: Optional[UniMsg] = None) if choice["finish_reason"] == CompletionsFinishReason.STOPPED: # 当对话成功时,将dict的上下文添加到上下文类中 context.append( - UserMessage(content=usermsg).as_dict(), target.id, target.private + UserMessage(content=usermsg).as_dict(), target.id, target.private # type: ignore ) context.append(choice.message.as_dict(), target.id, target.private) if [target.id, target.private] not in target_list: @@ -314,12 +304,12 @@ async def marsho(target: MsgTarget, event: Event, text: Optional[UniMsg] = None) tool_call.function.name, function_args ) # 获取返回值 tool_msg.append( - ToolMessage(tool_call_id=tool_call.id, content=func_return) + ToolMessage(tool_call_id=tool_call.id, content=func_return) # type: ignore ) response = await make_chat( client=client, model_name=model_name, - msg=context_msg + [UserMessage(content=usermsg)] + tool_msg, + msg=context_msg + [UserMessage(content=usermsg)] + tool_msg, # type: ignore tools=tools.get_tools_list(), ) choice = response.choices[0] @@ -327,7 +317,7 @@ async def marsho(target: MsgTarget, event: Event, text: Optional[UniMsg] = None) # 对话成功 添加上下文 context.append( - UserMessage(content=usermsg).as_dict(), target.id, target.private + UserMessage(content=usermsg).as_dict(), target.id, target.private # type: ignore ) # context.append(tool_msg, target.id, target.private) context.append(choice.message.as_dict(), target.id, target.private) @@ -351,6 +341,7 @@ async def marsho(target: MsgTarget, event: Event, text: Optional[UniMsg] = None) with contextlib.suppress(ImportError): # 优化先不做() import nonebot.adapters.onebot.v11 # type: ignore + from .azure_onebot import poke_notify @poke_notify.handle() diff --git a/nonebot_plugin_marshoai/azure_onebot.py b/nonebot_plugin_marshoai/azure_onebot.py index 82c866c4..62b85649 100644 --- a/nonebot_plugin_marshoai/azure_onebot.py +++ b/nonebot_plugin_marshoai/azure_onebot.py @@ -1,5 +1,5 @@ from nonebot import on_type -from nonebot.rule import to_me from nonebot.adapters.onebot.v11 import PokeNotifyEvent # type: ignore +from nonebot.rule import to_me poke_notify = on_type((PokeNotifyEvent,), rule=to_me()) diff --git a/nonebot_plugin_marshoai/config.py b/nonebot_plugin_marshoai/config.py index c842fa1e..53cb7ef9 100644 --- a/nonebot_plugin_marshoai/config.py +++ b/nonebot_plugin_marshoai/config.py @@ -1,11 +1,11 @@ import shutil - -from pydantic import BaseModel -from nonebot import logger, get_plugin_config -from ruamel.yaml import YAML -import yaml as yaml_ from pathlib import Path +import yaml as yaml_ +from nonebot import get_plugin_config, logger +from pydantic import BaseModel +from ruamel.yaml import YAML + class ConfigModel(BaseModel): marshoai_use_yaml_config: bool = False diff --git a/nonebot_plugin_marshoai/constants.py b/nonebot_plugin_marshoai/constants.py index 20362738..a8cd55b3 100644 --- a/nonebot_plugin_marshoai/constants.py +++ b/nonebot_plugin_marshoai/constants.py @@ -1,4 +1,5 @@ import re + from .config import config USAGE: str = f"""MarshoAI-NoneBot Beta by Asankilp diff --git a/nonebot_plugin_marshoai/deal_latex.py b/nonebot_plugin_marshoai/deal_latex.py index e66e2e90..5eeec9e8 100644 --- a/nonebot_plugin_marshoai/deal_latex.py +++ b/nonebot_plugin_marshoai/deal_latex.py @@ -14,10 +14,11 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. """ -from typing import Optional, Literal, Tuple -from nonebot import logger -import httpx import time +from typing import Literal, Optional, Tuple + +import httpx +from nonebot import logger class ConvertChannel: @@ -90,7 +91,7 @@ class L2PChannel(ConvertChannel): @staticmethod def channel_test() -> int: - with httpx.Client(timeout=5,verify=False) as client: + with httpx.Client(timeout=5, verify=False) as client: try: start_time = time.time_ns() latex2png = ( @@ -156,7 +157,7 @@ class CDCChannel(ConvertChannel): @staticmethod def channel_test() -> int: - with httpx.Client(timeout=5,verify=False) as client: + with httpx.Client(timeout=5, verify=False) as client: try: start_time = time.time_ns() codecogs = ( @@ -223,7 +224,7 @@ class JRTChannel(ConvertChannel): @staticmethod def channel_test() -> int: - with httpx.Client(timeout=5,verify=False) as client: + with httpx.Client(timeout=5, verify=False) as client: try: start_time = time.time_ns() joeraut = ( diff --git a/nonebot_plugin_marshoai/hunyuan.py b/nonebot_plugin_marshoai/hunyuan.py index 504fd922..9e521897 100644 --- a/nonebot_plugin_marshoai/hunyuan.py +++ b/nonebot_plugin_marshoai/hunyuan.py @@ -1,36 +1,38 @@ import contextlib -import traceback import json +import traceback from typing import Optional -from arclet.alconna import Alconna, Args, AllParam -from nonebot import on_command, logger -from nonebot.adapters import Message, Event +from arclet.alconna import Alconna, AllParam, Args +from nonebot import get_driver, logger, on_command +from nonebot.adapters import Event, Message from nonebot.params import CommandArg from nonebot.permission import SUPERUSER -from nonebot_plugin_alconna import on_alconna, MsgTarget +from nonebot_plugin_alconna import MsgTarget, on_alconna from nonebot_plugin_alconna.uniseg import UniMessage, UniMsg -from nonebot import get_driver + +from .config import config from .constants import * from .metadata import metadata from .models import MarshoContext from .util_hunyuan import * -from .config import config + genimage_cmd = on_alconna( Alconna( "genimage", Args["prompt?", str], - ) ) +) + @genimage_cmd.handle() async def genimage(event: Event, prompt=None): if not prompt: - await genimage_cmd.finish("无提示词") + await genimage_cmd.finish("无提示词") try: result = generate_image(prompt) url = json.loads(result)["ResultImage"] await UniMessage.image(url=url).send() except Exception as e: - # await genimage_cmd.finish(str(e)) + # await genimage_cmd.finish(str(e)) traceback.print_exc() diff --git a/nonebot_plugin_marshoai/models.py b/nonebot_plugin_marshoai/models.py index 174c03f6..e788e0c8 100644 --- a/nonebot_plugin_marshoai/models.py +++ b/nonebot_plugin_marshoai/models.py @@ -1,14 +1,15 @@ -from .util import * -from .config import config -import os -import json import importlib +import json +import os import sys - # import importlib.util import traceback + from nonebot import logger +from .config import config +from .util import * + class MarshoContext: """ @@ -75,7 +76,7 @@ class MarshoTools: for package_name in os.listdir(tools_dir): package_path = os.path.join(tools_dir, package_name) - # logger.info(f"尝试加载工具包 {package_name}") + # logger.info(f"尝试加载工具包 {package_name}") if package_name in config.marshoai_disabled_toolkits: logger.info(f"工具包 {package_name} 已被禁用。") continue diff --git a/nonebot_plugin_marshoai/tools/marshoai-bangumi/__init__.py b/nonebot_plugin_marshoai/tools/marshoai-bangumi/__init__.py index 1952c3df..88629ef2 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-bangumi/__init__.py +++ b/nonebot_plugin_marshoai/tools/marshoai-bangumi/__init__.py @@ -1,22 +1,26 @@ -import httpx import traceback + +import httpx + + async def fetch_calendar(): - url = 'https://api.bgm.tv/calendar' + url = "https://api.bgm.tv/calendar" headers = { - 'User-Agent': 'LiteyukiStudio/nonebot-plugin-marshoai (https://github.com/LiteyukiStudio/nonebot-plugin-marshoai)' + "User-Agent": "LiteyukiStudio/nonebot-plugin-marshoai (https://github.com/LiteyukiStudio/nonebot-plugin-marshoai)" } async with httpx.AsyncClient() as client: response = await client.get(url, headers=headers) - #print(response.text) + # print(response.text) return response.json() + async def get_bangumi_news(): result = await fetch_calendar() info = "" try: for i in result: weekday = i["weekday"]["cn"] - #print(weekday) + # print(weekday) info += f"{weekday}:" items = i["items"] for item in items: @@ -26,4 +30,4 @@ async def get_bangumi_news(): return info except Exception as e: traceback.print_exc() - return "" \ No newline at end of file + return "" diff --git a/nonebot_plugin_marshoai/tools/marshoai-bangumi/tools.json b/nonebot_plugin_marshoai/tools/marshoai-bangumi/tools.json index c2c0b938..a814f53a 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-bangumi/tools.json +++ b/nonebot_plugin_marshoai/tools/marshoai-bangumi/tools.json @@ -6,4 +6,4 @@ "description": "获取今天的新番(动漫)列表,在调用之前,你需要知道今天星期几。" } } -] \ No newline at end of file +] diff --git a/nonebot_plugin_marshoai/tools/marshoai-basic/__init__.py b/nonebot_plugin_marshoai/tools/marshoai-basic/__init__.py index 7fe87d44..a76a3333 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-basic/__init__.py +++ b/nonebot_plugin_marshoai/tools/marshoai-basic/__init__.py @@ -1,4 +1,5 @@ import os + from zhDateTime import DateTime diff --git a/nonebot_plugin_marshoai/tools/marshoai-basic/tools.json b/nonebot_plugin_marshoai/tools/marshoai-basic/tools.json index eda028ef..47b477ed 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-basic/tools.json +++ b/nonebot_plugin_marshoai/tools/marshoai-basic/tools.json @@ -6,4 +6,4 @@ "description": "获取现在的日期,时间和星期。" } } -] \ No newline at end of file +] diff --git a/nonebot_plugin_marshoai/tools/marshoai-basic/tools_test.json b/nonebot_plugin_marshoai/tools/marshoai-basic/tools_test.json index 57f39351..833ef7cc 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-basic/tools_test.json +++ b/nonebot_plugin_marshoai/tools/marshoai-basic/tools_test.json @@ -4,7 +4,7 @@ "function": { "name": "marshoai-basic__get_weather", "description": "当你想查询指定城市的天气时非常有用。", - "parameters": { + "parameters": { "type": "object", "properties": { "location": { @@ -23,7 +23,7 @@ "function": { "name": "marshoai-basic__get_current_env", "description": "获取当前的运行环境。", - "parameters": { + "parameters": { } } }, @@ -32,8 +32,8 @@ "function": { "name": "marshoai-basic__get_current_time", "description": "获取现在的时间。", - "parameters": { + "parameters": { } } } -] \ No newline at end of file +] diff --git a/nonebot_plugin_marshoai/tools/marshoai-megakits/__init__.py b/nonebot_plugin_marshoai/tools/marshoai-megakits/__init__.py index 4c948371..16abf7d1 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-megakits/__init__.py +++ b/nonebot_plugin_marshoai/tools/marshoai-megakits/__init__.py @@ -1,37 +1,41 @@ +from . import mk_Common, mk_Info, mk_MorseCode, mk_NyaCode -from . import mk_Info -from . import mk_Common -from . import mk_MorseCode -from . import mk_NyaCode # Twisuki async def twisuki(): return str(await mk_Info.twisuki()) + # MegaKits async def megakits(): return str(await mk_Info.megakits()) + # Random Turntable async def random_turntable(upper: int, lower: int = 0): return str(await mk_Common.random_turntable(upper, lower)) + # Number Calc async def number_calc(a: str, b: str, op: str): return str(await mk_Common.number_calc(a, b, op)) + # MorseCode Encrypt async def morse_encrypt(msg: str): return str(await mk_MorseCode.morse_encrypt(msg)) + # MorseCode Decrypt async def morse_decrypt(msg: str): return str(await mk_MorseCode.morse_decrypt(msg)) + # NyaCode Encrypt async def nya_encode(msg: str): return str(await mk_NyaCode.nya_encode(msg)) + # NyaCode Decrypt async def nya_decode(msg: str): return str(await mk_NyaCode.nya_decode(msg)) diff --git a/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_Common.py b/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_Common.py index f93e0836..d2c914c7 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_Common.py +++ b/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_Common.py @@ -1,9 +1,11 @@ import random + # Random Turntable async def random_turntable(upper: int, lower: int): return random.randint(lower, upper) + # Number Calc async def number_calc(a: str, b: str, op: str): a, b = float(a), float(b) @@ -17,8 +19,8 @@ async def number_calc(a: str, b: str, op: str): case "/": return str(a / b) case "**": - return str(a ** b) + return str(a**b) case "%": return str(a % b) case _: - return "未知运算符" \ No newline at end of file + return "未知运算符" diff --git a/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_Info.py b/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_Info.py index 1178fb75..af364c8d 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_Info.py +++ b/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_Info.py @@ -1,7 +1,8 @@ # Twisuki async def twisuki(): - return "Twiuski(苏阳)是megakits插件作者, Github : \"https://github.com/Twisuki\"" + return 'Twiuski(苏阳)是megakits插件作者, Github : "https://github.com/Twisuki"' + # MegaKits async def megakits(): - return "MegaKits插件是一个功能混杂的MarshoAI插件, 由Twisuki(Github : \"https://github.com/Twisuki\")开发, 插件仓库 : \"https://github.com/LiteyukiStudio/marsho-toolsets/tree/main/Twisuki/marshoai-megakits\"" + return 'MegaKits插件是一个功能混杂的MarshoAI插件, 由Twisuki(Github : "https://github.com/Twisuki")开发, 插件仓库 : "https://github.com/LiteyukiStudio/marsho-toolsets/tree/main/Twisuki/marshoai-megakits"' diff --git a/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_MorseCode.py b/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_MorseCode.py index 562d5f3c..05aa8914 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_MorseCode.py +++ b/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_MorseCode.py @@ -1,17 +1,59 @@ # MorseCode MorseEncode = { - "A": ".-", "B": "-...", "C": "-.-.", "D": "-..", "E": ".", "F": "..-.", - "G": "--.", "H": "....", "I": "..", "J": ".---", "K": "-.-", "L": ".-..", - "M": "--", "N": "-.", "O": "---", "P": ".--.", "Q": "--.-", "R": ".-.", - "S": "...", "T": "-", "U": "..-", "V": "...-", "W": ".--", "X": "-..-", - "Y": "-.--", "Z": "--..", - "1": ".----", "2": "..---", "3": "...--", "4": "....-", "5": ".....", - "6": "-....", "7": "--...", "8": "---..", "9": "----.", "0": "-----", - ".": ".-.-.-", ":": "---...", ",": "--..--", ";": "-.-.-.", - "?": "..--..", "=": "-...-", "\'": ".----.", "/": "-..-.", - "!": "-.-.--", "-": "-....-", "_": "..--.-", "\"": ".-..-.", - "(": "-.--.", ")": "-.--.-", "$": "...-..-", "&": "....", - "@": ".--.-.", " ": " " + "A": ".-", + "B": "-...", + "C": "-.-.", + "D": "-..", + "E": ".", + "F": "..-.", + "G": "--.", + "H": "....", + "I": "..", + "J": ".---", + "K": "-.-", + "L": ".-..", + "M": "--", + "N": "-.", + "O": "---", + "P": ".--.", + "Q": "--.-", + "R": ".-.", + "S": "...", + "T": "-", + "U": "..-", + "V": "...-", + "W": ".--", + "X": "-..-", + "Y": "-.--", + "Z": "--..", + "1": ".----", + "2": "..---", + "3": "...--", + "4": "....-", + "5": ".....", + "6": "-....", + "7": "--...", + "8": "---..", + "9": "----.", + "0": "-----", + ".": ".-.-.-", + ":": "---...", + ",": "--..--", + ";": "-.-.-.", + "?": "..--..", + "=": "-...-", + "'": ".----.", + "/": "-..-.", + "!": "-.-.--", + "-": "-....-", + "_": "..--.-", + '"': ".-..-.", + "(": "-.--.", + ")": "-.--.-", + "$": "...-..-", + "&": "....", + "@": ".--.-.", + " ": " ", } MorseDecode = {value: key for key, value in MorseEncode.items()} diff --git a/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_NyaCode.py b/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_NyaCode.py index 57f692ab..22ca865e 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_NyaCode.py +++ b/nonebot_plugin_marshoai/tools/marshoai-megakits/mk_NyaCode.py @@ -1,18 +1,23 @@ -import random import base64 +import random # NyaCode -NyaCodeCharset = [ - "喵", "呜", "?", "~" -] -NyaCodeSpecialCharset = [ - "唔", "!", "...", ".." -] +NyaCodeCharset = ["喵", "呜", "?", "~"] +NyaCodeSpecialCharset = ["唔", "!", "...", ".."] NyaCodeEncode = {} for i in range(64): - triplet = "".join(NyaCodeCharset[(i // (4 ** j)) % 4] for j in range(3)) - NyaCodeEncode[chr(65 + i if i < 26 else 97 + (i - 26) if i < 52 else 48 + (i - 52) if i < 62 else ( - 43 if i == 62 else 47))] = triplet + triplet = "".join(NyaCodeCharset[(i // (4**j)) % 4] for j in range(3)) + NyaCodeEncode[ + chr( + 65 + i + if i < 26 + else ( + 97 + (i - 26) + if i < 52 + else 48 + (i - 52) if i < 62 else (43 if i == 62 else 47) + ) + ) + ] = triplet NyaCodeDecode = {value: key for key, value in NyaCodeEncode.items()} @@ -22,7 +27,7 @@ async def nya_encode(msg: str): msg_nyastr = "".join(NyaCodeEncode[base64_char] for base64_char in msg_b64str) result = "" for char in msg_nyastr: - if char == "呜" and random.random() < 0.5: + if char == "呜" and random.random() < 0.5: result += "!" if random.random() < 0.25: @@ -37,7 +42,7 @@ async def nya_decode(msg: str): msg = msg.replace("唔", "").replace("!", "").replace(".", "") msg_nyastr = [] i = 0 - if len(msg) % 3 != 0 : + if len(msg) % 3 != 0: return "这句话不是正确的猫语" while i < len(msg): nyachar = msg[i : i + 3] diff --git a/nonebot_plugin_marshoai/tools/marshoai-megakits/tools.json b/nonebot_plugin_marshoai/tools/marshoai-megakits/tools.json index 397494f0..f71ecf26 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-megakits/tools.json +++ b/nonebot_plugin_marshoai/tools/marshoai-megakits/tools.json @@ -139,4 +139,4 @@ } } } -] \ No newline at end of file +] diff --git a/nonebot_plugin_marshoai/tools/marshoai-meogirl/__init__.py b/nonebot_plugin_marshoai/tools/marshoai-meogirl/__init__.py index 58d7a8e8..5c960999 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-meogirl/__init__.py +++ b/nonebot_plugin_marshoai/tools/marshoai-meogirl/__init__.py @@ -1,16 +1,16 @@ +from . import mg_Info, mg_Introduce, mg_Search -from . import mg_Info -from . import mg_Search -from . import mg_Introduce # meogirl -async def meogirl () : +async def meogirl(): return mg_Info.meogirl() + # Search -async def search (msg : str, num : int = 3) : +async def search(msg: str, num: int = 3): return str(await mg_Search.search(msg, num)) + # Show -async def introduce (msg : str) : +async def introduce(msg: str): return str(await mg_Introduce.introduce(msg)) diff --git a/nonebot_plugin_marshoai/tools/marshoai-meogirl/mg_Info.py b/nonebot_plugin_marshoai/tools/marshoai-meogirl/mg_Info.py index af3257dd..0a0bcf02 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-meogirl/mg_Info.py +++ b/nonebot_plugin_marshoai/tools/marshoai-meogirl/mg_Info.py @@ -1,4 +1,3 @@ - # Meogirl def meogirl(): - return "Meogirl指的是\"萌娘百科\"(https://zh.moegirl.org.cn/ , 简称\"萌百\"), 是一个\"万物皆可萌的百科全书!\"; 同时, MarshoTools也配有\"Meogirl\"插件, 可调用萌百的api" + return 'Meogirl指的是"萌娘百科"(https://zh.moegirl.org.cn/ , 简称"萌百"), 是一个"万物皆可萌的百科全书!"; 同时, MarshoTools也配有"Meogirl"插件, 可调用萌百的api' diff --git a/nonebot_plugin_marshoai/tools/marshoai-meogirl/mg_Introduce.py b/nonebot_plugin_marshoai/tools/marshoai-meogirl/mg_Introduce.py index ffc072ba..98e0026a 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-meogirl/mg_Introduce.py +++ b/nonebot_plugin_marshoai/tools/marshoai-meogirl/mg_Introduce.py @@ -1,36 +1,38 @@ -from nonebot.log import logger - import re -import httpx import urllib.parse + +import httpx from bs4 import BeautifulSoup +from nonebot.log import logger headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36" } -async def get_async_data (url) : - async with httpx.AsyncClient(timeout = None) as client: - return await client.get(url, headers = headers) -async def introduce (msg : str) : - logger.info(f"介绍 : \"{msg}\" ...") +async def get_async_data(url): + async with httpx.AsyncClient(timeout=None) as client: + return await client.get(url, headers=headers) + + +async def introduce(msg: str): + logger.info(f'介绍 : "{msg}" ...') result = "" url = "https://mzh.moegirl.org.cn/" + urllib.parse.quote_plus(msg) response = await get_async_data(url) - logger.success(f"连接\"{url}\"完成, 状态码 : {response.status_code}") + logger.success(f'连接"{url}"完成, 状态码 : {response.status_code}') soup = BeautifulSoup(response.text, "html.parser") # 正常页 - if response.status_code == 200 : + if response.status_code == 200: """ - 萌娘百科页面结构 - div#mw-content-text - └── div#404search # 空白页面出现 - └── div.mw-parser-output # 正常页面 - └── div, p, table ... # 大量的解释项 + 萌娘百科页面结构 + div#mw-content-text + └── div#404search # 空白页面出现 + └── div.mw-parser-output # 正常页面 + └── div, p, table ... # 大量的解释项 """ result += msg + "\n" @@ -44,7 +46,9 @@ async def introduce (msg : str) : num = 0 for p_tag in p_tags: p = str(p_tag) - p = re.sub(r"|", "", p, flags=re.DOTALL) + p = re.sub( + r"|", "", p, flags=re.DOTALL + ) p = re.sub(r"<.*?>", "", p, flags=re.DOTALL) p = re.sub(r"\[.*?]", "", p, flags=re.DOTALL) @@ -57,20 +61,21 @@ async def introduce (msg : str) : return result # 空白页 - elif response.status_code == 404 : - logger.info(f"未找到\"{msg}\", 进行搜索") + elif response.status_code == 404: + logger.info(f'未找到"{msg}", 进行搜索') from . import mg_Search - context = await mg_Search.search(msg, 1) - keyword = re.search(r".*?\n", context, flags = re.DOTALL).group()[: -1] - logger.success(f"搜索完成, 打开\"{keyword}\"") + context = await mg_Search.search(msg, 1) + keyword = re.search(r".*?\n", context, flags=re.DOTALL).group()[:-1] + + logger.success(f'搜索完成, 打开"{keyword}"') return await introduce(keyword) # 搜索失败 - elif response.status_code == 301 : + elif response.status_code == 301: return f"未找到{msg}" - else : + else: logger.error(f"网络错误, 状态码 : {response.status_code}") return f"网络错误, 状态码 : {response.status_code}" diff --git a/nonebot_plugin_marshoai/tools/marshoai-meogirl/mg_Search.py b/nonebot_plugin_marshoai/tools/marshoai-meogirl/mg_Search.py index 0b793a6e..b65d751c 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-meogirl/mg_Search.py +++ b/nonebot_plugin_marshoai/tools/marshoai-meogirl/mg_Search.py @@ -1,76 +1,85 @@ -from nonebot.log import logger +import urllib.parse import httpx -import urllib.parse from bs4 import BeautifulSoup +from nonebot.log import logger headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36" } -async def get_async_data (url) : - async with httpx.AsyncClient(timeout = None) as client: - return await client.get(url, headers = headers) -async def search (msg : str, num : int) : - logger.info(f"搜索 : \"{msg}\" ...") +async def get_async_data(url): + async with httpx.AsyncClient(timeout=None) as client: + return await client.get(url, headers=headers) + + +async def search(msg: str, num: int): + logger.info(f'搜索 : "{msg}" ...') result = "" url = "https://mzh.moegirl.org.cn/index.php?search=" + urllib.parse.quote_plus(msg) response = await get_async_data(url) - logger.success(f"连接\"{url}\"完成, 状态码 : {response.status_code}") + logger.success(f'连接"{url}"完成, 状态码 : {response.status_code}') # 正常搜索 - if response.status_code == 200 : + if response.status_code == 200: """ - 萌娘百科搜索页面结构 - div.searchresults - └── p ... - └── ul.mw-search-results # 若无, 证明无搜索结果 - └── li # 一个搜索结果 - └── div.mw-search-result-heading > a # 标题 - └── div.mw-searchresult # 内容 - └── div.mw-search-result-data - └── li ... - └── li ... + 萌娘百科搜索页面结构 + div.searchresults + └── p ... + └── ul.mw-search-results # 若无, 证明无搜索结果 + └── li # 一个搜索结果 + └── div.mw-search-result-heading > a # 标题 + └── div.mw-searchresult # 内容 + └── div.mw-search-result-data + └── li ... + └── li ... """ soup = BeautifulSoup(response.text, "html.parser") # 检测ul.mw-search-results, 是否有结果 - ul_tag = soup.find("ul", class_ = "mw-search-results") - if ul_tag : + ul_tag = soup.find("ul", class_="mw-search-results") + if ul_tag: li_tags = ul_tag.find_all("li") - for li_tag in li_tags : + for li_tag in li_tags: - div_heading = li_tag.find("div", class_ = "mw-search-result-heading") - if div_heading : + div_heading = li_tag.find("div", class_="mw-search-result-heading") + if div_heading: a_tag = div_heading.find("a") result += a_tag["title"] + "\n" - logger.info(f"搜索到 : \"{a_tag["title"]}\"") + logger.info(f'搜索到 : "{a_tag["title"]}"') div_result = li_tag.find("div", class_="searchresult") - if div_result : - content = str(div_result).replace("
", "").replace("
", "") - content = content.replace("", "").replace("", "") + if div_result: + content = ( + str(div_result) + .replace('
', "") + .replace("
", "") + ) + content = content.replace('', "").replace( + "", "" + ) result += content + "\n" num -= 1 - if num == 0 : + if num == 0: break return result # 无ul.mw-search-results, 无结果 - else : + else: logger.info("无结果") return "无结果" # 重定向 - elif response.status_code == 302 : - logger.info(f"\"{msg}\"已被重定向至\"{response.headers.get("location")}\"") + elif response.status_code == 302: + logger.info(f'"{msg}"已被重定向至"{response.headers.get("location")}"') # 读取重定向结果 from . import mg_Introduce + return await mg_Introduce.introduce(msg) - else : + else: logger.error(f"网络错误, 状态码 : {response.status_code}") return f"网络错误, 状态码 : {response.status_code}" diff --git a/nonebot_plugin_marshoai/tools/marshoai-meogirl/tools.json b/nonebot_plugin_marshoai/tools/marshoai-meogirl/tools.json index fa008317..d28a459f 100644 --- a/nonebot_plugin_marshoai/tools/marshoai-meogirl/tools.json +++ b/nonebot_plugin_marshoai/tools/marshoai-meogirl/tools.json @@ -48,4 +48,4 @@ ] } } -] \ No newline at end of file +] diff --git a/nonebot_plugin_marshoai/tools_wip/marshoai-memory/__init__.py b/nonebot_plugin_marshoai/tools_wip/marshoai-memory/__init__.py index b698cef3..11a7891c 100644 --- a/nonebot_plugin_marshoai/tools_wip/marshoai-memory/__init__.py +++ b/nonebot_plugin_marshoai/tools_wip/marshoai-memory/__init__.py @@ -1,2 +1,2 @@ async def write_memory(memory: str): - return "" \ No newline at end of file + return "" diff --git a/nonebot_plugin_marshoai/tools_wip/marshoai-memory/tools.json b/nonebot_plugin_marshoai/tools_wip/marshoai-memory/tools.json index 97e08afb..adab49a4 100644 --- a/nonebot_plugin_marshoai/tools_wip/marshoai-memory/tools.json +++ b/nonebot_plugin_marshoai/tools_wip/marshoai-memory/tools.json @@ -4,7 +4,7 @@ "function": { "name": "marshoai-memory__write_memory", "description": "当你想记住有关与你对话的人的一些信息的时候,调用此函数。", - "parameters": { + "parameters": { "type": "object", "properties": { "memory": { @@ -18,4 +18,4 @@ ] } } -] \ No newline at end of file +] diff --git a/nonebot_plugin_marshoai/util.py b/nonebot_plugin_marshoai/util.py index 17f3c1e4..7c7309e2 100644 --- a/nonebot_plugin_marshoai/util.py +++ b/nonebot_plugin_marshoai/util.py @@ -1,26 +1,19 @@ -import os -import json -import uuid -import httpx import base64 +import json import mimetypes - +import os +import uuid from typing import Any, Optional -from nonebot.log import logger - +import httpx import nonebot_plugin_localstore as store - -from nonebot_plugin_alconna import ( - Text as TextMsg, - Image as ImageMsg, - UniMessage, -) - - # from zhDateTime import DateTime from azure.ai.inference.aio import ChatCompletionsClient from azure.ai.inference.models import SystemMessage +from nonebot.log import logger +from nonebot_plugin_alconna import Image as ImageMsg +from nonebot_plugin_alconna import Text as TextMsg +from nonebot_plugin_alconna import UniMessage from .config import config from .constants import * @@ -304,7 +297,7 @@ if config.marshoai_enable_richtext_parse: if not IMG_LATEX_PATTERN.search(msg): # 没有图片和LaTeX标签 return UniMessage(msg) - result_msg = UniMessage() + result_msg = UniMessage() # type: ignore code_blank_uuid_map = [ (uuid.uuid4().hex, cbp.group()) for cbp in CODE_BLOCK_PATTERN.finditer(msg) ] @@ -338,7 +331,7 @@ if config.marshoai_enable_richtext_parse: last_tag_index = msg.find(tag_found) + len(tag_found) if each_find_tag.group(1): - + # 图形一定要优先考虑 # 别忘了有些图形的地址就是 LaTeX,所以要优先判断 @@ -380,7 +373,7 @@ if config.marshoai_enable_richtext_parse: if latex_generate_ok: result_msg.append( ImageMsg( - raw=latex_generate_result, + raw=latex_generate_result, # type: ignore mimetype="image/png", name="latex.png", ) diff --git a/nonebot_plugin_marshoai/util_hunyuan.py b/nonebot_plugin_marshoai/util_hunyuan.py index 47e899fd..42d24efd 100644 --- a/nonebot_plugin_marshoai/util_hunyuan.py +++ b/nonebot_plugin_marshoai/util_hunyuan.py @@ -1,12 +1,16 @@ import json import types -from tencentcloud.common import credential -from tencentcloud.common.profile.client_profile import ClientProfile -from tencentcloud.common.profile.http_profile import HttpProfile -from tencentcloud.common.exception.tencent_cloud_sdk_exception import ( - TencentCloudSDKException, -) -from tencentcloud.hunyuan.v20230901 import hunyuan_client, models + +from tencentcloud.common import credential # type: ignore +from tencentcloud.common.exception.tencent_cloud_sdk_exception import \ + TencentCloudSDKException # type: ignore +from tencentcloud.common.profile.client_profile import \ + ClientProfile # type: ignore +from tencentcloud.common.profile.http_profile import \ + HttpProfile # type: ignore +from tencentcloud.hunyuan.v20230901 import hunyuan_client # type: ignore +from tencentcloud.hunyuan.v20230901 import models + from .config import config diff --git a/pyproject.toml b/pyproject.toml index 72851cc4..6025b644 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "nonebot-plugin-marshoai" dynamic = ["version"] description = "Nonebot2插件,调用Azure OpenAI等AI服务实现猫娘聊天" readme = "README.md" -requires-python = "<4.0,>=3.9" +requires-python = "<4.0,>=3.10" authors = [{ name = "Asankilp", email = "asankilp@outlook.com" }] dependencies = [ "nonebot2>=2.2.0", @@ -14,8 +14,10 @@ dependencies = [ "aiohttp>=3.9", "httpx>=0.27.0", "ruamel.yaml>=0.18.6", - "pyyaml>=6.0.2" - + "pyyaml>=6.0.2", + "psutil>=6.1.0", + "beautifulsoup4>=4.12.3" + ] license = { text = "MIT, Mulan PSL v2" } @@ -32,6 +34,9 @@ adapters = [ [tool.pdm] distribution = true +python.use_venv = true +python.venv_in_project = true + [tool.pdm.version] source = "scm" @@ -49,4 +54,6 @@ build-backend = "pdm.backend" dev = [ "nb-cli>=1.4.2", "pytest>=8.3.4", -] + "pre-commit>=4.0.1", + "nonebot-adapter-onebot>=2.4.6", +] \ No newline at end of file diff --git a/resources/README.md b/resources/README.md index de95a13e..31294778 100644 --- a/resources/README.md +++ b/resources/README.md @@ -1,4 +1,4 @@ -# Marsho Resources +# Marsho Resources -本目录存放 Marsho 的图像资源(logo,icon),由[Asankilp](https://github.com/Asankilp)绘制。 -所有资源均在[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)许可下提供。 +本目录存放 Marsho 的图像资源(logo,icon),由[Asankilp](https://github.com/Asankilp)绘制。 +所有资源均在[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)许可下提供。 diff --git a/tests/test_none.py b/tests/test_none.py index 77cf8e04..ecd8f840 100644 --- a/tests/test_none.py +++ b/tests/test_none.py @@ -1,7 +1,7 @@ import logging + def test_none(): - """基准测试示例 - """ + """基准测试示例""" logging.info("测试成功") - pass \ No newline at end of file + pass