nonebot-plugin-dialectlist 2.3.0__tar.gz → 2.4.1__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.3.0 → nonebot_plugin_dialectlist-2.4.1}/PKG-INFO +2 -8
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/README.md +0 -6
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist/__init__.py +19 -28
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist/config.py +5 -5
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist/model.py +3 -8
- nonebot_plugin_dialectlist-2.4.1/nonebot_plugin_dialectlist/storage.py +130 -0
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist/time.py +0 -1
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist/utils.py +49 -33
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist.egg-info/PKG-INFO +2 -8
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist.egg-info/requires.txt +1 -1
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/pyproject.toml +5 -16
- nonebot_plugin_dialectlist-2.3.0/nonebot_plugin_dialectlist/storage.py +0 -2
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/MANIFEST.in +0 -0
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist/template/avatar/default.jpg +0 -0
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist/template/css/style.css +0 -0
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist/template/rank_template.j2 +0 -0
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist/usage.py +0 -0
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist.egg-info/SOURCES.txt +0 -0
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist.egg-info/dependency_links.txt +0 -0
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/nonebot_plugin_dialectlist.egg-info/top_level.txt +0 -0
- {nonebot_plugin_dialectlist-2.3.0 → nonebot_plugin_dialectlist-2.4.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: nonebot-plugin-dialectlist
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.1
|
|
4
4
|
Summary: 看看你群群友有多能说
|
|
5
5
|
Author-email: Chen_Xu233 <woyerpa@outlook.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,7 +12,7 @@ Requires-Dist: nonebot-plugin-orm[default]
|
|
|
12
12
|
Requires-Dist: nonebot-plugin-apscheduler>=0.4.0
|
|
13
13
|
Requires-Dist: nonebot-plugin-alconna>=0.50.2
|
|
14
14
|
Requires-Dist: nonebot-plugin-cesaa>=0.4.0
|
|
15
|
-
Requires-Dist: nonebot-plugin-userinfo>=0.2.
|
|
15
|
+
Requires-Dist: nonebot-plugin-userinfo>=0.2.6
|
|
16
16
|
Requires-Dist: nonebot-plugin-htmlrender>=0.3.3
|
|
17
17
|
Requires-Dist: nonebot2>=2.3.2
|
|
18
18
|
Requires-Dist: pillow>=10.4.0
|
|
@@ -186,12 +186,6 @@ __!!注意!!__
|
|
|
186
186
|
|
|
187
187
|
- [x] 私聊的查询(超级用户可以任意查询群聊的信息)一半完成
|
|
188
188
|
|
|
189
|
-
- [ ] 提供多样化的渲染器配置(html 渲染,pillow 渲染,统计绘图软件渲染)
|
|
190
|
-
|
|
191
|
-
- [ ] 使用管理员权限直接获取 QQ 官方统计的今日消息量以优化代码运行速度
|
|
192
|
-
|
|
193
|
-
- [ ] 为 pillow 渲染方式提供插件的加载方式(什么?插件里的插件???)
|
|
194
|
-
|
|
195
189
|
- [ ] 特殊的储存方案优化消息统计
|
|
196
190
|
|
|
197
191
|
- [ ] 查询带某关键词的消息量
|
|
@@ -158,12 +158,6 @@ __!!注意!!__
|
|
|
158
158
|
|
|
159
159
|
- [x] 私聊的查询(超级用户可以任意查询群聊的信息)一半完成
|
|
160
160
|
|
|
161
|
-
- [ ] 提供多样化的渲染器配置(html 渲染,pillow 渲染,统计绘图软件渲染)
|
|
162
|
-
|
|
163
|
-
- [ ] 使用管理员权限直接获取 QQ 官方统计的今日消息量以优化代码运行速度
|
|
164
|
-
|
|
165
|
-
- [ ] 为 pillow 渲染方式提供插件的加载方式(什么?插件里的插件???)
|
|
166
|
-
|
|
167
161
|
- [ ] 特殊的储存方案优化消息统计
|
|
168
162
|
|
|
169
163
|
- [ ] 查询带某关键词的消息量
|
|
@@ -8,21 +8,19 @@ require("nonebot_plugin_alconna")
|
|
|
8
8
|
require("nonebot_plugin_cesaa")
|
|
9
9
|
|
|
10
10
|
import re
|
|
11
|
-
import os
|
|
12
11
|
import time as t
|
|
13
12
|
import nonebot_plugin_saa as saa
|
|
14
13
|
|
|
15
|
-
from typing import Union, Optional
|
|
14
|
+
from typing import Union, Optional
|
|
16
15
|
from datetime import datetime, timedelta
|
|
17
16
|
from arclet.alconna import ArparmaBehavior
|
|
18
17
|
from arclet.alconna.arparma import Arparma
|
|
19
18
|
|
|
19
|
+
from nonebot import on_command
|
|
20
20
|
from nonebot.log import logger
|
|
21
21
|
from nonebot.typing import T_State
|
|
22
|
-
from nonebot.compat import model_dump
|
|
23
22
|
from nonebot.params import Arg, Depends
|
|
24
23
|
from nonebot.adapters import Bot, Event
|
|
25
|
-
from nonebot.permission import SUPERUSER
|
|
26
24
|
from nonebot.plugin import PluginMetadata, inherit_supported_adapters
|
|
27
25
|
from nonebot_plugin_alconna import (
|
|
28
26
|
Args,
|
|
@@ -30,14 +28,10 @@ from nonebot_plugin_alconna import (
|
|
|
30
28
|
Alconna,
|
|
31
29
|
on_alconna,
|
|
32
30
|
)
|
|
33
|
-
|
|
34
|
-
from nonebot_plugin_apscheduler import scheduler
|
|
35
|
-
from nonebot_plugin_userinfo import get_user_info
|
|
36
31
|
from nonebot_plugin_chatrecorder import get_message_records
|
|
37
32
|
from nonebot_plugin_session import Session, SessionIdType, extract_session
|
|
38
33
|
|
|
39
|
-
|
|
40
|
-
# from .function import *
|
|
34
|
+
from .storage import get_cache,build_cache
|
|
41
35
|
from .config import Config, plugin_config
|
|
42
36
|
from .usage import __usage__
|
|
43
37
|
from .time import (
|
|
@@ -45,14 +39,12 @@ from .time import (
|
|
|
45
39
|
get_datetime_now_with_timezone,
|
|
46
40
|
parse_datetime,
|
|
47
41
|
)
|
|
48
|
-
from .model import UserRankInfo
|
|
49
42
|
from .utils import (
|
|
50
43
|
got_rank,
|
|
51
44
|
msg_counter,
|
|
52
45
|
get_rank_image,
|
|
53
46
|
persist_id2user_id,
|
|
54
47
|
get_user_infos,
|
|
55
|
-
# get_user_info2,
|
|
56
48
|
)
|
|
57
49
|
|
|
58
50
|
__plugin_meta__ = PluginMetadata(
|
|
@@ -65,7 +57,6 @@ __plugin_meta__ = PluginMetadata(
|
|
|
65
57
|
"nonebot_plugin_chatrecorder", "nonebot_plugin_saa", "nonebot_plugin_alconna"
|
|
66
58
|
),
|
|
67
59
|
config=Config,
|
|
68
|
-
# extra={"orm_version_location": migrations},
|
|
69
60
|
)
|
|
70
61
|
|
|
71
62
|
|
|
@@ -83,6 +74,13 @@ def wrapper(slot: Union[int, str], content: Optional[str], context) -> str:
|
|
|
83
74
|
return content
|
|
84
75
|
return "" # pragma: no cover
|
|
85
76
|
|
|
77
|
+
build_cache_cmd = on_command("build_cache", aliases={"重建缓存"}, block=True)
|
|
78
|
+
|
|
79
|
+
@build_cache_cmd.handle()
|
|
80
|
+
async def _build_cache(bot: Bot, event: Event):
|
|
81
|
+
await saa.Text("正在重建缓存,请稍等。").send(reply=True)
|
|
82
|
+
await build_cache()
|
|
83
|
+
await saa.Text("重建缓存完成。").send(reply=True)
|
|
86
84
|
|
|
87
85
|
rank_cmd = on_alconna(
|
|
88
86
|
Alconna(
|
|
@@ -194,8 +192,6 @@ async def _group_message(
|
|
|
194
192
|
except ValueError:
|
|
195
193
|
await rank_cmd.finish("请输入正确的日期,不然我没法理解呢!")
|
|
196
194
|
|
|
197
|
-
logger.debug(f"命令解析花费时间:{t.time() - t1}")
|
|
198
|
-
|
|
199
195
|
|
|
200
196
|
@rank_cmd.got(
|
|
201
197
|
"start",
|
|
@@ -216,7 +212,7 @@ async def handle_rank(
|
|
|
216
212
|
start: datetime = Arg(),
|
|
217
213
|
stop: datetime = Arg(),
|
|
218
214
|
):
|
|
219
|
-
|
|
215
|
+
|
|
220
216
|
if id := state["group_id"]:
|
|
221
217
|
id = str(id)
|
|
222
218
|
logger.debug(f"group_id: {id}")
|
|
@@ -228,8 +224,11 @@ async def handle_rank(
|
|
|
228
224
|
await saa.Text("没有指定群哦").finish()
|
|
229
225
|
|
|
230
226
|
if plugin_config.counting_cache:
|
|
231
|
-
|
|
227
|
+
t1 = t.time()
|
|
228
|
+
raw_rank = await get_cache(start, stop, id)
|
|
229
|
+
logger.debug(f"获取计数消息花费时间:{t.time() - t1}")
|
|
232
230
|
else:
|
|
231
|
+
t1 = t.time()
|
|
233
232
|
messages = await get_message_records(
|
|
234
233
|
id2s=[id],
|
|
235
234
|
id_type=SessionIdType.GROUP,
|
|
@@ -240,14 +239,13 @@ async def handle_rank(
|
|
|
240
239
|
time_stop=stop,
|
|
241
240
|
exclude_id1s=plugin_config.excluded_people,
|
|
242
241
|
)
|
|
243
|
-
|
|
244
|
-
if not messages:
|
|
245
|
-
await saa.Text("明明这个时间段都没有人说话怎么会有话痨榜呢?").finish()
|
|
246
|
-
|
|
247
242
|
raw_rank = msg_counter(messages)
|
|
243
|
+
logger.debug(f"获取计数消息花费时间:{t.time() - t1}")
|
|
244
|
+
|
|
245
|
+
if not raw_rank:
|
|
246
|
+
await saa.Text("明明这个时间段都没有人说话怎么会有话痨榜呢?").finish()
|
|
248
247
|
|
|
249
248
|
rank = got_rank(raw_rank)
|
|
250
|
-
logger.debug(rank)
|
|
251
249
|
ids = await persist_id2user_id([int(i[0]) for i in rank])
|
|
252
250
|
for i in range(len(rank)):
|
|
253
251
|
rank[i][0] = str(ids[i])
|
|
@@ -283,10 +281,3 @@ async def handle_rank(
|
|
|
283
281
|
logger.debug(f"群聊消息渲染图片花费时间:{t.time() - t1}")
|
|
284
282
|
|
|
285
283
|
await msg.finish(reply=True)
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
# @scheduler.scheduled_job(
|
|
289
|
-
# "dialectlist", day="*/2", id="xxx", args=[1], kwargs={"arg2": 2}
|
|
290
|
-
# )
|
|
291
|
-
# async def __():
|
|
292
|
-
# pass
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
from pydantic import BaseModel
|
|
2
|
-
from typing import Optional, List
|
|
2
|
+
from typing import Optional, List
|
|
3
3
|
from nonebot import get_driver, get_plugin_config
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class ScopedConfig(BaseModel):
|
|
7
7
|
get_num: int = 5 # 获取人数数量
|
|
8
8
|
font: str = "SimHei" # 字体格式
|
|
9
|
-
suffix: bool =
|
|
10
|
-
excluded_self: bool = True
|
|
9
|
+
suffix: bool = True # 是否显示后缀
|
|
10
|
+
excluded_self: bool = True # 是否排除自己
|
|
11
11
|
visualization: bool = True # 是否可视化
|
|
12
|
-
counting_cache: bool = False
|
|
12
|
+
counting_cache: bool = False # 计数缓存(能够提高回复速度)
|
|
13
13
|
excluded_people: List[str] = [] # 排除的人的QQ号
|
|
14
|
-
timezone: Optional[str] = "Asia/Shanghai"
|
|
14
|
+
timezone: Optional[str] = "Asia/Shanghai" # 时区,影响统计时间
|
|
15
15
|
string_suffix: str = "统计花费时间:{timecost}秒" # 消息格式后缀
|
|
16
16
|
template_path: str = "./template/rank_template.j2" # 模板路径
|
|
17
17
|
string_format: str = "第{index}名:\n{nickname},{chatdatanum}条消息\n" # 消息格式
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
from typing import Union
|
|
3
|
-
from
|
|
4
|
-
from sqlalchemy import JSON, TEXT, String,Integer
|
|
3
|
+
from sqlalchemy import Integer
|
|
5
4
|
from nonebot_plugin_orm import Model
|
|
6
5
|
from nonebot_plugin_userinfo import UserInfo
|
|
7
6
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
@@ -15,13 +14,9 @@ class UserRankInfo(UserInfo):
|
|
|
15
14
|
user_avatar_bytes: bytes
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
# class MsgCountDayData(BaseModel):
|
|
19
|
-
# session_id: str
|
|
20
|
-
# session_bnum: int
|
|
21
|
-
|
|
22
17
|
class MessageCountCache(Model):
|
|
23
18
|
__table_args__ = {"extend_existing": True}
|
|
24
|
-
id: Mapped[int] = mapped_column(primary_key=True)
|
|
19
|
+
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
25
20
|
time: Mapped[datetime]
|
|
26
|
-
session_id: Mapped[int] = mapped_column(Integer)
|
|
21
|
+
session_id: Mapped[int] = mapped_column(Integer, index=True)
|
|
27
22
|
session_bnum: Mapped[int] = mapped_column(Integer)
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from sqlalchemy import delete, or_, select
|
|
5
|
+
|
|
6
|
+
from nonebot import get_driver
|
|
7
|
+
from nonebot.log import logger
|
|
8
|
+
from nonebot.params import Depends
|
|
9
|
+
from nonebot.adapters import Event,Bot
|
|
10
|
+
from nonebot.message import event_postprocessor
|
|
11
|
+
|
|
12
|
+
from .model import MessageCountCache
|
|
13
|
+
from .config import plugin_config
|
|
14
|
+
|
|
15
|
+
from nonebot_plugin_localstore import get_data_file
|
|
16
|
+
from nonebot_plugin_chatrecorder import get_message_records
|
|
17
|
+
from nonebot_plugin_chatrecorder.utils import remove_timezone
|
|
18
|
+
from nonebot_plugin_session import extract_session, Session
|
|
19
|
+
from nonebot_plugin_session_orm import SessionModel, get_session_persist_id
|
|
20
|
+
from nonebot_plugin_orm import get_session
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
async def get_cache(time_start: datetime, time_stop: datetime, group_id: str):
|
|
24
|
+
async with get_session() as db_session:
|
|
25
|
+
where = [or_(SessionModel.id2 == group_id)]
|
|
26
|
+
statement = select(SessionModel).where(*where)
|
|
27
|
+
|
|
28
|
+
sessions = (await db_session.scalars(statement)).all()
|
|
29
|
+
|
|
30
|
+
where = [
|
|
31
|
+
or_(*[MessageCountCache.session_id == session.id for session in sessions])
|
|
32
|
+
]
|
|
33
|
+
statement = select(MessageCountCache).where(*where)
|
|
34
|
+
where.append(or_(MessageCountCache.time >= remove_timezone(time_start)))
|
|
35
|
+
where.append(or_(MessageCountCache.time <= remove_timezone(time_stop)))
|
|
36
|
+
statement = select(MessageCountCache).where(*where)
|
|
37
|
+
|
|
38
|
+
user_caches = (await db_session.scalars(statement)).all()
|
|
39
|
+
raw_rank = {}
|
|
40
|
+
for i in user_caches:
|
|
41
|
+
raw_rank[i.session_id] = raw_rank.get(i.session_id, 0) + i.session_bnum
|
|
42
|
+
return raw_rank
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
async def build_cache():
|
|
46
|
+
async with get_session() as db_session:
|
|
47
|
+
await db_session.execute(delete(MessageCountCache))
|
|
48
|
+
await db_session.commit()
|
|
49
|
+
logger.info("先前可能存在的缓存已清空")
|
|
50
|
+
messages = await get_message_records(types=["message"])
|
|
51
|
+
async with get_session() as db_session:
|
|
52
|
+
for msg in messages:
|
|
53
|
+
msg_session_id = msg.session_persist_id
|
|
54
|
+
|
|
55
|
+
where = [or_(MessageCountCache.session_id == msg_session_id)]
|
|
56
|
+
where.append(
|
|
57
|
+
or_(
|
|
58
|
+
MessageCountCache.time
|
|
59
|
+
== remove_timezone(msg.time.replace(hour=1, minute=0, second=0, microsecond=0))
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
statement = select(MessageCountCache).where(*where)
|
|
63
|
+
|
|
64
|
+
user_cache = (await db_session.scalars(statement)).all()
|
|
65
|
+
|
|
66
|
+
if user_cache:
|
|
67
|
+
user_cache[0].session_bnum += 1
|
|
68
|
+
else:
|
|
69
|
+
user_cache = MessageCountCache(
|
|
70
|
+
session_id=msg.session_persist_id,
|
|
71
|
+
time=remove_timezone(msg.time.replace(hour=1, minute=0, second=0, microsecond=0)),
|
|
72
|
+
session_bnum=1,
|
|
73
|
+
)
|
|
74
|
+
db_session.add(user_cache)
|
|
75
|
+
await db_session.commit()
|
|
76
|
+
|
|
77
|
+
logger.info("缓存构建完成")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
driver = get_driver()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@driver.on_startup
|
|
84
|
+
async def _():
|
|
85
|
+
if not plugin_config.counting_cache:
|
|
86
|
+
return
|
|
87
|
+
f_name = get_data_file("nonebot-plugin-dialectlist", "is-pre-cached.json")
|
|
88
|
+
if not os.path.exists(f_name):
|
|
89
|
+
with open(f_name, "w", encoding="utf-8") as f:
|
|
90
|
+
s = json.dumps({"is-pre-cached": False}, ensure_ascii=False, indent=4)
|
|
91
|
+
f.write(s)
|
|
92
|
+
|
|
93
|
+
with open(f_name, "r", encoding="utf-8") as f:
|
|
94
|
+
if json.load(f)["is-pre-cached"]:
|
|
95
|
+
return
|
|
96
|
+
logger.info("未检查到缓存,开始构建缓存")
|
|
97
|
+
with open(f_name, "w", encoding="utf-8") as f:
|
|
98
|
+
await build_cache()
|
|
99
|
+
json.dump({"is-pre-cached": True}, f, ensure_ascii=False, indent=4)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@event_postprocessor
|
|
103
|
+
async def _(bot: Bot, event: Event,session: Session = Depends(extract_session)):
|
|
104
|
+
if not plugin_config.counting_cache:
|
|
105
|
+
return
|
|
106
|
+
if not session.id2:
|
|
107
|
+
return
|
|
108
|
+
if event.get_type() != "message":
|
|
109
|
+
return
|
|
110
|
+
now = datetime.now()
|
|
111
|
+
now = now.replace(hour=1, minute=0, second=0, microsecond=0)
|
|
112
|
+
|
|
113
|
+
async with get_session() as db_session:
|
|
114
|
+
session_id = await get_session_persist_id(session)
|
|
115
|
+
logger.debug("session_id:"+str(session_id))
|
|
116
|
+
where = [or_(MessageCountCache.session_id == session_id)]
|
|
117
|
+
where.append(or_(MessageCountCache.time == remove_timezone(now)))
|
|
118
|
+
statement = select(MessageCountCache).where(*where)
|
|
119
|
+
user_cache = (await db_session.scalars(statement)).first()
|
|
120
|
+
if user_cache:
|
|
121
|
+
user_cache.session_bnum += 1
|
|
122
|
+
else:
|
|
123
|
+
user_cache = MessageCountCache(
|
|
124
|
+
session_id=session_id,
|
|
125
|
+
time=remove_timezone(now),
|
|
126
|
+
session_bnum=1,
|
|
127
|
+
)
|
|
128
|
+
db_session.add(user_cache)
|
|
129
|
+
await db_session.commit()
|
|
130
|
+
logger.debug("已计入缓存")
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import httpx
|
|
2
3
|
import asyncio
|
|
3
4
|
import unicodedata
|
|
4
5
|
|
|
5
|
-
from typing import Dict, List
|
|
6
|
+
from typing import Dict, List
|
|
6
7
|
from sqlalchemy import or_, select
|
|
7
8
|
from sqlalchemy.sql import ColumnElement
|
|
8
9
|
|
|
@@ -15,6 +16,7 @@ from nonebot.adapters import Bot, Event
|
|
|
15
16
|
from nonebot_plugin_orm import get_session
|
|
16
17
|
from nonebot_plugin_session import Session, SessionLevel, extract_session
|
|
17
18
|
from nonebot_plugin_userinfo import get_user_info, UserInfo
|
|
19
|
+
from nonebot_plugin_userinfo.exception import NetworkError
|
|
18
20
|
from nonebot_plugin_localstore import get_cache_dir
|
|
19
21
|
from nonebot_plugin_htmlrender import template_to_pic
|
|
20
22
|
from nonebot_plugin_session_orm import SessionModel
|
|
@@ -26,16 +28,6 @@ from .config import plugin_config
|
|
|
26
28
|
|
|
27
29
|
cache_path = get_cache_dir("nonebot_plugin_dialectlist")
|
|
28
30
|
|
|
29
|
-
# 暂时不做考虑
|
|
30
|
-
# def admin_permission():
|
|
31
|
-
# permission = SUPERUSER
|
|
32
|
-
# with contextlib.suppress(ImportError):
|
|
33
|
-
# from nonebot.adapters.onebot.v11.permission import GROUP_ADMIN, GROUP_OWNER
|
|
34
|
-
|
|
35
|
-
# permission = permission | GROUP_ADMIN | GROUP_OWNER
|
|
36
|
-
|
|
37
|
-
# return permission
|
|
38
|
-
|
|
39
31
|
|
|
40
32
|
async def ensure_group(matcher: Matcher, session: Session = Depends(extract_session)):
|
|
41
33
|
"""确保在群组中使用"""
|
|
@@ -184,7 +176,9 @@ async def get_rank_image(rank: List[UserRankInfo]) -> bytes:
|
|
|
184
176
|
},
|
|
185
177
|
pages={"viewport": {"width": 1000, "height": 10}},
|
|
186
178
|
)
|
|
187
|
-
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _get_user_nickname(user_info: UserInfo) -> str:
|
|
188
182
|
user_nickname = (
|
|
189
183
|
user_info.user_displayname
|
|
190
184
|
if user_info.user_displayname
|
|
@@ -192,56 +186,78 @@ def _get_user_nickname(user_info:UserInfo)->str:
|
|
|
192
186
|
)
|
|
193
187
|
return user_nickname
|
|
194
188
|
|
|
195
|
-
|
|
189
|
+
|
|
190
|
+
async def _get_user_default_avatar() -> bytes:
|
|
196
191
|
img = open(
|
|
197
|
-
os.path.dirname(os.path.abspath(__file__))
|
|
198
|
-
+ "/template/avatar/default.jpg",
|
|
192
|
+
os.path.dirname(os.path.abspath(__file__)) + "/template/avatar/default.jpg",
|
|
199
193
|
"rb",
|
|
200
|
-
|
|
194
|
+
).read()
|
|
201
195
|
return img
|
|
202
196
|
|
|
203
|
-
def
|
|
197
|
+
async def _get_user_avatar(user: UserInfo, client: httpx.AsyncClient) -> bytes:
|
|
198
|
+
if not user.user_avatar:
|
|
199
|
+
return await _get_user_default_avatar()
|
|
200
|
+
url = user.user_avatar.get_url()
|
|
201
|
+
for i in range(3):
|
|
202
|
+
try:
|
|
203
|
+
resp = await client.get(url, timeout=10)
|
|
204
|
+
resp.raise_for_status()
|
|
205
|
+
return resp.content
|
|
206
|
+
except Exception as e:
|
|
207
|
+
logger.warning(f"Error downloading {url}, retry {i}/3: {e}")
|
|
208
|
+
await asyncio.sleep(3)
|
|
209
|
+
raise NetworkError(f"{url} 下载失败!")
|
|
210
|
+
|
|
211
|
+
def get_default_user_info() -> UserInfo:
|
|
204
212
|
user_info = UserInfo(
|
|
205
213
|
user_id="114514",
|
|
206
214
|
user_name="鬼知道这谁,bot获取不了",
|
|
207
215
|
)
|
|
208
216
|
return user_info
|
|
209
217
|
|
|
210
|
-
async def get_user_infos(
|
|
211
|
-
|
|
218
|
+
async def get_user_infos(
|
|
219
|
+
bot: Bot, event: Event, rank: List, use_cache: bool = True
|
|
220
|
+
) -> List[UserRankInfo]:
|
|
221
|
+
|
|
212
222
|
user_ids = [i[0] for i in rank]
|
|
213
223
|
pool = [get_user_info(bot, event, id, use_cache) for id in user_ids]
|
|
214
|
-
user_infos =
|
|
224
|
+
user_infos = await asyncio.gather(*pool)
|
|
215
225
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
226
|
+
async with httpx.AsyncClient() as client:
|
|
227
|
+
pool = []
|
|
228
|
+
for i in user_infos:
|
|
229
|
+
if not i:
|
|
230
|
+
pool.append(_get_user_default_avatar())
|
|
231
|
+
continue
|
|
232
|
+
if i.user_avatar:
|
|
233
|
+
pool.append(_get_user_avatar(i, client))
|
|
234
|
+
user_avatars = await asyncio.gather(*pool)
|
|
235
|
+
|
|
224
236
|
for i in user_avatars:
|
|
225
237
|
if not i:
|
|
226
|
-
user_avatars[user_avatars.index(i)] = await
|
|
238
|
+
user_avatars[user_avatars.index(i)] = await _get_user_default_avatar()
|
|
227
239
|
|
|
228
240
|
total = sum([i[1] for i in rank])
|
|
229
241
|
rank2 = []
|
|
230
242
|
for i in range(len(rank)):
|
|
231
|
-
|
|
243
|
+
|
|
232
244
|
user_info = user_infos[i]
|
|
233
245
|
if not user_info:
|
|
234
246
|
user_info = get_default_user_info()
|
|
235
|
-
|
|
247
|
+
|
|
236
248
|
user = UserRankInfo(
|
|
237
249
|
**model_dump(user_info),
|
|
238
250
|
user_bnum=rank[i][1],
|
|
239
251
|
user_proportion=round(rank[i][1] / total * 100, 2),
|
|
240
|
-
user_index=i+1,
|
|
252
|
+
user_index=i + 1,
|
|
241
253
|
user_nickname=_get_user_nickname(user_info),
|
|
242
254
|
user_avatar_bytes=user_avatars[i],
|
|
243
255
|
)
|
|
256
|
+
user.user_gender = (
|
|
257
|
+
"♂"
|
|
258
|
+
if user.user_gender == "male"
|
|
259
|
+
else "♀" if user.user_gender == "female" else ""
|
|
260
|
+
)
|
|
244
261
|
rank2.append(user)
|
|
245
262
|
|
|
246
263
|
return rank2
|
|
247
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: nonebot-plugin-dialectlist
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.1
|
|
4
4
|
Summary: 看看你群群友有多能说
|
|
5
5
|
Author-email: Chen_Xu233 <woyerpa@outlook.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,7 +12,7 @@ Requires-Dist: nonebot-plugin-orm[default]
|
|
|
12
12
|
Requires-Dist: nonebot-plugin-apscheduler>=0.4.0
|
|
13
13
|
Requires-Dist: nonebot-plugin-alconna>=0.50.2
|
|
14
14
|
Requires-Dist: nonebot-plugin-cesaa>=0.4.0
|
|
15
|
-
Requires-Dist: nonebot-plugin-userinfo>=0.2.
|
|
15
|
+
Requires-Dist: nonebot-plugin-userinfo>=0.2.6
|
|
16
16
|
Requires-Dist: nonebot-plugin-htmlrender>=0.3.3
|
|
17
17
|
Requires-Dist: nonebot2>=2.3.2
|
|
18
18
|
Requires-Dist: pillow>=10.4.0
|
|
@@ -186,12 +186,6 @@ __!!注意!!__
|
|
|
186
186
|
|
|
187
187
|
- [x] 私聊的查询(超级用户可以任意查询群聊的信息)一半完成
|
|
188
188
|
|
|
189
|
-
- [ ] 提供多样化的渲染器配置(html 渲染,pillow 渲染,统计绘图软件渲染)
|
|
190
|
-
|
|
191
|
-
- [ ] 使用管理员权限直接获取 QQ 官方统计的今日消息量以优化代码运行速度
|
|
192
|
-
|
|
193
|
-
- [ ] 为 pillow 渲染方式提供插件的加载方式(什么?插件里的插件???)
|
|
194
|
-
|
|
195
189
|
- [ ] 特殊的储存方案优化消息统计
|
|
196
190
|
|
|
197
191
|
- [ ] 查询带某关键词的消息量
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "nonebot-plugin-dialectlist"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.4.1"
|
|
4
4
|
description = "看看你群群友有多能说"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "Chen_Xu233", email = "woyerpa@outlook.com"},
|
|
@@ -12,7 +12,7 @@ dependencies = [
|
|
|
12
12
|
"nonebot-plugin-apscheduler>=0.4.0",
|
|
13
13
|
"nonebot-plugin-alconna>=0.50.2",
|
|
14
14
|
"nonebot-plugin-cesaa>=0.4.0",
|
|
15
|
-
"nonebot-plugin-userinfo>=0.2.
|
|
15
|
+
"nonebot-plugin-userinfo>=0.2.6",
|
|
16
16
|
"nonebot-plugin-htmlrender>=0.3.3",
|
|
17
17
|
"nonebot2>=2.3.2",
|
|
18
18
|
"pillow>=10.4.0",
|
|
@@ -40,21 +40,10 @@ distribution = true
|
|
|
40
40
|
|
|
41
41
|
[tool.ruff]
|
|
42
42
|
line-length = 80
|
|
43
|
+
|
|
43
44
|
[tool.ruff.format]
|
|
44
45
|
quote-style = "single"
|
|
45
46
|
indent-style = "tab"
|
|
46
47
|
|
|
47
|
-
[tool.
|
|
48
|
-
|
|
49
|
-
build = 'pdm run setup.py sdist'
|
|
50
|
-
publish = 'pdm run python -m twine upload dist/*'
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
# 以下为智普 AI 生成,还不知道这玩意有啥用。
|
|
54
|
-
# [tool.pdm.dev-dependencies]
|
|
55
|
-
# black = "^23.1.0"
|
|
56
|
-
# isort = "^5.10.1"
|
|
57
|
-
# pre-commit = "^2.20.0"
|
|
58
|
-
|
|
59
|
-
# [tool.pdm.global-options]
|
|
60
|
-
# --no-pip-version-check = true
|
|
48
|
+
[tool.ruff.lint]
|
|
49
|
+
ignore = ["E402"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|