nonebot-plugin-osubot 6.23.1__py3-none-any.whl → 6.24.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.

Files changed (81) hide show
  1. nonebot_plugin_osubot/api.py +7 -5
  2. nonebot_plugin_osubot/draw/bmap.py +19 -21
  3. nonebot_plugin_osubot/draw/bp.py +1 -1
  4. nonebot_plugin_osubot/draw/echarts.py +8 -2
  5. nonebot_plugin_osubot/draw/info.py +2 -0
  6. nonebot_plugin_osubot/draw/map.py +5 -2
  7. nonebot_plugin_osubot/draw/osu_preview.py +64 -0
  8. nonebot_plugin_osubot/draw/osu_preview_templates/css/style.css +258 -0
  9. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/README.md +109 -0
  10. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js +3 -0
  11. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js.map +1 -0
  12. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js +3 -0
  13. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js.map +1 -0
  14. nonebot_plugin_osubot/draw/osu_preview_templates/index.html +437 -0
  15. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/beatmap.js +211 -0
  16. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/hitobject.js +29 -0
  17. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/point.js +55 -0
  18. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/scroll.js +45 -0
  19. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/timingpoint.js +35 -0
  20. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/LegacyRandom.js +81 -0
  21. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/PalpableCatchHitObject.js +53 -0
  22. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/bananashower.js +33 -0
  23. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/catch.js +211 -0
  24. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/fruit.js +21 -0
  25. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/juicestream.js +176 -0
  26. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/hitnote.js +21 -0
  27. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/holdnote.js +37 -0
  28. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/mania.js +164 -0
  29. nonebot_plugin_osubot/draw/osu_preview_templates/js/preview.js +61 -0
  30. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/bezier2.js +33 -0
  31. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/catmullcurve.js +34 -0
  32. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/centripetalcatmullrom.js +30 -0
  33. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/circumstancedcircle.js +47 -0
  34. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curve.js +25 -0
  35. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curvetype.js +17 -0
  36. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/equaldistancemulticurve.js +70 -0
  37. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/linearbezier.js +40 -0
  38. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/hitcircle.js +85 -0
  39. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/slider.js +120 -0
  40. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/spinner.js +56 -0
  41. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/standard.js +170 -0
  42. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/donkat.js +40 -0
  43. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/drumroll.js +34 -0
  44. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/shaker.js +58 -0
  45. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/taiko.js +120 -0
  46. nonebot_plugin_osubot/draw/osu_preview_templates/js/util.js +61 -0
  47. nonebot_plugin_osubot/draw/osu_preview_templates/pic.html +115 -0
  48. nonebot_plugin_osubot/draw/score.py +4 -4
  49. nonebot_plugin_osubot/file.py +1 -12
  50. nonebot_plugin_osubot/mania/__init__.py +9 -10
  51. nonebot_plugin_osubot/matcher/bp_analyze.py +9 -9
  52. nonebot_plugin_osubot/matcher/guess.py +3 -3
  53. nonebot_plugin_osubot/matcher/map_convert.py +12 -7
  54. nonebot_plugin_osubot/matcher/preview.py +10 -3
  55. nonebot_plugin_osubot/matcher/recommend.py +7 -12
  56. nonebot_plugin_osubot/osufile/mods/AP.png +0 -0
  57. nonebot_plugin_osubot/osufile/mods/CL.png +0 -0
  58. nonebot_plugin_osubot/osufile/mods/DT.png +0 -0
  59. nonebot_plugin_osubot/osufile/mods/EZ.png +0 -0
  60. nonebot_plugin_osubot/osufile/mods/FI.png +0 -0
  61. nonebot_plugin_osubot/osufile/mods/FL.png +0 -0
  62. nonebot_plugin_osubot/osufile/mods/HD.png +0 -0
  63. nonebot_plugin_osubot/osufile/mods/HR.png +0 -0
  64. nonebot_plugin_osubot/osufile/mods/HT.png +0 -0
  65. nonebot_plugin_osubot/osufile/mods/MR.png +0 -0
  66. nonebot_plugin_osubot/osufile/mods/NC.png +0 -0
  67. nonebot_plugin_osubot/osufile/mods/NF.png +0 -0
  68. nonebot_plugin_osubot/osufile/mods/PF.png +0 -0
  69. nonebot_plugin_osubot/osufile/mods/RX.png +0 -0
  70. nonebot_plugin_osubot/osufile/mods/SD.png +0 -0
  71. nonebot_plugin_osubot/osufile/mods/SO.png +0 -0
  72. nonebot_plugin_osubot/osufile/mods/TD.png +0 -0
  73. nonebot_plugin_osubot/osufile/mods/V2.png +0 -0
  74. nonebot_plugin_osubot/pp.py +7 -0
  75. nonebot_plugin_osubot/schema/__init__.py +0 -2
  76. nonebot_plugin_osubot/schema/beatmapsets.py +42 -0
  77. nonebot_plugin_osubot/schema/score.py +1 -0
  78. {nonebot_plugin_osubot-6.23.1.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/METADATA +2 -2
  79. {nonebot_plugin_osubot-6.23.1.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/RECORD +80 -39
  80. nonebot_plugin_osubot/schema/sayo_beatmap.py +0 -59
  81. {nonebot_plugin_osubot-6.23.1.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,120 @@
1
+ function Taiko(osu)
2
+ {
3
+ Scroll.call(this, osu);
4
+
5
+ for (var i = 0; i < this.HitObjects.length; i++)
6
+ {
7
+ var hitObject = this.HitObjects[i];
8
+ hitObject.position.x = this.scrollAt(hitObject.time);
9
+ hitObject.endPosition.x = this.scrollAt(hitObject.endTime);
10
+ }
11
+ }
12
+ Taiko.prototype = Object.create(Scroll.prototype, {
13
+
14
+ });
15
+ Taiko.prototype.constructor = Taiko;
16
+ Taiko.prototype.hitObjectTypes = {};
17
+ Taiko.ID = 1;
18
+ Beatmap.modes[Taiko.ID] = Taiko;
19
+ Taiko.DEFAULT_COLORS = [
20
+ '#eb452c',
21
+ '#438eac',
22
+ '#fcb806'
23
+ ];
24
+ Taiko.DIAMETER = 56;
25
+ Taiko.prototype.calcX = function(x, scroll)
26
+ {
27
+ return (x - scroll) * 20 * (260) / 1000 / (this.SliderMultiplier * 8);
28
+ };
29
+ Taiko.prototype.update = function(ctx)
30
+ {
31
+ ctx.shadowColor = '#666';
32
+ ctx.lineCap = 'round';
33
+ ctx.lineJoin = 'round';
34
+ ctx.textAlign = 'center';
35
+ ctx.textBaseline = 'middle';
36
+ ctx.translate(160, 200);
37
+ };
38
+ Taiko.prototype.draw = function(time, ctx)
39
+ {
40
+ if (typeof this.tmp.first == 'undefined')
41
+ {
42
+ this.tmp.first = 0;
43
+ this.tmp.last = -1;
44
+ this.tmp.barLine = 0;
45
+ }
46
+
47
+ var scroll = this.scrollAt(time);
48
+ while (this.tmp.first < this.HitObjects.length &&
49
+ time > this.HitObjects[this.tmp.first].endTime)
50
+ {
51
+ this.tmp.first++;
52
+ }
53
+ while (this.tmp.last + 1 < this.HitObjects.length)
54
+ {
55
+ var hitObject = this.HitObjects[this.tmp.last + 1];
56
+ if (this.calcX(hitObject.position.x, scroll) > Beatmap.WIDTH)
57
+ {
58
+ break;
59
+ }
60
+ this.tmp.last++;
61
+ }
62
+ while (this.tmp.barLine < this.barLines.length &&
63
+ this.calcX(this.barLines[this.tmp.barLine], scroll) < -Taiko.DIAMETER)
64
+ {
65
+ this.tmp.barLine++;
66
+ }
67
+ for (var i = this.tmp.barLine; i < this.barLines.length && this.calcX(this.barLines[i], scroll) < Beatmap.WIDTH; i++)
68
+ {
69
+ var barLine = this.calcX(this.barLines[i], scroll);
70
+ ctx.beginPath();
71
+ ctx.moveTo(barLine, -Taiko.DIAMETER);
72
+ ctx.lineTo(barLine, Taiko.DIAMETER);
73
+ ctx.strokeStyle = '#fff';
74
+ ctx.lineWidth = 1;
75
+ ctx.stroke();
76
+ }
77
+ for (var i = this.tmp.last; i >= this.tmp.first; i--)
78
+ {
79
+ var hitObject = this.HitObjects[i];
80
+ if (time > hitObject.endTime)
81
+ {
82
+ continue;
83
+ }
84
+ hitObject.draw(scroll, ctx);
85
+ }
86
+ ctx.clearRect(-160, -200, Taiko.DIAMETER * 2, 400);
87
+ };
88
+ Taiko.prototype.processBG = function(ctx)
89
+ {
90
+ var offset = - Taiko.DIAMETER;
91
+ //ctx.drawImage(ctx.canvas, -160, offset, ctx.canvas.width, ctx.canvas.height);
92
+ //ctx.beginPath();
93
+ //ctx.rect(0, 0, Beatmap.WIDTH, offset);
94
+ //ctx.fillStyle = '#000';
95
+ //ctx.fill();
96
+
97
+ // rail
98
+ ctx.beginPath();
99
+ ctx.rect(-160, offset, Beatmap.WIDTH, Taiko.DIAMETER * 2);
100
+ ctx.strokeStyle = '#ddd';
101
+ ctx.lineWidth = 8;
102
+ ctx.stroke();
103
+ ctx.fillStyle = '#000';
104
+ ctx.fill();
105
+
106
+ // drum
107
+ ctx.beginPath();
108
+ ctx.rect(-160, offset, Taiko.DIAMETER * 2, Taiko.DIAMETER * 2);
109
+ ctx.fillStyle = '#ff0080';
110
+ ctx.fill();
111
+
112
+ var border = 6;
113
+ ctx.beginPath();
114
+ ctx.arc(0, 0, Taiko.DIAMETER / 2, -Math.PI, Math.PI);
115
+ ctx.fillStyle = 'rgba(255,255,255,.2)';
116
+ ctx.fill();
117
+ ctx.strokeStyle = 'rgba(255,255,255,.2)';
118
+ ctx.lineWidth = border;
119
+ ctx.stroke();
120
+ };
@@ -0,0 +1,61 @@
1
+ Math.hypot = Math.hypot || function()
2
+ {
3
+ var power = 0;
4
+ for (var i = 0; i < arguments.length; i++)
5
+ {
6
+ power += arguments[i] * arguments[i];
7
+ }
8
+ return Math.sqrt(power);
9
+ };
10
+ Math.lerp = Math.lerp || function(a, b, t)
11
+ {
12
+ if (a instanceof Point)
13
+ {
14
+ return new Point(Math.lerp(a.x, b.x, t), Math.lerp(a.y, b.y, t));
15
+ }
16
+ return a + (b - a) * t;
17
+ };
18
+ /** Calculate point C's direction by line AB
19
+ * @return {Number}
20
+ * 1 C is counter-clockwise to AB
21
+ * 0 C is parallel to AB
22
+ * -1 C is clockwise to AB
23
+ */
24
+ Math.ccw = function(a, b, c)
25
+ {
26
+ var ret = (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
27
+ if (ret > 0)
28
+ {
29
+ return 1;
30
+ }
31
+ if (ret < 0)
32
+ {
33
+ return -1;
34
+ }
35
+ return 0;
36
+ };
37
+ Math.clamp = function(num, min, max) {
38
+ if (num < min) return min;
39
+ if (num > max) return max;
40
+ return num;
41
+ }
42
+ // https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#Polyfill
43
+ if (!HTMLCanvasElement.prototype.toBlob)
44
+ {
45
+ Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
46
+ value: function (callback, type, quality)
47
+ {
48
+
49
+ var binStr = atob(this.toDataURL(type, quality).split(',')[1]),
50
+ len = binStr.length,
51
+ arr = new Uint8Array(len);
52
+
53
+ for (var i = 0; i < len; i++)
54
+ {
55
+ arr[i] = binStr.charCodeAt(i);
56
+ }
57
+
58
+ callback(new Blob([ arr ], { type: type || 'image/png' }));
59
+ }
60
+ });
61
+ }
@@ -0,0 +1,115 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
7
+ <meta name="robots" content="nofollow, noindex, noarchive">
8
+ <title>gif生成测试 网址后加#bid</title>
9
+ </head>
10
+
11
+
12
+ <body class="h">
13
+ <img id="img"></img>
14
+
15
+ <script src="js/util.js"></script>
16
+
17
+ <script src="js/beatmap/beatmap.js"></script>
18
+ <script src="js/beatmap/timingpoint.js"></script>
19
+ <script src="js/beatmap/hitobject.js"></script>
20
+ <script src="js/beatmap/point.js"></script>
21
+ <script src="js/beatmap/scroll.js"></script>
22
+
23
+ <script src="js/standard/standard.js"></script>
24
+ <script src="js/standard/hitcircle.js"></script>
25
+ <script src="js/standard/slider.js"></script>
26
+ <script src="js/standard/curve/curve.js"></script>
27
+ <script src="js/standard/curve/equaldistancemulticurve.js"></script>
28
+ <script src="js/standard/curve/linearbezier.js"></script>
29
+ <script src="js/standard/curve/catmullcurve.js"></script>
30
+ <script src="js/standard/curve/curvetype.js"></script>
31
+ <script src="js/standard/curve/bezier2.js"></script>
32
+ <script src="js/standard/curve/centripetalcatmullrom.js"></script>
33
+ <script src="js/standard/curve/circumstancedcircle.js"></script>
34
+ <script src="js/standard/spinner.js"></script>
35
+
36
+ <script src="js/taiko/taiko.js"></script>
37
+ <script src="js/taiko/donkat.js"></script>
38
+ <script src="js/taiko/drumroll.js"></script>
39
+ <script src="js/taiko/shaker.js"></script>
40
+
41
+ <script src="js/catch/LegacyRandom.js"></script>
42
+ <script src="js/catch/catch.js"></script>
43
+ <script src="js/catch/fruit.js"></script>
44
+ <script src="js/catch/bananashower.js"></script>
45
+ <script src="js/catch/juicestream.js"></script>
46
+ <script src="js/catch/PalpableCatchHitObject.js"></script>
47
+
48
+ <script src="js/mania/mania.js"></script>
49
+ <script src="js/mania/hitnote.js"></script>
50
+ <script src="js/mania/holdnote.js"></script>
51
+
52
+ <script src="js/preview.js"></script>
53
+ <script src="gif.js/gif.js"></script>
54
+
55
+ <script>
56
+ const scaleValue = 0.2;
57
+ const durationValue = 10000;
58
+ const qualityValue = 10;
59
+ const timeSpanValue = 50;
60
+
61
+ const createImg = function () {
62
+ let preview = new Preview(scaleValue);
63
+ const osufile = {{ osu_file|tojson }};
64
+ preview.load(osufile, function () {
65
+ let actualStartTime;
66
+ const previewEndTime = preview.previewTime + durationValue;
67
+ if (previewEndTime <= preview.endTime) {
68
+ // 使用谱面预览时间
69
+ actualStartTime = preview.previewTime;
70
+ } else {
71
+ // 预览时间加上持续时间超过谱面结束时间,使用用户指定的开始时间
72
+ actualStartTime = preview.startTime;
73
+ }
74
+ const actualEndTime = durationValue === -1 ? preview.endTime : Math.min(actualStartTime + durationValue, preview.endTime);
75
+ let gif = new GIF({
76
+ workers: 4,
77
+ workerScript: './gif.js/gif.worker.js',
78
+ quality: qualityValue,
79
+ width: preview.screen.width * scaleValue,
80
+ height: preview.screen.height * scaleValue,
81
+ //transparent: "0x000000",
82
+ });
83
+
84
+ const totalFrames = Math.ceil((actualEndTime - actualStartTime) / timeSpanValue);
85
+ let currentFrame = 0;
86
+
87
+ // 添加帧
88
+ while (currentFrame <= totalFrames) {
89
+ const t = actualStartTime + currentFrame * timeSpanValue;
90
+ preview.at(t);
91
+
92
+ gif.addFrame(preview.ctx, {
93
+ copy: true,
94
+ delay: timeSpanValue
95
+ });
96
+ currentFrame++;
97
+ }
98
+ gif.on('finished', function (blob) {
99
+ const url = URL.createObjectURL(blob);
100
+ const img = document.createElement('img');
101
+ img.id = 'img';
102
+ img.src = url;
103
+ img.alt = '生成的GIF预览';
104
+ });
105
+ gif.render();
106
+ });
107
+ }
108
+
109
+ window.addEventListener('hashchange', createImg);
110
+
111
+ createImg();
112
+ </script>
113
+ </body>
114
+
115
+ </html>
@@ -107,7 +107,7 @@ async def draw_score(
107
107
  map_json = await task2
108
108
  # 判断是否开启lazer模式
109
109
  if source == "osu":
110
- score = cal_score_info(is_lazer, score)
110
+ score = cal_score_info(is_lazer, score, source)
111
111
  return await draw_score_pic(score, info, map_json, "", is_lazer, source)
112
112
 
113
113
 
@@ -180,7 +180,7 @@ async def get_score_data(
180
180
  user_path.mkdir(parents=True, exist_ok=True)
181
181
  # 判断是否开启lazer模式
182
182
  if source == "osu":
183
- score = cal_score_info(is_lazer, score)
183
+ score = cal_score_info(is_lazer, score, source)
184
184
  return await draw_score_pic(score, info, map_json, grank, is_lazer, source)
185
185
 
186
186
 
@@ -795,10 +795,10 @@ def cal_legacy_rank(score_info: UnifiedScore, is_hidden: bool):
795
795
  return "N/A"
796
796
 
797
797
 
798
- def cal_score_info(is_lazer: bool, score_info: UnifiedScore) -> UnifiedScore:
798
+ def cal_score_info(is_lazer: bool, score_info: UnifiedScore, source: str = "osu") -> UnifiedScore:
799
799
  if is_lazer:
800
800
  score_info.legacy_total_score = score_info.total_score
801
- if score_info.ruleset_id == 3 and not is_lazer:
801
+ if score_info.ruleset_id == 3 and not is_lazer and source != "ppysb":
802
802
  score_info.accuracy = cal_legacy_acc(score_info.statistics)
803
803
  if not is_lazer:
804
804
  is_hidden = any(i in score_info.mods for i in (Mod(acronym="HD"), Mod(acronym="FL"), Mod(acronym="FI")))
@@ -47,18 +47,6 @@ async def download_map(setid: int) -> Optional[Path]:
47
47
  return filepath
48
48
 
49
49
 
50
- async def download_tmp_osu(map_id):
51
- url = f"https://osu.ppy.sh/osu/{map_id}"
52
- logger.info(f"开始下载谱面: <{map_id}>")
53
- req = await safe_async_get(url)
54
- filename = f"{map_id}.osu"
55
- filepath = map_path / filename
56
- chunk = req.read()
57
- with open(filepath, "wb") as f:
58
- f.write(chunk)
59
- return filepath
60
-
61
-
62
50
  @auto_retry
63
51
  async def download_osu(set_id, map_id):
64
52
  url = [
@@ -71,6 +59,7 @@ async def download_osu(set_id, map_id):
71
59
  if req := await get_first_response(url):
72
60
  filename = f"{map_id}.osu"
73
61
  filepath = map_path / str(set_id) / filename
62
+ filepath.parent.mkdir(parents=True, exist_ok=True)
74
63
  with open(filepath, "wb") as f:
75
64
  f.write(req)
76
65
  return filepath
@@ -25,7 +25,7 @@ from reamber.algorithms.playField.parts import (
25
25
  )
26
26
 
27
27
  from ..file import download_map
28
- from ..schema import SayoBeatmap
28
+ from ..schema.beatmapsets import BeatmapSets
29
29
 
30
30
  osu_path = Path() / "data" / "osu"
31
31
  if not osu_path.exists():
@@ -39,7 +39,7 @@ class Options:
39
39
  od: Optional[float]
40
40
  set: Optional[int]
41
41
  map: Optional[int] = None
42
- sayo_info: Optional[SayoBeatmap] = None
42
+ beatmapsets: Optional[BeatmapSets] = None
43
43
  nsv: bool = False
44
44
  nln: bool = False
45
45
  fln: bool = False
@@ -89,15 +89,14 @@ async def convert_mania_map(options: Options) -> Optional[Path]:
89
89
  with ZipFile(osz_file.absolute()) as my_zip:
90
90
  my_zip.extractall(path)
91
91
  os.remove(osz_file)
92
- if options.sayo_info:
93
- for i in options.sayo_info.data.bid_data:
94
- if i.bid == options.map:
95
- audio_file_name = i.audio
96
- audio_name = audio_file_name[:-4]
97
- audio_type = audio_file_name[-4:]
92
+ if options.beatmapsets:
93
+ for file in path.rglob("*.osu"):
94
+ osu = OsuMap.read_file(str(file.absolute()))
95
+ if osu.beatmap_id == options.map:
96
+ audio_file_name = osu.audio_file_name
97
+ audio_name = osu.audio_file_name[:-4]
98
+ audio_type = osu.audio_file_name[-4:]
98
99
  break
99
- else:
100
- raise Exception("小夜api有问题啊")
101
100
  if options.rate:
102
101
  if options.rate > 10:
103
102
  options.rate = 10
@@ -42,7 +42,6 @@ async def _(event: Event, state: T_State):
42
42
  f"在查找用户:{state['username']} {NGM[state['mode']]}模式 {lazer_mode}时 {str(e)}"
43
43
  ).finish(reply_to=True)
44
44
  for score in score_ls:
45
- # Filter mods outside of the iteration
46
45
  if not state["is_lazer"] or state["source"] == "ppysb":
47
46
  score.mods = [mod for mod in score.mods if mod.acronym != "CL"]
48
47
  for mod in score.mods:
@@ -94,14 +93,15 @@ async def _(event: Event, state: T_State):
94
93
  pp_data.append({"name": mod, "value": round(pp, 2)})
95
94
  mapper_pp = defaultdict(int)
96
95
  for num, i in enumerate(score_ls):
97
- mapper_pp[i.beatmap.user_id] += i.pp * 0.95**num
98
- mapper_pp = sorted(mapper_pp.items(), key=lambda x: x[1], reverse=True)
99
- mapper_pp = mapper_pp[:9]
100
- users = await get_users([i[0] for i in mapper_pp])
101
- user_dic = {i.id: i.username for i in users}
102
- mapper_pp_data = []
103
- for mapper, pp in mapper_pp:
104
- mapper_pp_data.append({"name": user_dic.get(mapper, ""), "value": round(pp, 2)})
96
+ key = i.beatmap.creator if state["source"] == "ppysb" else i.beatmap.user_id
97
+ mapper_pp[key] += i.pp * 0.95**num
98
+ mapper_pp = sorted(mapper_pp.items(), key=lambda x: x[1], reverse=True)[:9]
99
+ if state["source"] == "ppysb":
100
+ mapper_pp_data = [{"name": mapper, "value": round(pp, 2)} for mapper, pp in mapper_pp]
101
+ else:
102
+ users = await get_users([i[0] for i in mapper_pp])
103
+ user_dic = {i.id: i.username for i in users}
104
+ mapper_pp_data = [{"name": user_dic.get(mapper, ""), "value": round(pp, 2)} for mapper, pp in mapper_pp]
105
105
  if len(mapper_pp_data) > 20:
106
106
  mapper_pp_data = mapper_pp_data[:20]
107
107
  name = f"{state['username']} {NGM[state['mode']]} 模式 "
@@ -26,7 +26,7 @@ from ..exceptions import NetworkError
26
26
  from ..database.models import UserData
27
27
  from ..mania import generate_preview_pic
28
28
  from ..api import safe_async_get, get_user_scores
29
- from ..file import map_path, download_tmp_osu
29
+ from ..file import map_path, download_osu
30
30
  from ..draw.catch_preview import draw_cath_preview
31
31
 
32
32
  games: dict[str, NewScore] = {}
@@ -470,10 +470,10 @@ async def _(
470
470
  chart_games[session_id] = selected_score
471
471
  chart_set_timeout(matcher, session_id)
472
472
  if mode == "3":
473
- osu = await download_tmp_osu(selected_score.beatmap.id)
473
+ osu = await download_osu(selected_score.beatmapset.id, selected_score.beatmap.id)
474
474
  pic = await generate_preview_pic(osu)
475
475
  elif mode == "1":
476
- osu = await download_tmp_osu(selected_score.beatmap.id)
476
+ osu = await download_osu(selected_score.beatmapset.id, selected_score.beatmap.id)
477
477
  beatmap = parse_map(osu)
478
478
  pic = map_to_image(beatmap)
479
479
  else:
@@ -7,8 +7,9 @@ from nonebot import on_command, on_shell_command
7
7
  from nonebot.exception import ParserExit, ActionFailed
8
8
  from nonebot.params import CommandArg, ShellCommandArgv
9
9
 
10
- from ..api import get_sayo_map_info
10
+ from ..api import get_beatmapsets_info, osu_api
11
11
  from ..mania import Options, convert_mania_map
12
+ from ..schema import Beatmap
12
13
 
13
14
  parser = ArgumentParser("convert", description="变换mania谱面")
14
15
  parser.add_argument("--set", type=int, help="要转换的谱面的setid")
@@ -37,9 +38,11 @@ async def _(argv: list[str] = ShellCommandArgv()):
37
38
  return
38
39
  options = Options(**vars(args))
39
40
  if options.map:
40
- sayo_map_info = await get_sayo_map_info(options.map, 1)
41
- options.set = sayo_map_info.data.sid
42
- options.sayo_info = sayo_map_info
41
+ map_data = await osu_api("map", options.map)
42
+ mapinfo = Beatmap(**map_data)
43
+ beatmapsets_info = await get_beatmapsets_info(mapinfo.beatmapset_id)
44
+ options.set = mapinfo.beatmapset_id
45
+ options.beatmapsets = beatmapsets_info
43
46
  if not options.set:
44
47
  await UniMessage.text("请提供需要转换的谱面setid").finish(reply_to=True)
45
48
  if options.nln and options.fln:
@@ -85,9 +88,11 @@ async def _(msg: Message = CommandArg()):
85
88
  args = parser.parse_args(argv)
86
89
  options = Options(**vars(args))
87
90
  if options.map:
88
- sayo_map_info = await get_sayo_map_info(options.map, 1)
89
- options.set = sayo_map_info.data.sid
90
- options.sayo_info = sayo_map_info
91
+ map_data = await osu_api("map", options.map)
92
+ mapinfo = Beatmap(**map_data)
93
+ beatmapsets_info = await get_beatmapsets_info(mapinfo.beatmapset_id)
94
+ options.set = mapinfo.beatmapset_id
95
+ options.beatmapsets = beatmapsets_info
91
96
  osz_path = await convert_mania_map(options)
92
97
  if not osz_path:
93
98
  await UniMessage.text("未找到该地图,请检查是否搞混了mapID与setID").finish(reply_to=True)
@@ -5,9 +5,10 @@ from nonebot_plugin_alconna import UniMessage
5
5
  from ..utils import NGM
6
6
  from ..api import osu_api
7
7
  from .utils import split_msg
8
- from ..file import download_tmp_osu
8
+ from ..file import download_osu
9
9
  from ..exceptions import NetworkError
10
10
  from ..mania import generate_preview_pic
11
+ from ..draw.osu_preview import draw_osu_preview
11
12
  from ..draw.catch_preview import draw_cath_preview
12
13
  from ..draw.taiko_preview import parse_map, map_to_image
13
14
 
@@ -24,7 +25,7 @@ async def _(state: T_State):
24
25
  except NetworkError as e:
25
26
  await UniMessage.text(f"查找map_id:{osu_id} 信息时 {str(e)}").finish(reply_to=True)
26
27
  if state["mode"] == "3":
27
- osu = await download_tmp_osu(osu_id)
28
+ osu = await download_osu(data["beatmapset_id"], int(osu_id))
28
29
  if state["_prefix"]["command"][0] == "完整预览":
29
30
  pic = await generate_preview_pic(osu, True)
30
31
  else:
@@ -34,10 +35,16 @@ async def _(state: T_State):
34
35
  pic = await draw_cath_preview(int(osu_id), data["beatmapset_id"], state["mods"])
35
36
  await UniMessage.image(raw=pic).finish(reply_to=True)
36
37
  elif state["mode"] == "1":
37
- osu = await download_tmp_osu(osu_id)
38
+ osu = await download_osu(data["beatmapset_id"], int(osu_id))
38
39
  beatmap = parse_map(osu)
39
40
  pic = map_to_image(beatmap)
40
41
  await UniMessage.image(raw=pic).finish(reply_to=True)
42
+ elif state["mode"] == "0":
43
+ pic = await draw_osu_preview(int(osu_id), data["beatmapset_id"])
44
+ msg = UniMessage.image(raw=pic) + UniMessage.text(
45
+ f"点击预览:\nhttps://beatmap.try-z.net/?b={osu_id}\nhttps://beatmap.try-z.net/dev/?b={osu_id}"
46
+ )
47
+ await msg.finish(reply_to=True)
41
48
  elif not (0 <= int(state["mode"]) <= 3):
42
49
  await UniMessage.text("模式应为0-3!\n0: std\n1:taiko\n2:ctb\n3: mania").finish()
43
50
  else:
@@ -2,14 +2,14 @@ import re
2
2
  from random import shuffle
3
3
 
4
4
  from nonebot import on_command
5
- from nonebot.log import logger
6
5
  from nonebot.typing import T_State
7
6
  from expiringdict import ExpiringDict
8
7
  from nonebot.internal.matcher import Matcher
9
8
  from nonebot_plugin_alconna import UniMessage
10
9
 
11
10
  from .utils import split_msg
12
- from ..api import get_recommend, update_recommend, get_sayo_map_info
11
+ from ..api import get_recommend, update_recommend, osu_api
12
+ from ..schema import Beatmap
13
13
 
14
14
  recommend = on_command("推荐", priority=11, block=True, aliases={"recommend", "推荐铺面", "推荐谱面"})
15
15
  recommend_cache = ExpiringDict(1000, 60 * 60 * 12)
@@ -41,23 +41,18 @@ async def handle_recommend(state: T_State, matcher: type[Matcher]):
41
41
  break
42
42
  else:
43
43
  await matcher.finish("今天已经没有可以推荐的图啦,明天再来吧")
44
+ return None
44
45
  bid = int(re.findall("https://osu.ppy.sh/beatmaps/(.*)", recommend_map.mapLink)[0])
45
- map_info = await get_sayo_map_info(bid, 1)
46
- sid = map_info.data.sid
47
- for i in map_info.data.bid_data:
48
- if i.bid == bid:
49
- bg = i.bg
50
- break
51
- else:
52
- bg = ""
53
- logger.error(f"出现问题: 有问题的是{bid}, {sid}")
46
+ map_data = await osu_api("map", bid)
47
+ map_info = Beatmap(**map_data)
48
+ sid = map_info.beatmapset_id
54
49
  s = (
55
50
  f"推荐的铺面是{recommend_map.mapName} ⭐{round(recommend_map.difficulty, 2)}\n{''.join(recommend_map.mod)}\n"
56
51
  f"预计pp为{round(recommend_map.predictPP, 2)}\n提升概率为{round(recommend_map.passPercent * 100, 2)}%\n"
57
52
  f"{recommend_map.mapLink}\nhttps://kitsu.moe/api/d/{sid}\n"
58
53
  f"https://txy1.sayobot.cn/beatmaps/download/novideo/{sid}"
59
54
  )
60
- pic_url = f"https://dl.sayobot.cn/beatmaps/files/{sid}/{bg}"
55
+ pic_url = f"https://osu.direct/api/media/background/{bid}"
61
56
  return pic_url, s
62
57
 
63
58
 
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -3,6 +3,7 @@ import importlib.metadata
3
3
 
4
4
  from rosu_pp_py import Beatmap, Strains, GameMode, Performance, PerformanceAttributes
5
5
 
6
+ from .exceptions import NetworkError
6
7
  from .schema.score import UnifiedScore
7
8
 
8
9
  is_v2 = importlib.metadata.version("pydantic").startswith("2")
@@ -10,6 +11,8 @@ is_v2 = importlib.metadata.version("pydantic").startswith("2")
10
11
 
11
12
  def cal_pp(score: UnifiedScore, path: str, is_lazer: bool) -> PerformanceAttributes:
12
13
  beatmap = Beatmap(path=path)
14
+ if beatmap.is_suspicious():
15
+ raise NetworkError("这似乎不是一个正常谱面 OAO")
13
16
  convert_mode(score, beatmap)
14
17
  c = Performance(
15
18
  accuracy=score.accuracy,
@@ -31,6 +34,8 @@ def cal_pp(score: UnifiedScore, path: str, is_lazer: bool) -> PerformanceAttribu
31
34
 
32
35
  def get_if_pp_ss_pp(score: UnifiedScore, path: str, is_lazer: bool) -> tuple:
33
36
  beatmap = Beatmap(path=path)
37
+ if beatmap.is_suspicious():
38
+ return "nan", "nan"
34
39
  convert_mode(score, beatmap)
35
40
  total = beatmap.n_objects
36
41
  passed = score.statistics.great + score.statistics.miss + score.statistics.ok + score.statistics.meh
@@ -62,6 +67,8 @@ def get_if_pp_ss_pp(score: UnifiedScore, path: str, is_lazer: bool) -> tuple:
62
67
 
63
68
  def get_ss_pp(path: str, mods: int, is_lazer) -> PerformanceAttributes:
64
69
  beatmap = Beatmap(path=path)
70
+ if beatmap.is_suspicious():
71
+ raise NetworkError("这似乎不是一个正常谱面 OAO")
65
72
  c = Performance(accuracy=100, mods=mods, lazer=is_lazer)
66
73
  ss_pp_info = c.calculate(beatmap)
67
74
  return ss_pp_info