nonebot-plugin-osubot 6.19.0__py3-none-any.whl → 6.20.1__py3-none-any.whl
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.
Potentially problematic release.
This version of nonebot-plugin-osubot might be problematic. Click here for more details.
- nonebot_plugin_osubot/api.py +86 -39
- nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/PalpableCatchHitObject.js +21 -2
- nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/bananashower.js +1 -0
- nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/catch.js +62 -11
- nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/juicestream.js +6 -1
- nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/curve/curve.js +21 -1
- nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/slider.js +2 -0
- nonebot_plugin_osubot/draw/utils.py +6 -4
- nonebot_plugin_osubot/matcher/bp.py +8 -8
- {nonebot_plugin_osubot-6.19.0.dist-info → nonebot_plugin_osubot-6.20.1.dist-info}/METADATA +1 -1
- {nonebot_plugin_osubot-6.19.0.dist-info → nonebot_plugin_osubot-6.20.1.dist-info}/RECORD +12 -12
- {nonebot_plugin_osubot-6.19.0.dist-info → nonebot_plugin_osubot-6.20.1.dist-info}/WHEEL +0 -0
nonebot_plugin_osubot/api.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import random
|
|
2
3
|
from io import BytesIO
|
|
3
4
|
from urllib.parse import urlencode
|
|
@@ -73,6 +74,58 @@ async def get_headers() -> dict[str, str]:
|
|
|
73
74
|
return {"Authorization": f"Bearer {token}", "x-api-version": "20220705"}
|
|
74
75
|
|
|
75
76
|
|
|
77
|
+
async def fetch_score_batch(
|
|
78
|
+
uid: Union[int, str],
|
|
79
|
+
mode: str,
|
|
80
|
+
scope: str,
|
|
81
|
+
batch_size: int,
|
|
82
|
+
offset: int,
|
|
83
|
+
legacy_only: bool,
|
|
84
|
+
include_failed: bool,
|
|
85
|
+
) -> list[UnifiedScore]:
|
|
86
|
+
"""并发获取单次批次数据"""
|
|
87
|
+
url = (
|
|
88
|
+
f"{api}/users/{uid}/scores/{scope}?mode={mode}&limit={batch_size}"
|
|
89
|
+
f"&offset={offset}&legacy_only={int(legacy_only)}"
|
|
90
|
+
f"&include_fails={int(include_failed)}"
|
|
91
|
+
)
|
|
92
|
+
data = await make_request(url, await get_headers(), "未找到该玩家BP")
|
|
93
|
+
if not data:
|
|
94
|
+
return []
|
|
95
|
+
scores = [NewScore(**i) for i in data]
|
|
96
|
+
return [
|
|
97
|
+
UnifiedScore(
|
|
98
|
+
mods=i.mods,
|
|
99
|
+
ruleset_id=i.ruleset_id,
|
|
100
|
+
rank=i.rank,
|
|
101
|
+
accuracy=i.accuracy * 100,
|
|
102
|
+
total_score=i.total_score,
|
|
103
|
+
ended_at=datetime.strptime(i.ended_at.replace("Z", ""), "%Y-%m-%dT%H:%M:%S") + timedelta(hours=8),
|
|
104
|
+
max_combo=i.max_combo,
|
|
105
|
+
statistics=i.statistics,
|
|
106
|
+
legacy_total_score=i.legacy_total_score,
|
|
107
|
+
passed=i.passed,
|
|
108
|
+
beatmap=UnifiedBeatmap(
|
|
109
|
+
id=i.beatmap_id,
|
|
110
|
+
set_id=i.beatmapset.id,
|
|
111
|
+
artist=i.beatmapset.artist,
|
|
112
|
+
title=i.beatmapset.title,
|
|
113
|
+
version=i.beatmap.version,
|
|
114
|
+
creator=i.beatmapset.creator,
|
|
115
|
+
total_length=i.beatmap.total_length,
|
|
116
|
+
mode=i.beatmap.mode_int,
|
|
117
|
+
bpm=i.beatmap.bpm,
|
|
118
|
+
cs=i.beatmap.cs,
|
|
119
|
+
ar=i.beatmap.ar,
|
|
120
|
+
hp=i.beatmap.drain,
|
|
121
|
+
od=i.beatmap.accuracy,
|
|
122
|
+
stars=i.beatmap.difficulty_rating,
|
|
123
|
+
),
|
|
124
|
+
)
|
|
125
|
+
for i in scores
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
|
|
76
129
|
async def get_user_scores(
|
|
77
130
|
uid: Union[int, str],
|
|
78
131
|
mode: str,
|
|
@@ -81,49 +134,43 @@ async def get_user_scores(
|
|
|
81
134
|
legacy_only: bool = 0,
|
|
82
135
|
include_failed: bool = True,
|
|
83
136
|
offset: int = 0,
|
|
84
|
-
limit: int =
|
|
137
|
+
limit: int = 200,
|
|
85
138
|
) -> list[UnifiedScore]:
|
|
86
139
|
if source == "osu":
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
od=i.beatmap.accuracy,
|
|
119
|
-
stars=i.beatmap.difficulty_rating,
|
|
120
|
-
),
|
|
121
|
-
)
|
|
122
|
-
for i in scores
|
|
123
|
-
]
|
|
124
|
-
return unified_scores
|
|
140
|
+
if limit <= 0:
|
|
141
|
+
return []
|
|
142
|
+
|
|
143
|
+
# 计算需要多少次请求
|
|
144
|
+
# 计算需要多少批次
|
|
145
|
+
batch_size = 100
|
|
146
|
+
total_batches = (limit + batch_size - 1) // batch_size # ceiling(limit/batch_size)
|
|
147
|
+
all_scores = []
|
|
148
|
+
# 分批并发请求
|
|
149
|
+
for batch_idx in range(0, total_batches, 2):
|
|
150
|
+
current_batches = range(batch_idx, min(batch_idx + 2, total_batches))
|
|
151
|
+
|
|
152
|
+
# 生成 tasks(并发执行)
|
|
153
|
+
tasks = []
|
|
154
|
+
for batch_n in current_batches:
|
|
155
|
+
offset = batch_n * batch_size
|
|
156
|
+
actual_batch_size = min(batch_size, limit - len(all_scores) - offset)
|
|
157
|
+
|
|
158
|
+
if actual_batch_size <= 0:
|
|
159
|
+
continue # 已获取足够数据
|
|
160
|
+
|
|
161
|
+
task = fetch_score_batch(uid, mode, scope, actual_batch_size, offset, legacy_only, include_failed)
|
|
162
|
+
tasks.append(task)
|
|
163
|
+
# 并发请求当前批次
|
|
164
|
+
batch_results = await asyncio.gather(*tasks)
|
|
165
|
+
|
|
166
|
+
for batch_scores in batch_results:
|
|
167
|
+
all_scores.extend(batch_scores)
|
|
168
|
+
if len(all_scores) >= limit:
|
|
169
|
+
return all_scores[:limit] # 提前终止
|
|
170
|
+
return all_scores[:limit]
|
|
125
171
|
|
|
126
172
|
elif source == "ppysb":
|
|
173
|
+
limit = min(limit, 100)
|
|
127
174
|
url = f"https://api.ppy.sb/v1/get_player_scores?scope={scope}&id={uid}&mode={FGM[mode]}&limit={limit}&include_failed={int(include_failed)}"
|
|
128
175
|
data = await make_request(url, {}, "未找到该玩家BP")
|
|
129
176
|
data = ScoresResponse(**data)
|
|
@@ -6,8 +6,24 @@ function PalpableCatchHitObject(data, beatmap) {
|
|
|
6
6
|
this.color = data.color;
|
|
7
7
|
this.radius = data.radius;
|
|
8
8
|
this.hyperDash = false;
|
|
9
|
+
this.edge = false;
|
|
9
10
|
this.XDistToNext = [1, 1, 1];
|
|
11
|
+
this.hitSound = data.hitSound || "0";
|
|
10
12
|
}
|
|
13
|
+
|
|
14
|
+
PalpableCatchHitObject.prototype.getHitsoundLabel = function (){
|
|
15
|
+
let hsLabels = [];
|
|
16
|
+
if (this.hitSound == null || this.hitSound == undefined || !this.hitSound) // hs = null | undifined | "" | "0"
|
|
17
|
+
return null;
|
|
18
|
+
else {
|
|
19
|
+
if (this.hitSound & 2) hsLabels.push("W");
|
|
20
|
+
if (this.hitSound & 8) hsLabels.push("C");
|
|
21
|
+
if (this.hitSound & 4) hsLabels.push("F");
|
|
22
|
+
if (hsLabels.length === 0) return null;
|
|
23
|
+
return hsLabels.join("|");
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
11
27
|
PalpableCatchHitObject.prototype.draw = function (time, ctx) {
|
|
12
28
|
var dt = this.time - time;
|
|
13
29
|
if (dt >= -this.beatmap.FALLOUT_TIME) {
|
|
@@ -24,7 +40,10 @@ PalpableCatchHitObject.prototype.draw2 = function (obj, SCALE, ctx, BORDER_WIDTH
|
|
|
24
40
|
if (this.hyperDash) this.drawDashCircle2({ x: obj.x + BORDER_WIDTH, y: obj.y + BORDER_HEIGHT }, SCALE, ctx);
|
|
25
41
|
this.drawCircle2({ x: obj.x + BORDER_WIDTH, y: obj.y + BORDER_HEIGHT }, SCALE, ctx);
|
|
26
42
|
}
|
|
27
|
-
if (combo)
|
|
43
|
+
if (combo) {
|
|
44
|
+
if (typeof(combo) === "number") this.drawCombo2({ x: obj.x + BORDER_WIDTH, y: obj.y + BORDER_HEIGHT }, SCALE, "x" + combo, ctx);
|
|
45
|
+
else this.drawCombo2({ x: obj.x + BORDER_WIDTH, y: obj.y + BORDER_HEIGHT }, SCALE, combo, ctx);
|
|
46
|
+
}
|
|
28
47
|
}
|
|
29
48
|
PalpableCatchHitObject.prototype.predraw2 = function (SCREENSHEIGHT, COLMARGIN, SCALE, offset) {
|
|
30
49
|
// 去除offset
|
|
@@ -83,7 +102,7 @@ PalpableCatchHitObject.prototype.drawCombo2 = function (position, SCALE, combo,
|
|
|
83
102
|
ctx.font = "normal 16px 'Segoe UI'";
|
|
84
103
|
ctx.textBaseline = "middle";
|
|
85
104
|
ctx.textAlign = "start";
|
|
86
|
-
ctx.fillText(
|
|
105
|
+
ctx.fillText(combo, position.x + this.radius * SCALE * 2, position.y);
|
|
87
106
|
ctx.restore();
|
|
88
107
|
};
|
|
89
108
|
PalpableCatchHitObject.prototype.drawBanana = function (position, ctx) {
|
|
@@ -150,6 +150,7 @@ function Catch(osu, mods) {
|
|
|
150
150
|
x: hitObject.position.x,
|
|
151
151
|
color: hitObject.color,
|
|
152
152
|
radius: this.circleRadius,
|
|
153
|
+
hitSound: hitObject.hitSound,
|
|
153
154
|
}, this);
|
|
154
155
|
|
|
155
156
|
this.palpableObjects.push(pch);
|
|
@@ -289,6 +290,8 @@ function Catch(osu, mods) {
|
|
|
289
290
|
else {
|
|
290
291
|
lastExcess = Math.clamp(distanceToHyper, 0, this.halfCatcherWidth);
|
|
291
292
|
//this.whiteDashes.push({ score: distanceToHyper, time: currentObject.time });
|
|
293
|
+
// 标注再加20像素就变红果的白果跳
|
|
294
|
+
if (distanceToNext > 2 * this.halfCatcherWidth && distanceToHyper < 20) currentObject.edge = true;
|
|
292
295
|
}
|
|
293
296
|
|
|
294
297
|
lastDirection = thisDirection;
|
|
@@ -357,7 +360,7 @@ Catch.prototype.draw = function (time, ctx) {
|
|
|
357
360
|
/**
|
|
358
361
|
* @param {number} SCALE 缩放大小(0.2=缩放为1/5)
|
|
359
362
|
* @param {number} SPEED 播放速度 DT=1.5 HT=0.75 在ctb不影响谱面,只影响时间和BPM标注
|
|
360
|
-
* @param {{
|
|
363
|
+
* @param {{showLabelType: number, distanceStart: number, distanceEnd: number, distanceType: number}} params 其他参数
|
|
361
364
|
*/
|
|
362
365
|
Catch.prototype.draw2 = function (SCALE, SPEED = 1, params = {}) {
|
|
363
366
|
// 初定每一列20个屏幕大小,不够换列
|
|
@@ -405,7 +408,7 @@ Catch.prototype.draw2 = function (SCALE, SPEED = 1, params = {}) {
|
|
|
405
408
|
if (this.TimingPoints[i].kiai) lastKiaiStart = this.TimingPoints[i].time - offset;
|
|
406
409
|
}
|
|
407
410
|
// 绿线在ctb无关紧要,正常模式不用加,标注距离时只加变化的
|
|
408
|
-
if (params.
|
|
411
|
+
if (params.showLabelType === 1) {
|
|
409
412
|
if (this.TimingPoints[i].parent) {
|
|
410
413
|
if (Math.abs(this.TimingPoints[i].sliderVelocity - lastSV) < 0.001) {
|
|
411
414
|
lastSV = this.TimingPoints[i].sliderVelocity;
|
|
@@ -679,16 +682,59 @@ Catch.prototype.draw2 = function (SCALE, SPEED = 1, params = {}) {
|
|
|
679
682
|
combo += 1;
|
|
680
683
|
}
|
|
681
684
|
// 借用combo位显示距离,省事!
|
|
682
|
-
if (params.
|
|
685
|
+
if (params.showLabelType === 1) {
|
|
683
686
|
if (objs[i].type === "Fruit" || objs[i].type === "Droplet") {
|
|
684
687
|
let distanceType = params.distanceType;
|
|
685
688
|
if (this.fullCatchObjects[i].XDistToNext[distanceType] >= params.distanceStart && this.fullCatchObjects[i].XDistToNext[distanceType] <= params.distanceEnd)
|
|
686
689
|
showCombo = this.fullCatchObjects[i].XDistToNext[distanceType];
|
|
687
690
|
}
|
|
688
691
|
}
|
|
692
|
+
// 借用combo位显示音效,省事!
|
|
693
|
+
else if (params.showLabelType === 2) {
|
|
694
|
+
if (objs[i].type === "Fruit" || objs[i].type === "Banana") {
|
|
695
|
+
showCombo = this.fullCatchObjects[i].getHitsoundLabel();
|
|
696
|
+
}
|
|
697
|
+
}
|
|
689
698
|
|
|
690
|
-
else if (combo > lastCombo && combo > 0 && combo % comboSplit === 0) showCombo = combo;
|
|
699
|
+
else if (combo > lastCombo && combo > 0 && (combo % comboSplit === 0 || this.fullCatchObjects[i].edge)) showCombo = combo;
|
|
691
700
|
this.fullCatchObjects[i].draw2(objs[i], SCALE, ctx2, BORDER_WIDTH, BORDER_HEIGHT, showCombo);
|
|
701
|
+
|
|
702
|
+
// 标注edge
|
|
703
|
+
if (this.fullCatchObjects[i].edge && i < this.fullCatchObjects.length - 1) {
|
|
704
|
+
ctx2.save();
|
|
705
|
+
ctx2.beginPath();
|
|
706
|
+
let _x1 = objs[i].x + BORDER_WIDTH;
|
|
707
|
+
let _y1 = objs[i].y + BORDER_HEIGHT;
|
|
708
|
+
let _x2 = objs[i+1].x + BORDER_WIDTH;
|
|
709
|
+
let _y2 = objs[i+1].y + BORDER_HEIGHT;
|
|
710
|
+
if (_y1 > _y2) {
|
|
711
|
+
ctx2.moveTo(_x1, _y1);
|
|
712
|
+
ctx2.lineTo(_x2, _y2);
|
|
713
|
+
}
|
|
714
|
+
// 不在同一轨道上
|
|
715
|
+
else if (_y1 < _y2) {
|
|
716
|
+
let line_end_x2 = _x2 - Beatmap.WIDTH * SCALE - 2 * COLMARGIN;
|
|
717
|
+
let line_end_y2 = _y2 + 2 * BORDER_HEIGHT - height;
|
|
718
|
+
let line_middle_y2 = BORDER_HEIGHT;
|
|
719
|
+
let line_middle_x2 = (line_end_x2 - _x1) * (line_end_y2 - line_middle_y2) / (_y1 - line_end_y2) + line_end_x2;
|
|
720
|
+
if (line_middle_x2) {
|
|
721
|
+
ctx2.moveTo(_x1, _y1);
|
|
722
|
+
ctx2.lineTo(line_middle_x2, line_middle_y2);
|
|
723
|
+
}
|
|
724
|
+
let line_start_x1 = _x1 + Beatmap.WIDTH * SCALE + 2 * COLMARGIN;
|
|
725
|
+
let line_start_y1 = _y1 + height - 2 * BORDER_HEIGHT;
|
|
726
|
+
let line_middle_y1 = height - BORDER_HEIGHT;
|
|
727
|
+
let line_middle_x1 = (_x2 - line_start_x1) * (_y2 - line_middle_y1) / (line_start_y1 - _y2) + _x2;
|
|
728
|
+
if (line_middle_x1) {
|
|
729
|
+
ctx2.moveTo(line_middle_x1, line_middle_y1);
|
|
730
|
+
ctx2.lineTo(_x2, _y2);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
ctx2.strokeStyle = '#fff';
|
|
734
|
+
ctx2.lineWidth = 3;
|
|
735
|
+
ctx2.stroke();
|
|
736
|
+
}
|
|
737
|
+
|
|
692
738
|
lastCombo = combo;
|
|
693
739
|
}
|
|
694
740
|
|
|
@@ -698,18 +744,23 @@ Catch.prototype.draw2 = function (SCALE, SPEED = 1, params = {}) {
|
|
|
698
744
|
extraBarTimes.map((_barTime) => {
|
|
699
745
|
let _objs = objs.filter((obj) => Math.abs(obj.time - _barTime * 1000) < EDGE_OFFSET);
|
|
700
746
|
_objs.map((_obj) => {
|
|
701
|
-
let
|
|
702
|
-
|
|
703
|
-
|
|
747
|
+
let label = null;
|
|
748
|
+
if (params.showLabelType === 1) {
|
|
749
|
+
let distanceType = params.distanceType;
|
|
750
|
+
label = this.fullCatchObjects[_obj.index].XDistToNext[distanceType];
|
|
751
|
+
if (label < params.distanceStart || label > params.distanceEnd) label = null;
|
|
752
|
+
}
|
|
753
|
+
else if (params.showLabelType === 2) {
|
|
754
|
+
label = this.fullCatchObjects[_obj.index].getHitsoundLabel();
|
|
755
|
+
}
|
|
756
|
+
|
|
704
757
|
if (_obj.y > SCREENSHEIGHT * SCALE - 5) {
|
|
705
758
|
// note靠近下边缘,在上一列的上边缘再画一个
|
|
706
|
-
|
|
707
|
-
else this.fullCatchObjects[_obj.index].draw2({ time: _obj.time, type: _obj.type, x: _obj.x - (Beatmap.WIDTH * SCALE + 2 * COLMARGIN), y: 0, col: _obj.col - 1 }, SCALE, ctx2, BORDER_WIDTH, BORDER_HEIGHT);
|
|
759
|
+
this.fullCatchObjects[_obj.index].draw2({ time: _obj.time, type: _obj.type, x: _obj.x - (Beatmap.WIDTH * SCALE + 2 * COLMARGIN), y: 0, col: _obj.col - 1 }, SCALE, ctx2, BORDER_WIDTH, BORDER_HEIGHT, label);
|
|
708
760
|
}
|
|
709
761
|
else if (_obj.y < 5) {
|
|
710
762
|
// note靠近上边缘,在下一列的下边缘再画一个
|
|
711
|
-
|
|
712
|
-
else this.fullCatchObjects[_obj.index].draw2({ time: _obj.time, type: _obj.type, x: _obj.x + (Beatmap.WIDTH * SCALE + 2 * COLMARGIN), y: SCREENSHEIGHT * SCALE, col: _obj.col + 1 }, SCALE, ctx2, BORDER_WIDTH, BORDER_HEIGHT);
|
|
763
|
+
this.fullCatchObjects[_obj.index].draw2({ time: _obj.time, type: _obj.type, x: _obj.x + (Beatmap.WIDTH * SCALE + 2 * COLMARGIN), y: SCREENSHEIGHT * SCALE, col: _obj.col + 1 }, SCALE, ctx2, BORDER_WIDTH, BORDER_HEIGHT, label);
|
|
713
764
|
}
|
|
714
765
|
});
|
|
715
766
|
});
|
|
@@ -6,12 +6,14 @@ function JuiceStream(data, beatmap)
|
|
|
6
6
|
this.sliderType = this.points[0];
|
|
7
7
|
this.points[0] = this.position;
|
|
8
8
|
for (var i = 1; i < this.points.length; i++)
|
|
9
|
-
{
|
|
9
|
+
{
|
|
10
10
|
this.points[i] = new Point(this.points[i].split(':'));
|
|
11
11
|
}
|
|
12
12
|
this.repeat = data[6] | 0;
|
|
13
13
|
this.pixelLength = +data[7];
|
|
14
14
|
|
|
15
|
+
this.hitSounds = this.hitSoundString.split('|');
|
|
16
|
+
|
|
15
17
|
this.timingPoint = this.beatmap.timingPointAt(this.time);
|
|
16
18
|
this.beatLength = this.timingPoint.beatLength;
|
|
17
19
|
this.timingPointStart = this.timingPoint.time;
|
|
@@ -99,6 +101,7 @@ JuiceStream.prototype.generateTicks = function(spanIndex, spanStartTime, spanDur
|
|
|
99
101
|
JuiceStream.prototype.buildNested = function() {
|
|
100
102
|
this.nested = [];
|
|
101
103
|
|
|
104
|
+
let nestedIndex = 0;
|
|
102
105
|
let lastEvent = null;
|
|
103
106
|
for(let i = 0; i < this.events.length; i++) {
|
|
104
107
|
// generate tiny droplets since the last point
|
|
@@ -151,7 +154,9 @@ JuiceStream.prototype.buildNested = function() {
|
|
|
151
154
|
x: this.curve.pointAt(this.events[i].pathProgress).x,
|
|
152
155
|
color: this.color,
|
|
153
156
|
radius: this.beatmap.circleRadius,
|
|
157
|
+
hitSound: this.hitSounds[nestedIndex] || "0",
|
|
154
158
|
}, this.beatmap));
|
|
159
|
+
nestedIndex++;
|
|
155
160
|
break;
|
|
156
161
|
}
|
|
157
162
|
}
|
|
@@ -21,5 +21,25 @@ Curve.parse = function(sliderType, points, pixelLength)
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
catch(e) {}
|
|
24
|
-
|
|
24
|
+
try
|
|
25
|
+
{
|
|
26
|
+
return new LinearBezier(points, pixelLength, sliderType == 'L');
|
|
27
|
+
}
|
|
28
|
+
catch(e)
|
|
29
|
+
{
|
|
30
|
+
return new SingleNoteCurve(points[0]);
|
|
31
|
+
}
|
|
25
32
|
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
function SingleNoteCurve(point)
|
|
37
|
+
{
|
|
38
|
+
this.path = [point];
|
|
39
|
+
};
|
|
40
|
+
SingleNoteCurve.prototype = Object.create(Curve.prototype);
|
|
41
|
+
SingleNoteCurve.prototype.constructor = SingleNoteCurve;
|
|
42
|
+
SingleNoteCurve.prototype.pointAt = function(t)
|
|
43
|
+
{
|
|
44
|
+
return this.path[0];
|
|
45
|
+
};
|
|
@@ -12,6 +12,8 @@ function Slider(data, beatmap)
|
|
|
12
12
|
this.repeat = data[6] | 0;
|
|
13
13
|
this.pixelLength = +data[7];
|
|
14
14
|
|
|
15
|
+
this.hitSoundString = data[8] || "";
|
|
16
|
+
|
|
15
17
|
var sliderTime = this.beatmap.timingPointAt(this.time).beatLength * (
|
|
16
18
|
this.pixelLength / this.beatmap.SliderMultiplier
|
|
17
19
|
) / 100;
|
|
@@ -414,13 +414,15 @@ def filter_scores_with_regex(scores_with_index, conditions):
|
|
|
414
414
|
|
|
415
415
|
def trim_text_with_ellipsis(text, max_width, font):
|
|
416
416
|
# 初始检查:空字符串或无需处理
|
|
417
|
-
|
|
417
|
+
bbox = font.getbbox(text)
|
|
418
|
+
text_width = bbox[2] - bbox[0]
|
|
419
|
+
if not text or text_width <= max_width:
|
|
418
420
|
return text
|
|
419
421
|
# 逐字符检查
|
|
420
422
|
ellipsis_symbol = "…"
|
|
421
|
-
ellipsis_width = font.getbbox("…")
|
|
423
|
+
ellipsis_width = font.getbbox("…")[2] - font.getbbox("…")[0]
|
|
422
424
|
# 确保最大宽度能至少容纳一个字符+省略号
|
|
423
|
-
if max_width < font.getbbox("A") + ellipsis_width:
|
|
425
|
+
if max_width < font.getbbox("A")[2] - font.getbbox("A")[0] + ellipsis_width:
|
|
424
426
|
return ellipsis_symbol
|
|
425
427
|
|
|
426
428
|
truncated_text = ""
|
|
@@ -428,7 +430,7 @@ def trim_text_with_ellipsis(text, max_width, font):
|
|
|
428
430
|
|
|
429
431
|
for char in text:
|
|
430
432
|
# 检查当前字符宽度 + 省略号宽度是否超标
|
|
431
|
-
char_width = font.getbbox(char)
|
|
433
|
+
char_width = font.getbbox(char)[2] - font.getbbox(char)[0]
|
|
432
434
|
if current_width + char_width + ellipsis_width > max_width:
|
|
433
435
|
break
|
|
434
436
|
truncated_text += char
|
|
@@ -25,8 +25,8 @@ async def _bp(state: T_State):
|
|
|
25
25
|
if not best.isdigit():
|
|
26
26
|
await UniMessage.text("只能接受纯数字的bp参数").finish(reply_to=True)
|
|
27
27
|
best = int(best)
|
|
28
|
-
if best <= 0 or best >
|
|
29
|
-
await UniMessage.text("只允许查询bp 1-
|
|
28
|
+
if best <= 0 or best > 200:
|
|
29
|
+
await UniMessage.text("只允许查询bp 1-200 的成绩").finish(reply_to=True)
|
|
30
30
|
try:
|
|
31
31
|
data = await draw_score(
|
|
32
32
|
"bp",
|
|
@@ -52,11 +52,11 @@ async def _pfm(state: T_State):
|
|
|
52
52
|
if "error" in state:
|
|
53
53
|
await UniMessage.text(state["error"]).finish(reply_to=True)
|
|
54
54
|
if not state["range"]:
|
|
55
|
-
state["range"] = "1-
|
|
55
|
+
state["range"] = "1-200"
|
|
56
56
|
ls = state["range"].split("-")
|
|
57
57
|
low, high = int(ls[0]), int(ls[1])
|
|
58
|
-
if not 0 < low < high <=
|
|
59
|
-
await UniMessage.text("仅支持查询bp1-
|
|
58
|
+
if not 0 < low < high <= 200:
|
|
59
|
+
await UniMessage.text("仅支持查询bp1-200").finish(reply_to=True)
|
|
60
60
|
try:
|
|
61
61
|
data = await draw_bp(
|
|
62
62
|
"bp",
|
|
@@ -84,11 +84,11 @@ async def _tbp(state: T_State):
|
|
|
84
84
|
if "error" in state:
|
|
85
85
|
await UniMessage.text(state["error"]).finish(reply_to=True)
|
|
86
86
|
if not state["range"]:
|
|
87
|
-
state["range"] = "1-
|
|
87
|
+
state["range"] = "1-200"
|
|
88
88
|
ls = state["range"].split("-")
|
|
89
89
|
low, high = int(ls[0]), int(ls[1])
|
|
90
|
-
if not 0 < low < high <=
|
|
91
|
-
await UniMessage.text("仅支持查询bp1-
|
|
90
|
+
if not 0 < low < high <= 200:
|
|
91
|
+
await UniMessage.text("仅支持查询bp1-200").finish(reply_to=True)
|
|
92
92
|
try:
|
|
93
93
|
data = await draw_bp(
|
|
94
94
|
"tbp",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
nonebot_plugin_osubot/__init__.py,sha256=Q-mTTnOIdKiKG6JrVm-kqpPrAhOP9lWyiKHNRqA7gpc,1478
|
|
2
|
-
nonebot_plugin_osubot/api.py,sha256=
|
|
2
|
+
nonebot_plugin_osubot/api.py,sha256=8GXbumU7_1D0gyYuGtjHgNT82rSXKZUV-WG5mpUubYE,16336
|
|
3
3
|
nonebot_plugin_osubot/beatmap_stats_moder.py,sha256=mNNTufc-gvO4NdYa3TnealSZI4-LBoiTlb599SeLBck,2915
|
|
4
4
|
nonebot_plugin_osubot/config.py,sha256=Ub2s5Ny09-d1ZwT6x8cirB6zWy0brtO-oZV3W0qEM5Q,311
|
|
5
5
|
nonebot_plugin_osubot/database/__init__.py,sha256=7CDo9xU_DGLQ6uTj_mU_Px92phg_DMU5mP6WvgOxFLY,101
|
|
@@ -15,23 +15,23 @@ nonebot_plugin_osubot/draw/catch_preview_templates/js/beatmap/point.js,sha256=AX
|
|
|
15
15
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/beatmap/scroll.js,sha256=wR9dkpKabP1TyMssfs8i2WLUxyR_ZX7RRc7KLXUjoXo,1833
|
|
16
16
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/beatmap/timingpoint.js,sha256=boHMAQOT-860VOi-jQIrq4cwKgCo1kZvNDy0bzUxZLE,803
|
|
17
17
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/LegacyRandom.js,sha256=HDiks3FCVQBtVK5VzN7YV9Ekkk_WHYi0fPk3-XCQaj8,2155
|
|
18
|
-
nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/PalpableCatchHitObject.js,sha256=
|
|
19
|
-
nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/bananashower.js,sha256=
|
|
20
|
-
nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/catch.js,sha256=
|
|
18
|
+
nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/PalpableCatchHitObject.js,sha256=CnUBiIkAqFUaCrc5TXRtL_fuK20NeK1yMti1Sp4dJAE,5702
|
|
19
|
+
nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/bananashower.js,sha256=sPISMifUWVXK9nXuOD7JUPeXBNPBKquiDNKpYzbSJyg,988
|
|
20
|
+
nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/catch.js,sha256=MnYorETgLMjXJ8X0uPNyapD3m0KHHzHdoPnkUcBU374,34430
|
|
21
21
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/fruit.js,sha256=ABvFMbmXP0t5wACUhSVbu8sVJ845mWJ9sWiQJtMV5co,437
|
|
22
|
-
nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/juicestream.js,sha256=
|
|
22
|
+
nonebot_plugin_osubot/draw/catch_preview_templates/js/catch/juicestream.js,sha256=kWjmPtT_UgnUlg5G-_8q-1AyNTv6GLRp0bOOfiMcojc,7347
|
|
23
23
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/fakeaudio.js,sha256=gJrdVwNrAVjWx80z_XkzybL9ldfV97nKl7k1v7NulBg,1211
|
|
24
24
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/preview.js,sha256=5zKNenhzhMdP_SPuA74wbtgsqiqUNL8PIJ4OYFW2r-U,2875
|
|
25
25
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/curve/bezier2.js,sha256=J3wvdScuhYCngTvZ3vg9ld6yoDE09ht5g4Etsp4bJkE,955
|
|
26
26
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/curve/catmullcurve.js,sha256=aGmfIAONuOoy87W5Pyl1X8ifr3w6W9mkM_AENmZRUF0,932
|
|
27
27
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/curve/centripetalcatmullrom.js,sha256=bndps8pDX4JMEbqLxIVb-aO7IoHHXnT8-jkWJnLlfq0,1203
|
|
28
28
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/curve/circumstancedcircle.js,sha256=qf7wZMH3-thilEoB1Grrhr9W-U-JIClRNkhZh2RzGTY,1558
|
|
29
|
-
nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/curve/curve.js,sha256=
|
|
29
|
+
nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/curve/curve.js,sha256=KeR8szJ0N2FWBTYMnXBcnQFWYHxqRRh0f-oaALSXvYs,1002
|
|
30
30
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/curve/curvetype.js,sha256=y3uiQSz1BjGIhIMn4fNlplPRGqxozHOuIa8jN-G06Vs,496
|
|
31
31
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/curve/equaldistancemulticurve.js,sha256=U8sjoBG1ETEa9vlToqc32hyQYj41KrcRVvEdxnD-uGo,2280
|
|
32
32
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/curve/linearbezier.js,sha256=sGe0u0Aqwh8R4y2BP91Dsz1MfhvtvTrrOVMV_gYsQhY,1075
|
|
33
33
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/hitcircle.js,sha256=erJCRQYojmlCnTvnkrWMJHkJxBabeWopE8PACr1aSUw,2391
|
|
34
|
-
nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/slider.js,sha256=
|
|
34
|
+
nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/slider.js,sha256=alosJJRDgXreSrheROxwVi4Dt9S3lxq9aZfG_EQCbWU,3873
|
|
35
35
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/standard/spinner.js,sha256=9El2G7UfJv1xikHmfO5-VJJ7e6f-1tOPLyrMf2huh7g,1668
|
|
36
36
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/util.js,sha256=XveUlX-d0vrUnXaGbR8y428s6Nw2zhDR235pFko_MxM,1504
|
|
37
37
|
nonebot_plugin_osubot/draw/catch_preview_templates/js/viewbox.js,sha256=RPsUyoKNAQub2n7oUGwWyFppZu0iVuy6DD5gggQZS3E,1641
|
|
@@ -49,7 +49,7 @@ nonebot_plugin_osubot/draw/templates/bpa_chart.html,sha256=cnpM0qRvvyCMTRP-mIOAB
|
|
|
49
49
|
nonebot_plugin_osubot/draw/templates/echarts.min.js,sha256=IF32ooP8NPIzQg_fs7lVHpwG92JcCPE1TZAEyFSgGZU,1022939
|
|
50
50
|
nonebot_plugin_osubot/draw/templates/mod_chart.html,sha256=Iz71KM5v9z_Rt2vqJ5WIZumRIHgDfcGIUmWGvVGZ-nQ,1508
|
|
51
51
|
nonebot_plugin_osubot/draw/templates/pp_rank_line_chart.html,sha256=Gyf-GR8ZBlWQTks0TlB3M8EWUBMVwiUaesFAmDISxLo,1417
|
|
52
|
-
nonebot_plugin_osubot/draw/utils.py,sha256=
|
|
52
|
+
nonebot_plugin_osubot/draw/utils.py,sha256=LZVDmrQizVwVFX0kDJISYYO68jmZbn5Xz40gV5bj8bo,15276
|
|
53
53
|
nonebot_plugin_osubot/exceptions.py,sha256=N_FsEk-9Eu2QnuznhdfWn6OoyA1HH73Q7bUaY89gVi0,40
|
|
54
54
|
nonebot_plugin_osubot/file.py,sha256=GhG54EdVsxFf8_8GZOPh4YGvw9iw5bAX9JFz4Mg4kMg,4379
|
|
55
55
|
nonebot_plugin_osubot/info/__init__.py,sha256=I7YlMQiuHExEeJWqyzZb2I-Vl2uql3Py2LdhSH2Z9N0,136
|
|
@@ -58,7 +58,7 @@ nonebot_plugin_osubot/info/bind.py,sha256=b2ua625hbYym7rpb-kLBB-VDP5YWFdmT5RweM5
|
|
|
58
58
|
nonebot_plugin_osubot/mania/__init__.py,sha256=XRPn563jDJiPohFekcoFFCqCJYznb-6uORneioZv4xI,5534
|
|
59
59
|
nonebot_plugin_osubot/matcher/__init__.py,sha256=yID7QcdQF6_Mouwbej3JwYUBbKSU3VQdrjq6B1Fz9P8,1331
|
|
60
60
|
nonebot_plugin_osubot/matcher/bind.py,sha256=QQJc2S7XFo5tu4CPloIET6fKaeiQixgb8M7QvULV6E0,2834
|
|
61
|
-
nonebot_plugin_osubot/matcher/bp.py,sha256=
|
|
61
|
+
nonebot_plugin_osubot/matcher/bp.py,sha256=GidJfuZ9lJ7LwMq126DDOwMksNUOz4Bkab83OlKg8t8,3983
|
|
62
62
|
nonebot_plugin_osubot/matcher/bp_analyze.py,sha256=S1dhYiGqtPQapJt4PB5mNKfpPbOpVNAqDIToNEJVpSY,3949
|
|
63
63
|
nonebot_plugin_osubot/matcher/getbg.py,sha256=Ar2yIST556MYRxzuXCLSDAMAmESRENN1fCty-kdH7PI,699
|
|
64
64
|
nonebot_plugin_osubot/matcher/guess.py,sha256=iE5oRZ3mDTC_wcjLJTyyAWlmnDzkAgzGN5rvoTIn0uM,24093
|
|
@@ -403,6 +403,6 @@ nonebot_plugin_osubot/schema/sayo_beatmap.py,sha256=lS1PQZ-HvHl0VhkzlI0-pNLeJrLY
|
|
|
403
403
|
nonebot_plugin_osubot/schema/score.py,sha256=zHU-w2e7RzMDL8vdPkX5vggcqalBo83JTvu96abcflo,3124
|
|
404
404
|
nonebot_plugin_osubot/schema/user.py,sha256=sxNmqymG_kIVuGuzfchSv9UML6NPG70cqo2_h5xDIpM,2250
|
|
405
405
|
nonebot_plugin_osubot/utils/__init__.py,sha256=pyv8XxBcCOeQVDj1E4dgvktzcefgQXfKBlarsYGx1sg,815
|
|
406
|
-
nonebot_plugin_osubot-6.
|
|
407
|
-
nonebot_plugin_osubot-6.
|
|
408
|
-
nonebot_plugin_osubot-6.
|
|
406
|
+
nonebot_plugin_osubot-6.20.1.dist-info/WHEEL,sha256=B19PGBCYhWaz2p_UjAoRVh767nYQfk14Sn4TpIZ-nfU,87
|
|
407
|
+
nonebot_plugin_osubot-6.20.1.dist-info/METADATA,sha256=cosRoPpyiqrB686g_vBWg7JhlUs9jQ7CGFVvGZonDzU,4476
|
|
408
|
+
nonebot_plugin_osubot-6.20.1.dist-info/RECORD,,
|
|
File without changes
|