nonebot-plugin-dialectlist 2.2.3__tar.gz → 2.3.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.
Files changed (23) hide show
  1. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/PKG-INFO +18 -12
  2. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/README.md +14 -10
  3. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/nonebot_plugin_dialectlist/__init__.py +24 -60
  4. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/nonebot_plugin_dialectlist/config.py +2 -2
  5. nonebot_plugin_dialectlist-2.3.0/nonebot_plugin_dialectlist/model.py +27 -0
  6. nonebot_plugin_dialectlist-2.3.0/nonebot_plugin_dialectlist/template/css/style.css +170 -0
  7. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/nonebot_plugin_dialectlist/template/rank_template.j2 +15 -7
  8. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/nonebot_plugin_dialectlist/utils.py +67 -2
  9. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/nonebot_plugin_dialectlist.egg-info/PKG-INFO +18 -12
  10. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/nonebot_plugin_dialectlist.egg-info/SOURCES.txt +0 -1
  11. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/nonebot_plugin_dialectlist.egg-info/requires.txt +3 -1
  12. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/pyproject.toml +5 -3
  13. nonebot_plugin_dialectlist-2.2.3/nonebot_plugin_dialectlist/model.py +0 -17
  14. nonebot_plugin_dialectlist-2.2.3/nonebot_plugin_dialectlist/template/avatar/master.jpg +0 -0
  15. nonebot_plugin_dialectlist-2.2.3/nonebot_plugin_dialectlist/template/css/style.css +0 -118
  16. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/MANIFEST.in +0 -0
  17. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/nonebot_plugin_dialectlist/storage.py +0 -0
  18. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/nonebot_plugin_dialectlist/template/avatar/default.jpg +0 -0
  19. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/nonebot_plugin_dialectlist/time.py +0 -0
  20. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/nonebot_plugin_dialectlist/usage.py +0 -0
  21. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/nonebot_plugin_dialectlist.egg-info/dependency_links.txt +0 -0
  22. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/nonebot_plugin_dialectlist.egg-info/top_level.txt +0 -0
  23. {nonebot_plugin_dialectlist-2.2.3 → nonebot_plugin_dialectlist-2.3.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nonebot-plugin-dialectlist
3
- Version: 2.2.3
3
+ Version: 2.3.0
4
4
  Summary: 看看你群群友有多能说
5
5
  Author-email: Chen_Xu233 <woyerpa@outlook.com>
6
6
  License: MIT
@@ -15,12 +15,14 @@ Requires-Dist: nonebot-plugin-cesaa>=0.4.0
15
15
  Requires-Dist: nonebot-plugin-userinfo>=0.2.4
16
16
  Requires-Dist: nonebot-plugin-htmlrender>=0.3.3
17
17
  Requires-Dist: nonebot2>=2.3.2
18
- Requires-Dist: cn2an>=0.5.22
18
+ Requires-Dist: pillow>=10.4.0
19
+ Requires-Dist: nonebot-plugin-uninfo>=0.1.1
19
20
  Provides-Extra: dev
20
21
  Requires-Dist: ruff>=0.5.5; extra == "dev"
21
22
  Requires-Dist: setuptools>=71.1.0; extra == "dev"
22
23
  Requires-Dist: twine>=5.1.0; extra == "dev"
23
24
  Requires-Dist: nb-cli>=0.7.6; extra == "dev"
25
+ Requires-Dist: py-spy>=0.3.14; extra == "dev"
24
26
  Provides-Extra: test
25
27
  Requires-Dist: nonebot-adapter-onebot>=2.4.4; extra == "test"
26
28
 
@@ -64,12 +66,15 @@ nonebot-plugin-dialectlist
64
66
 
65
67
  ### ✅ 插件依赖于
66
68
 
67
- 1. [nonebot-plugin-datastore](https://github.com/he0119/nonebot-plugin-datastore) ————储存历史的消息
69
+ 1. [nonebot-plugin-datastore](https://github.com/he0119/nonebot-plugin-datastore) ————本地化储存
68
70
  2. [nonebot-plugin-userinfo](https://github.com/noneplugin/nonebot-plugin-userinfo) ————获取用户信息
69
71
  3. [nonebot-plugin-apscheduler](https://github.com/nonebot/plugin-apscheduler) ————定时发送排行榜信息
70
72
  4. [nonebot-plugin-alconna](https://github.com/ArcletProject/nonebot-plugin-alconna) ————实现命令解析
71
- 5. [nonebot-plugin-cesaa](https://github.com/MountainDash/nonebot-plugin-send-anything-anywhere) ————实现多平台
72
-
73
+ 5. [nonebot-plugin-chatrecorder](https://github.com/noneplugin/nonebot-plugin-chatrecorder) ————实现消息储存
74
+ 6. [nonebot-plugin-cesaa](https://github.com/MountainDash/nonebot-plugin-send-anything-anywhere) ————实现多平台
75
+
76
+ **⚠注意** 若先前没有安装过```nonebot-plugin-chatrecorder```或者```nonebot-plugin-orm```,则会在启动时报错,请按报错的提示安装数据库!
77
+
73
78
  ## ⚙ 配置
74
79
 
75
80
  需要**提前配置**本插件所**依赖的插件**!
@@ -173,22 +178,23 @@ __!!注意!!__
173
178
 
174
179
  - [x] 适配全平台
175
180
 
176
- - [x] 尝试利用 jinja2 模板引擎制作可视化图片
177
-
178
- - [x] 私聊的查询(超级用户可以任意查询群聊的信息)一半完成
181
+ - [x] 更好看的图片渲染
179
182
 
180
183
  - [x] 添加一些全新的可配置项
184
+
185
+ - [x] 尝试利用 jinja2 模板引擎制作可视化图片
181
186
 
182
- - [x] 更好看的图片渲染
187
+ - [x] 私聊的查询(超级用户可以任意查询群聊的信息)一半完成
183
188
 
184
189
  - [ ] 提供多样化的渲染器配置(html 渲染,pillow 渲染,统计绘图软件渲染)
185
- - [ ] 为 pillow 渲染方式提供插件的加载方式(什么?插件里的插件???)
186
-
187
- - [ ] 查询带某关键词的消息量
188
190
 
189
191
  - [ ] 使用管理员权限直接获取 QQ 官方统计的今日消息量以优化代码运行速度
190
192
 
193
+ - [ ] 为 pillow 渲染方式提供插件的加载方式(什么?插件里的插件???)
194
+
191
195
  - [ ] 特殊的储存方案优化消息统计
196
+
197
+ - [ ] 查询带某关键词的消息量
192
198
 
193
199
  待补充。.....
194
200
 
@@ -38,12 +38,15 @@ nonebot-plugin-dialectlist
38
38
 
39
39
  ### ✅ 插件依赖于
40
40
 
41
- 1. [nonebot-plugin-datastore](https://github.com/he0119/nonebot-plugin-datastore) ————储存历史的消息
41
+ 1. [nonebot-plugin-datastore](https://github.com/he0119/nonebot-plugin-datastore) ————本地化储存
42
42
  2. [nonebot-plugin-userinfo](https://github.com/noneplugin/nonebot-plugin-userinfo) ————获取用户信息
43
43
  3. [nonebot-plugin-apscheduler](https://github.com/nonebot/plugin-apscheduler) ————定时发送排行榜信息
44
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
-
45
+ 5. [nonebot-plugin-chatrecorder](https://github.com/noneplugin/nonebot-plugin-chatrecorder) ————实现消息储存
46
+ 6. [nonebot-plugin-cesaa](https://github.com/MountainDash/nonebot-plugin-send-anything-anywhere) ————实现多平台
47
+
48
+ **⚠注意** 若先前没有安装过```nonebot-plugin-chatrecorder```或者```nonebot-plugin-orm```,则会在启动时报错,请按报错的提示安装数据库!
49
+
47
50
  ## ⚙ 配置
48
51
 
49
52
  需要**提前配置**本插件所**依赖的插件**!
@@ -147,22 +150,23 @@ __!!注意!!__
147
150
 
148
151
  - [x] 适配全平台
149
152
 
150
- - [x] 尝试利用 jinja2 模板引擎制作可视化图片
151
-
152
- - [x] 私聊的查询(超级用户可以任意查询群聊的信息)一半完成
153
+ - [x] 更好看的图片渲染
153
154
 
154
155
  - [x] 添加一些全新的可配置项
156
+
157
+ - [x] 尝试利用 jinja2 模板引擎制作可视化图片
155
158
 
156
- - [x] 更好看的图片渲染
159
+ - [x] 私聊的查询(超级用户可以任意查询群聊的信息)一半完成
157
160
 
158
161
  - [ ] 提供多样化的渲染器配置(html 渲染,pillow 渲染,统计绘图软件渲染)
159
- - [ ] 为 pillow 渲染方式提供插件的加载方式(什么?插件里的插件???)
160
-
161
- - [ ] 查询带某关键词的消息量
162
162
 
163
163
  - [ ] 使用管理员权限直接获取 QQ 官方统计的今日消息量以优化代码运行速度
164
164
 
165
+ - [ ] 为 pillow 渲染方式提供插件的加载方式(什么?插件里的插件???)
166
+
165
167
  - [ ] 特殊的储存方案优化消息统计
168
+
169
+ - [ ] 查询带某关键词的消息量
166
170
 
167
171
  待补充。.....
168
172
 
@@ -9,7 +9,6 @@ require("nonebot_plugin_cesaa")
9
9
 
10
10
  import re
11
11
  import os
12
- import cn2an
13
12
  import time as t
14
13
  import nonebot_plugin_saa as saa
15
14
 
@@ -52,6 +51,7 @@ from .utils import (
52
51
  msg_counter,
53
52
  get_rank_image,
54
53
  persist_id2user_id,
54
+ get_user_infos,
55
55
  # get_user_info2,
56
56
  )
57
57
 
@@ -193,7 +193,7 @@ async def _group_message(
193
193
  state["stop"] = state["start"] + timedelta(days=1)
194
194
  except ValueError:
195
195
  await rank_cmd.finish("请输入正确的日期,不然我没法理解呢!")
196
-
196
+
197
197
  logger.debug(f"命令解析花费时间:{t.time() - t1}")
198
198
 
199
199
 
@@ -216,7 +216,7 @@ async def handle_rank(
216
216
  start: datetime = Arg(),
217
217
  stop: datetime = Arg(),
218
218
  ):
219
- t1 = t.time()
219
+
220
220
  if id := state["group_id"]:
221
221
  id = str(id)
222
222
  logger.debug(f"group_id: {id}")
@@ -227,70 +227,35 @@ async def handle_rank(
227
227
  if not id:
228
228
  await saa.Text("没有指定群哦").finish()
229
229
 
230
- logger.debug(f"所属群聊解析花费时间:{t.time() - t1}")
231
- t1 = t.time()
230
+ if plugin_config.counting_cache:
231
+ raise Exception("我草缓存功能还没端上来呢,你怎么就先用上了")
232
+ else:
233
+ messages = await get_message_records(
234
+ id2s=[id],
235
+ id_type=SessionIdType.GROUP,
236
+ include_bot_id=False,
237
+ include_bot_type=False,
238
+ types=["message"], # 排除机器人自己发的消息
239
+ time_start=start,
240
+ time_stop=stop,
241
+ exclude_id1s=plugin_config.excluded_people,
242
+ )
232
243
 
233
- messages = await get_message_records(
234
- id2s=[id],
235
- id_type=SessionIdType.GROUP,
236
- include_bot_id=False,
237
- include_bot_type=False,
238
- types=["message"], # 排除机器人自己发的消息
239
- time_start=start,
240
- time_stop=stop,
241
- exclude_id1s=plugin_config.excluded_people,
242
- )
243
-
244
- logger.debug(f"获取群聊消息花费时间:{t.time() - t1}")
245
- t1 = t.time()
246
-
247
- if not messages:
248
- await saa.Text("明明这个时间段都没有人说话怎么会有话痨榜呢?").finish()
244
+ if not messages:
245
+ await saa.Text("明明这个时间段都没有人说话怎么会有话痨榜呢?").finish()
249
246
 
250
- rank = got_rank(msg_counter(messages))
251
- logger.debug(f"群聊消息计数花费时间:{t.time() - t1}")
252
- t1 = t.time()
247
+ raw_rank = msg_counter(messages)
248
+
249
+ rank = got_rank(raw_rank)
253
250
  logger.debug(rank)
254
- rank2: List[UserRankInfo] = []
255
251
  ids = await persist_id2user_id([int(i[0]) for i in rank])
256
252
  for i in range(len(rank)):
257
253
  rank[i][0] = str(ids[i])
258
254
  logger.debug(rank[i])
259
255
 
260
- total = sum([i[1] for i in rank])
261
- index = 1
262
- for i in rank:
263
- if user_info := await get_user_info(bot, event, user_id=str(i[0])):
264
- logger.debug(user_info)
265
- user_nickname = (
266
- user_info.user_displayname
267
- if user_info.user_displayname
268
- else user_info.user_name if user_info.user_name else user_info.user_id
269
- )
270
- user_avatar = (
271
- await user_info.user_avatar.get_image()
272
- if user_info.user_avatar
273
- else open(
274
- os.path.dirname(os.path.abspath(__file__))
275
- + "/template/avatar/default.jpg",
276
- "rb",
277
- ).read()
278
- )
279
- user = UserRankInfo(
280
- **model_dump(user_info),
281
- user_bnum=i[1],
282
- user_proportion=round(i[1] / total * 100, 2),
283
- user_index=cn2an.an2cn(index),
284
- user_nickname=user_nickname,
285
- user_avatar_bytes=user_avatar,
286
- )
287
- user.user_gender = (
288
- "她"
289
- if user_info.user_gender == "female"
290
- else "他" if user_info.user_gender == "male" else "ta"
291
- )
292
- rank2.append(user)
293
- index += 1
256
+ t1 = t.time()
257
+ rank2 = await get_user_infos(bot, event, rank)
258
+ logger.debug(f"获取用户信息花费时间:{t.time() - t1}")
294
259
 
295
260
  string: str = ""
296
261
  for i in rank2:
@@ -304,7 +269,6 @@ async def handle_rank(
304
269
  string += str_example
305
270
 
306
271
  msg = saa.Text(string)
307
- logger.debug(f"群聊消息渲染文字花费时间:{t.time() - t1}")
308
272
  t1 = t.time()
309
273
 
310
274
  if plugin_config.visualization:
@@ -1,5 +1,5 @@
1
1
  from pydantic import BaseModel
2
- from typing import Optional, List
2
+ from typing import Optional, List, Literal
3
3
  from nonebot import get_driver, get_plugin_config
4
4
 
5
5
 
@@ -9,7 +9,7 @@ class ScopedConfig(BaseModel):
9
9
  suffix: bool = False # 是否显示后缀
10
10
  excluded_self: bool = True
11
11
  visualization: bool = True # 是否可视化
12
- counting_cache: bool = True
12
+ counting_cache: bool = False # 计数缓存(没有完工)
13
13
  excluded_people: List[str] = [] # 排除的人的QQ号
14
14
  timezone: Optional[str] = "Asia/Shanghai"
15
15
  string_suffix: str = "统计花费时间:{timecost}秒" # 消息格式后缀
@@ -0,0 +1,27 @@
1
+ from datetime import datetime
2
+ from typing import Union
3
+ from pydantic import BaseModel
4
+ from sqlalchemy import JSON, TEXT, String,Integer
5
+ from nonebot_plugin_orm import Model
6
+ from nonebot_plugin_userinfo import UserInfo
7
+ from sqlalchemy.orm import Mapped, mapped_column
8
+
9
+
10
+ class UserRankInfo(UserInfo):
11
+ user_bnum: int
12
+ user_proportion: float
13
+ user_nickname: str
14
+ user_index: Union[int, str]
15
+ user_avatar_bytes: bytes
16
+
17
+
18
+ # class MsgCountDayData(BaseModel):
19
+ # session_id: str
20
+ # session_bnum: int
21
+
22
+ class MessageCountCache(Model):
23
+ __table_args__ = {"extend_existing": True}
24
+ id: Mapped[int] = mapped_column(primary_key=True)
25
+ time: Mapped[datetime]
26
+ session_id: Mapped[int] = mapped_column(Integer)
27
+ session_bnum: Mapped[int] = mapped_column(Integer)
@@ -0,0 +1,170 @@
1
+ body {
2
+ background-color: #1A1A1A;
3
+ /* Dark gradient */
4
+ background-size: cover;
5
+ background-attachment: fixed;
6
+ /* Ensure background stays fixed during scroll */
7
+ margin: 0;
8
+ width: 100%;
9
+ height: 100%;
10
+ font-family: "text", sans-serif;
11
+ color: #E0E0E0;
12
+ /* Light gray text for better contrast */
13
+ }
14
+
15
+ @font-face {
16
+ font-family: "text";
17
+ src: url("../res/HarmonyOS_Sans_SC.woff2");
18
+ }
19
+
20
+ .container {
21
+ padding: 20px 40px;
22
+ position: relative;
23
+ display: flex;
24
+ flex-direction: column;
25
+ }
26
+
27
+ .glow {
28
+ border: 2px solid rgba(77, 228, 255, 0.8);
29
+ box-shadow: 0 0 15px rgba(0, 255, 255, 0.3);
30
+ /* Neon glow */
31
+ }
32
+
33
+ .card,
34
+ .card2 {
35
+ text-align: center;
36
+ align-content: center;
37
+ margin: 1%;
38
+ border-radius: 1rem;
39
+ /* background: rgba(25, 25, 25, 0.9); Darker background */
40
+ -webkit-backdrop-filter: blur(5px);
41
+ backdrop-filter: blur(5px);
42
+ }
43
+
44
+ .card2 {
45
+ display: flex;
46
+ justify-content: center;
47
+ flex-wrap: wrap;
48
+ flex-direction: revert;
49
+ }
50
+
51
+ .center_text {
52
+ text-align: center;
53
+ font-size: 3rem;
54
+ font-weight: 900;
55
+ color: #00FFFF;
56
+ /* Cyan color for a techno vibe */
57
+ }
58
+
59
+ .center_text2 {
60
+ text-align: center;
61
+ font-size: 1.5rem;
62
+ color: #A0A0A0;
63
+ /* Slightly lighter gray */
64
+ }
65
+
66
+ .rank_container {
67
+ display: flex;
68
+ flex-direction: column;
69
+ border-radius: 1rem;
70
+ padding: 10px 10px;
71
+ margin: 1%;
72
+ justify-content: center;
73
+ align-items: center;
74
+ /* background: rgba(30, 30, 30, 0.9); Dark background */
75
+ }
76
+
77
+ .rank_card {
78
+ display: flex;
79
+ width: 100%;
80
+ flex-direction: row;
81
+ /* border: 2px solid rgba(100, 100, 100, 0.7); */
82
+ margin: 10px 10px;
83
+ border-radius: 1rem;
84
+ align-content: center;
85
+ backdrop-filter: blur(10px);
86
+ -webkit-backdrop-filter: blur(10px);
87
+ /* background: rgba(40, 40, 40, 0.8); Slightly lighter for contrast */
88
+ }
89
+
90
+ .profile,
91
+ .profile2 {
92
+ border: 2px solid rgba(100, 100, 100, 0.7);
93
+ border-radius: 50%;
94
+ background-size: cover;
95
+ margin-right: 20px;
96
+ }
97
+
98
+ .avatar {
99
+ display: flex;
100
+ justify-content: center;
101
+ align-items: center;
102
+ }
103
+
104
+ .profile {
105
+ width: 12vw;
106
+ height: 12vw;
107
+ }
108
+
109
+ .profile2 {
110
+ width: 8%;
111
+ height: 8%;
112
+ }
113
+
114
+ .rank_card_info {
115
+ width: 100%;
116
+ display: flex;
117
+ flex-direction: column;
118
+ }
119
+
120
+ .g-container {
121
+ width: 90%;
122
+ height: 25px;
123
+ border-radius: 25px;
124
+ background: rgb(0 0 0 / 31%);
125
+ }
126
+
127
+ .g-progress {
128
+ width: 50%;
129
+ height: inherit;
130
+ border-radius: 25px 20px 20px 25px;
131
+ background: linear-gradient(90deg, rgb(0, 128, 255), rgb(255, 0, 174));
132
+ /* Neon cyan to magenta gradient */
133
+ }
134
+
135
+ .rank {
136
+ display: flex;
137
+ flex-direction: row;
138
+ align-items: center;
139
+ justify-content: center;
140
+ }
141
+
142
+ .rank_number {
143
+ margin: 50px;
144
+ font-size: 32px;
145
+ width: 32px;
146
+ height: 32px;
147
+ padding: 6px;
148
+ display: flex;
149
+ justify-content: center;
150
+ align-items: center;
151
+ font-weight: 600;
152
+ }
153
+
154
+ .rank_number_1 {
155
+ border-radius: 999px;
156
+ background-color: gold;
157
+ color: rgb(154, 105, 14);
158
+ }
159
+
160
+ .rank_number_2 {
161
+ border-radius: 999px;
162
+ background-color: silver;
163
+ color: rgb(80, 80, 80);
164
+ }
165
+
166
+ .rank_number_3 {
167
+ border-radius: 999px;
168
+ background-color: #CD7F32;
169
+ color: rgb(95 52 14);
170
+ }
@@ -9,29 +9,37 @@
9
9
  </head>
10
10
  <body>
11
11
  <div class="container">
12
- <div class="card" >
12
+ <div class="card glow" >
13
13
  <p class="center_text">话痨排行榜</p>
14
14
  </div>
15
15
 
16
- <div class="rank_container">
16
+ <div class="rank_container glow">
17
17
 
18
18
  {% for i in users %}
19
19
  <div class="rank_card">
20
- <img class="profile" src="{{ cache_path }}/{{ i.user_id }}.jpg"/>
20
+ <div class="rank">
21
+ <div class="rank_number rank_number_{{ i.user_index }}">{{ i.user_index }}</div>
22
+ </div>
23
+ <div class="avatar">
24
+ <img class="profile" src="{{ cache_path }}/{{ i.user_id }}.jpg"/>
25
+ </div>
21
26
  <div class="rank_card_info">
22
- <h1>第{{ i.user_index }}名:{{ i.user_nickname }}</h1>
27
+ <h1>{{ i.user_nickname }} {{ i.user_gender }}</h1>
23
28
  <div class="g-container">
24
29
  <div class="g-progress" style="width: {{ i.user_proportion }}%"></div>
25
30
  </div>
26
- <p>{{ i.user_gender }}一共废话了{{ i.user_bnum }}句,占比{{ i.user_proportion }}%</p>
31
+ <p>{{ i.user_proportion }}%</p>
32
+ </div>
33
+ <div class="rank">
34
+ <div class="rank_number">{{ i.user_bnum }}</div>
27
35
  </div>
28
36
  </div>
29
37
  {% endfor %}
30
38
 
31
39
  </div>
32
40
 
33
- <div class="card2">
34
- <img class="profile2" src="{{ file_path }}/template/avatar/master.jpg"/>
41
+ <div class="card2 glow">
42
+ <img class="profile2" src="https://q2.qlogo.cn/headimg_dl?dst_uin=1964324406&spec=100"/>
35
43
  <p class="center_text2">Designed By ChenXu233</p>
36
44
  </div>
37
45
  </div>
@@ -1,16 +1,20 @@
1
1
  import os
2
+ import asyncio
2
3
  import unicodedata
3
4
 
4
- from typing import Dict, List
5
+ from typing import Dict, List, Optional
5
6
  from sqlalchemy import or_, select
6
7
  from sqlalchemy.sql import ColumnElement
7
8
 
8
9
  from nonebot.log import logger
9
10
  from nonebot.params import Depends
11
+ from nonebot.compat import model_dump
10
12
  from nonebot.matcher import Matcher
13
+ from nonebot.adapters import Bot, Event
11
14
 
12
15
  from nonebot_plugin_orm import get_session
13
16
  from nonebot_plugin_session import Session, SessionLevel, extract_session
17
+ from nonebot_plugin_userinfo import get_user_info, UserInfo
14
18
  from nonebot_plugin_localstore import get_cache_dir
15
19
  from nonebot_plugin_htmlrender import template_to_pic
16
20
  from nonebot_plugin_session_orm import SessionModel
@@ -178,5 +182,66 @@ async def get_rank_image(rank: List[UserRankInfo]) -> bytes:
178
182
  "cache_path": cache_path,
179
183
  "file_path": os.path.dirname(os.path.abspath(__file__)),
180
184
  },
181
- pages={"viewport": {"width": 1100, "height": 10}},
185
+ pages={"viewport": {"width": 1000, "height": 10}},
182
186
  )
187
+ def _get_user_nickname(user_info:UserInfo)->str:
188
+ user_nickname = (
189
+ user_info.user_displayname
190
+ if user_info.user_displayname
191
+ else user_info.user_name if user_info.user_name else user_info.user_id
192
+ )
193
+ return user_nickname
194
+
195
+ async def _get_user_default_avatar()->bytes:
196
+ img = open(
197
+ os.path.dirname(os.path.abspath(__file__))
198
+ + "/template/avatar/default.jpg",
199
+ "rb",
200
+ ).read()
201
+ return img
202
+
203
+ def get_default_user_info()->UserInfo:
204
+ user_info = UserInfo(
205
+ user_id="114514",
206
+ user_name="鬼知道这谁,bot获取不了",
207
+ )
208
+ return user_info
209
+
210
+ async def get_user_infos(bot:Bot,event:Event,rank:List,use_cache: bool = True)-> List[UserRankInfo]:
211
+
212
+ user_ids = [i[0] for i in rank]
213
+ pool = [get_user_info(bot, event, id, use_cache) for id in user_ids]
214
+ user_infos = (await asyncio.gather(*pool))
215
+
216
+ pool = []
217
+ for i in user_infos:
218
+ if not i:
219
+ pool.append(_get_user_default_avatar())
220
+ continue
221
+ if i.user_avatar:
222
+ pool.append(i.user_avatar.get_image())
223
+ user_avatars = await asyncio.gather(*pool)
224
+ for i in user_avatars:
225
+ if not i:
226
+ user_avatars[user_avatars.index(i)] = await(_get_user_default_avatar())
227
+
228
+ total = sum([i[1] for i in rank])
229
+ rank2 = []
230
+ for i in range(len(rank)):
231
+
232
+ user_info = user_infos[i]
233
+ if not user_info:
234
+ user_info = get_default_user_info()
235
+
236
+ user = UserRankInfo(
237
+ **model_dump(user_info),
238
+ user_bnum=rank[i][1],
239
+ user_proportion=round(rank[i][1] / total * 100, 2),
240
+ user_index=i+1,
241
+ user_nickname=_get_user_nickname(user_info),
242
+ user_avatar_bytes=user_avatars[i],
243
+ )
244
+ rank2.append(user)
245
+
246
+ return rank2
247
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nonebot-plugin-dialectlist
3
- Version: 2.2.3
3
+ Version: 2.3.0
4
4
  Summary: 看看你群群友有多能说
5
5
  Author-email: Chen_Xu233 <woyerpa@outlook.com>
6
6
  License: MIT
@@ -15,12 +15,14 @@ Requires-Dist: nonebot-plugin-cesaa>=0.4.0
15
15
  Requires-Dist: nonebot-plugin-userinfo>=0.2.4
16
16
  Requires-Dist: nonebot-plugin-htmlrender>=0.3.3
17
17
  Requires-Dist: nonebot2>=2.3.2
18
- Requires-Dist: cn2an>=0.5.22
18
+ Requires-Dist: pillow>=10.4.0
19
+ Requires-Dist: nonebot-plugin-uninfo>=0.1.1
19
20
  Provides-Extra: dev
20
21
  Requires-Dist: ruff>=0.5.5; extra == "dev"
21
22
  Requires-Dist: setuptools>=71.1.0; extra == "dev"
22
23
  Requires-Dist: twine>=5.1.0; extra == "dev"
23
24
  Requires-Dist: nb-cli>=0.7.6; extra == "dev"
25
+ Requires-Dist: py-spy>=0.3.14; extra == "dev"
24
26
  Provides-Extra: test
25
27
  Requires-Dist: nonebot-adapter-onebot>=2.4.4; extra == "test"
26
28
 
@@ -64,12 +66,15 @@ nonebot-plugin-dialectlist
64
66
 
65
67
  ### ✅ 插件依赖于
66
68
 
67
- 1. [nonebot-plugin-datastore](https://github.com/he0119/nonebot-plugin-datastore) ————储存历史的消息
69
+ 1. [nonebot-plugin-datastore](https://github.com/he0119/nonebot-plugin-datastore) ————本地化储存
68
70
  2. [nonebot-plugin-userinfo](https://github.com/noneplugin/nonebot-plugin-userinfo) ————获取用户信息
69
71
  3. [nonebot-plugin-apscheduler](https://github.com/nonebot/plugin-apscheduler) ————定时发送排行榜信息
70
72
  4. [nonebot-plugin-alconna](https://github.com/ArcletProject/nonebot-plugin-alconna) ————实现命令解析
71
- 5. [nonebot-plugin-cesaa](https://github.com/MountainDash/nonebot-plugin-send-anything-anywhere) ————实现多平台
72
-
73
+ 5. [nonebot-plugin-chatrecorder](https://github.com/noneplugin/nonebot-plugin-chatrecorder) ————实现消息储存
74
+ 6. [nonebot-plugin-cesaa](https://github.com/MountainDash/nonebot-plugin-send-anything-anywhere) ————实现多平台
75
+
76
+ **⚠注意** 若先前没有安装过```nonebot-plugin-chatrecorder```或者```nonebot-plugin-orm```,则会在启动时报错,请按报错的提示安装数据库!
77
+
73
78
  ## ⚙ 配置
74
79
 
75
80
  需要**提前配置**本插件所**依赖的插件**!
@@ -173,22 +178,23 @@ __!!注意!!__
173
178
 
174
179
  - [x] 适配全平台
175
180
 
176
- - [x] 尝试利用 jinja2 模板引擎制作可视化图片
177
-
178
- - [x] 私聊的查询(超级用户可以任意查询群聊的信息)一半完成
181
+ - [x] 更好看的图片渲染
179
182
 
180
183
  - [x] 添加一些全新的可配置项
184
+
185
+ - [x] 尝试利用 jinja2 模板引擎制作可视化图片
181
186
 
182
- - [x] 更好看的图片渲染
187
+ - [x] 私聊的查询(超级用户可以任意查询群聊的信息)一半完成
183
188
 
184
189
  - [ ] 提供多样化的渲染器配置(html 渲染,pillow 渲染,统计绘图软件渲染)
185
- - [ ] 为 pillow 渲染方式提供插件的加载方式(什么?插件里的插件???)
186
-
187
- - [ ] 查询带某关键词的消息量
188
190
 
189
191
  - [ ] 使用管理员权限直接获取 QQ 官方统计的今日消息量以优化代码运行速度
190
192
 
193
+ - [ ] 为 pillow 渲染方式提供插件的加载方式(什么?插件里的插件???)
194
+
191
195
  - [ ] 特殊的储存方案优化消息统计
196
+
197
+ - [ ] 查询带某关键词的消息量
192
198
 
193
199
  待补充。.....
194
200
 
@@ -15,5 +15,4 @@ nonebot_plugin_dialectlist.egg-info/requires.txt
15
15
  nonebot_plugin_dialectlist.egg-info/top_level.txt
16
16
  nonebot_plugin_dialectlist/template/rank_template.j2
17
17
  nonebot_plugin_dialectlist/template/avatar/default.jpg
18
- nonebot_plugin_dialectlist/template/avatar/master.jpg
19
18
  nonebot_plugin_dialectlist/template/css/style.css
@@ -7,7 +7,8 @@ nonebot-plugin-cesaa>=0.4.0
7
7
  nonebot-plugin-userinfo>=0.2.4
8
8
  nonebot-plugin-htmlrender>=0.3.3
9
9
  nonebot2>=2.3.2
10
- cn2an>=0.5.22
10
+ pillow>=10.4.0
11
+ nonebot-plugin-uninfo>=0.1.1
11
12
 
12
13
  [Test]
13
14
  nonebot-adapter-onebot>=2.4.4
@@ -17,3 +18,4 @@ ruff>=0.5.5
17
18
  setuptools>=71.1.0
18
19
  twine>=5.1.0
19
20
  nb-cli>=0.7.6
21
+ py-spy>=0.3.14
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nonebot-plugin-dialectlist"
3
- version = "2.2.3"
3
+ version = "2.3.0"
4
4
  description = "看看你群群友有多能说"
5
5
  authors = [
6
6
  {name = "Chen_Xu233", email = "woyerpa@outlook.com"},
@@ -15,7 +15,8 @@ dependencies = [
15
15
  "nonebot-plugin-userinfo>=0.2.4",
16
16
  "nonebot-plugin-htmlrender>=0.3.3",
17
17
  "nonebot2>=2.3.2",
18
- "cn2an>=0.5.22"
18
+ "pillow>=10.4.0",
19
+ "nonebot-plugin-uninfo>=0.1.1",
19
20
  ]
20
21
  requires-python = ">=3.9,<4.0"
21
22
  readme = "README.md"
@@ -27,7 +28,8 @@ dev = [
27
28
  "ruff>=0.5.5",
28
29
  "setuptools>=71.1.0",
29
30
  "twine>=5.1.0",
30
- "nb-cli>=0.7.6"
31
+ "nb-cli>=0.7.6",
32
+ "py-spy>=0.3.14",
31
33
  ]
32
34
  Test = [
33
35
  "nonebot-adapter-onebot>=2.4.4",
@@ -1,17 +0,0 @@
1
- from typing import Union
2
- from pydantic import BaseModel
3
- from nonebot_plugin_orm import Model
4
- from nonebot_plugin_userinfo import UserInfo
5
-
6
-
7
- class UserRankInfo(UserInfo):
8
- user_bnum: int
9
- user_proportion: float
10
- user_nickname: str
11
- user_index: Union[int, str]
12
- user_avatar_bytes: bytes
13
-
14
- class MsgCountDayData(BaseModel):
15
- user_id:str
16
- # class MsgCountData(Model):
17
- # __tablename__ = 'dialectlist_msg_data'
@@ -1,118 +0,0 @@
1
- body {
2
- background-image: url('https://api.yimian.xyz/img');
3
- background-attachment: scroll;
4
- margin: 0;
5
- background-size: cover;
6
- background-position: center;
7
- background-repeat: no-repeat;
8
- width: 1024;
9
- }
10
-
11
- .container {
12
- padding: 20px 40px;
13
- position: relative;
14
- flex-direction: column;
15
- display: flex;
16
- }
17
-
18
- .card {
19
- border: 5px solid rgba(200, 200, 200, 1);
20
- text-align: center; /*设置文本水平居中*/
21
- align-content: center;
22
- margin: 1% 1% 1% 1%;
23
- border-radius: 2rem;
24
- background: rgba(255, 255, 255, .2);
25
- -webkit-backdrop-filter: blur(3px);
26
- backdrop-filter: blur(3px);
27
- }
28
-
29
- .card2 {
30
- justify-content: center;
31
- flex-wrap: wrap;
32
- align-items: center;
33
- flex-direction: revert;
34
- display: flex;
35
- border: 5px solid rgba(200, 200, 200, 1);
36
- text-align: center; /*设置文本水平居中*/
37
- align-content: center;
38
- margin: 1% 1% 1% 1%;
39
- border-radius: 2rem;
40
- background: rgba(255, 255, 255, .2);
41
- -webkit-backdrop-filter: blur(3px);
42
- backdrop-filter: blur(3px);
43
- }
44
-
45
- .center_text {
46
- text-align: center;
47
- font-size: 300%;
48
- font-weight: bolder;
49
- }
50
-
51
- .center_text2 {
52
- text-align: center;
53
- font-size: 150%;
54
- }
55
-
56
- .rank_container {
57
- flex-direction: column;
58
- display: flex;
59
- border: 5px solid rgba(200, 200, 200, 1);
60
- border-radius: 2rem;
61
- padding: 10px 20px;
62
- margin: 1% 1% 1% 1%;
63
- display: flex;
64
- justify-content: center;
65
- align-items: center;
66
- background: rgba(243, 243, 240, 0.6);
67
- }
68
-
69
- .rank_card {
70
- display: flex;
71
- width: 90%;
72
- flex-direction: row;
73
- border: 3px solid rgba(255, 255, 255, 0.61);
74
- margin: 20px 10px;
75
- border-radius: 2rem;
76
- /* padding: 20px 40px; */
77
- align-content: center;
78
- backdrop-filter: blur(10px);
79
- -webkit-backdrop-filter: blur(10px);
80
- }
81
-
82
- .profile{
83
- width: 20%;
84
- height: 20%;
85
- border: 3px solid rgba(255, 255, 255, 0.61);
86
- border-radius: 2000px;
87
- background-size: cover;
88
- margin-right: 20px;
89
- }
90
-
91
- .profile2{
92
- width: 8%;
93
- height: 8%;
94
- border: 3px solid rgba(255, 255, 255, 0.61);
95
- border-radius: 2000px;
96
- background-size: cover;
97
- margin-right: 20px;
98
- }
99
-
100
- .rank_card_info {
101
- width: 100%;
102
- display: flex;
103
- flex-direction: column;
104
- }
105
-
106
- .g-container {
107
- width: 90%;
108
- height: 25px;
109
- border-radius: 25px;
110
- background: #ffb2b25d;
111
- }
112
-
113
- .g-progress {
114
- width: 50%;
115
- height: inherit;
116
- border-radius: 25px 20px 20px 25px;
117
- background: linear-gradient(90deg,rgb(57, 230, 230), rgb(21, 161, 248));
118
- }