nonebot-plugin-R6States 1.1.0__tar.gz → 1.1.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_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/PKG-INFO +18 -29
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/README.md +17 -28
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/pyproject.toml +1 -1
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/src/nonebot_plugin_R6States/__init__.py +5 -1
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/src/nonebot_plugin_R6States/config.py +4 -0
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/src/nonebot_plugin_R6States/formatter.py +17 -1
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/src/nonebot_plugin_R6States/r6data.py +1 -25
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/src/nonebot_plugin_R6States/renderer.py +8 -1
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/src/nonebot_plugin_R6States/service.py +7 -4
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/LICENSE +0 -0
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/src/nonebot_plugin_R6States/assets/MonaSans.ttf +0 -0
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/src/nonebot_plugin_R6States/assets/NotoSansSC.ttf +0 -0
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/src/nonebot_plugin_R6States/cache.py +0 -0
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/src/nonebot_plugin_R6States/config_mannger.py +0 -0
- {nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/src/nonebot_plugin_R6States/storage.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: nonebot-plugin-R6States
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.1
|
|
4
4
|
Summary: 查询指定玩家的各项数据
|
|
5
5
|
Author-Email: Siornya <wxh200607@outlook.com>
|
|
6
6
|
License: MIT
|
|
@@ -15,53 +15,42 @@ Description-Content-Type: text/markdown
|
|
|
15
15
|
|
|
16
16
|
一个基于 **NoneBot2** 的《彩虹六号:围攻》战绩查询插件
|
|
17
17
|
|
|
18
|
-
---
|
|
19
|
-
|
|
20
18
|
## 功能特性
|
|
21
19
|
|
|
22
20
|
* ✅ 通过 QQ 指令查询 R6 玩家战绩
|
|
23
21
|
* ✅ 支持 **单人查询 / 多人查询**
|
|
24
22
|
* ✅ 数据源自 [R6Data API](https://r6data.com/)
|
|
25
|
-
* ✅
|
|
23
|
+
* ✅ 玩家数据缓存,降低 API 用量
|
|
26
24
|
* ✅ 数据分析功能
|
|
27
25
|
* ⚙️ 地图筛选 `-m / --map`
|
|
28
26
|
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## 参考运行环境
|
|
32
|
-
|
|
33
|
-
* **Python 3.12**
|
|
34
|
-
* **NoneBot2**
|
|
35
|
-
* **OneBot v11**
|
|
36
|
-
* **NapCat(反向 WebSocket)**
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
27
|
## Usage 使用说明
|
|
41
28
|
|
|
42
29
|
### 安装
|
|
43
30
|
|
|
44
|
-
|
|
31
|
+
- (推荐)使用nb安装`nb plugin install nonebot-plugin-R6States`
|
|
32
|
+
- 使用pip安装`pip install nonebot-plugin-R6States`
|
|
33
|
+
- 下载release放到`plugins`文件夹中
|
|
45
34
|
|
|
46
|
-
###
|
|
35
|
+
### 指令
|
|
47
36
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
```
|
|
37
|
+
数据查询:`/R6 <player_ids...>`
|
|
38
|
+
其他指令与帮助信息:`/R6help`
|
|
51
39
|
|
|
52
|
-
|
|
40
|
+
## 环境配置
|
|
53
41
|
|
|
54
|
-
|
|
55
|
-
/R6help
|
|
56
|
-
```
|
|
42
|
+
CURRENT_SEASON = "Y11S2"
|
|
57
43
|
|
|
58
|
-
|
|
44
|
+
R6_OUTPUT_IMAGE = True
|
|
59
45
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
46
|
+
R6_CACHE_MINUTES = 45
|
|
47
|
+
|
|
48
|
+
## 参考运行环境
|
|
63
49
|
|
|
64
|
-
|
|
50
|
+
* **Python 3.12**
|
|
51
|
+
* **NoneBot2**
|
|
52
|
+
* **OneBot v11**
|
|
53
|
+
* **NapCat(反向 WebSocket)**
|
|
65
54
|
|
|
66
55
|
## 特别提醒
|
|
67
56
|
|
|
@@ -2,53 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
一个基于 **NoneBot2** 的《彩虹六号:围攻》战绩查询插件
|
|
4
4
|
|
|
5
|
-
---
|
|
6
|
-
|
|
7
5
|
## 功能特性
|
|
8
6
|
|
|
9
7
|
* ✅ 通过 QQ 指令查询 R6 玩家战绩
|
|
10
8
|
* ✅ 支持 **单人查询 / 多人查询**
|
|
11
9
|
* ✅ 数据源自 [R6Data API](https://r6data.com/)
|
|
12
|
-
* ✅
|
|
10
|
+
* ✅ 玩家数据缓存,降低 API 用量
|
|
13
11
|
* ✅ 数据分析功能
|
|
14
12
|
* ⚙️ 地图筛选 `-m / --map`
|
|
15
13
|
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## 参考运行环境
|
|
19
|
-
|
|
20
|
-
* **Python 3.12**
|
|
21
|
-
* **NoneBot2**
|
|
22
|
-
* **OneBot v11**
|
|
23
|
-
* **NapCat(反向 WebSocket)**
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
14
|
## Usage 使用说明
|
|
28
15
|
|
|
29
16
|
### 安装
|
|
30
17
|
|
|
31
|
-
|
|
18
|
+
- (推荐)使用nb安装`nb plugin install nonebot-plugin-R6States`
|
|
19
|
+
- 使用pip安装`pip install nonebot-plugin-R6States`
|
|
20
|
+
- 下载release放到`plugins`文件夹中
|
|
32
21
|
|
|
33
|
-
###
|
|
22
|
+
### 指令
|
|
34
23
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
```
|
|
24
|
+
数据查询:`/R6 <player_ids...>`
|
|
25
|
+
其他指令与帮助信息:`/R6help`
|
|
38
26
|
|
|
39
|
-
|
|
27
|
+
## 环境配置
|
|
40
28
|
|
|
41
|
-
|
|
42
|
-
/R6help
|
|
43
|
-
```
|
|
29
|
+
CURRENT_SEASON = "Y11S2"
|
|
44
30
|
|
|
45
|
-
|
|
31
|
+
R6_OUTPUT_IMAGE = True
|
|
46
32
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
33
|
+
R6_CACHE_MINUTES = 45
|
|
34
|
+
|
|
35
|
+
## 参考运行环境
|
|
50
36
|
|
|
51
|
-
|
|
37
|
+
* **Python 3.12**
|
|
38
|
+
* **NoneBot2**
|
|
39
|
+
* **OneBot v11**
|
|
40
|
+
* **NapCat(反向 WebSocket)**
|
|
52
41
|
|
|
53
42
|
## 特别提醒
|
|
54
43
|
|
|
@@ -104,9 +104,13 @@ async def _(event: MessageEvent, args: Message = CommandArg()):
|
|
|
104
104
|
await r6.send(f"⚠️ 当前 API Key 已设置 {age:.0f} 天,可能已过期,如查询失败请 /r6key 重设")
|
|
105
105
|
|
|
106
106
|
# 并发取数(单个失败不连累其余),再按原顺序逐个发送
|
|
107
|
+
ttl = plugin_config.r6_cache_minutes * 60
|
|
107
108
|
results = await asyncio.gather(
|
|
108
109
|
*(
|
|
109
|
-
get_full_stats(
|
|
110
|
+
get_full_stats(
|
|
111
|
+
pid, scopes, platform,
|
|
112
|
+
season_year=plugin_config.current_season, ttl=ttl,
|
|
113
|
+
)
|
|
110
114
|
for pid in tokens
|
|
111
115
|
),
|
|
112
116
|
return_exceptions=True,
|
|
@@ -7,11 +7,23 @@ fullStats 顶层有三块:
|
|
|
7
7
|
"""
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
from typing import Any
|
|
10
|
+
from typing import Any, Optional
|
|
11
|
+
from datetime import timezone, datetime, timedelta
|
|
11
12
|
|
|
12
13
|
#: 默认展示出场最多的前 N 个干员
|
|
13
14
|
TOP_N = 8
|
|
14
15
|
|
|
16
|
+
#: 展示时间用东八区(CN bot)
|
|
17
|
+
_CST = timezone(timedelta(hours=8))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def fetched_label(data: dict[str, Any]) -> Optional[str]:
|
|
21
|
+
"""数据实际取回时刻(随缓存保存),格式 '更新 06-14 17:30';无则返回 None。"""
|
|
22
|
+
ts = data.get("_fetched_at")
|
|
23
|
+
if not ts:
|
|
24
|
+
return None
|
|
25
|
+
return "更新 " + datetime.fromtimestamp(ts, _CST).strftime("%m-%d %H:%M")
|
|
26
|
+
|
|
15
27
|
_SIDE_CN = {"Attacker": "攻", "Defender": "防"}
|
|
16
28
|
_BOARD_CN = {
|
|
17
29
|
"ranked": "排位", "casual": "休闲", "standard": "标准",
|
|
@@ -103,4 +115,8 @@ def format_full_stats(player_id: str, data: dict[str, Any], top_n: int = TOP_N)
|
|
|
103
115
|
|
|
104
116
|
if not board_lines and not operators:
|
|
105
117
|
return f"🎯 {handle}:没有查询到数据"
|
|
118
|
+
|
|
119
|
+
label = fetched_label(data)
|
|
120
|
+
if label:
|
|
121
|
+
lines.append(label)
|
|
106
122
|
return "\n".join(lines)
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
"""
|
|
2
|
-
r6data.
|
|
2
|
+
对 https://api.r6data.com/api 的封装,从官方 npm 包 `r6-data.js` 移植修改而来。
|
|
3
3
|
|
|
4
|
-
对 https://api.r6data.com/api 的薄封装,异步 (httpx)。从官方 npm 包
|
|
5
|
-
`r6-data.js` 移植而来;源码层逻辑长期稳定,只有下面 ``易变常量`` 区域会
|
|
6
|
-
随赛季/平台调整,跟新版时基本只动那几行。
|
|
7
|
-
|
|
8
|
-
依赖: pip install httpx
|
|
9
4
|
用法:
|
|
10
5
|
from .r6data import R6Client
|
|
11
6
|
|
|
@@ -13,31 +8,12 @@ r6data.py — Python 移植版 r6-data.js (Players + Game)
|
|
|
13
8
|
info = await r6.players.get_account_info("PlayerName", "uplay")
|
|
14
9
|
ops = await r6.game.get_operators(side="attacker")
|
|
15
10
|
await r6.aclose()
|
|
16
|
-
|
|
17
|
-
NoneBot 启动时检查版本(贴进插件 __init__.py):
|
|
18
|
-
from nonebot import get_driver, logger
|
|
19
|
-
from .r6data import check_latest_version, BASED_ON_VERSION
|
|
20
|
-
|
|
21
|
-
@get_driver().on_startup
|
|
22
|
-
async def _r6_version_check():
|
|
23
|
-
latest = await check_latest_version()
|
|
24
|
-
if latest and latest != BASED_ON_VERSION:
|
|
25
|
-
logger.warning(
|
|
26
|
-
f"r6data 移植基于 r6-data.js@{BASED_ON_VERSION}, "
|
|
27
|
-
f"上游最新为 {latest},建议核对是否有接口变化。"
|
|
28
|
-
)
|
|
29
11
|
"""
|
|
30
12
|
|
|
31
13
|
from __future__ import annotations
|
|
32
|
-
|
|
33
14
|
from typing import Any, Optional, Sequence, Mapping
|
|
34
|
-
|
|
35
15
|
import httpx
|
|
36
16
|
|
|
37
|
-
# ──────────────────────────────────────────────────────────────────────────
|
|
38
|
-
# 易变常量 —— 跟随上游版本时,基本只需要改这一段
|
|
39
|
-
# ──────────────────────────────────────────────────────────────────────────
|
|
40
|
-
|
|
41
17
|
#: 本移植对标的 r6-data.js 版本。启动时与 npm 最新版比对。
|
|
42
18
|
BASED_ON_VERSION = "3.1.7"
|
|
43
19
|
|
|
@@ -6,7 +6,7 @@ from pathlib import Path
|
|
|
6
6
|
|
|
7
7
|
from PIL import Image, ImageDraw, ImageFont
|
|
8
8
|
|
|
9
|
-
from .formatter import _format_boards
|
|
9
|
+
from .formatter import _format_boards, fetched_label
|
|
10
10
|
|
|
11
11
|
_ASSETS = Path(__file__).parent / "assets"
|
|
12
12
|
_MONA = str(_ASSETS / "MonaSans.ttf")
|
|
@@ -188,6 +188,13 @@ def render_full_stats(player_id: str, data: dict[str, Any]) -> bytes:
|
|
|
188
188
|
_draw(draw, p, y, "没有查询到数据", 22, _GRAY)
|
|
189
189
|
y += _font(_NOTO, 22).getmetrics()[1]
|
|
190
190
|
|
|
191
|
+
# 底部:数据实际取回时间(右下角,小字)
|
|
192
|
+
label = fetched_label(data)
|
|
193
|
+
if label:
|
|
194
|
+
y += 14 * _SCALE + _ascent(14)
|
|
195
|
+
_draw_right(draw, rcol, y, label, 14, _DIM)
|
|
196
|
+
y += _font(_NOTO, 14).getmetrics()[1]
|
|
197
|
+
|
|
191
198
|
img = img.crop((0, 0, _W, y + _PAD))
|
|
192
199
|
buf = BytesIO()
|
|
193
200
|
img.save(buf, format="PNG")
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
"""
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
+
import time
|
|
9
10
|
from typing import Any, Optional
|
|
10
11
|
|
|
11
12
|
import httpx
|
|
@@ -15,9 +16,6 @@ from .storage import PLAYER_CACHE_FILE
|
|
|
15
16
|
from .r6data import R6Client, R6APIError
|
|
16
17
|
from .config_mannger import resolve_apikey
|
|
17
18
|
|
|
18
|
-
#: 玩家快照属于会变的数据,缓存 45 分钟即可显著降低 API 用量。
|
|
19
|
-
FULL_STATS_TTL = 45 * 60
|
|
20
|
-
|
|
21
19
|
VALID_PLATFORMS = ("uplay", "psn", "xbl")
|
|
22
20
|
|
|
23
21
|
#: 免费申请 api-key 的入口,附在缺/失效提示里
|
|
@@ -57,6 +55,8 @@ async def get_full_stats(
|
|
|
57
55
|
platform: str = "uplay",
|
|
58
56
|
season_year: str | None = None,
|
|
59
57
|
modes: str | None = None,
|
|
58
|
+
*,
|
|
59
|
+
ttl: float,
|
|
60
60
|
) -> dict[str, Any]:
|
|
61
61
|
if platform not in VALID_PLATFORMS:
|
|
62
62
|
raise ServiceError(f"平台无效,可选:{', '.join(VALID_PLATFORMS)}")
|
|
@@ -85,5 +85,8 @@ async def get_full_stats(
|
|
|
85
85
|
except Exception as e: # noqa: BLE001 - 网络等异常统一兜底
|
|
86
86
|
raise ServiceError(f"请求失败:{type(e).__name__}") from e
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
# 打上实际取数时间,随数据一起缓存(缓存命中时展示的就是这个原始取数时刻)
|
|
89
|
+
if isinstance(data, dict):
|
|
90
|
+
data["_fetched_at"] = time.time()
|
|
91
|
+
await _cache.set(cache_key, data, ttl)
|
|
89
92
|
return data
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nonebot_plugin_r6states-1.1.0 → nonebot_plugin_r6states-1.1.1}/src/nonebot_plugin_R6States/cache.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|