nonebot-plugin-dialectlist 2.0.4__tar.gz → 2.1.4__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_dialectlist-2.1.4/PKG-INFO +203 -0
- nonebot_plugin_dialectlist-2.1.4/README.md +179 -0
- {nonebot_plugin_dialectlist-2.0.4 → nonebot_plugin_dialectlist-2.1.4}/nonebot_plugin_dialectlist/__init__.py +54 -39
- {nonebot_plugin_dialectlist-2.0.4 → nonebot_plugin_dialectlist-2.1.4}/nonebot_plugin_dialectlist/config.py +2 -1
- nonebot_plugin_dialectlist-2.1.4/nonebot_plugin_dialectlist/model.py +11 -0
- {nonebot_plugin_dialectlist-2.0.4 → nonebot_plugin_dialectlist-2.1.4}/nonebot_plugin_dialectlist/storage.py +1 -1
- nonebot_plugin_dialectlist-2.1.4/nonebot_plugin_dialectlist/time.py +80 -0
- nonebot_plugin_dialectlist-2.1.4/nonebot_plugin_dialectlist/utils.py +151 -0
- nonebot_plugin_dialectlist-2.1.4/nonebot_plugin_dialectlist.egg-info/PKG-INFO +203 -0
- {nonebot_plugin_dialectlist-2.0.4 → nonebot_plugin_dialectlist-2.1.4}/nonebot_plugin_dialectlist.egg-info/SOURCES.txt +1 -1
- {nonebot_plugin_dialectlist-2.0.4 → nonebot_plugin_dialectlist-2.1.4}/nonebot_plugin_dialectlist.egg-info/requires.txt +1 -0
- {nonebot_plugin_dialectlist-2.0.4 → nonebot_plugin_dialectlist-2.1.4}/pyproject.toml +4 -3
- nonebot_plugin_dialectlist-2.0.4/PKG-INFO +0 -152
- nonebot_plugin_dialectlist-2.0.4/README.md +0 -129
- nonebot_plugin_dialectlist-2.0.4/nonebot_plugin_dialectlist/render.py +0 -1
- nonebot_plugin_dialectlist-2.0.4/nonebot_plugin_dialectlist/time.py +0 -1
- nonebot_plugin_dialectlist-2.0.4/nonebot_plugin_dialectlist/utils.py +0 -460
- nonebot_plugin_dialectlist-2.0.4/nonebot_plugin_dialectlist.egg-info/PKG-INFO +0 -152
- {nonebot_plugin_dialectlist-2.0.4 → nonebot_plugin_dialectlist-2.1.4}/nonebot_plugin_dialectlist/usage.py +0 -0
- {nonebot_plugin_dialectlist-2.0.4 → nonebot_plugin_dialectlist-2.1.4}/nonebot_plugin_dialectlist.egg-info/dependency_links.txt +0 -0
- {nonebot_plugin_dialectlist-2.0.4 → nonebot_plugin_dialectlist-2.1.4}/nonebot_plugin_dialectlist.egg-info/top_level.txt +0 -0
- {nonebot_plugin_dialectlist-2.0.4 → nonebot_plugin_dialectlist-2.1.4}/setup.cfg +0 -0
- {nonebot_plugin_dialectlist-2.0.4 → nonebot_plugin_dialectlist-2.1.4}/setup.py +0 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: nonebot_plugin_dialectlist
|
|
3
|
+
Version: 2.1.4
|
|
4
|
+
Summary: 看看你群群友有多能说
|
|
5
|
+
Author-email: Chen_Xu233 <woyerpa@outlook.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: <4.0,>=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: nonebot2>=2.3.1
|
|
10
|
+
Requires-Dist: nonebot-plugin-chatrecorder>=0.6.0
|
|
11
|
+
Requires-Dist: pygal>=3.0.4
|
|
12
|
+
Requires-Dist: requests>=2.32.3
|
|
13
|
+
Requires-Dist: nonebot-plugin-apscheduler>=0.4.0
|
|
14
|
+
Requires-Dist: nonebot-plugin-alconna>=0.46.6
|
|
15
|
+
Requires-Dist: nonebot-plugin-cesaa>=0.4.0
|
|
16
|
+
Requires-Dist: nonebot-plugin-userinfo>=0.2.4
|
|
17
|
+
Requires-Dist: pyecharts>=2.0.5
|
|
18
|
+
Requires-Dist: nonebot-plugin-htmlrender>=0.3.2
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: ruff>=0.4.9; extra == "dev"
|
|
21
|
+
Requires-Dist: setuptools>=70.0.0; extra == "dev"
|
|
22
|
+
Requires-Dist: twine>=5.1.0; extra == "dev"
|
|
23
|
+
Requires-Dist: nb-cli>=0.7.6; extra == "dev"
|
|
24
|
+
|
|
25
|
+
<div align="center">
|
|
26
|
+
<a href="https://v2.nonebot.dev/store"><img src="./docs/NoneBotPlugin.svg" width="400" alt="NoneBotPluginLogo"></a>
|
|
27
|
+
<br>
|
|
28
|
+
<p><img src="https://s2.loli.net/2022/06/16/xsVUGRrkbn1ljTD.png" width="240" alt="NoneBotPluginText"></p>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div align="center">
|
|
32
|
+
|
|
33
|
+
# 📃话痨排行榜
|
|
34
|
+
nonebot-plugin-dialectlist
|
|
35
|
+
|
|
36
|
+
<p align="center">
|
|
37
|
+
<a href="https://pypi.python.org/pypi/nonebot-plugin-wordcloud">
|
|
38
|
+
<img src="https://img.shields.io/pypi/v/nonebot-plugin-wordcloud.svg" alt="pypi">
|
|
39
|
+
</a>
|
|
40
|
+
|
|
41
|
+
<img src="https://img.shields.io/badge/python-3.9+-blue.svg" alt="python">
|
|
42
|
+
|
|
43
|
+
<a href="https://qm.qq.com/q/Yty2yc9Bee">
|
|
44
|
+
<img src="https://img.shields.io/badge/QQ%E7%BE%A4-1128359833-orange?style=flat-square" alt="QQ Chat Group">
|
|
45
|
+
</a>
|
|
46
|
+
</p>
|
|
47
|
+
|
|
48
|
+
\>💬**看看群友们这些天在群里水了多少话**💬<
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
## 💿 安装
|
|
52
|
+
|
|
53
|
+
通过`pip`或`nb`安装;
|
|
54
|
+
|
|
55
|
+
>**通过 pip **安装
|
|
56
|
+
|
|
57
|
+
`pip install nonebot-plugin-dialectlist`
|
|
58
|
+
|
|
59
|
+
>**通过 nb **安装
|
|
60
|
+
|
|
61
|
+
`nb plugin install nonebot-plugin-dialectlist`
|
|
62
|
+
|
|
63
|
+
### ✅ 插件依赖于
|
|
64
|
+
|
|
65
|
+
1. [nonebot-plugin-datastore](https://github.com/he0119/nonebot-plugin-datastore) ————储存历史的消息
|
|
66
|
+
2. [nonebot-plugin-userinfo](https://github.com/noneplugin/nonebot-plugin-userinfo) ————获取用户信息
|
|
67
|
+
3. [nonebot-plugin-apscheduler](https://github.com/nonebot/plugin-apscheduler) ————定时发送排行榜信息
|
|
68
|
+
4. [nonebot-plugin-alconna](https://github.com/ArcletProject/nonebot-plugin-alconna) ————实现命令解析
|
|
69
|
+
5. [nonebot-plugin-cesaa](https://github.com/MountainDash/nonebot-plugin-send-anything-anywhere) ————实现多平台
|
|
70
|
+
|
|
71
|
+
## ⚙ 配置
|
|
72
|
+
|
|
73
|
+
需要**提前配置**本插件所**依赖的插件**!
|
|
74
|
+
|
|
75
|
+
在 .env 中,可以添加以下配置项
|
|
76
|
+
```python
|
|
77
|
+
dialectlist__string_format = '第{index}名:\n{nickname},{chatdatanum}条消息、n' #消息格式
|
|
78
|
+
dialectlist__string_suffix_format = '你们的职业是水群吗?————MYX\n 计算花费时间:{timecost}秒' #消息后缀格式
|
|
79
|
+
dialectlist__get_num = 10 #获取人数数量
|
|
80
|
+
dialectlist__visualization = True #是否可视化
|
|
81
|
+
dialectlist__visualization_type = '圆环图' #可视化方案
|
|
82
|
+
dialectlist__font = 'SimHei'#字体格式
|
|
83
|
+
dialectlist__excluded_people = []#排除的人的 QQ 号(或频道号?(未经测试))
|
|
84
|
+
dialectlist__excluded_self = True #是否排除机器人自己 QQ
|
|
85
|
+
```
|
|
86
|
+
💭也可以不进行配置,这将会使插件按照默认配置运行
|
|
87
|
+
|
|
88
|
+
### ⚠ 注意!!
|
|
89
|
+
|
|
90
|
+
> 在旧版插件(2.0.0 以下)中,dialectlist 与后面的配置项只隔了一个下划线,若更新到新版本以后需要俩个下划线。
|
|
91
|
+
|
|
92
|
+
## 🗨命令
|
|
93
|
+
__!!注意!!__
|
|
94
|
+
新版本指令调用方式改变,改为更易理解也更好打的 B 话榜。
|
|
95
|
+
同时也可以用类似 `/今日废话榜` 的方式(只要改前面的就好了)(算是给[盘古之白](https://github.com/vinta/pangu.js)风格爱好者的福利吧?)
|
|
96
|
+
|
|
97
|
+
### 🎨一般用法
|
|
98
|
+
|
|
99
|
+
-`/B话榜` ————看看有史以来(机器人存在以来)群友们发了多少消息! (好像没写)
|
|
100
|
+
|
|
101
|
+
-`/今日B话榜` ————看看今天的群友发了多少消息!
|
|
102
|
+
|
|
103
|
+
-`/昨日B话榜` ————看看昨天的群友发了多少消息!
|
|
104
|
+
|
|
105
|
+
-`/前日B话榜` ————看看前天的群友发了多少消息!
|
|
106
|
+
|
|
107
|
+
-`/本周B话榜` ————看看本周的群友发了多少消息!
|
|
108
|
+
|
|
109
|
+
-`/上周B话榜` ————看看上周的群友发了多少消息!
|
|
110
|
+
|
|
111
|
+
-`/本月B话榜` ————看看这个月的群友发了多少消息!
|
|
112
|
+
|
|
113
|
+
-`/年度B话榜` ————看看今年的群友发了多少消息!
|
|
114
|
+
|
|
115
|
+
-`/历史B话榜` ————看看历史上(机器人存在以来)的群友发了多少消息!
|
|
116
|
+
|
|
117
|
+
### 🚀进阶用法
|
|
118
|
+
|
|
119
|
+
`/{时间类型(今日|年度)?}{B话榜|废话榜} {时间类型?} {ISO8601格式时间} {群号}`
|
|
120
|
+
|
|
121
|
+
如:`/B话榜 历史 2024-01-01~2024-01-02 12345678`
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
## 📖版本
|
|
125
|
+
|
|
126
|
+
### V1.0
|
|
127
|
+
|
|
128
|
+
- 看看群里群友能有多话痨
|
|
129
|
+
|
|
130
|
+
### V1.1
|
|
131
|
+
|
|
132
|
+
- 支持频道咯!(*^_^*)
|
|
133
|
+
|
|
134
|
+
### V1.2
|
|
135
|
+
|
|
136
|
+
- 排行榜可视化
|
|
137
|
+
|
|
138
|
+
### V1.3
|
|
139
|
+
|
|
140
|
+
- 添加了一些可配置项
|
|
141
|
+
|
|
142
|
+
### V1.4
|
|
143
|
+
|
|
144
|
+
- 适配新版本的 chatrecorder, 暂时停止频道支持
|
|
145
|
+
|
|
146
|
+
### V2.0
|
|
147
|
+
|
|
148
|
+
- 理论支持全平台!暂停图片支持。
|
|
149
|
+
|
|
150
|
+
## 💪 目前支持的平台
|
|
151
|
+
|
|
152
|
+
| 平台 | 是否经过测试 | 是否能够正常工作 | 测试环境 |
|
|
153
|
+
|:-----:|:----:|:----:| :----: |
|
|
154
|
+
| Onebot | ✅ | ✅ | NapCat + Window11|
|
|
155
|
+
| 飞书 | ❌ | ❓ | 🤔 |
|
|
156
|
+
| Red | ❌ | ❓ | 🤔 |
|
|
157
|
+
| DoDo | ❌ | ❓ | 🤔 |
|
|
158
|
+
| Mirai | ❌ | ❓ | 🤔 |
|
|
159
|
+
| 开黑啦 | ❌ | ❓ | 🤔 |
|
|
160
|
+
| Kritor | ❌ | ❓ | 🤔 |
|
|
161
|
+
| Ntchat | ❌ | ❓ | 🤔 |
|
|
162
|
+
| Satori | ❌ | ❓ | 🤔 |
|
|
163
|
+
| Telegram | ❌ | ❓ | 🤔 |
|
|
164
|
+
| Discord | ❌ | ❓ | 🤔 |
|
|
165
|
+
| Tailchat | ❌ | ❓ | 🤔 |
|
|
166
|
+
| QQ 官方接口 | ❌ | ❓ | 🤔 |
|
|
167
|
+
| Rocket.Chat | ❌ | ❓ | 🤔 |
|
|
168
|
+
|
|
169
|
+
- 如果你测试过能够使用,请在 Issue 中指出
|
|
170
|
+
|
|
171
|
+
## 📦另外
|
|
172
|
+
|
|
173
|
+
### 😳加入作者的 BUG 反馈群 ~~(🥵女装粉丝群)~~
|
|
174
|
+
|
|
175
|
+
[群连接](https://qm.qq.com/q/Yty2yc9Bee)
|
|
176
|
+
|
|
177
|
+
<details>
|
|
178
|
+
<summary>群二维码 点我展开</summary>
|
|
179
|
+
|
|
180
|
+

|
|
181
|
+
|
|
182
|
+
</details>
|
|
183
|
+
|
|
184
|
+
### 💕感谢
|
|
185
|
+
|
|
186
|
+
本插件的__init__.py 中的处理函数参考了词云中的方法 ~~(其实大部分都是 Ctrl+C Ctr+V)~~
|
|
187
|
+
|
|
188
|
+
[nonebot-plugin-wordcloud](https://github.com/he0119/nonebot-plugin-wordcloud)
|
|
189
|
+
|
|
190
|
+
### 🎀TODO
|
|
191
|
+
|
|
192
|
+
- [x] 适配全平台
|
|
193
|
+
|
|
194
|
+
- [ ] 私聊的查询(超级用户可以任意查询群聊的信息)
|
|
195
|
+
|
|
196
|
+
- [ ] 关键词查询
|
|
197
|
+
|
|
198
|
+
- [ ] 尝试利用 jinja2 模板引擎制作可视化图片 (((真的可以吗?))
|
|
199
|
+
|
|
200
|
+
待补充。.....
|
|
201
|
+
|
|
202
|
+
### 👾题外话
|
|
203
|
+
~~整个项目快被我写成屎山了~~
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<a href="https://v2.nonebot.dev/store"><img src="./docs/NoneBotPlugin.svg" width="400" alt="NoneBotPluginLogo"></a>
|
|
3
|
+
<br>
|
|
4
|
+
<p><img src="https://s2.loli.net/2022/06/16/xsVUGRrkbn1ljTD.png" width="240" alt="NoneBotPluginText"></p>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
<div align="center">
|
|
8
|
+
|
|
9
|
+
# 📃话痨排行榜
|
|
10
|
+
nonebot-plugin-dialectlist
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://pypi.python.org/pypi/nonebot-plugin-wordcloud">
|
|
14
|
+
<img src="https://img.shields.io/pypi/v/nonebot-plugin-wordcloud.svg" alt="pypi">
|
|
15
|
+
</a>
|
|
16
|
+
|
|
17
|
+
<img src="https://img.shields.io/badge/python-3.9+-blue.svg" alt="python">
|
|
18
|
+
|
|
19
|
+
<a href="https://qm.qq.com/q/Yty2yc9Bee">
|
|
20
|
+
<img src="https://img.shields.io/badge/QQ%E7%BE%A4-1128359833-orange?style=flat-square" alt="QQ Chat Group">
|
|
21
|
+
</a>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
\>💬**看看群友们这些天在群里水了多少话**💬<
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
## 💿 安装
|
|
28
|
+
|
|
29
|
+
通过`pip`或`nb`安装;
|
|
30
|
+
|
|
31
|
+
>**通过 pip **安装
|
|
32
|
+
|
|
33
|
+
`pip install nonebot-plugin-dialectlist`
|
|
34
|
+
|
|
35
|
+
>**通过 nb **安装
|
|
36
|
+
|
|
37
|
+
`nb plugin install nonebot-plugin-dialectlist`
|
|
38
|
+
|
|
39
|
+
### ✅ 插件依赖于
|
|
40
|
+
|
|
41
|
+
1. [nonebot-plugin-datastore](https://github.com/he0119/nonebot-plugin-datastore) ————储存历史的消息
|
|
42
|
+
2. [nonebot-plugin-userinfo](https://github.com/noneplugin/nonebot-plugin-userinfo) ————获取用户信息
|
|
43
|
+
3. [nonebot-plugin-apscheduler](https://github.com/nonebot/plugin-apscheduler) ————定时发送排行榜信息
|
|
44
|
+
4. [nonebot-plugin-alconna](https://github.com/ArcletProject/nonebot-plugin-alconna) ————实现命令解析
|
|
45
|
+
5. [nonebot-plugin-cesaa](https://github.com/MountainDash/nonebot-plugin-send-anything-anywhere) ————实现多平台
|
|
46
|
+
|
|
47
|
+
## ⚙ 配置
|
|
48
|
+
|
|
49
|
+
需要**提前配置**本插件所**依赖的插件**!
|
|
50
|
+
|
|
51
|
+
在 .env 中,可以添加以下配置项
|
|
52
|
+
```python
|
|
53
|
+
dialectlist__string_format = '第{index}名:\n{nickname},{chatdatanum}条消息、n' #消息格式
|
|
54
|
+
dialectlist__string_suffix_format = '你们的职业是水群吗?————MYX\n 计算花费时间:{timecost}秒' #消息后缀格式
|
|
55
|
+
dialectlist__get_num = 10 #获取人数数量
|
|
56
|
+
dialectlist__visualization = True #是否可视化
|
|
57
|
+
dialectlist__visualization_type = '圆环图' #可视化方案
|
|
58
|
+
dialectlist__font = 'SimHei'#字体格式
|
|
59
|
+
dialectlist__excluded_people = []#排除的人的 QQ 号(或频道号?(未经测试))
|
|
60
|
+
dialectlist__excluded_self = True #是否排除机器人自己 QQ
|
|
61
|
+
```
|
|
62
|
+
💭也可以不进行配置,这将会使插件按照默认配置运行
|
|
63
|
+
|
|
64
|
+
### ⚠ 注意!!
|
|
65
|
+
|
|
66
|
+
> 在旧版插件(2.0.0 以下)中,dialectlist 与后面的配置项只隔了一个下划线,若更新到新版本以后需要俩个下划线。
|
|
67
|
+
|
|
68
|
+
## 🗨命令
|
|
69
|
+
__!!注意!!__
|
|
70
|
+
新版本指令调用方式改变,改为更易理解也更好打的 B 话榜。
|
|
71
|
+
同时也可以用类似 `/今日废话榜` 的方式(只要改前面的就好了)(算是给[盘古之白](https://github.com/vinta/pangu.js)风格爱好者的福利吧?)
|
|
72
|
+
|
|
73
|
+
### 🎨一般用法
|
|
74
|
+
|
|
75
|
+
-`/B话榜` ————看看有史以来(机器人存在以来)群友们发了多少消息! (好像没写)
|
|
76
|
+
|
|
77
|
+
-`/今日B话榜` ————看看今天的群友发了多少消息!
|
|
78
|
+
|
|
79
|
+
-`/昨日B话榜` ————看看昨天的群友发了多少消息!
|
|
80
|
+
|
|
81
|
+
-`/前日B话榜` ————看看前天的群友发了多少消息!
|
|
82
|
+
|
|
83
|
+
-`/本周B话榜` ————看看本周的群友发了多少消息!
|
|
84
|
+
|
|
85
|
+
-`/上周B话榜` ————看看上周的群友发了多少消息!
|
|
86
|
+
|
|
87
|
+
-`/本月B话榜` ————看看这个月的群友发了多少消息!
|
|
88
|
+
|
|
89
|
+
-`/年度B话榜` ————看看今年的群友发了多少消息!
|
|
90
|
+
|
|
91
|
+
-`/历史B话榜` ————看看历史上(机器人存在以来)的群友发了多少消息!
|
|
92
|
+
|
|
93
|
+
### 🚀进阶用法
|
|
94
|
+
|
|
95
|
+
`/{时间类型(今日|年度)?}{B话榜|废话榜} {时间类型?} {ISO8601格式时间} {群号}`
|
|
96
|
+
|
|
97
|
+
如:`/B话榜 历史 2024-01-01~2024-01-02 12345678`
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
## 📖版本
|
|
101
|
+
|
|
102
|
+
### V1.0
|
|
103
|
+
|
|
104
|
+
- 看看群里群友能有多话痨
|
|
105
|
+
|
|
106
|
+
### V1.1
|
|
107
|
+
|
|
108
|
+
- 支持频道咯!(*^_^*)
|
|
109
|
+
|
|
110
|
+
### V1.2
|
|
111
|
+
|
|
112
|
+
- 排行榜可视化
|
|
113
|
+
|
|
114
|
+
### V1.3
|
|
115
|
+
|
|
116
|
+
- 添加了一些可配置项
|
|
117
|
+
|
|
118
|
+
### V1.4
|
|
119
|
+
|
|
120
|
+
- 适配新版本的 chatrecorder, 暂时停止频道支持
|
|
121
|
+
|
|
122
|
+
### V2.0
|
|
123
|
+
|
|
124
|
+
- 理论支持全平台!暂停图片支持。
|
|
125
|
+
|
|
126
|
+
## 💪 目前支持的平台
|
|
127
|
+
|
|
128
|
+
| 平台 | 是否经过测试 | 是否能够正常工作 | 测试环境 |
|
|
129
|
+
|:-----:|:----:|:----:| :----: |
|
|
130
|
+
| Onebot | ✅ | ✅ | NapCat + Window11|
|
|
131
|
+
| 飞书 | ❌ | ❓ | 🤔 |
|
|
132
|
+
| Red | ❌ | ❓ | 🤔 |
|
|
133
|
+
| DoDo | ❌ | ❓ | 🤔 |
|
|
134
|
+
| Mirai | ❌ | ❓ | 🤔 |
|
|
135
|
+
| 开黑啦 | ❌ | ❓ | 🤔 |
|
|
136
|
+
| Kritor | ❌ | ❓ | 🤔 |
|
|
137
|
+
| Ntchat | ❌ | ❓ | 🤔 |
|
|
138
|
+
| Satori | ❌ | ❓ | 🤔 |
|
|
139
|
+
| Telegram | ❌ | ❓ | 🤔 |
|
|
140
|
+
| Discord | ❌ | ❓ | 🤔 |
|
|
141
|
+
| Tailchat | ❌ | ❓ | 🤔 |
|
|
142
|
+
| QQ 官方接口 | ❌ | ❓ | 🤔 |
|
|
143
|
+
| Rocket.Chat | ❌ | ❓ | 🤔 |
|
|
144
|
+
|
|
145
|
+
- 如果你测试过能够使用,请在 Issue 中指出
|
|
146
|
+
|
|
147
|
+
## 📦另外
|
|
148
|
+
|
|
149
|
+
### 😳加入作者的 BUG 反馈群 ~~(🥵女装粉丝群)~~
|
|
150
|
+
|
|
151
|
+
[群连接](https://qm.qq.com/q/Yty2yc9Bee)
|
|
152
|
+
|
|
153
|
+
<details>
|
|
154
|
+
<summary>群二维码 点我展开</summary>
|
|
155
|
+
|
|
156
|
+

|
|
157
|
+
|
|
158
|
+
</details>
|
|
159
|
+
|
|
160
|
+
### 💕感谢
|
|
161
|
+
|
|
162
|
+
本插件的__init__.py 中的处理函数参考了词云中的方法 ~~(其实大部分都是 Ctrl+C Ctr+V)~~
|
|
163
|
+
|
|
164
|
+
[nonebot-plugin-wordcloud](https://github.com/he0119/nonebot-plugin-wordcloud)
|
|
165
|
+
|
|
166
|
+
### 🎀TODO
|
|
167
|
+
|
|
168
|
+
- [x] 适配全平台
|
|
169
|
+
|
|
170
|
+
- [ ] 私聊的查询(超级用户可以任意查询群聊的信息)
|
|
171
|
+
|
|
172
|
+
- [ ] 关键词查询
|
|
173
|
+
|
|
174
|
+
- [ ] 尝试利用 jinja2 模板引擎制作可视化图片 (((真的可以吗?))
|
|
175
|
+
|
|
176
|
+
待补充。.....
|
|
177
|
+
|
|
178
|
+
### 👾题外话
|
|
179
|
+
~~整个项目快被我写成屎山了~~
|
|
@@ -8,12 +8,9 @@ require("nonebot_plugin_alconna")
|
|
|
8
8
|
require("nonebot_plugin_cesaa")
|
|
9
9
|
|
|
10
10
|
import re
|
|
11
|
+
import os
|
|
11
12
|
import nonebot_plugin_saa as saa
|
|
12
13
|
|
|
13
|
-
from pyecharts.charts import Bar
|
|
14
|
-
from pyecharts import options as opts
|
|
15
|
-
from pyecharts.globals import ThemeType
|
|
16
|
-
|
|
17
14
|
from typing import Union, Optional, List
|
|
18
15
|
from datetime import datetime, timedelta
|
|
19
16
|
from arclet.alconna import ArparmaBehavior
|
|
@@ -50,13 +47,13 @@ from nonebot_plugin_session import Session, SessionIdType, extract_session
|
|
|
50
47
|
# from .function import *
|
|
51
48
|
from .config import Config, plugin_config
|
|
52
49
|
from .usage import __usage__
|
|
50
|
+
from .time import get_datetime_fromisoformat_with_timezone, get_datetime_now_with_timezone,parse_datetime
|
|
51
|
+
from .model import UserRankInfo
|
|
53
52
|
from .utils import (
|
|
54
|
-
get_datetime_fromisoformat_with_timezone,
|
|
55
|
-
get_datetime_now_with_timezone,
|
|
56
53
|
got_rank,
|
|
57
54
|
msg_counter,
|
|
58
55
|
persist_id2user_id,
|
|
59
|
-
|
|
56
|
+
get_rank_image
|
|
60
57
|
)
|
|
61
58
|
|
|
62
59
|
__plugin_meta__ = PluginMetadata(
|
|
@@ -81,17 +78,19 @@ class SameTime(ArparmaBehavior):
|
|
|
81
78
|
if type is None and time:
|
|
82
79
|
interface.behave_fail()
|
|
83
80
|
|
|
81
|
+
|
|
84
82
|
def wrapper(slot: Union[int, str], content: Optional[str]) -> str:
|
|
85
83
|
if slot == "type" and content:
|
|
86
84
|
return content
|
|
87
85
|
return "" # pragma: no cover
|
|
88
86
|
|
|
87
|
+
|
|
89
88
|
rank_cmd = on_alconna(
|
|
90
89
|
Alconna(
|
|
91
90
|
"B话榜",
|
|
92
91
|
Args["type?", ["今日", "昨日", "本周", "上周", "本月", "上月", "年度", "历史"]][
|
|
93
|
-
"time?",
|
|
94
|
-
"group_id?",
|
|
92
|
+
"time?",str,][
|
|
93
|
+
"group_id?", str
|
|
95
94
|
],
|
|
96
95
|
behaviors=[SameTime()],
|
|
97
96
|
),
|
|
@@ -110,6 +109,7 @@ rank_cmd.shortcut(
|
|
|
110
109
|
},
|
|
111
110
|
)
|
|
112
111
|
|
|
112
|
+
|
|
113
113
|
# 这段函数完全抄的词云
|
|
114
114
|
@rank_cmd.handle()
|
|
115
115
|
async def _group_message(
|
|
@@ -117,13 +117,15 @@ async def _group_message(
|
|
|
117
117
|
session: Session = Depends(extract_session),
|
|
118
118
|
type: Optional[str] = None,
|
|
119
119
|
time: Optional[str] = None,
|
|
120
|
-
group_id: Optional[
|
|
120
|
+
group_id: Optional[str] = None,
|
|
121
121
|
):
|
|
122
122
|
|
|
123
123
|
dt = get_datetime_now_with_timezone()
|
|
124
124
|
|
|
125
|
-
if
|
|
126
|
-
|
|
125
|
+
if group_id is None:
|
|
126
|
+
group_id = session.id2
|
|
127
|
+
|
|
128
|
+
state["group_id"] = group_id
|
|
127
129
|
|
|
128
130
|
if not type:
|
|
129
131
|
await rank_cmd.finish(__plugin_meta__.usage)
|
|
@@ -191,15 +193,25 @@ async def _group_message(
|
|
|
191
193
|
prompt="请输入你要查询的结束日期(如 2022-02-22)",
|
|
192
194
|
parameterless=[Depends(parse_datetime("stop"))],
|
|
193
195
|
)
|
|
196
|
+
@rank_cmd.got("group_id", prompt="请输入你要查询的群号。")
|
|
194
197
|
async def handle_rank(
|
|
195
198
|
bot: Bot,
|
|
196
199
|
event: Event,
|
|
197
200
|
session: Session = Depends(extract_session),
|
|
198
201
|
start: datetime = Arg(),
|
|
199
202
|
stop: datetime = Arg(),
|
|
203
|
+
group_id: str = Arg(),
|
|
200
204
|
):
|
|
205
|
+
if group_id:
|
|
206
|
+
id = group_id
|
|
207
|
+
else:
|
|
208
|
+
id = session.id2
|
|
209
|
+
|
|
210
|
+
if not id:
|
|
211
|
+
await saa.Text("没有指定群哦").finish()
|
|
212
|
+
|
|
201
213
|
messages = await get_message_records(
|
|
202
|
-
|
|
214
|
+
id2s=[id],
|
|
203
215
|
id_type=SessionIdType.GROUP,
|
|
204
216
|
include_bot_id=False,
|
|
205
217
|
include_bot_type=False,
|
|
@@ -208,42 +220,45 @@ async def handle_rank(
|
|
|
208
220
|
time_stop=stop,
|
|
209
221
|
exclude_id1s=plugin_config.excluded_people,
|
|
210
222
|
)
|
|
211
|
-
|
|
212
223
|
rank = got_rank(msg_counter(messages))
|
|
224
|
+
rank2: List[UserRankInfo] = []
|
|
213
225
|
ids = await persist_id2user_id([int(i[0]) for i in rank])
|
|
214
226
|
for i in range(len(rank)):
|
|
215
227
|
rank[i][0] = str(ids[i])
|
|
228
|
+
logger.debug(rank[i])
|
|
229
|
+
|
|
230
|
+
total = sum([i[1] for i in rank])
|
|
216
231
|
|
|
217
|
-
string: str = ""
|
|
218
|
-
nicknames: List = []
|
|
219
232
|
for i in rank:
|
|
220
233
|
if user_info := await get_user_info(bot, event, user_id=str(i[0])):
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
234
|
+
user_nickname = user_info.user_displayname\
|
|
235
|
+
if user_info.user_displayname\
|
|
236
|
+
else user_info.user_name\
|
|
237
|
+
if user_info.user_name\
|
|
238
|
+
else\
|
|
239
|
+
user_info.user_id
|
|
240
|
+
user_avatar = await user_info.user_avatar.get_image()\
|
|
241
|
+
if user_info.user_avatar\
|
|
242
|
+
else open(os.path.dirname(os.path.abspath(__file__))+"/template/avatar/default.jpg", "rb").read()
|
|
243
|
+
user = UserRankInfo(**user_info.model_dump(),
|
|
244
|
+
user_bnum=i[1],
|
|
245
|
+
user_proportion= round(i[1] / total * 100, 2),
|
|
246
|
+
user_index= rank.index(i) + 1,
|
|
247
|
+
user_nickname=user_nickname,
|
|
248
|
+
user_avatar_bytes= user_avatar,
|
|
229
249
|
)
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
250
|
+
user.user_gender="她" if user_info.user_gender == "female" else "他" if user_info.user_gender == "male" else "ta"
|
|
251
|
+
rank2.append(user)
|
|
252
|
+
|
|
253
|
+
string: str = ""
|
|
233
254
|
for i in range(len(rank)):
|
|
234
|
-
index = i + 1
|
|
235
|
-
nickname, chatdatanum = nicknames[i], rank[i][1]
|
|
236
255
|
str_example = plugin_config.string_format.format(
|
|
237
|
-
index=
|
|
256
|
+
index=rank2[i].user_index,
|
|
257
|
+
nickname=rank2[i].user_nickname,
|
|
258
|
+
chatdatanum=rank2[i].user_bnum
|
|
238
259
|
)
|
|
239
260
|
string += str_example
|
|
261
|
+
|
|
262
|
+
image = await get_rank_image(rank2)
|
|
240
263
|
|
|
241
|
-
|
|
242
|
-
bar.add_xaxis(nicknames)
|
|
243
|
-
bar.add_yaxis("B话数量", [i[1] for i in rank]) # type: ignore
|
|
244
|
-
bar.render(str(get_cache_file("nonebot_plugin_dialectlist","cache.html")))
|
|
245
|
-
with open(get_cache_file("nonebot_plugin_dialectlist","cache.html")) as f:
|
|
246
|
-
a = f.read()
|
|
247
|
-
image = await html_to_pic(a,device_scale_factor=3.2)
|
|
248
|
-
|
|
249
|
-
await (saa.Text(string)+saa.Image(image)).finish(reply=True)
|
|
264
|
+
await (saa.Text(string) + saa.Image(image)).finish(reply=True)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Optional, Literal, List
|
|
2
2
|
from nonebot import get_driver, get_plugin_config
|
|
3
|
-
from pydantic import BaseModel
|
|
3
|
+
from pydantic import BaseModel
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class ScopedConfig(BaseModel):
|
|
@@ -9,6 +9,7 @@ class ScopedConfig(BaseModel):
|
|
|
9
9
|
timezone: Optional[str] = "Asia/Shanghai"
|
|
10
10
|
excluded_self: bool = True
|
|
11
11
|
string_format: str = "第{index}名:\n{nickname},{chatdatanum}条消息\n" # 消息格式
|
|
12
|
+
template_path: str = "./template/rank_template.j2" # 模板路径
|
|
12
13
|
visualization: bool = True # 是否可视化
|
|
13
14
|
excluded_people: List[str] = [] # 排除的人的QQ号
|
|
14
15
|
visualization_type: Literal["饼图", "圆环图", "柱状图"] = "圆环图" # 可视化方案
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from typing import Optional, Literal, List, Union
|
|
2
|
+
from pydantic import BaseModel
|
|
3
|
+
from nonebot_plugin_userinfo import get_user_info, UserInfo
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class UserRankInfo(UserInfo):
|
|
7
|
+
user_bnum: int
|
|
8
|
+
user_proportion: float
|
|
9
|
+
user_nickname: str
|
|
10
|
+
user_index: Union[int,str]
|
|
11
|
+
user_avatar_bytes: bytes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
# TODO 使用计数缓存进行数据库查询优化,避免一次性查询过多消息导致内存爆炸。
|
|
1
|
+
# TODO 使用计数缓存进行数据库查询优化,避免一次性查询过多消息导致内存爆炸。
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# TODO 时间处理模块,用于处理时间相关操作。
|
|
2
|
+
from datetime import datetime, time, tzinfo
|
|
3
|
+
from typing import Optional, Union
|
|
4
|
+
from zoneinfo import ZoneInfo
|
|
5
|
+
|
|
6
|
+
from nonebot.typing import T_State
|
|
7
|
+
from nonebot.params import Arg
|
|
8
|
+
from nonebot.adapters import Message
|
|
9
|
+
|
|
10
|
+
from nonebot_plugin_apscheduler import scheduler
|
|
11
|
+
from nonebot_plugin_alconna import AlconnaMatcher
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
from .config import plugin_config
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def parse_datetime(key: str):
|
|
18
|
+
"""解析数字,并将结果存入 state 中"""
|
|
19
|
+
|
|
20
|
+
async def _key_parser(
|
|
21
|
+
matcher: AlconnaMatcher,
|
|
22
|
+
state: T_State,
|
|
23
|
+
input: Union[datetime, Message] = Arg(key),
|
|
24
|
+
):
|
|
25
|
+
if isinstance(input, datetime):
|
|
26
|
+
return
|
|
27
|
+
|
|
28
|
+
plaintext = input.extract_plain_text()
|
|
29
|
+
try:
|
|
30
|
+
state[key] = get_datetime_fromisoformat_with_timezone(plaintext)
|
|
31
|
+
except ValueError:
|
|
32
|
+
await matcher.reject_arg(key, "请输入正确的日期,不然我没法理解呢!")
|
|
33
|
+
|
|
34
|
+
return _key_parser
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def get_datetime_now_with_timezone() -> datetime:
|
|
38
|
+
"""获取当前时间,并包含时区信息"""
|
|
39
|
+
if plugin_config.timezone:
|
|
40
|
+
return datetime.now(ZoneInfo(plugin_config.timezone))
|
|
41
|
+
else:
|
|
42
|
+
return datetime.now().astimezone()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def get_datetime_fromisoformat_with_timezone(date_string: str) -> datetime:
|
|
46
|
+
"""从 ISO-8601 格式字符串中获取时间,并包含时区信息"""
|
|
47
|
+
if not plugin_config.timezone:
|
|
48
|
+
return datetime.fromisoformat(date_string).astimezone()
|
|
49
|
+
raw = datetime.fromisoformat(date_string)
|
|
50
|
+
return (
|
|
51
|
+
raw.astimezone(ZoneInfo(plugin_config.timezone))
|
|
52
|
+
if raw.tzinfo
|
|
53
|
+
else raw.replace(tzinfo=ZoneInfo(plugin_config.timezone))
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def time_astimezone(time: time, tz: Optional[tzinfo] = None) -> time:
|
|
58
|
+
"""将 time 对象转换为指定时区的 time 对象
|
|
59
|
+
|
|
60
|
+
如果 tz 为 None,则转换为本地时区
|
|
61
|
+
"""
|
|
62
|
+
local_time = datetime.combine(datetime.today(), time)
|
|
63
|
+
return local_time.astimezone(tz).timetz()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def get_time_fromisoformat_with_timezone(time_string: str) -> time:
|
|
67
|
+
"""从 iso8601 格式字符串中获取时间,并包含时区信息"""
|
|
68
|
+
if not plugin_config.timezone:
|
|
69
|
+
return time_astimezone(time.fromisoformat(time_string))
|
|
70
|
+
raw = time.fromisoformat(time_string)
|
|
71
|
+
return (
|
|
72
|
+
time_astimezone(raw, ZoneInfo(plugin_config.timezone))
|
|
73
|
+
if raw.tzinfo
|
|
74
|
+
else raw.replace(tzinfo=ZoneInfo(plugin_config.timezone))
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def get_time_with_scheduler_timezone(time: time) -> time:
|
|
79
|
+
"""获取转换到 APScheduler 时区的时间"""
|
|
80
|
+
return time_astimezone(time, scheduler.timezone)
|