nonebot-plugin-group-heat 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_group_heat-0.1.0/PKG-INFO +62 -0
- nonebot_plugin_group_heat-0.1.0/README.md +46 -0
- nonebot_plugin_group_heat-0.1.0/pyproject.toml +29 -0
- nonebot_plugin_group_heat-0.1.0/setup.cfg +4 -0
- nonebot_plugin_group_heat-0.1.0/src/nonebot_plugin_group_heat/__init__.py +128 -0
- nonebot_plugin_group_heat-0.1.0/src/nonebot_plugin_group_heat/config.py +7 -0
- nonebot_plugin_group_heat-0.1.0/src/nonebot_plugin_group_heat/database.py +116 -0
- nonebot_plugin_group_heat-0.1.0/src/nonebot_plugin_group_heat/heat_image.py +58 -0
- nonebot_plugin_group_heat-0.1.0/src/nonebot_plugin_group_heat.egg-info/PKG-INFO +62 -0
- nonebot_plugin_group_heat-0.1.0/src/nonebot_plugin_group_heat.egg-info/SOURCES.txt +11 -0
- nonebot_plugin_group_heat-0.1.0/src/nonebot_plugin_group_heat.egg-info/dependency_links.txt +1 -0
- nonebot_plugin_group_heat-0.1.0/src/nonebot_plugin_group_heat.egg-info/requires.txt +5 -0
- nonebot_plugin_group_heat-0.1.0/src/nonebot_plugin_group_heat.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nonebot-plugin-group-heat
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: 群热度统计插件 - 实时查询群内热度,生成昨日热度折线图
|
|
5
|
+
Author-email: Wojusensei <3442006415@qq.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Wojusensei/nonebot-plugin-group-heat
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Requires-Python: >=3.9
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: nonebot2>=2.3.0
|
|
12
|
+
Requires-Dist: nonebot-adapter-onebot>=2.0.0
|
|
13
|
+
Requires-Dist: nonebot-plugin-localstore>=0.5.0
|
|
14
|
+
Requires-Dist: matplotlib>=3.5.0
|
|
15
|
+
Requires-Dist: numpy>=1.21.0
|
|
16
|
+
|
|
17
|
+
# nonebot-plugin-group-heat
|
|
18
|
+
|
|
19
|
+
群热度统计插件 for NoneBot2
|
|
20
|
+
|
|
21
|
+
## 功能
|
|
22
|
+
|
|
23
|
+
- `/群热度` - 获取过去30分钟的群热度值,附带 bot 评价
|
|
24
|
+
- `/昨日热度图` - 生成昨日每30分钟的热度折线图,并显示平均热度
|
|
25
|
+
|
|
26
|
+
## 热度计算规则
|
|
27
|
+
|
|
28
|
+
| 消息类型 | 热度值 |
|
|
29
|
+
|---------|--------|
|
|
30
|
+
| 文本消息 | +0.05 |
|
|
31
|
+
| 表情包 | +0.20 |
|
|
32
|
+
| 文件(图片/视频/语音等) | +0.30 |
|
|
33
|
+
| 其他消息 | 不计入 |
|
|
34
|
+
|
|
35
|
+
- 每个统计周期的初始热度为 -10°
|
|
36
|
+
|
|
37
|
+
## 评价机制
|
|
38
|
+
|
|
39
|
+
| 热度范围 | 评价 |
|
|
40
|
+
|---------|------|
|
|
41
|
+
| < 0 | 群成冰块啦,群主快开暖气 |
|
|
42
|
+
| 0 ~ 10 | 是冬天到了吗,好冷www |
|
|
43
|
+
| 10 ~ 20 | 温度非常舒适,大家继续努力~ |
|
|
44
|
+
| 20 ~ 30 | 群热度达到最佳状态! |
|
|
45
|
+
| 30 ~ 39 | 好热,群主快开空调! |
|
|
46
|
+
| ≥ 39 | 请发送高温补贴喵。。 |
|
|
47
|
+
|
|
48
|
+
## 安装
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
nb plugin install nonebot-plugin-group-heat
|
|
52
|
+
pip install nonebot-plugin-group-heat(也可以)
|
|
53
|
+
|
|
54
|
+
## 使用
|
|
55
|
+
在群聊中发送以下命令:
|
|
56
|
+
|
|
57
|
+
/群热度 - 查询过去30分钟的群热度
|
|
58
|
+
|
|
59
|
+
/昨日热度图 - 获取昨日热度折线图
|
|
60
|
+
|
|
61
|
+
## 开源协议
|
|
62
|
+
MIT
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# nonebot-plugin-group-heat
|
|
2
|
+
|
|
3
|
+
群热度统计插件 for NoneBot2
|
|
4
|
+
|
|
5
|
+
## 功能
|
|
6
|
+
|
|
7
|
+
- `/群热度` - 获取过去30分钟的群热度值,附带 bot 评价
|
|
8
|
+
- `/昨日热度图` - 生成昨日每30分钟的热度折线图,并显示平均热度
|
|
9
|
+
|
|
10
|
+
## 热度计算规则
|
|
11
|
+
|
|
12
|
+
| 消息类型 | 热度值 |
|
|
13
|
+
|---------|--------|
|
|
14
|
+
| 文本消息 | +0.05 |
|
|
15
|
+
| 表情包 | +0.20 |
|
|
16
|
+
| 文件(图片/视频/语音等) | +0.30 |
|
|
17
|
+
| 其他消息 | 不计入 |
|
|
18
|
+
|
|
19
|
+
- 每个统计周期的初始热度为 -10°
|
|
20
|
+
|
|
21
|
+
## 评价机制
|
|
22
|
+
|
|
23
|
+
| 热度范围 | 评价 |
|
|
24
|
+
|---------|------|
|
|
25
|
+
| < 0 | 群成冰块啦,群主快开暖气 |
|
|
26
|
+
| 0 ~ 10 | 是冬天到了吗,好冷www |
|
|
27
|
+
| 10 ~ 20 | 温度非常舒适,大家继续努力~ |
|
|
28
|
+
| 20 ~ 30 | 群热度达到最佳状态! |
|
|
29
|
+
| 30 ~ 39 | 好热,群主快开空调! |
|
|
30
|
+
| ≥ 39 | 请发送高温补贴喵。。 |
|
|
31
|
+
|
|
32
|
+
## 安装
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
nb plugin install nonebot-plugin-group-heat
|
|
36
|
+
pip install nonebot-plugin-group-heat(也可以)
|
|
37
|
+
|
|
38
|
+
## 使用
|
|
39
|
+
在群聊中发送以下命令:
|
|
40
|
+
|
|
41
|
+
/群热度 - 查询过去30分钟的群热度
|
|
42
|
+
|
|
43
|
+
/昨日热度图 - 获取昨日热度折线图
|
|
44
|
+
|
|
45
|
+
## 开源协议
|
|
46
|
+
MIT
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "nonebot-plugin-group-heat"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "群热度统计插件 - 实时查询群内热度,生成昨日热度折线图"
|
|
9
|
+
authors = [{name = "Wojusensei", email = "3442006415@qq.com"}]
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
]
|
|
15
|
+
dependencies = [
|
|
16
|
+
"nonebot2>=2.3.0",
|
|
17
|
+
"nonebot-adapter-onebot>=2.0.0",
|
|
18
|
+
"nonebot-plugin-localstore>=0.5.0",
|
|
19
|
+
"matplotlib>=3.5.0",
|
|
20
|
+
"numpy>=1.21.0",
|
|
21
|
+
]
|
|
22
|
+
requires-python = ">=3.9"
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://github.com/Wojusensei/nonebot-plugin-group-heat"
|
|
26
|
+
|
|
27
|
+
[tool.setuptools]
|
|
28
|
+
packages = ["nonebot_plugin_group_heat"]
|
|
29
|
+
package-dir = {"" = "src"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
from nonebot.plugin import PluginMetadata
|
|
2
|
+
from nonebot.adapters.onebot.v11 import Event, Bot, MessageSegment
|
|
3
|
+
from nonebot.adapters.onebot.v11.event import GroupMessageEvent
|
|
4
|
+
from .config import Config
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
__plugin_meta__ = PluginMetadata(
|
|
8
|
+
name="群热度统计",
|
|
9
|
+
description="统计群内热度,支持实时查询和昨日热度图",
|
|
10
|
+
usage=(
|
|
11
|
+
"/群热度 - 获取过去30分钟的群热度\n"
|
|
12
|
+
"/昨日热度图 - 获取昨日每30分钟的热度折线图和平均热度"
|
|
13
|
+
),
|
|
14
|
+
type="application",
|
|
15
|
+
homepage="https://github.com/Wojusensei/nonebot-plugin-group-heat",
|
|
16
|
+
config=Config,
|
|
17
|
+
supported_adapters={"~onebot.v11"},
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# 延迟导入其他需要 NoneBot 初始化的模块
|
|
22
|
+
_imported = False
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _import_all():
|
|
26
|
+
global _imported
|
|
27
|
+
if _imported:
|
|
28
|
+
return
|
|
29
|
+
global re, datetime, on_command, on_message, get_driver, CommandArg, logger
|
|
30
|
+
global init_db, add_message, get_recent_heat, get_yesterday_heat
|
|
31
|
+
global draw_heat_line, get_heat_comment
|
|
32
|
+
|
|
33
|
+
import re
|
|
34
|
+
from datetime import datetime
|
|
35
|
+
from nonebot import on_command, on_message, get_driver
|
|
36
|
+
from nonebot.params import CommandArg
|
|
37
|
+
from nonebot.log import logger
|
|
38
|
+
|
|
39
|
+
from .database import init_db, add_message, get_recent_heat, get_yesterday_heat
|
|
40
|
+
from .heat_image import draw_heat_line, get_heat_comment
|
|
41
|
+
|
|
42
|
+
_imported = True
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
async def get_message_type(event: Event) -> str:
|
|
46
|
+
msg = event.get_message()
|
|
47
|
+
for seg in msg:
|
|
48
|
+
if seg.type == "text":
|
|
49
|
+
return "text"
|
|
50
|
+
elif seg.type == "face":
|
|
51
|
+
return "sticker"
|
|
52
|
+
elif seg.type in ["file", "image", "record", "video"]:
|
|
53
|
+
return "file"
|
|
54
|
+
return "other"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
_import_all()
|
|
59
|
+
driver = get_driver()
|
|
60
|
+
|
|
61
|
+
@driver.on_startup
|
|
62
|
+
async def startup():
|
|
63
|
+
await init_db()
|
|
64
|
+
logger.info("群热度插件数据库初始化完成")
|
|
65
|
+
except ValueError:
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
_import_all()
|
|
71
|
+
msg_recorder = on_message(priority=1, block=False)
|
|
72
|
+
|
|
73
|
+
@msg_recorder.handle()
|
|
74
|
+
async def record_message(bot: Bot, event: Event):
|
|
75
|
+
if not isinstance(event, GroupMessageEvent):
|
|
76
|
+
return
|
|
77
|
+
group_id = event.group_id
|
|
78
|
+
user_id = event.user_id
|
|
79
|
+
msg_type = await get_message_type(event)
|
|
80
|
+
timestamp = datetime.now().timestamp()
|
|
81
|
+
await add_message(group_id, user_id, msg_type, timestamp)
|
|
82
|
+
except ValueError:
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
_import_all()
|
|
88
|
+
heat_cmd = on_command("/群热度", aliases={"群热度"}, priority=10, block=True)
|
|
89
|
+
|
|
90
|
+
@heat_cmd.handle()
|
|
91
|
+
async def handle_heat(event: Event):
|
|
92
|
+
if not isinstance(event, GroupMessageEvent):
|
|
93
|
+
await heat_cmd.finish("该命令仅支持群聊")
|
|
94
|
+
group_id = event.group_id
|
|
95
|
+
try:
|
|
96
|
+
heat = await get_recent_heat(group_id, minutes=30)
|
|
97
|
+
comment = get_heat_comment(heat)
|
|
98
|
+
await heat_cmd.finish(f"过去30分钟的群热度:{heat:.2f}°\n{comment}")
|
|
99
|
+
except Exception as e:
|
|
100
|
+
logger.error(f"获取群热度失败: {e}")
|
|
101
|
+
await heat_cmd.finish("获取热度失败,请稍后再试")
|
|
102
|
+
except ValueError:
|
|
103
|
+
pass
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
_import_all()
|
|
108
|
+
yesterday_cmd = on_command("/昨日热度图", aliases={"昨日热度图"}, priority=10, block=True)
|
|
109
|
+
|
|
110
|
+
@yesterday_cmd.handle()
|
|
111
|
+
async def handle_yesterday(event: Event):
|
|
112
|
+
if not isinstance(event, GroupMessageEvent):
|
|
113
|
+
await yesterday_cmd.finish("该命令仅支持群聊")
|
|
114
|
+
group_id = event.group_id
|
|
115
|
+
try:
|
|
116
|
+
heat_values, time_labels, avg_heat = await get_yesterday_heat(group_id)
|
|
117
|
+
if not heat_values:
|
|
118
|
+
await yesterday_cmd.finish("暂无昨日数据,请明天再来~")
|
|
119
|
+
img_path = draw_heat_line(heat_values, time_labels, avg_heat)
|
|
120
|
+
comment = get_heat_comment(avg_heat)
|
|
121
|
+
msg = f"昨日群平均热度:{avg_heat:.2f}°\n{comment}"
|
|
122
|
+
await yesterday_cmd.send(MessageSegment.image(img_path))
|
|
123
|
+
await yesterday_cmd.finish(msg)
|
|
124
|
+
except Exception as e:
|
|
125
|
+
logger.error(f"生成昨日热度图失败: {e}")
|
|
126
|
+
await yesterday_cmd.finish("生成热度图失败,请稍后再试")
|
|
127
|
+
except ValueError:
|
|
128
|
+
pass
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import sqlite3
|
|
2
|
+
import asyncio
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from datetime import datetime, timedelta
|
|
5
|
+
from typing import List, Tuple
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_data_dir():
|
|
9
|
+
from nonebot_plugin_localstore import get_data_dir as _get_data_dir
|
|
10
|
+
return _get_data_dir("nonebot_plugin_group_heat")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_db_path():
|
|
14
|
+
data_dir = get_data_dir()
|
|
15
|
+
data_dir.mkdir(parents=True, exist_ok=True)
|
|
16
|
+
return data_dir / "heat.db"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
async def init_db():
|
|
20
|
+
def _init():
|
|
21
|
+
conn = sqlite3.connect(str(get_db_path()))
|
|
22
|
+
c = conn.cursor()
|
|
23
|
+
c.execute('''
|
|
24
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
25
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
26
|
+
group_id INTEGER NOT NULL,
|
|
27
|
+
user_id INTEGER NOT NULL,
|
|
28
|
+
msg_type TEXT NOT NULL,
|
|
29
|
+
timestamp REAL NOT NULL
|
|
30
|
+
)
|
|
31
|
+
''')
|
|
32
|
+
c.execute('CREATE INDEX IF NOT EXISTS idx_group_time ON messages (group_id, timestamp)')
|
|
33
|
+
conn.commit()
|
|
34
|
+
conn.close()
|
|
35
|
+
await asyncio.get_event_loop().run_in_executor(None, _init)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
async def add_message(group_id: int, user_id: int, msg_type: str, timestamp: float):
|
|
39
|
+
def _add():
|
|
40
|
+
conn = sqlite3.connect(str(get_db_path()))
|
|
41
|
+
c = conn.cursor()
|
|
42
|
+
c.execute(
|
|
43
|
+
"INSERT INTO messages (group_id, user_id, msg_type, timestamp) VALUES (?, ?, ?, ?)",
|
|
44
|
+
(group_id, user_id, msg_type, timestamp)
|
|
45
|
+
)
|
|
46
|
+
conn.commit()
|
|
47
|
+
conn.close()
|
|
48
|
+
await asyncio.get_event_loop().run_in_executor(None, _add)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
async def get_recent_heat(group_id: int, minutes: int = 30) -> float:
|
|
52
|
+
now = datetime.now().timestamp()
|
|
53
|
+
start = now - minutes * 60
|
|
54
|
+
|
|
55
|
+
def _calc():
|
|
56
|
+
conn = sqlite3.connect(str(get_db_path()))
|
|
57
|
+
c = conn.cursor()
|
|
58
|
+
c.execute('SELECT msg_type FROM messages WHERE group_id = ? AND timestamp >= ?', (group_id, start))
|
|
59
|
+
rows = c.fetchall()
|
|
60
|
+
conn.close()
|
|
61
|
+
heat = -10.0
|
|
62
|
+
for row in rows:
|
|
63
|
+
msg_type = row[0]
|
|
64
|
+
if msg_type == 'text':
|
|
65
|
+
heat += 0.05
|
|
66
|
+
elif msg_type == 'sticker':
|
|
67
|
+
heat += 0.2
|
|
68
|
+
elif msg_type == 'file':
|
|
69
|
+
heat += 0.3
|
|
70
|
+
return heat
|
|
71
|
+
return await asyncio.get_event_loop().run_in_executor(None, _calc)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
async def get_yesterday_heat(group_id: int) -> Tuple[List[float], List[str], float]:
|
|
75
|
+
now = datetime.now()
|
|
76
|
+
yesterday_start = now.replace(hour=0, minute=0, second=0, microsecond=0) - timedelta(days=1)
|
|
77
|
+
yesterday_end = yesterday_start + timedelta(days=1)
|
|
78
|
+
|
|
79
|
+
intervals = []
|
|
80
|
+
current = yesterday_start
|
|
81
|
+
while current < yesterday_end:
|
|
82
|
+
intervals.append(current)
|
|
83
|
+
current += timedelta(minutes=30)
|
|
84
|
+
|
|
85
|
+
heat_values = []
|
|
86
|
+
time_labels = []
|
|
87
|
+
|
|
88
|
+
for interval_start in intervals:
|
|
89
|
+
interval_end = interval_start + timedelta(minutes=30)
|
|
90
|
+
start_ts = interval_start.timestamp()
|
|
91
|
+
end_ts = interval_end.timestamp()
|
|
92
|
+
|
|
93
|
+
def _calc_interval():
|
|
94
|
+
conn = sqlite3.connect(str(get_db_path()))
|
|
95
|
+
c = conn.cursor()
|
|
96
|
+
c.execute('SELECT msg_type FROM messages WHERE group_id = ? AND timestamp >= ? AND timestamp < ?',
|
|
97
|
+
(group_id, start_ts, end_ts))
|
|
98
|
+
rows = c.fetchall()
|
|
99
|
+
conn.close()
|
|
100
|
+
heat = -10.0
|
|
101
|
+
for row in rows:
|
|
102
|
+
t = row[0]
|
|
103
|
+
if t == 'text':
|
|
104
|
+
heat += 0.05
|
|
105
|
+
elif t == 'sticker':
|
|
106
|
+
heat += 0.2
|
|
107
|
+
elif t == 'file':
|
|
108
|
+
heat += 0.3
|
|
109
|
+
return heat
|
|
110
|
+
|
|
111
|
+
heat = await asyncio.get_event_loop().run_in_executor(None, _calc_interval)
|
|
112
|
+
heat_values.append(heat)
|
|
113
|
+
time_labels.append(interval_start.strftime("%H:%M"))
|
|
114
|
+
|
|
115
|
+
avg_heat = sum(heat_values) / len(heat_values) if heat_values else -10.0
|
|
116
|
+
return heat_values, time_labels, avg_heat
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import matplotlib
|
|
2
|
+
matplotlib.use('Agg')
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
import numpy as np
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import List
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_cache_dir():
|
|
10
|
+
from nonebot_plugin_localstore import get_cache_dir as _get_cache_dir
|
|
11
|
+
cache_dir = _get_cache_dir("nonebot_plugin_group_heat")
|
|
12
|
+
cache_dir.mkdir(parents=True, exist_ok=True)
|
|
13
|
+
return cache_dir
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def draw_heat_line(heat_values: List[float], time_labels: List[str], avg_heat: float) -> Path:
|
|
17
|
+
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei']
|
|
18
|
+
plt.rcParams['axes.unicode_minus'] = False
|
|
19
|
+
|
|
20
|
+
fig, ax = plt.subplots(figsize=(14, 6))
|
|
21
|
+
x = np.arange(len(heat_values))
|
|
22
|
+
|
|
23
|
+
ax.plot(x, heat_values, marker='o', linestyle='-', color='#FF6B6B', linewidth=2, markersize=6)
|
|
24
|
+
ax.fill_between(x, heat_values, -10, alpha=0.2, color='orange')
|
|
25
|
+
ax.axhline(y=avg_heat, color='blue', linestyle='--', linewidth=1.5, label=f'平均热度: {avg_heat:.2f}')
|
|
26
|
+
|
|
27
|
+
ax.set_xlabel('时间 (每30分钟)', fontsize=12)
|
|
28
|
+
ax.set_ylabel('热度值', fontsize=12)
|
|
29
|
+
ax.set_title('昨日群热度变化趋势图', fontsize=14, fontweight='bold')
|
|
30
|
+
|
|
31
|
+
tick_step = max(1, len(time_labels) // 12)
|
|
32
|
+
ax.set_xticks(x[::tick_step])
|
|
33
|
+
ax.set_xticklabels(time_labels[::tick_step], rotation=45, ha='right', fontsize=8)
|
|
34
|
+
|
|
35
|
+
ax.grid(True, alpha=0.3)
|
|
36
|
+
ax.legend(loc='upper right')
|
|
37
|
+
plt.tight_layout()
|
|
38
|
+
|
|
39
|
+
img_path = get_cache_dir() / "yesterday_heat.png"
|
|
40
|
+
plt.savefig(img_path, dpi=100, bbox_inches='tight')
|
|
41
|
+
plt.close(fig)
|
|
42
|
+
|
|
43
|
+
return img_path
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get_heat_comment(heat: float) -> str:
|
|
47
|
+
if heat < 0:
|
|
48
|
+
return "群成冰块啦,群主快开暖气"
|
|
49
|
+
elif heat < 10:
|
|
50
|
+
return "是冬天到了吗,好冷www"
|
|
51
|
+
elif heat < 20:
|
|
52
|
+
return "温度非常舒适,大家继续努力~"
|
|
53
|
+
elif heat < 30:
|
|
54
|
+
return "群热度达到最佳状态!"
|
|
55
|
+
elif heat < 39:
|
|
56
|
+
return "好热,群主快开空调!"
|
|
57
|
+
else:
|
|
58
|
+
return "请发送高温补贴喵。。"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nonebot-plugin-group-heat
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: 群热度统计插件 - 实时查询群内热度,生成昨日热度折线图
|
|
5
|
+
Author-email: Wojusensei <3442006415@qq.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Wojusensei/nonebot-plugin-group-heat
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Requires-Python: >=3.9
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: nonebot2>=2.3.0
|
|
12
|
+
Requires-Dist: nonebot-adapter-onebot>=2.0.0
|
|
13
|
+
Requires-Dist: nonebot-plugin-localstore>=0.5.0
|
|
14
|
+
Requires-Dist: matplotlib>=3.5.0
|
|
15
|
+
Requires-Dist: numpy>=1.21.0
|
|
16
|
+
|
|
17
|
+
# nonebot-plugin-group-heat
|
|
18
|
+
|
|
19
|
+
群热度统计插件 for NoneBot2
|
|
20
|
+
|
|
21
|
+
## 功能
|
|
22
|
+
|
|
23
|
+
- `/群热度` - 获取过去30分钟的群热度值,附带 bot 评价
|
|
24
|
+
- `/昨日热度图` - 生成昨日每30分钟的热度折线图,并显示平均热度
|
|
25
|
+
|
|
26
|
+
## 热度计算规则
|
|
27
|
+
|
|
28
|
+
| 消息类型 | 热度值 |
|
|
29
|
+
|---------|--------|
|
|
30
|
+
| 文本消息 | +0.05 |
|
|
31
|
+
| 表情包 | +0.20 |
|
|
32
|
+
| 文件(图片/视频/语音等) | +0.30 |
|
|
33
|
+
| 其他消息 | 不计入 |
|
|
34
|
+
|
|
35
|
+
- 每个统计周期的初始热度为 -10°
|
|
36
|
+
|
|
37
|
+
## 评价机制
|
|
38
|
+
|
|
39
|
+
| 热度范围 | 评价 |
|
|
40
|
+
|---------|------|
|
|
41
|
+
| < 0 | 群成冰块啦,群主快开暖气 |
|
|
42
|
+
| 0 ~ 10 | 是冬天到了吗,好冷www |
|
|
43
|
+
| 10 ~ 20 | 温度非常舒适,大家继续努力~ |
|
|
44
|
+
| 20 ~ 30 | 群热度达到最佳状态! |
|
|
45
|
+
| 30 ~ 39 | 好热,群主快开空调! |
|
|
46
|
+
| ≥ 39 | 请发送高温补贴喵。。 |
|
|
47
|
+
|
|
48
|
+
## 安装
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
nb plugin install nonebot-plugin-group-heat
|
|
52
|
+
pip install nonebot-plugin-group-heat(也可以)
|
|
53
|
+
|
|
54
|
+
## 使用
|
|
55
|
+
在群聊中发送以下命令:
|
|
56
|
+
|
|
57
|
+
/群热度 - 查询过去30分钟的群热度
|
|
58
|
+
|
|
59
|
+
/昨日热度图 - 获取昨日热度折线图
|
|
60
|
+
|
|
61
|
+
## 开源协议
|
|
62
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/nonebot_plugin_group_heat/__init__.py
|
|
4
|
+
src/nonebot_plugin_group_heat/config.py
|
|
5
|
+
src/nonebot_plugin_group_heat/database.py
|
|
6
|
+
src/nonebot_plugin_group_heat/heat_image.py
|
|
7
|
+
src/nonebot_plugin_group_heat.egg-info/PKG-INFO
|
|
8
|
+
src/nonebot_plugin_group_heat.egg-info/SOURCES.txt
|
|
9
|
+
src/nonebot_plugin_group_heat.egg-info/dependency_links.txt
|
|
10
|
+
src/nonebot_plugin_group_heat.egg-info/requires.txt
|
|
11
|
+
src/nonebot_plugin_group_heat.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
nonebot_plugin_group_heat
|