nonebot-plugin-hzys 0.2.0__tar.gz

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.
@@ -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](https://img.shields.io/github/license/Misty02600/nonebot-plugin-hzys.svg)](./LICENSE)
22
+ [![python](https://img.shields.io/badge/python-3.11+-blue.svg?logo=python&logoColor=white)](https://www.python.org)
23
+ [![Adapters](https://img.shields.io/badge/Adapters-OneBot%20v11-blue)](#supported-adapters)
24
+ <br/>
25
+
26
+ [![uv](https://img.shields.io/badge/package%20manager-uv-black?logo=uv)](https://github.com/astral-sh/uv)
27
+ [![ruff](https://img.shields.io/badge/code%20style-ruff-black?logo=ruff)](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,108 @@
1
+ <div align="center">
2
+ <a href="https://v2.nonebot.dev/store">
3
+ <img src="https://github.com/Misty02600/nonebot-plugin-template/releases/download/assets/NoneBotPlugin.png" width="310" alt="logo"></a>
4
+
5
+ ## ✨ nonebot-plugin-hzys ✨
6
+ [![LICENSE](https://img.shields.io/github/license/Misty02600/nonebot-plugin-hzys.svg)](./LICENSE)
7
+ [![python](https://img.shields.io/badge/python-3.11+-blue.svg?logo=python&logoColor=white)](https://www.python.org)
8
+ [![Adapters](https://img.shields.io/badge/Adapters-OneBot%20v11-blue)](#supported-adapters)
9
+ <br/>
10
+
11
+ [![uv](https://img.shields.io/badge/package%20manager-uv-black?logo=uv)](https://github.com/astral-sh/uv)
12
+ [![ruff](https://img.shields.io/badge/code%20style-ruff-black?logo=ruff)](https://github.com/astral-sh/ruff)
13
+
14
+ </div>
15
+
16
+ ## 📖 介绍
17
+
18
+ 由于饼干的 [`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)。
19
+
20
+ ## 💿 安装
21
+
22
+ <details open>
23
+ <summary>使用 nb-cli 安装</summary>
24
+ 在 nonebot2 项目的根目录下打开命令行, 输入以下指令即可安装
25
+
26
+ nb plugin install nonebot-plugin-hzys --upgrade
27
+ 使用 **pypi** 源安装
28
+
29
+ nb plugin install nonebot-plugin-hzys --upgrade -i "https://pypi.org/simple"
30
+ 使用**清华源**安装
31
+
32
+ nb plugin install nonebot-plugin-hzys --upgrade -i "https://pypi.tuna.tsinghua.edu.cn/simple"
33
+
34
+
35
+ </details>
36
+
37
+ <details>
38
+ <summary>使用包管理器安装</summary>
39
+ 在 nonebot2 项目的插件目录下, 打开命令行, 根据你使用的包管理器, 输入相应的安装命令
40
+
41
+ <details open>
42
+ <summary>uv</summary>
43
+
44
+ uv add nonebot-plugin-hzys
45
+ 安装仓库 main 分支
46
+
47
+ uv add git+https://github.com/Misty02600/nonebot-plugin-hzys@main
48
+ </details>
49
+
50
+ <details>
51
+ <summary>pdm</summary>
52
+
53
+ pdm add nonebot-plugin-hzys
54
+ 安装仓库 main 分支
55
+
56
+ pdm add git+https://github.com/Misty02600/nonebot-plugin-hzys@main
57
+ </details>
58
+ <details>
59
+ <summary>poetry</summary>
60
+
61
+ poetry add nonebot-plugin-hzys
62
+ 安装仓库 main 分支
63
+
64
+ poetry add git+https://github.com/Misty02600/nonebot-plugin-hzys@main
65
+ </details>
66
+
67
+ 打开 nonebot2 项目根目录下的 `pyproject.toml` 文件, 在 `[tool.nonebot]` 部分追加写入
68
+
69
+ plugins = ["nonebot_plugin_hzys"]
70
+
71
+ </details>
72
+
73
+ <details>
74
+ <summary>使用 nbr 安装(使用 uv 管理依赖可用)</summary>
75
+
76
+ [nbr](https://github.com/fllesser/nbr) 是一个基于 uv 的 nb-cli,可以方便地管理 nonebot2
77
+
78
+ nbr plugin install nonebot-plugin-hzys
79
+ 使用 **pypi** 源安装
80
+
81
+ nbr plugin install nonebot-plugin-hzys -i "https://pypi.org/simple"
82
+ 使用**清华源**安装
83
+
84
+ nbr plugin install nonebot-plugin-hzys -i "https://pypi.tuna.tsinghua.edu.cn/simple"
85
+
86
+ </details>
87
+
88
+
89
+ ## ⚙️ 配置
90
+
91
+ 在 NoneBot 项目的 `.env` 中配置:
92
+
93
+ | 配置项 | 必填 | 默认值 | 说明 |
94
+ | :-- | :--: | :--: | :-- |
95
+ | `OTTO_HZYS_BACKEND_URL` | 否 | `https://otto-hzys-api-backend.vercel.app` | 后端地址,例如 `http://127.0.0.1:3000` |
96
+ | `OTTO_HZYS_API_KEY` | 否 | 无 | 后端 Token |
97
+
98
+ 示例:
99
+
100
+ ```env
101
+ OTTO_HZYS_BACKEND_URL=http://127.0.0.1:3000
102
+ ```
103
+
104
+ ## 🎉 使用
105
+ ### 指令表
106
+ | 指令 | 说明 |
107
+ | :-- | :-- |
108
+ | `ottohzys/活字印刷 <文本>` | 生成活字印刷语音 |
@@ -0,0 +1,140 @@
1
+ [project]
2
+ name = "nonebot-plugin-hzys"
3
+ version = "0.2.0"
4
+ description = "插件描述"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ authors = [{ name = "Misty02600", email = "Misty02600@gmail.com" }]
8
+ dependencies = [
9
+ "httpx>=0.27.0,<1.0.0",
10
+ "nonebot-plugin-alconna>=0.60.0,<1.0.0", # 跨平台命令解析拓展
11
+ # "nonebot-plugin-apscheduler>=0.5.0,<1.0.0", # 定时任务
12
+ # "nonebot-plugin-localstore>=0.7.4,<1.0.0", # 存储文件
13
+ # "nonebot-plugin-uninfo>=0.10.0,<1.0.0", # 多平台用户信息获取
14
+ # "nonebot-adapter-onebot>=2.4.6,<3.0.0",
15
+ "nonebot2>=2.4.2,<3.0.0",
16
+
17
+ ]
18
+
19
+ [project.urls]
20
+ Homepage = "https://github.com/Misty02600/nonebot-plugin-hzys"
21
+ Issues = "https://github.com/Misty02600/nonebot-plugin-hzys/issues"
22
+ Repository = "https://github.com/Misty02600/nonebot-plugin-hzys.git"
23
+
24
+ [dependency-groups]
25
+ dev = [
26
+ "commitizen>=4.1.0",
27
+ "git-cliff>=2.11.0,<3.0.0",
28
+ "prek>=0.2.0",
29
+ { include-group = "test" },
30
+ ]
31
+ test = [
32
+ "basedpyright>=1.16.0",
33
+ "ruff>=0.14.13,<1.0.0",
34
+ "nonebot-adapter-onebot>=2.4.6,<3.0.0",
35
+ "nonebot2[fastapi]>=2.4.4,<3.0.0",
36
+ "nonebug>=0.4.3,<1.0.0",
37
+ "pytest-asyncio>=1.3.0,<1.4.0",
38
+ "pytest-cov>=7.0.0",
39
+ ]
40
+
41
+ [tool.nonebot.plugins]
42
+ nonebot-plugin-hzys = ["nonebot_plugin_hzys"]
43
+
44
+ [tool.nonebot.adapters]
45
+ nonebot-adapter-onebot = [
46
+ { name = "OneBot V11", module_name = "nonebot.adapters.onebot.v11" },
47
+ ]
48
+
49
+ [build-system]
50
+ requires = ["uv_build>=0.10.0,<0.11.0"]
51
+ build-backend = "uv_build"
52
+
53
+ [tool.commitizen]
54
+ name = "cz_conventional_commits"
55
+ version = "0.2.0" # 当前版本
56
+ tag_format = "v$version"
57
+ version_files = ["pyproject.toml:^version"]
58
+ major_version_zero = true # 允许 0.x.x 版本号
59
+
60
+ [tool.coverage.report]
61
+ exclude_lines = [
62
+ "raise NotImplementedError",
63
+ "if TYPE_CHECKING:",
64
+ "@overload",
65
+ "except ImportError:",
66
+ ]
67
+
68
+ [tool.pyright]
69
+ include = ["src", "tests"] # 要检查的目录
70
+ pythonVersion = "3.11" # 目标 Python 版本(影响可用的类型特性)
71
+ pythonPlatform = "All" # 目标平台:All | Linux | Windows | Darwin
72
+ # typeCheckingMode 类型检查严格程度,可选值:
73
+ # - "off": 关闭类型检查
74
+ # - "basic": 基础检查(仅报告明确的类型错误)
75
+ # - "standard": 标准检查(推荐,平衡严格性与实用性)
76
+ # - "strict": 严格检查(要求完整的类型注解,适合新项目)
77
+ # - "all": 最严格(启用所有检查,可能产生大量警告)
78
+ typeCheckingMode = "standard"
79
+
80
+ # 测试目录的特殊配置(放宽部分规则以适应测试场景)
81
+ [[tool.pyright.executionEnvironments]]
82
+ root = "tests"
83
+ reportPrivateUsage = "none" # 允许测试访问私有属性 (_variable)
84
+ reportUnknownMemberType = "none" # 允许 Mock 对象等动态类型
85
+
86
+ [tool.pytest.ini_options]
87
+ addopts = [
88
+ "--import-mode=importlib", # 使用 importlib 导入模式(推荐,避免 sys.path 污染)
89
+ "--strict-markers", # 严格标记模式(未注册的 marker 会报错)
90
+ "--tb=short", # 简短的错误回溯(减少输出噪音)
91
+ "-ra", # 显示所有非通过测试的摘要(a=all except passed)
92
+ ]
93
+ testpaths = ["tests"] # 仅运行 tests 目录下的测试
94
+ pythonpath = ["src", "tests"] # 添加到 Python 路径,确保模块可导入
95
+ asyncio_mode = "auto" # 自动检测异步测试函数,无需手动标记 @pytest.mark.asyncio
96
+ asyncio_default_fixture_loop_scope = "session" # 每个测试函数使用独立的事件循环
97
+
98
+ [tool.ruff]
99
+ line-length = 88 # 每行最大字符数(与 Black 保持一致)
100
+ src = ["src", "tests"] # 源代码目录(用于判断导入是本地模块还是第三方模块)
101
+ include = ["src/**", "tests/**"] # 仅检查 src 和 tests 目录
102
+ extend-exclude = ["scripts"] # 脚本目录不做 lint 检查
103
+
104
+ [tool.ruff.format]
105
+ line-ending = "lf" # 行尾符:lf(Unix)| crlf(Windows)| auto | native
106
+
107
+ [tool.ruff.lint]
108
+ # 启用的规则集,每个字母代码对应一组规则
109
+ select = [
110
+ "F", # Pyflakes:基础语法和逻辑错误检查
111
+ "W", # pycodestyle warnings:PEP 8 风格警告
112
+ "E", # pycodestyle errors:PEP 8 风格错误
113
+ "I", # isort:导入语句排序
114
+ "B", # flake8-bugbear:发现潜在 bug 和设计问题
115
+ "UP", # pyupgrade:升级到新版 Python 语法
116
+ "ASYNC", # flake8-async:异步代码最佳实践
117
+ "C4", # flake8-comprehensions:推导式优化建议
118
+ "T10", # flake8-debugger:检测遗留的调试器语句(如 pdb)
119
+ "T20", # flake8-print:检测 print 语句(生产代码应使用 logging)
120
+ "PYI", # flake8-pyi:类型存根文件(.pyi)规范检查
121
+ "PT", # flake8-pytest-style:pytest 代码风格检查
122
+ "Q", # flake8-quotes:引号使用规范
123
+ "TID", # flake8-tidy-imports:导入语句整理
124
+ "RUF", # Ruff-specific:Ruff 特有的规则
125
+ ]
126
+ # 忽略的规则(根据项目需求放宽)
127
+ ignore = [
128
+ "E501", # 行长度由 formatter 控制,lint 不重复检查
129
+ "E402", # 允许模块导入不在文件顶部(某些情况下需要先执行代码)
130
+ "UP037", # 允许使用引号包裹的类型注解(前向引用)
131
+ "RUF001", # 允许字符串中的中文等 Unicode 字符
132
+ "RUF002", # 允许文档字符串中的中文等 Unicode 字符
133
+ "RUF003", # 允许注释中的中文等 Unicode 字符
134
+ "W191", # 允许使用制表符缩进
135
+ "TID252", # 允许使用相对导入
136
+ "B008", # 允许在函数参数默认值中使用函数调用
137
+ ]
138
+
139
+ [tool.ruff.lint.isort]
140
+ extra-standard-library = ["typing_extensions"] # 将 typing_extensions 视为标准库
@@ -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
+ )