nonebot-plugin-mantou-affection 0.1.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.
- nonebot_plugin_mantou_affection-0.1.0/LICENSE +21 -0
- nonebot_plugin_mantou_affection-0.1.0/PKG-INFO +221 -0
- nonebot_plugin_mantou_affection-0.1.0/README.md +196 -0
- nonebot_plugin_mantou_affection-0.1.0/nonebot_plugin_mantou_affection/__init__.py +114 -0
- nonebot_plugin_mantou_affection-0.1.0/nonebot_plugin_mantou_affection/commands.py +162 -0
- nonebot_plugin_mantou_affection-0.1.0/nonebot_plugin_mantou_affection/config.py +29 -0
- nonebot_plugin_mantou_affection-0.1.0/nonebot_plugin_mantou_affection/copywriting.py +88 -0
- nonebot_plugin_mantou_affection-0.1.0/nonebot_plugin_mantou_affection/integration.py +80 -0
- nonebot_plugin_mantou_affection-0.1.0/nonebot_plugin_mantou_affection/logic.py +174 -0
- nonebot_plugin_mantou_affection-0.1.0/nonebot_plugin_mantou_affection/models.py +111 -0
- nonebot_plugin_mantou_affection-0.1.0/nonebot_plugin_mantou_affection/parsing.py +35 -0
- nonebot_plugin_mantou_affection-0.1.0/nonebot_plugin_mantou_affection/resources/affection_texts.json +130 -0
- nonebot_plugin_mantou_affection-0.1.0/nonebot_plugin_mantou_affection/service.py +116 -0
- nonebot_plugin_mantou_affection-0.1.0/nonebot_plugin_mantou_affection/storage.py +117 -0
- nonebot_plugin_mantou_affection-0.1.0/pyproject.toml +50 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TonyLiangP2010405
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nonebot-plugin-mantou-affection
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: 为群聊机器人馒头提供互动、等级称号和跨插件共享状态的好感度系统
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: nonebot,nonebot2,onebot,affection,friendship,plugin
|
|
8
|
+
Author: TonyLiangP2010405
|
|
9
|
+
Requires-Python: >=3.9,<4.0
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Requires-Dist: nonebot-adapter-onebot (>=2.4.0,<3.0.0)
|
|
18
|
+
Requires-Dist: nonebot-plugin-localstore (>=0.7.0,<1.0.0)
|
|
19
|
+
Requires-Dist: nonebot2 (>=2.2.0,<3.0.0)
|
|
20
|
+
Requires-Dist: pydantic (>=2.0,<3.0)
|
|
21
|
+
Project-URL: Homepage, https://github.com/TonyLiangP2010405/nonebot-plugin-mantou-affection
|
|
22
|
+
Project-URL: Repository, https://github.com/TonyLiangP2010405/nonebot-plugin-mantou-affection
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# nonebot-plugin-mantou-affection
|
|
26
|
+
|
|
27
|
+
为群聊机器人“馒头”设计的 NoneBot2 共享好感度系统。群友通过 `/馒头互动` 以及现有插件的真实互动积累好感;每日运势、戳一戳、水群榜和桃纸助手会读取同一份关系状态,逐渐改变文案、语气与展示。
|
|
28
|
+
|
|
29
|
+
## 功能
|
|
30
|
+
|
|
31
|
+
- 好感数据按“群号 + 用户”隔离
|
|
32
|
+
- 主动互动、冷却时间和每日次数限制
|
|
33
|
+
- 七级好感称号和群排行榜
|
|
34
|
+
- 自动感知其他插件的命令、正则及完整匹配 Matcher
|
|
35
|
+
- 每插件独立冷却、每日联动奖励上限,避免刷分
|
|
36
|
+
- SUPERUSER 手动增减群友好感度
|
|
37
|
+
- 为其他插件提供好感上报与状态读取 API
|
|
38
|
+
- 使用 `nonebot-plugin-localstore` 和原子写入持久化数据
|
|
39
|
+
|
|
40
|
+
## 安装
|
|
41
|
+
|
|
42
|
+
### 使用 nb-cli
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
nb plugin install nonebot-plugin-mantou-affection
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 使用 pip
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install nonebot-plugin-mantou-affection
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 使用 Poetry
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
poetry add nonebot-plugin-mantou-affection
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
本地开发阶段也可以把 `nonebot_plugin_mantou_affection` 放进机器人项目的插件目录加载。
|
|
61
|
+
|
|
62
|
+
## 配置
|
|
63
|
+
|
|
64
|
+
全部配置均有默认值,零配置即可加载。在 NoneBot 项目的 `.env` 或对应环境文件中按需修改:
|
|
65
|
+
|
|
66
|
+
```env
|
|
67
|
+
MANTOU_AFFECTION_BOT_NAME=馒头
|
|
68
|
+
MANTOU_AFFECTION_TIMEZONE=Asia/Shanghai
|
|
69
|
+
MANTOU_AFFECTION_TEXT_PATH=
|
|
70
|
+
MANTOU_AFFECTION_INTERACTION_LIMIT=5
|
|
71
|
+
MANTOU_AFFECTION_INTERACTION_COOLDOWN=60
|
|
72
|
+
MANTOU_AFFECTION_MAX=999
|
|
73
|
+
MANTOU_AFFECTION_RANKING_SIZE=10
|
|
74
|
+
MANTOU_AFFECTION_LINK_ENABLED=true
|
|
75
|
+
MANTOU_AFFECTION_LINK_DAILY_LIMIT=10
|
|
76
|
+
MANTOU_AFFECTION_LINK_COOLDOWN=300
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`MANTOU_AFFECTION_LINK_REWARDS` 是“插件模块名 -> 单次变化值”的 JSON 对象,支持正数和负数。默认值如下:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"nonebot_plugin_taozi": 2,
|
|
84
|
+
"nonebot_plugin_taozi_music": 2,
|
|
85
|
+
"nonebot_plugin_xianmei": 1,
|
|
86
|
+
"nonebot_plugin_daily_attendance": 2,
|
|
87
|
+
"nonebot_plugin_crystelf": 1,
|
|
88
|
+
"nonebot_plugin_chat_learning": 1,
|
|
89
|
+
"nonebot_plugin_msg_rank_card": 1,
|
|
90
|
+
"nonebot_plugin_bili_dynamic": 1,
|
|
91
|
+
"nonebot_plugin_miao": 1
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 大型文案库
|
|
96
|
+
|
|
97
|
+
内置文案位于 `nonebot_plugin_mantou_affection/resources/affection_texts.json`,按“插件场景 + 好感阶段”组织。
|
|
98
|
+
当前场景包括 `daily_attendance.fortune`、`crystelf.poke`、`taozi.fortune` 和 `taozi.lexicon`;
|
|
99
|
+
每个场景可分别配置 `neutral`、`warm`、`close`、`flirty`、`intimate` 数组。
|
|
100
|
+
|
|
101
|
+
如果准备维护几百或几千条文案,建议把同结构 JSON 放在 bot 的数据目录外,并设置:
|
|
102
|
+
|
|
103
|
+
```env
|
|
104
|
+
MANTOU_AFFECTION_TEXT_PATH=/absolute/path/to/mantou_affection_texts.json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
外部文件只需写想覆盖的场景或阶段,其他部分继续使用内置文案。插件会检查文件修改时间并自动重载,
|
|
108
|
+
不需要改 Python 代码;格式错误时会保留内置文案并记录警告。戳一戳默认随机抽取,运势、桃签等场景
|
|
109
|
+
可以传入日期等 `seed`,让同一天的文案保持稳定。
|
|
110
|
+
|
|
111
|
+
例如只保留桃纸助手和每日运势联动:
|
|
112
|
+
|
|
113
|
+
```env
|
|
114
|
+
MANTOU_AFFECTION_LINK_REWARDS={"nonebot_plugin_taozi":2,"nonebot_plugin_daily_attendance":2}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## 使用方法
|
|
118
|
+
|
|
119
|
+
| 指令 | 权限 | 范围 | 说明 |
|
|
120
|
+
|---|---|---|---|
|
|
121
|
+
| `/馒头互动` | 群员 | 群聊 | 和馒头互动并获得 0~3 点好感 |
|
|
122
|
+
| `/馒头好感` | 群员 | 群聊 | 查看好感度、关系称号和联动额度 |
|
|
123
|
+
| `/馒头好感榜` | 群员 | 群聊 | 查看本群好感度排行榜 |
|
|
124
|
+
| `/馒头好感帮助` | 群员 | 群聊 | 查看菜单 |
|
|
125
|
+
| `/馒头好感调整 @群友 +10` | SUPERUSER | 群聊 | 手动增加或扣除好感度 |
|
|
126
|
+
|
|
127
|
+
## 插件联动
|
|
128
|
+
|
|
129
|
+
插件注册了 NoneBot `run_postprocessor`。其他插件的 Matcher 成功执行后,如果:
|
|
130
|
+
|
|
131
|
+
1. 来源插件出现在奖励表中;
|
|
132
|
+
2. 事件来自群聊;
|
|
133
|
+
3. Matcher 是命令、正则、完整匹配、关键词、开头或结尾匹配之一;
|
|
134
|
+
4. 本次执行没有抛出异常;
|
|
135
|
+
5. 没有触发该插件的联动冷却或每日上限;
|
|
136
|
+
|
|
137
|
+
则按配置向发起者静默增减好感度。普通 `on_message` 监听器不会自动变化,避免聊天学习、消息统计等插件在每条群消息上刷分。每日联动上限按变化值的绝对值计算。
|
|
138
|
+
|
|
139
|
+
### 主动上报 API
|
|
140
|
+
|
|
141
|
+
对于自动推送、戳一戳、献媚成功等无法从 Matcher 类型准确判断的事件,其他插件可以软依赖本插件并主动上报:
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from nonebot import require
|
|
145
|
+
|
|
146
|
+
require("nonebot_plugin_mantou_affection")
|
|
147
|
+
|
|
148
|
+
from nonebot_plugin_mantou_affection import (
|
|
149
|
+
add_affection,
|
|
150
|
+
change_affection,
|
|
151
|
+
get_affection,
|
|
152
|
+
get_affection_response,
|
|
153
|
+
get_affection_snapshot,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
actual = await add_affection(
|
|
157
|
+
group_id=event.group_id,
|
|
158
|
+
user_id=event.user_id,
|
|
159
|
+
delta=2,
|
|
160
|
+
nickname=event.sender.card or event.sender.nickname,
|
|
161
|
+
source="nonebot_plugin_xianmei:flatter",
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# 也可以让某个明确行为降低好感度
|
|
165
|
+
actual = await change_affection(
|
|
166
|
+
group_id=event.group_id,
|
|
167
|
+
user_id=event.user_id,
|
|
168
|
+
delta=-1,
|
|
169
|
+
nickname=event.sender.card or event.sender.nickname,
|
|
170
|
+
source="another_plugin:bad_action",
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
# 当前数值,以及适合调整语气的 neutral/warm/close/flirty/intimate 分层
|
|
174
|
+
score = await get_affection(event.group_id, event.user_id)
|
|
175
|
+
snapshot = await get_affection_snapshot(event.group_id, event.user_id)
|
|
176
|
+
print(snapshot.affection, snapshot.level, snapshot.title, snapshot.band)
|
|
177
|
+
|
|
178
|
+
# 按场景抽取文案;seed 非空时同一输入稳定返回同一句
|
|
179
|
+
response = await get_affection_response(
|
|
180
|
+
"crystelf.poke",
|
|
181
|
+
event.group_id,
|
|
182
|
+
event.user_id,
|
|
183
|
+
)
|
|
184
|
+
print(response.text)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
`add_affection` 与 `change_affection` 都会遵守每日联动上限和同一 `source` 的冷却,并返回实际变化值。`add_affection` 只接受正数,`change_affection` 接受正负数;两个读取 API 不会改变数据。
|
|
188
|
+
|
|
189
|
+
当前工作区还完成了四类展示联动:每日运势随关系阶段改写短句;Crystelf 戳一戳会增加好感并改变回复;水群榜展示每位群友的馒头好感;桃纸助手的桃签和词典卡片会出现不同程度的“馒头私语”。所有接入均为软依赖,好感插件未加载时原插件照常运行。
|
|
190
|
+
|
|
191
|
+
当前工作区中的 `nonebot-plugin-xianmei` 已在真正发出献媚文案时上报 `+2`,`nonebot-plugin-chat-learning` 已在真正回复成功时上报 `+1`;两处均为软联动,好感度插件未加载时不会影响原插件运行。
|
|
192
|
+
|
|
193
|
+
## 称号
|
|
194
|
+
|
|
195
|
+
| 好感度 | 称号 |
|
|
196
|
+
|---:|---|
|
|
197
|
+
| 0 | 初次见面 |
|
|
198
|
+
| 10 | 有点眼熟 |
|
|
199
|
+
| 30 | 愿意靠近 |
|
|
200
|
+
| 60 | 悄悄在意 |
|
|
201
|
+
| 100 | 暧昧升温 |
|
|
202
|
+
| 160 | 特别偏爱 |
|
|
203
|
+
| 250 | 心照不宣 |
|
|
204
|
+
|
|
205
|
+
## 数据存储
|
|
206
|
+
|
|
207
|
+
数据由 `nonebot-plugin-localstore` 保存为插件数据目录中的 `affection.json`。文件采用临时文件写入后原子替换,插件不会在 Python 安装包目录内写运行数据。
|
|
208
|
+
|
|
209
|
+
## 开发与测试
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
poetry install
|
|
213
|
+
poetry run python -m compileall nonebot_plugin_mantou_affection
|
|
214
|
+
poetry run pytest
|
|
215
|
+
poetry run ruff check .
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## 许可证
|
|
219
|
+
|
|
220
|
+
MIT
|
|
221
|
+
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# nonebot-plugin-mantou-affection
|
|
2
|
+
|
|
3
|
+
为群聊机器人“馒头”设计的 NoneBot2 共享好感度系统。群友通过 `/馒头互动` 以及现有插件的真实互动积累好感;每日运势、戳一戳、水群榜和桃纸助手会读取同一份关系状态,逐渐改变文案、语气与展示。
|
|
4
|
+
|
|
5
|
+
## 功能
|
|
6
|
+
|
|
7
|
+
- 好感数据按“群号 + 用户”隔离
|
|
8
|
+
- 主动互动、冷却时间和每日次数限制
|
|
9
|
+
- 七级好感称号和群排行榜
|
|
10
|
+
- 自动感知其他插件的命令、正则及完整匹配 Matcher
|
|
11
|
+
- 每插件独立冷却、每日联动奖励上限,避免刷分
|
|
12
|
+
- SUPERUSER 手动增减群友好感度
|
|
13
|
+
- 为其他插件提供好感上报与状态读取 API
|
|
14
|
+
- 使用 `nonebot-plugin-localstore` 和原子写入持久化数据
|
|
15
|
+
|
|
16
|
+
## 安装
|
|
17
|
+
|
|
18
|
+
### 使用 nb-cli
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
nb plugin install nonebot-plugin-mantou-affection
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 使用 pip
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install nonebot-plugin-mantou-affection
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 使用 Poetry
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
poetry add nonebot-plugin-mantou-affection
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
本地开发阶段也可以把 `nonebot_plugin_mantou_affection` 放进机器人项目的插件目录加载。
|
|
37
|
+
|
|
38
|
+
## 配置
|
|
39
|
+
|
|
40
|
+
全部配置均有默认值,零配置即可加载。在 NoneBot 项目的 `.env` 或对应环境文件中按需修改:
|
|
41
|
+
|
|
42
|
+
```env
|
|
43
|
+
MANTOU_AFFECTION_BOT_NAME=馒头
|
|
44
|
+
MANTOU_AFFECTION_TIMEZONE=Asia/Shanghai
|
|
45
|
+
MANTOU_AFFECTION_TEXT_PATH=
|
|
46
|
+
MANTOU_AFFECTION_INTERACTION_LIMIT=5
|
|
47
|
+
MANTOU_AFFECTION_INTERACTION_COOLDOWN=60
|
|
48
|
+
MANTOU_AFFECTION_MAX=999
|
|
49
|
+
MANTOU_AFFECTION_RANKING_SIZE=10
|
|
50
|
+
MANTOU_AFFECTION_LINK_ENABLED=true
|
|
51
|
+
MANTOU_AFFECTION_LINK_DAILY_LIMIT=10
|
|
52
|
+
MANTOU_AFFECTION_LINK_COOLDOWN=300
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`MANTOU_AFFECTION_LINK_REWARDS` 是“插件模块名 -> 单次变化值”的 JSON 对象,支持正数和负数。默认值如下:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"nonebot_plugin_taozi": 2,
|
|
60
|
+
"nonebot_plugin_taozi_music": 2,
|
|
61
|
+
"nonebot_plugin_xianmei": 1,
|
|
62
|
+
"nonebot_plugin_daily_attendance": 2,
|
|
63
|
+
"nonebot_plugin_crystelf": 1,
|
|
64
|
+
"nonebot_plugin_chat_learning": 1,
|
|
65
|
+
"nonebot_plugin_msg_rank_card": 1,
|
|
66
|
+
"nonebot_plugin_bili_dynamic": 1,
|
|
67
|
+
"nonebot_plugin_miao": 1
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 大型文案库
|
|
72
|
+
|
|
73
|
+
内置文案位于 `nonebot_plugin_mantou_affection/resources/affection_texts.json`,按“插件场景 + 好感阶段”组织。
|
|
74
|
+
当前场景包括 `daily_attendance.fortune`、`crystelf.poke`、`taozi.fortune` 和 `taozi.lexicon`;
|
|
75
|
+
每个场景可分别配置 `neutral`、`warm`、`close`、`flirty`、`intimate` 数组。
|
|
76
|
+
|
|
77
|
+
如果准备维护几百或几千条文案,建议把同结构 JSON 放在 bot 的数据目录外,并设置:
|
|
78
|
+
|
|
79
|
+
```env
|
|
80
|
+
MANTOU_AFFECTION_TEXT_PATH=/absolute/path/to/mantou_affection_texts.json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
外部文件只需写想覆盖的场景或阶段,其他部分继续使用内置文案。插件会检查文件修改时间并自动重载,
|
|
84
|
+
不需要改 Python 代码;格式错误时会保留内置文案并记录警告。戳一戳默认随机抽取,运势、桃签等场景
|
|
85
|
+
可以传入日期等 `seed`,让同一天的文案保持稳定。
|
|
86
|
+
|
|
87
|
+
例如只保留桃纸助手和每日运势联动:
|
|
88
|
+
|
|
89
|
+
```env
|
|
90
|
+
MANTOU_AFFECTION_LINK_REWARDS={"nonebot_plugin_taozi":2,"nonebot_plugin_daily_attendance":2}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## 使用方法
|
|
94
|
+
|
|
95
|
+
| 指令 | 权限 | 范围 | 说明 |
|
|
96
|
+
|---|---|---|---|
|
|
97
|
+
| `/馒头互动` | 群员 | 群聊 | 和馒头互动并获得 0~3 点好感 |
|
|
98
|
+
| `/馒头好感` | 群员 | 群聊 | 查看好感度、关系称号和联动额度 |
|
|
99
|
+
| `/馒头好感榜` | 群员 | 群聊 | 查看本群好感度排行榜 |
|
|
100
|
+
| `/馒头好感帮助` | 群员 | 群聊 | 查看菜单 |
|
|
101
|
+
| `/馒头好感调整 @群友 +10` | SUPERUSER | 群聊 | 手动增加或扣除好感度 |
|
|
102
|
+
|
|
103
|
+
## 插件联动
|
|
104
|
+
|
|
105
|
+
插件注册了 NoneBot `run_postprocessor`。其他插件的 Matcher 成功执行后,如果:
|
|
106
|
+
|
|
107
|
+
1. 来源插件出现在奖励表中;
|
|
108
|
+
2. 事件来自群聊;
|
|
109
|
+
3. Matcher 是命令、正则、完整匹配、关键词、开头或结尾匹配之一;
|
|
110
|
+
4. 本次执行没有抛出异常;
|
|
111
|
+
5. 没有触发该插件的联动冷却或每日上限;
|
|
112
|
+
|
|
113
|
+
则按配置向发起者静默增减好感度。普通 `on_message` 监听器不会自动变化,避免聊天学习、消息统计等插件在每条群消息上刷分。每日联动上限按变化值的绝对值计算。
|
|
114
|
+
|
|
115
|
+
### 主动上报 API
|
|
116
|
+
|
|
117
|
+
对于自动推送、戳一戳、献媚成功等无法从 Matcher 类型准确判断的事件,其他插件可以软依赖本插件并主动上报:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from nonebot import require
|
|
121
|
+
|
|
122
|
+
require("nonebot_plugin_mantou_affection")
|
|
123
|
+
|
|
124
|
+
from nonebot_plugin_mantou_affection import (
|
|
125
|
+
add_affection,
|
|
126
|
+
change_affection,
|
|
127
|
+
get_affection,
|
|
128
|
+
get_affection_response,
|
|
129
|
+
get_affection_snapshot,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
actual = await add_affection(
|
|
133
|
+
group_id=event.group_id,
|
|
134
|
+
user_id=event.user_id,
|
|
135
|
+
delta=2,
|
|
136
|
+
nickname=event.sender.card or event.sender.nickname,
|
|
137
|
+
source="nonebot_plugin_xianmei:flatter",
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# 也可以让某个明确行为降低好感度
|
|
141
|
+
actual = await change_affection(
|
|
142
|
+
group_id=event.group_id,
|
|
143
|
+
user_id=event.user_id,
|
|
144
|
+
delta=-1,
|
|
145
|
+
nickname=event.sender.card or event.sender.nickname,
|
|
146
|
+
source="another_plugin:bad_action",
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
# 当前数值,以及适合调整语气的 neutral/warm/close/flirty/intimate 分层
|
|
150
|
+
score = await get_affection(event.group_id, event.user_id)
|
|
151
|
+
snapshot = await get_affection_snapshot(event.group_id, event.user_id)
|
|
152
|
+
print(snapshot.affection, snapshot.level, snapshot.title, snapshot.band)
|
|
153
|
+
|
|
154
|
+
# 按场景抽取文案;seed 非空时同一输入稳定返回同一句
|
|
155
|
+
response = await get_affection_response(
|
|
156
|
+
"crystelf.poke",
|
|
157
|
+
event.group_id,
|
|
158
|
+
event.user_id,
|
|
159
|
+
)
|
|
160
|
+
print(response.text)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`add_affection` 与 `change_affection` 都会遵守每日联动上限和同一 `source` 的冷却,并返回实际变化值。`add_affection` 只接受正数,`change_affection` 接受正负数;两个读取 API 不会改变数据。
|
|
164
|
+
|
|
165
|
+
当前工作区还完成了四类展示联动:每日运势随关系阶段改写短句;Crystelf 戳一戳会增加好感并改变回复;水群榜展示每位群友的馒头好感;桃纸助手的桃签和词典卡片会出现不同程度的“馒头私语”。所有接入均为软依赖,好感插件未加载时原插件照常运行。
|
|
166
|
+
|
|
167
|
+
当前工作区中的 `nonebot-plugin-xianmei` 已在真正发出献媚文案时上报 `+2`,`nonebot-plugin-chat-learning` 已在真正回复成功时上报 `+1`;两处均为软联动,好感度插件未加载时不会影响原插件运行。
|
|
168
|
+
|
|
169
|
+
## 称号
|
|
170
|
+
|
|
171
|
+
| 好感度 | 称号 |
|
|
172
|
+
|---:|---|
|
|
173
|
+
| 0 | 初次见面 |
|
|
174
|
+
| 10 | 有点眼熟 |
|
|
175
|
+
| 30 | 愿意靠近 |
|
|
176
|
+
| 60 | 悄悄在意 |
|
|
177
|
+
| 100 | 暧昧升温 |
|
|
178
|
+
| 160 | 特别偏爱 |
|
|
179
|
+
| 250 | 心照不宣 |
|
|
180
|
+
|
|
181
|
+
## 数据存储
|
|
182
|
+
|
|
183
|
+
数据由 `nonebot-plugin-localstore` 保存为插件数据目录中的 `affection.json`。文件采用临时文件写入后原子替换,插件不会在 Python 安装包目录内写运行数据。
|
|
184
|
+
|
|
185
|
+
## 开发与测试
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
poetry install
|
|
189
|
+
poetry run python -m compileall nonebot_plugin_mantou_affection
|
|
190
|
+
poetry run pytest
|
|
191
|
+
poetry run ruff check .
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## 许可证
|
|
195
|
+
|
|
196
|
+
MIT
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from nonebot import get_plugin_config, require
|
|
6
|
+
from nonebot.plugin import PluginMetadata
|
|
7
|
+
|
|
8
|
+
from .config import Config
|
|
9
|
+
|
|
10
|
+
__plugin_meta__ = PluginMetadata(
|
|
11
|
+
name="馒头好感度",
|
|
12
|
+
description="为群聊机器人馒头提供互动、关系阶段和跨插件共享好感状态",
|
|
13
|
+
usage=(
|
|
14
|
+
"/馒头互动|/馒头好感|/馒头好感榜|/馒头好感帮助\n"
|
|
15
|
+
"SUPERUSER:/馒头好感调整 @群友 +10"
|
|
16
|
+
),
|
|
17
|
+
type="application",
|
|
18
|
+
homepage="https://github.com/TonyLiangP2010405/nonebot-plugin-mantou-affection",
|
|
19
|
+
config=Config,
|
|
20
|
+
supported_adapters={"~onebot.v11"},
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
require("nonebot_plugin_localstore")
|
|
24
|
+
|
|
25
|
+
from nonebot_plugin_localstore import get_plugin_data_dir
|
|
26
|
+
|
|
27
|
+
from .commands import register_commands
|
|
28
|
+
from .copywriting import AffectionTextLibrary
|
|
29
|
+
from .integration import register_plugin_linkage
|
|
30
|
+
from .models import AffectionResponse, AffectionSnapshot
|
|
31
|
+
from .service import AffectionService
|
|
32
|
+
from .storage import AffectionStore
|
|
33
|
+
|
|
34
|
+
plugin_config = get_plugin_config(Config)
|
|
35
|
+
data_file = Path(get_plugin_data_dir()) / "affection.json"
|
|
36
|
+
store = AffectionStore(data_file)
|
|
37
|
+
service = AffectionService(store, plugin_config)
|
|
38
|
+
text_library = AffectionTextLibrary(
|
|
39
|
+
Path(__file__).parent / "resources" / "affection_texts.json",
|
|
40
|
+
plugin_config.mantou_affection_text_path,
|
|
41
|
+
)
|
|
42
|
+
matchers = register_commands(service, plugin_config)
|
|
43
|
+
plugin_linkage = register_plugin_linkage(service, plugin_config)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
async def add_affection(
|
|
47
|
+
group_id: str | int,
|
|
48
|
+
user_id: str | int,
|
|
49
|
+
delta: int,
|
|
50
|
+
*,
|
|
51
|
+
nickname: str = "",
|
|
52
|
+
source: str = "external",
|
|
53
|
+
) -> int:
|
|
54
|
+
"""供其他插件主动增加好感度;返回实际增加值。"""
|
|
55
|
+
|
|
56
|
+
if delta <= 0:
|
|
57
|
+
raise ValueError("联动增加值必须大于 0")
|
|
58
|
+
result = await service.reward_external(
|
|
59
|
+
str(group_id), str(user_id), nickname, source, delta
|
|
60
|
+
)
|
|
61
|
+
return result.delta
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
async def change_affection(
|
|
65
|
+
group_id: str | int,
|
|
66
|
+
user_id: str | int,
|
|
67
|
+
delta: int,
|
|
68
|
+
*,
|
|
69
|
+
nickname: str = "",
|
|
70
|
+
source: str = "external",
|
|
71
|
+
) -> int:
|
|
72
|
+
"""供其他插件按正负数改变好感度;返回实际变化值。"""
|
|
73
|
+
|
|
74
|
+
if delta == 0:
|
|
75
|
+
return 0
|
|
76
|
+
result = await service.reward_external(
|
|
77
|
+
str(group_id), str(user_id), nickname, source, delta
|
|
78
|
+
)
|
|
79
|
+
return result.delta
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
async def get_affection(group_id: str | int, user_id: str | int) -> int:
|
|
83
|
+
"""读取指定群友的当前好感度;不存在记录时返回 0。"""
|
|
84
|
+
|
|
85
|
+
return (await service.profile(str(group_id), str(user_id))).affection
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
async def get_affection_snapshot(
|
|
89
|
+
group_id: str | int,
|
|
90
|
+
user_id: str | int,
|
|
91
|
+
) -> AffectionSnapshot:
|
|
92
|
+
"""读取好感度、等级、称号和语气分层,供其他插件软联动。"""
|
|
93
|
+
|
|
94
|
+
return await service.snapshot(str(group_id), str(user_id))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
async def get_affection_response(
|
|
98
|
+
scene: str,
|
|
99
|
+
group_id: str | int,
|
|
100
|
+
user_id: str | int,
|
|
101
|
+
*,
|
|
102
|
+
seed: str = "",
|
|
103
|
+
) -> AffectionResponse:
|
|
104
|
+
"""按场景与当前好感阶段选择文案;seed 非空时结果稳定。"""
|
|
105
|
+
|
|
106
|
+
snapshot = await service.snapshot(str(group_id), str(user_id))
|
|
107
|
+
text = text_library.pick(scene, snapshot, seed=seed)
|
|
108
|
+
return AffectionResponse(
|
|
109
|
+
affection=snapshot.affection,
|
|
110
|
+
level=snapshot.level,
|
|
111
|
+
title=snapshot.title,
|
|
112
|
+
band=snapshot.band,
|
|
113
|
+
text=text,
|
|
114
|
+
)
|