nonebot-plugin-hzys 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nonebot_plugin_hzys/__init__.py +20 -0
- nonebot_plugin_hzys/backend.py +115 -0
- nonebot_plugin_hzys/command.py +42 -0
- nonebot_plugin_hzys/config.py +14 -0
- nonebot_plugin_hzys-0.2.0.dist-info/METADATA +123 -0
- nonebot_plugin_hzys-0.2.0.dist-info/RECORD +7 -0
- nonebot_plugin_hzys-0.2.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from nonebot import require
|
|
2
|
+
from nonebot.plugin import PluginMetadata
|
|
3
|
+
|
|
4
|
+
require("nonebot_plugin_alconna")
|
|
5
|
+
|
|
6
|
+
from .command import otto_cmd
|
|
7
|
+
from .config import Config
|
|
8
|
+
|
|
9
|
+
__plugin_meta__ = PluginMetadata(
|
|
10
|
+
name="otto 活字印刷",
|
|
11
|
+
description="调用兼容后端生成 otto 活字印刷语音",
|
|
12
|
+
usage="/ottohzys 大家好啊",
|
|
13
|
+
type="application",
|
|
14
|
+
homepage="https://github.com/Misty02600/nonebot-plugin-hzys",
|
|
15
|
+
config=Config,
|
|
16
|
+
supported_adapters={"~onebot.v11"},
|
|
17
|
+
extra={"author": "Misty02600 <Misty02600@gmail.com>"},
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = ("__plugin_meta__", "otto_cmd")
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from .config import Config
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class OttoBackendError(Exception):
|
|
11
|
+
"""Base exception for remote otto backend failures."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class OttoBackendConfigError(OttoBackendError):
|
|
15
|
+
"""Raised when the plugin is missing required backend configuration."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class OttoBackendRequestError(OttoBackendError):
|
|
19
|
+
"""Raised when the backend request fails or returns an invalid response."""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(slots=True, frozen=True)
|
|
23
|
+
class OttoSynthesisOptions:
|
|
24
|
+
is_ysdd: bool = True
|
|
25
|
+
use_non_ddb_pinyin: bool = True
|
|
26
|
+
is_sliced: bool = False
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class OttoBackendClient:
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
*,
|
|
33
|
+
base_url: str,
|
|
34
|
+
api_key: str | None = None,
|
|
35
|
+
timeout: float = 20.0,
|
|
36
|
+
transport: httpx.AsyncBaseTransport | None = None,
|
|
37
|
+
) -> None:
|
|
38
|
+
self.base_url = base_url.rstrip("/")
|
|
39
|
+
self.api_key = api_key
|
|
40
|
+
self.timeout = timeout
|
|
41
|
+
self.transport = transport
|
|
42
|
+
|
|
43
|
+
async def synthesize(self, text: str, *, options: OttoSynthesisOptions) -> bytes:
|
|
44
|
+
payload = {
|
|
45
|
+
"text": text,
|
|
46
|
+
"isYsdd": options.is_ysdd,
|
|
47
|
+
"useNonDdbPinyin": options.use_non_ddb_pinyin,
|
|
48
|
+
"isSliced": options.is_sliced,
|
|
49
|
+
}
|
|
50
|
+
headers = {"Content-Type": "application/json"}
|
|
51
|
+
if self.api_key:
|
|
52
|
+
headers["Authorization"] = f"Bearer {self.api_key}"
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
async with httpx.AsyncClient(
|
|
56
|
+
base_url=self.base_url,
|
|
57
|
+
timeout=self.timeout,
|
|
58
|
+
transport=self.transport,
|
|
59
|
+
) as client:
|
|
60
|
+
response = await client.post(
|
|
61
|
+
"/api/text-to-wav", json=payload, headers=headers
|
|
62
|
+
)
|
|
63
|
+
except httpx.HTTPError as exc:
|
|
64
|
+
raise OttoBackendRequestError(f"请求后端失败:{exc}") from exc
|
|
65
|
+
|
|
66
|
+
if response.status_code >= 400:
|
|
67
|
+
detail = _extract_error_detail(response)
|
|
68
|
+
raise OttoBackendRequestError(
|
|
69
|
+
f"后端返回错误 {response.status_code}:{detail}"
|
|
70
|
+
)
|
|
71
|
+
if not response.content:
|
|
72
|
+
raise OttoBackendRequestError("后端没有返回音频数据")
|
|
73
|
+
|
|
74
|
+
return response.content
|
|
75
|
+
|
|
76
|
+
async def health(self) -> bool:
|
|
77
|
+
try:
|
|
78
|
+
async with httpx.AsyncClient(
|
|
79
|
+
base_url=self.base_url,
|
|
80
|
+
timeout=self.timeout,
|
|
81
|
+
transport=self.transport,
|
|
82
|
+
) as client:
|
|
83
|
+
response = await client.get("/health")
|
|
84
|
+
except httpx.HTTPError:
|
|
85
|
+
return False
|
|
86
|
+
return response.status_code < 400
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def build_backend_client(config: Config) -> OttoBackendClient:
|
|
90
|
+
if not config.otto_hzys_backend_url.strip():
|
|
91
|
+
raise OttoBackendConfigError("未配置 OTTO_HZYS_BACKEND_URL")
|
|
92
|
+
|
|
93
|
+
return OttoBackendClient(
|
|
94
|
+
base_url=config.otto_hzys_backend_url,
|
|
95
|
+
api_key=config.otto_hzys_api_key,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def default_synthesis_options(config: Config) -> OttoSynthesisOptions:
|
|
100
|
+
return OttoSynthesisOptions()
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _extract_error_detail(response: httpx.Response) -> str:
|
|
104
|
+
try:
|
|
105
|
+
data = response.json()
|
|
106
|
+
except ValueError:
|
|
107
|
+
return response.text.strip() or "未知错误"
|
|
108
|
+
|
|
109
|
+
if isinstance(data, dict):
|
|
110
|
+
for key in ("error", "message", "detail"):
|
|
111
|
+
value = data.get(key)
|
|
112
|
+
if isinstance(value, str) and value.strip():
|
|
113
|
+
return value.strip()
|
|
114
|
+
|
|
115
|
+
return response.text.strip() or "未知错误"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from arclet.alconna import Alconna, AllParam, Args
|
|
4
|
+
from nonebot import get_plugin_config
|
|
5
|
+
from nonebot_plugin_alconna import UniMessage, Voice, on_alconna
|
|
6
|
+
|
|
7
|
+
from .backend import (
|
|
8
|
+
OttoBackendConfigError,
|
|
9
|
+
OttoBackendError,
|
|
10
|
+
build_backend_client,
|
|
11
|
+
default_synthesis_options,
|
|
12
|
+
)
|
|
13
|
+
from .config import Config
|
|
14
|
+
|
|
15
|
+
otto_cmd = on_alconna(
|
|
16
|
+
Alconna("ottohzys", Args["text", AllParam]),
|
|
17
|
+
aliases={"活字印刷"},
|
|
18
|
+
use_cmd_start=True,
|
|
19
|
+
block=True,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@otto_cmd.handle()
|
|
24
|
+
async def handle_otto(text: UniMessage) -> None:
|
|
25
|
+
plain_text = text.extract_plain_text().strip()
|
|
26
|
+
if not plain_text:
|
|
27
|
+
await otto_cmd.finish("请输入要转换的文本")
|
|
28
|
+
|
|
29
|
+
config = get_plugin_config(Config)
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
client = build_backend_client(config)
|
|
33
|
+
audio = await client.synthesize(
|
|
34
|
+
plain_text,
|
|
35
|
+
options=default_synthesis_options(config),
|
|
36
|
+
)
|
|
37
|
+
except OttoBackendConfigError as exc:
|
|
38
|
+
await otto_cmd.finish(str(exc))
|
|
39
|
+
except OttoBackendError as exc:
|
|
40
|
+
await otto_cmd.finish(f"活字印刷生成失败:{exc}")
|
|
41
|
+
|
|
42
|
+
await otto_cmd.finish(UniMessage(Voice(raw=audio, name="otto.wav")))
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Config(BaseModel):
|
|
5
|
+
model_config = ConfigDict(extra="ignore")
|
|
6
|
+
|
|
7
|
+
otto_hzys_backend_url: str = Field(
|
|
8
|
+
default="https://otto-hzys-api-backend.vercel.app",
|
|
9
|
+
description="兼容 otto-hzys API 的后端地址",
|
|
10
|
+
)
|
|
11
|
+
otto_hzys_api_key: str | None = Field(
|
|
12
|
+
default=None,
|
|
13
|
+
description="兼容后端的 Bearer Token",
|
|
14
|
+
)
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: nonebot-plugin-hzys
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: 插件描述
|
|
5
|
+
Author: Misty02600
|
|
6
|
+
Author-email: Misty02600 <Misty02600@gmail.com>
|
|
7
|
+
Requires-Dist: httpx>=0.27.0,<1.0.0
|
|
8
|
+
Requires-Dist: nonebot-plugin-alconna>=0.60.0,<1.0.0
|
|
9
|
+
Requires-Dist: nonebot2>=2.4.2,<3.0.0
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
|
+
Project-URL: Homepage, https://github.com/Misty02600/nonebot-plugin-hzys
|
|
12
|
+
Project-URL: Issues, https://github.com/Misty02600/nonebot-plugin-hzys/issues
|
|
13
|
+
Project-URL: Repository, https://github.com/Misty02600/nonebot-plugin-hzys.git
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
<div align="center">
|
|
17
|
+
<a href="https://v2.nonebot.dev/store">
|
|
18
|
+
<img src="https://github.com/Misty02600/nonebot-plugin-template/releases/download/assets/NoneBotPlugin.png" width="310" alt="logo"></a>
|
|
19
|
+
|
|
20
|
+
## ✨ nonebot-plugin-hzys ✨
|
|
21
|
+
[](./LICENSE)
|
|
22
|
+
[](https://www.python.org)
|
|
23
|
+
[](#supported-adapters)
|
|
24
|
+
<br/>
|
|
25
|
+
|
|
26
|
+
[](https://github.com/astral-sh/uv)
|
|
27
|
+
[](https://github.com/astral-sh/ruff)
|
|
28
|
+
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
## 📖 介绍
|
|
32
|
+
|
|
33
|
+
由于饼干的 [`nonebot-plugin-ottohzys`](https://github.com/lgc-NB2Dev/nonebot-plugin-ottohzys) 已归档,写了这个插件来跟踪最新上游数据。服务端来自 [`kaixinol/otto-hzys-api-backend`](https://github.com/kaixinol/otto-hzys-api-backend),上游数据源来自 [`hua-zhi-wan/otto-hzys`](https://github.com/hua-zhi-wan/otto-hzys)。
|
|
34
|
+
|
|
35
|
+
## 💿 安装
|
|
36
|
+
|
|
37
|
+
<details open>
|
|
38
|
+
<summary>使用 nb-cli 安装</summary>
|
|
39
|
+
在 nonebot2 项目的根目录下打开命令行, 输入以下指令即可安装
|
|
40
|
+
|
|
41
|
+
nb plugin install nonebot-plugin-hzys --upgrade
|
|
42
|
+
使用 **pypi** 源安装
|
|
43
|
+
|
|
44
|
+
nb plugin install nonebot-plugin-hzys --upgrade -i "https://pypi.org/simple"
|
|
45
|
+
使用**清华源**安装
|
|
46
|
+
|
|
47
|
+
nb plugin install nonebot-plugin-hzys --upgrade -i "https://pypi.tuna.tsinghua.edu.cn/simple"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
</details>
|
|
51
|
+
|
|
52
|
+
<details>
|
|
53
|
+
<summary>使用包管理器安装</summary>
|
|
54
|
+
在 nonebot2 项目的插件目录下, 打开命令行, 根据你使用的包管理器, 输入相应的安装命令
|
|
55
|
+
|
|
56
|
+
<details open>
|
|
57
|
+
<summary>uv</summary>
|
|
58
|
+
|
|
59
|
+
uv add nonebot-plugin-hzys
|
|
60
|
+
安装仓库 main 分支
|
|
61
|
+
|
|
62
|
+
uv add git+https://github.com/Misty02600/nonebot-plugin-hzys@main
|
|
63
|
+
</details>
|
|
64
|
+
|
|
65
|
+
<details>
|
|
66
|
+
<summary>pdm</summary>
|
|
67
|
+
|
|
68
|
+
pdm add nonebot-plugin-hzys
|
|
69
|
+
安装仓库 main 分支
|
|
70
|
+
|
|
71
|
+
pdm add git+https://github.com/Misty02600/nonebot-plugin-hzys@main
|
|
72
|
+
</details>
|
|
73
|
+
<details>
|
|
74
|
+
<summary>poetry</summary>
|
|
75
|
+
|
|
76
|
+
poetry add nonebot-plugin-hzys
|
|
77
|
+
安装仓库 main 分支
|
|
78
|
+
|
|
79
|
+
poetry add git+https://github.com/Misty02600/nonebot-plugin-hzys@main
|
|
80
|
+
</details>
|
|
81
|
+
|
|
82
|
+
打开 nonebot2 项目根目录下的 `pyproject.toml` 文件, 在 `[tool.nonebot]` 部分追加写入
|
|
83
|
+
|
|
84
|
+
plugins = ["nonebot_plugin_hzys"]
|
|
85
|
+
|
|
86
|
+
</details>
|
|
87
|
+
|
|
88
|
+
<details>
|
|
89
|
+
<summary>使用 nbr 安装(使用 uv 管理依赖可用)</summary>
|
|
90
|
+
|
|
91
|
+
[nbr](https://github.com/fllesser/nbr) 是一个基于 uv 的 nb-cli,可以方便地管理 nonebot2
|
|
92
|
+
|
|
93
|
+
nbr plugin install nonebot-plugin-hzys
|
|
94
|
+
使用 **pypi** 源安装
|
|
95
|
+
|
|
96
|
+
nbr plugin install nonebot-plugin-hzys -i "https://pypi.org/simple"
|
|
97
|
+
使用**清华源**安装
|
|
98
|
+
|
|
99
|
+
nbr plugin install nonebot-plugin-hzys -i "https://pypi.tuna.tsinghua.edu.cn/simple"
|
|
100
|
+
|
|
101
|
+
</details>
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
## ⚙️ 配置
|
|
105
|
+
|
|
106
|
+
在 NoneBot 项目的 `.env` 中配置:
|
|
107
|
+
|
|
108
|
+
| 配置项 | 必填 | 默认值 | 说明 |
|
|
109
|
+
| :-- | :--: | :--: | :-- |
|
|
110
|
+
| `OTTO_HZYS_BACKEND_URL` | 否 | `https://otto-hzys-api-backend.vercel.app` | 后端地址,例如 `http://127.0.0.1:3000` |
|
|
111
|
+
| `OTTO_HZYS_API_KEY` | 否 | 无 | 后端 Token |
|
|
112
|
+
|
|
113
|
+
示例:
|
|
114
|
+
|
|
115
|
+
```env
|
|
116
|
+
OTTO_HZYS_BACKEND_URL=http://127.0.0.1:3000
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## 🎉 使用
|
|
120
|
+
### 指令表
|
|
121
|
+
| 指令 | 说明 |
|
|
122
|
+
| :-- | :-- |
|
|
123
|
+
| `ottohzys/活字印刷 <文本>` | 生成活字印刷语音 |
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
nonebot_plugin_hzys/__init__.py,sha256=zJRhyXQWBy9RPHTLKvXcRxPMKFqbX8aFTsPwg4V3vKc,585
|
|
2
|
+
nonebot_plugin_hzys/backend.py,sha256=7Fi9CTE9ugOHxsAkp-NJ4luOJB7gh1ctt4f1SMh4yDU,3498
|
|
3
|
+
nonebot_plugin_hzys/command.py,sha256=aHaSsYYBPPwPwE41WXyEKVvG1Y_F9Z4yJ2_HsvR9wVc,1185
|
|
4
|
+
nonebot_plugin_hzys/config.py,sha256=tR_Amo2mVpwriLngdyAiqSQBK_bUbhIRSYon14DiWao,413
|
|
5
|
+
nonebot_plugin_hzys-0.2.0.dist-info/WHEEL,sha256=s_zqWxHFEH8b58BCtf46hFCqPaISurdB9R1XJ8za6XI,80
|
|
6
|
+
nonebot_plugin_hzys-0.2.0.dist-info/METADATA,sha256=CBPVhYfpWF71IjejbP_-Z8LlQVgeJZBom7HfOyP8I2w,3994
|
|
7
|
+
nonebot_plugin_hzys-0.2.0.dist-info/RECORD,,
|