koishi-plugin-noah 1.6.2 → 1.7.1
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.
- package/lib/core/utils/card.d.ts +4 -4
- package/lib/games/sdvx/services/music-service.d.ts +9 -3
- package/lib/games/sdvx/types/index.d.ts +42 -40
- package/lib/index.cjs +279 -67
- package/lib/servers/Official/index.d.ts +14 -0
- package/lib/servers/Official/services/sdvx-service.d.ts +29 -0
- package/lib/types/config.d.ts +4 -0
- package/lib/types/index.d.ts +7 -7
- package/package.json +1 -1
package/lib/core/utils/card.d.ts
CHANGED
|
@@ -14,16 +14,16 @@ export declare function uidToKonamiId(uid: string): string;
|
|
|
14
14
|
*/
|
|
15
15
|
export declare function konamiIdToUid(konamiId: string): string;
|
|
16
16
|
/**
|
|
17
|
-
* 判断给定的字符串是 UID、KONAMI ID 还是非法字符串
|
|
17
|
+
* 判断给定的字符串是 UID、KONAMI ID、Official ID 还是非法字符串
|
|
18
18
|
* @param ctx - Koishi Context 对象
|
|
19
19
|
* @param input - 待判断的字符串
|
|
20
|
-
* @returns "uid" 表示 e-Amusement UID, "konamiid" 表示 KONAMI ID, "invalid" 表示非法字符串
|
|
20
|
+
* @returns "uid" 表示 e-Amusement UID, "konamiid" 表示 KONAMI ID, "access" 表示 Access Code, "official" 表示 Official Server ID (SV-xxxx-xxxx), "invalid" 表示非法字符串
|
|
21
21
|
*/
|
|
22
|
-
export declare function classifyCardId(ctx: Context, input: string): 'uid' | 'konamiid' | 'access' | 'invalid';
|
|
22
|
+
export declare function classifyCardId(ctx: Context, input: string): 'uid' | 'konamiid' | 'access' | 'official' | 'invalid';
|
|
23
23
|
/**
|
|
24
24
|
* 处理用户输入的卡号
|
|
25
25
|
* @param input - 用户输入的卡号
|
|
26
|
-
* @returns 删去空格的全大写字符串,并转换特殊字符(I→1, O/Q→0, V→U)
|
|
26
|
+
* @returns 删去空格的全大写字符串,并转换特殊字符(I→1, O/Q→0, V→U),但SV卡号不做替换
|
|
27
27
|
*/
|
|
28
28
|
export declare function processInputCardCode(input: string): string;
|
|
29
29
|
/**
|
|
@@ -13,12 +13,18 @@ export declare class MusicService {
|
|
|
13
13
|
*/
|
|
14
14
|
static getInstance(config: SDVXConfig): MusicService;
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* 获取音乐信息(支持数字和字符串 ID)
|
|
17
17
|
* @param ctx - Koishi 上下文对象
|
|
18
|
-
* @param musicIds - 音乐 ID
|
|
18
|
+
* @param musicIds - 音乐 ID 数组(数字或字符串)
|
|
19
19
|
* @returns 音乐信息数组
|
|
20
20
|
*/
|
|
21
|
-
getMusic(ctx: Context, musicIds: number[]): Promise<SDVXMusic[]>;
|
|
21
|
+
getMusic(ctx: Context, musicIds: (number | string)[]): Promise<SDVXMusic[]>;
|
|
22
|
+
/**
|
|
23
|
+
* 转换外部音乐数据到标准格式
|
|
24
|
+
* @param externalData - 外部音乐数据数组
|
|
25
|
+
* @returns 标准格式音乐数据数组
|
|
26
|
+
*/
|
|
27
|
+
private convertExternalToStandard;
|
|
22
28
|
/**
|
|
23
29
|
* 根据曲名查询歌曲
|
|
24
30
|
* @param ctx - Koishi 上下文对象
|
|
@@ -8,7 +8,7 @@ export interface SDVXProfile {
|
|
|
8
8
|
*/
|
|
9
9
|
export interface SDVXScore {
|
|
10
10
|
music: {
|
|
11
|
-
music_id: number;
|
|
11
|
+
music_id: number | string;
|
|
12
12
|
music_diff: number;
|
|
13
13
|
music_diff_name: string;
|
|
14
14
|
music_diff_full_name: string;
|
|
@@ -42,20 +42,20 @@ export type SDVXClearType = 'S-PUC' | 'PUC' | 'UC' | 'MC' | 'HC' | 'NC' | 'PLAYE
|
|
|
42
42
|
export interface SDVXMusicDifficulty {
|
|
43
43
|
difstr: string;
|
|
44
44
|
difnum: number;
|
|
45
|
-
raw_illustrator
|
|
46
|
-
illustrator
|
|
47
|
-
raw_effected_by
|
|
48
|
-
effected_by
|
|
49
|
-
price
|
|
50
|
-
limited
|
|
51
|
-
jacket_print
|
|
52
|
-
jacket_mask
|
|
53
|
-
max_exscore
|
|
54
|
-
max_chain
|
|
55
|
-
chip_count
|
|
56
|
-
hold_count
|
|
57
|
-
tsumami_count
|
|
58
|
-
radar
|
|
45
|
+
raw_illustrator?: string;
|
|
46
|
+
illustrator?: string;
|
|
47
|
+
raw_effected_by?: string;
|
|
48
|
+
effected_by?: string;
|
|
49
|
+
price?: number;
|
|
50
|
+
limited?: number;
|
|
51
|
+
jacket_print?: number;
|
|
52
|
+
jacket_mask?: number;
|
|
53
|
+
max_exscore?: number;
|
|
54
|
+
max_chain?: number;
|
|
55
|
+
chip_count?: number;
|
|
56
|
+
hold_count?: number;
|
|
57
|
+
tsumami_count?: number;
|
|
58
|
+
radar?: {
|
|
59
59
|
notes: number;
|
|
60
60
|
peak: number;
|
|
61
61
|
tsumami: number;
|
|
@@ -63,38 +63,40 @@ export interface SDVXMusicDifficulty {
|
|
|
63
63
|
hand_trip: number;
|
|
64
64
|
one_hand: number;
|
|
65
65
|
};
|
|
66
|
-
big_cover_url
|
|
66
|
+
big_cover_url?: string;
|
|
67
67
|
cover_url: string;
|
|
68
|
-
chart_url
|
|
69
|
-
mirror_chart_url
|
|
68
|
+
chart_url?: string;
|
|
69
|
+
mirror_chart_url?: string;
|
|
70
|
+
inf_ver?: number;
|
|
70
71
|
}
|
|
71
72
|
/**
|
|
72
73
|
* SDVX 音乐数据接口
|
|
73
74
|
*/
|
|
74
75
|
export interface SDVXMusic {
|
|
75
|
-
id: number;
|
|
76
|
-
label
|
|
77
|
-
raw_title_name
|
|
76
|
+
id: number | string;
|
|
77
|
+
label?: string;
|
|
78
|
+
raw_title_name?: string;
|
|
78
79
|
title_name: string;
|
|
79
|
-
main_title_name
|
|
80
|
-
sub_title_name
|
|
81
|
-
title_yomigana
|
|
82
|
-
title_romaji
|
|
83
|
-
raw_artist_name
|
|
80
|
+
main_title_name?: string;
|
|
81
|
+
sub_title_name?: string;
|
|
82
|
+
title_yomigana?: string;
|
|
83
|
+
title_romaji?: string;
|
|
84
|
+
raw_artist_name?: string;
|
|
84
85
|
artist_name: string;
|
|
85
|
-
artist_yomigana
|
|
86
|
-
artist_romaji
|
|
87
|
-
ascii
|
|
88
|
-
bpm_max
|
|
89
|
-
bpm_min
|
|
90
|
-
distribution_date
|
|
91
|
-
volume
|
|
92
|
-
bg_no
|
|
93
|
-
genre
|
|
94
|
-
genre_name
|
|
95
|
-
is_fixed
|
|
96
|
-
version
|
|
97
|
-
demo_pri
|
|
98
|
-
inf_ver
|
|
86
|
+
artist_yomigana?: string;
|
|
87
|
+
artist_romaji?: string;
|
|
88
|
+
ascii?: string;
|
|
89
|
+
bpm_max?: string;
|
|
90
|
+
bpm_min?: string;
|
|
91
|
+
distribution_date?: string;
|
|
92
|
+
volume?: number;
|
|
93
|
+
bg_no?: number;
|
|
94
|
+
genre?: number;
|
|
95
|
+
genre_name?: string;
|
|
96
|
+
is_fixed?: number;
|
|
97
|
+
version?: number;
|
|
98
|
+
demo_pri?: number;
|
|
99
|
+
inf_ver?: number;
|
|
99
100
|
difficulty: SDVXMusicDifficulty[];
|
|
101
|
+
source_url?: string;
|
|
100
102
|
}
|
package/lib/index.cjs
CHANGED
|
@@ -676,6 +676,10 @@ function konamiIdToUid(konamiId) {
|
|
|
676
676
|
}
|
|
677
677
|
__name(konamiIdToUid, "konamiIdToUid");
|
|
678
678
|
function classifyCardId(ctx, input) {
|
|
679
|
+
const officialRegex = /^SV-\d{4}-\d{4}$/i;
|
|
680
|
+
if (officialRegex.test(input)) {
|
|
681
|
+
return "official";
|
|
682
|
+
}
|
|
679
683
|
if (input.length === 20) {
|
|
680
684
|
try {
|
|
681
685
|
accessToUid(ctx, input);
|
|
@@ -709,7 +713,11 @@ function classifyCardId(ctx, input) {
|
|
|
709
713
|
}
|
|
710
714
|
__name(classifyCardId, "classifyCardId");
|
|
711
715
|
function processInputCardCode(input) {
|
|
712
|
-
|
|
716
|
+
const trimmed = input.replaceAll(" ", "").toUpperCase();
|
|
717
|
+
if (/^SV-\d{4}-\d{4}$/i.test(trimmed)) {
|
|
718
|
+
return trimmed;
|
|
719
|
+
}
|
|
720
|
+
return trimmed.replace(/[IOQV]/gi, (match) => {
|
|
713
721
|
switch (match.toUpperCase()) {
|
|
714
722
|
case "I":
|
|
715
723
|
return "1";
|
|
@@ -798,7 +806,8 @@ function bind(ctx, config) {
|
|
|
798
806
|
if (!cardCode) return session.text("commands.timeout");
|
|
799
807
|
}
|
|
800
808
|
cardCode = processInputCardCode(cardCode);
|
|
801
|
-
|
|
809
|
+
const cardType = classifyCardId(ctx, cardCode);
|
|
810
|
+
switch (cardType) {
|
|
802
811
|
case "invalid":
|
|
803
812
|
return session.text(".invalid-code");
|
|
804
813
|
case "access":
|
|
@@ -807,6 +816,8 @@ function bind(ctx, config) {
|
|
|
807
816
|
case "konamiid":
|
|
808
817
|
cardCode = konamiIdToUid(cardCode);
|
|
809
818
|
break;
|
|
819
|
+
case "official":
|
|
820
|
+
break;
|
|
810
821
|
}
|
|
811
822
|
if (await cardService.getCardByCode(cardCode) != null)
|
|
812
823
|
return session.text(".duplicate");
|
|
@@ -1136,7 +1147,8 @@ async function showCardMenu(ctx, session, card2, cardService, serverService, use
|
|
|
1136
1147
|
);
|
|
1137
1148
|
if (cardCode === "q") return session.text(".quit");
|
|
1138
1149
|
cardCode = processInputCardCode(cardCode);
|
|
1139
|
-
|
|
1150
|
+
const cardType = classifyCardId(ctx, cardCode);
|
|
1151
|
+
switch (cardType) {
|
|
1140
1152
|
case "invalid":
|
|
1141
1153
|
return session.text(".menu-2-error-invalid-code");
|
|
1142
1154
|
case "access":
|
|
@@ -1144,6 +1156,9 @@ async function showCardMenu(ctx, session, card2, cardService, serverService, use
|
|
|
1144
1156
|
break;
|
|
1145
1157
|
case "konamiid":
|
|
1146
1158
|
cardCode = konamiIdToUid(cardCode);
|
|
1159
|
+
break;
|
|
1160
|
+
case "official":
|
|
1161
|
+
break;
|
|
1147
1162
|
}
|
|
1148
1163
|
if (await cardService.getCardByCode(cardCode) != null) return session.text(".duplicate");
|
|
1149
1164
|
await cardService.updateCard(card2.id, { code: cardCode });
|
|
@@ -1314,7 +1329,7 @@ __name(maintain, "maintain");
|
|
|
1314
1329
|
var import_koishi3 = require("koishi");
|
|
1315
1330
|
|
|
1316
1331
|
// src/types/index.ts
|
|
1317
|
-
var serverValues = ["asphyxia", "mao"];
|
|
1332
|
+
var serverValues = ["asphyxia", "mao", "official"];
|
|
1318
1333
|
|
|
1319
1334
|
// src/core/commands/server.ts
|
|
1320
1335
|
function normalizeUrl(url) {
|
|
@@ -1613,6 +1628,8 @@ async function addServer(ctx, session, serverService, userService, from, uid, us
|
|
|
1613
1628
|
let url;
|
|
1614
1629
|
if (serverType === "mao") {
|
|
1615
1630
|
url = ctx.config.maoServerUrl;
|
|
1631
|
+
} else if (serverType === "official") {
|
|
1632
|
+
url = ctx.config.sdvx.official_support_url;
|
|
1616
1633
|
} else {
|
|
1617
1634
|
let attempts = 0;
|
|
1618
1635
|
const maxAttempts = 3;
|
|
@@ -1923,10 +1940,10 @@ function apply4(ctx, config) {
|
|
|
1923
1940
|
__name(apply4, "apply");
|
|
1924
1941
|
|
|
1925
1942
|
// src/core/locales/en-US.yml
|
|
1926
|
-
var en_US_default2 = { _config: { $desc: "Core Module Settings", adminUsers: "**Plugin Admin** User ID (use inspect command to get)", guildNameCards: "**Group Card** Name List" }, commands: { maintain: { description: "Switch to maintenance mode", messages: { "no-auth": "<p>You don't have permission to use this feature~</p>", start: "<p>Entering maintenance mode</p>", "success-start": "<p>Successfully switched to maintenance mode</p>", stop: "<p>Exiting maintenance mode</p>", "success-stop": "<p>Successfully exited maintenance mode</p>" } }, timeout: "Noah didn't wait for your reply, please try again!", noah: { help: { description: "Show Noah help information", messages: { content: "<p>Guide:</p>\n<a>https://docs.logthm.cn/noah</a>" } } }, locale: { description: "Set language", messages: { "no-auth": "<p>Only group admins can use this feature~</p>", "invalid-select": "<p>No such option!</p>", quit: "<p>Quit!</p>", "reset-channel": "<p>Reset successfully!</p>", "reset-user": "<p>Reset successfully!</p>", success: "<p>Set successfully!</p>", "set-channel": "<p>Select the default language for group chats:</p>\n<p>1. 简体中文</p>\n<p>2. English</p>\n<p>q. Quit</p>", "set-user": "<p>Select the language you use:</p>\n<p>1. 中文</p>\n<p>2. English</p>\n<p>q. Quit</p>" } }, bind: { description: "Bind card", messages: { prompt: "<p>Please enter your card number:</p>", "invalid-code": "<p>The card number is incorrect, if you don't remember it, go to the arcade to check it~</p>", duplicate: "<p>This card has already been bound (︶^︶)</p>", name: "<p>Received! Please give this card a name, no spaces allowed:</p>", invalid_name: "<p>No spaces allowed! Please try again o(一︿一+)o</p>", success: "<p>Bound successfully, your card information is as follows:</p>\n<p>[{cardName}]</p>\n<p>{cardCode}</p>" } }, card: { description: "Manage cards", options: { detail: "Show detailed card information" }, messages: { "invalid-code": "<p>The card number is incorrect, if you don't remember it, go to the arcade to check it~</p>", "invalid-select": "<p>No such option!</p>", "lookup-error": "Lookup failed: {message}", "lookup-error-unknown": "Lookup failed: unknown error", "menu-select": "<p>[Card Management]</p>\n{card_list}\n<p>0. Add new card</p>\n<p>Please enter the serial number:</p>", menu: "<p>[{name}]</p>\n<p>1. Set as default card</p>\n<p>2. View or modify card number</p>\n<p>3. Delete the card</p>\n<p>4. Rename the card</p>\n<p>5. Bind the card to a specified server</p>\n<p>0. Return to card selection</p>\n<p>Please enter the serial number:</p>", "menu-has-bound-server": "<p>[{name}]</p>\n<p>Bound server: {defaultServerName}</p>\n<p>1. Set as default card</p>\n<p>2. View or modify card number</p>\n<p>3. Delete the card</p>\n<p>4. Rename the card</p>\n<p>5. Bind the card to a specified server</p>\n<p>0. Return to card selection</p>\n<p>Please enter the serial number:</p>", "menu-1-success": "<p>Set successfully!</p>", "menu-1-error-duplicate": "<p>The selected card is the same as the old default card!</p>", "menu-2-prompt": "<p>Card number: {code}</p>\n<p>Please enter the new card number:</p>\n<p>Enter 0 to return</p>", "menu-2-success": "<p>Modified successfully!</p>", "menu-2-error-invalid-code": "<p>The card number is incorrect, if you don't remember it, go to the arcade to check it~</p>", "menu-3-success": "<p>Deleted successfully!</p>", "menu-4-prompt": "<p>Enter a new name, no spaces allowed:</p>", "menu-4-error-invalid-name": "<p>No spaces allowed! Please try again o(一︿一+)o</p>", "menu-4-success": "<p>Modified successfully!</p>", "menu-5": "{server_list}\n<p>Please enter the serial number:</p>", "menu-5-success": "<p>Set successfully!</p>", "menu-5-error-duplicate": "<p>The selected server is the same as the old default server!</p>" } }, server: { description: "Manage servers", messages: { "no-channel": "<p>Please use this feature in group chats~</p>", "invalid-select": "<p>No such option!</p>", "no-auth": "<p>Only group admins can use this feature~</p>", "admin-menu-select": "<p>[Group server management]</p>\n{server_list}\n<p>0. Add new server</p>\n<p>Please enter the serial number:</p>", "menu-select": "<p>[Server management]</p>\n{server_list}\n<p>0. Add new server</p>\n<p>Please enter the serial number:</p>", menu: "<p>[{name}]</p>\n<p>Type: {type}</p>\n<p>1. Set as default server</p>\n<p>2. View or modify url</p>\n<p>3. Delete the server</p>\n<p>4. Rename the server</p>\n<p>0. Return to server selection</p>\n<p>Please enter the serial number:</p>", "menu-1-success": "<p>Set successfully!</p>", "menu-1-error-duplicate": "<p>The selected server is the same as the old default server!</p>", "menu-2-prompt": "<p>The server's url: {baseUrl}</p>\n<p>Please enter the new server url:</p>\n<p>Enter 0 to return</p>", "menu-2-success": "<p>Modified successfully!</p>", "menu-2-invalid-url": "<p>Invalid URL format! Please enter a valid url address.</p>", "menu-2-too-many-attempts": "<p>Too many attempts. Operation cancelled.</p>", "menu-3-success": "<p>Deleted successfully!</p>", "menu-4-prompt": "<p>Enter a new name, no spaces allowed:</p>", "menu-4-error-invalid-name": "<p>No spaces allowed! Please try again o(一︿一+)o</p>", "menu-4-success": "<p>Modified successfully!</p>", "add-type": "<p>Please select the server type:</p>\n{server_type_list}", "add-url": "<p>Please enter the server url:</p>", "add-invalid-url": "<p>Invalid URL format! Please enter a valid url address.</p>", "add-too-many-attempts": "<p>Too many attempts. Operation cancelled.</p>", "add-name": "<p>Received! Please give the server a name, no spaces allowed:</p>", "add-invalid_name": "<p>No spaces allowed! Please try again o(一︿一+)o</p>", "add-success": "<p>Added successfully, the server information is as follows:</p>\n<p>[{serverName}]</p>\n<p>Type: {serverType}</p>" } } } };
|
|
1943
|
+
var en_US_default2 = { _config: { $desc: "Core Module Settings", adminUsers: "**Plugin Admin** User ID (use inspect command to get)", guildNameCards: "**Group Card** Name List", maoServerUrl: "**Mao Server** URL address", official_support_url: "**Official Support** URL address" }, commands: { maintain: { description: "Switch to maintenance mode", messages: { "no-auth": "<p>You don't have permission to use this feature~</p>", start: "<p>Entering maintenance mode</p>", "success-start": "<p>Successfully switched to maintenance mode</p>", stop: "<p>Exiting maintenance mode</p>", "success-stop": "<p>Successfully exited maintenance mode</p>" } }, timeout: "Noah didn't wait for your reply, please try again!", noah: { help: { description: "Show Noah help information", messages: { content: "<p>Guide:</p>\n<a>https://docs.logthm.cn/noah</a>" } } }, locale: { description: "Set language", messages: { "no-auth": "<p>Only group admins can use this feature~</p>", "invalid-select": "<p>No such option!</p>", quit: "<p>Quit!</p>", "reset-channel": "<p>Reset successfully!</p>", "reset-user": "<p>Reset successfully!</p>", success: "<p>Set successfully!</p>", "set-channel": "<p>Select the default language for group chats:</p>\n<p>1. 简体中文</p>\n<p>2. English</p>\n<p>q. Quit</p>", "set-user": "<p>Select the language you use:</p>\n<p>1. 中文</p>\n<p>2. English</p>\n<p>q. Quit</p>" } }, bind: { description: "Bind card", messages: { prompt: "<p>Please enter your card number:</p>", "invalid-code": "<p>The card number is incorrect, if you don't remember it, go to the arcade to check it~</p>", duplicate: "<p>This card has already been bound (︶^︶)</p>", name: "<p>Received! Please give this card a name, no spaces allowed:</p>", invalid_name: "<p>No spaces allowed! Please try again o(一︿一+)o</p>", success: "<p>Bound successfully, your card information is as follows:</p>\n<p>[{cardName}]</p>\n<p>{cardCode}</p>" } }, card: { description: "Manage cards", options: { detail: "Show detailed card information" }, messages: { "invalid-code": "<p>The card number is incorrect, if you don't remember it, go to the arcade to check it~</p>", "invalid-select": "<p>No such option!</p>", "lookup-error": "Lookup failed: {message}", "lookup-error-unknown": "Lookup failed: unknown error", "menu-select": "<p>[Card Management]</p>\n{card_list}\n<p>0. Add new card</p>\n<p>Please enter the serial number:</p>", menu: "<p>[{name}]</p>\n<p>1. Set as default card</p>\n<p>2. View or modify card number</p>\n<p>3. Delete the card</p>\n<p>4. Rename the card</p>\n<p>5. Bind the card to a specified server</p>\n<p>0. Return to card selection</p>\n<p>Please enter the serial number:</p>", "menu-has-bound-server": "<p>[{name}]</p>\n<p>Bound server: {defaultServerName}</p>\n<p>1. Set as default card</p>\n<p>2. View or modify card number</p>\n<p>3. Delete the card</p>\n<p>4. Rename the card</p>\n<p>5. Bind the card to a specified server</p>\n<p>0. Return to card selection</p>\n<p>Please enter the serial number:</p>", "menu-1-success": "<p>Set successfully!</p>", "menu-1-error-duplicate": "<p>The selected card is the same as the old default card!</p>", "menu-2-prompt": "<p>Card number: {code}</p>\n<p>Please enter the new card number:</p>\n<p>Enter 0 to return</p>", "menu-2-success": "<p>Modified successfully!</p>", "menu-2-error-invalid-code": "<p>The card number is incorrect, if you don't remember it, go to the arcade to check it~</p>", "menu-3-success": "<p>Deleted successfully!</p>", "menu-4-prompt": "<p>Enter a new name, no spaces allowed:</p>", "menu-4-error-invalid-name": "<p>No spaces allowed! Please try again o(一︿一+)o</p>", "menu-4-success": "<p>Modified successfully!</p>", "menu-5": "{server_list}\n<p>Please enter the serial number:</p>", "menu-5-success": "<p>Set successfully!</p>", "menu-5-error-duplicate": "<p>The selected server is the same as the old default server!</p>" } }, server: { description: "Manage servers", messages: { "no-channel": "<p>Please use this feature in group chats~</p>", "invalid-select": "<p>No such option!</p>", "no-auth": "<p>Only group admins can use this feature~</p>", "admin-menu-select": "<p>[Group server management]</p>\n{server_list}\n<p>0. Add new server</p>\n<p>Please enter the serial number:</p>", "menu-select": "<p>[Server management]</p>\n{server_list}\n<p>0. Add new server</p>\n<p>Please enter the serial number:</p>", menu: "<p>[{name}]</p>\n<p>Type: {type}</p>\n<p>1. Set as default server</p>\n<p>2. View or modify url</p>\n<p>3. Delete the server</p>\n<p>4. Rename the server</p>\n<p>0. Return to server selection</p>\n<p>Please enter the serial number:</p>", "menu-1-success": "<p>Set successfully!</p>", "menu-1-error-duplicate": "<p>The selected server is the same as the old default server!</p>", "menu-2-prompt": "<p>The server's url: {baseUrl}</p>\n<p>Please enter the new server url:</p>\n<p>Enter 0 to return</p>", "menu-2-success": "<p>Modified successfully!</p>", "menu-2-invalid-url": "<p>Invalid URL format! Please enter a valid url address.</p>", "menu-2-too-many-attempts": "<p>Too many attempts. Operation cancelled.</p>", "menu-3-success": "<p>Deleted successfully!</p>", "menu-4-prompt": "<p>Enter a new name, no spaces allowed:</p>", "menu-4-error-invalid-name": "<p>No spaces allowed! Please try again o(一︿一+)o</p>", "menu-4-success": "<p>Modified successfully!</p>", "add-type": "<p>Please select the server type:</p>\n{server_type_list}", "add-url": "<p>Please enter the server url:</p>", "add-invalid-url": "<p>Invalid URL format! Please enter a valid url address.</p>", "add-too-many-attempts": "<p>Too many attempts. Operation cancelled.</p>", "add-name": "<p>Received! Please give the server a name, no spaces allowed:</p>", "add-invalid_name": "<p>No spaces allowed! Please try again o(一︿一+)o</p>", "add-success": "<p>Added successfully, the server information is as follows:</p>\n<p>[{serverName}]</p>\n<p>Type: {serverType}</p>" } } } };
|
|
1927
1944
|
|
|
1928
1945
|
// src/core/locales/zh-CN.yml
|
|
1929
|
-
var zh_CN_default2 = { _config: { $desc: "Core 模块设置", adminUsers: "**插件管理员** 的用户id (使用 inspect 指令获取)", guildNameCards: "**群聊卡片** 的名称列表" }, commands: { maintain: { description: "切换到维护模式", messages: { "no-auth": "<p>你没有权限使用本功能哦~</p>", start: "<p>正在进入维护模式</p>", "success-start": "<p>成功切换到维护模式</p>", stop: "<p>正在退出维护模式</p>", "success-stop": "<p>成功退出维护模式</p>" } }, timeout: "Noah 没等到你的回复,请重试!", noah: { help: { description: "显示 Noah 帮助信息", messages: { content: "<p>使用文档:</p>\n<a>https://docs.logthm.cn/noah</a>" } } }, locale: { description: "设置语言", messages: { "no-auth": "<p>只有群管理员能使用本功能哦~</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>", "reset-channel": "<p>重置成功!</p>", "reset-user": "<p>重置成功!</p>", success: "<p>设置成功!</p>", "set-channel": "<p>选择群聊默认使用的语言:</p>\n<p>1. 简体中文</p>\n<p>2. English</p>\n<p>q. 退出</p>", "set-user": "<p>选择你使用的语言:</p>\n<p>1. 简体中文</p>\n<p>2. English</p>\n<p>q. 退出</p>" } }, bind: { description: "绑定卡片", messages: { prompt: "<p>请输入你的卡号:</p>", "invalid-code": "<p>卡号不对哟,不记得的话去机台刷一下吧~</p>", duplicate: "<p>这张卡已经被绑定啦 (︶^︶)</p>", name: "<p>收到!为这张卡取一个名字吧,不要带空格哦:</p>", invalid_name: "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", success: "<p>绑好啦,你的卡片信息如下:</p>\n<p>[{cardName}]</p>\n<p>{cardCode}</p>" } }, card: { description: "管理卡片", options: { detail: "显示卡片详细信息" }, messages: { "invalid-code": "<p>卡号不对哟,不记得的话去机台刷一下吧~</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>", "lookup-error": "查询失败: {message}", "lookup-error-unknown": "查询失败: 未知错误", "menu-select": "<p>[卡片管理]</p>\n{card_list}\n<p>0. 添加新卡片</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", menu: "<p>[{name}]</p>\n<p>1. 设为默认卡片</p>\n<p>2. 查看或修改卡号</p>\n<p>3. 删除该卡</p>\n<p>4. 重命名该卡片</p>\n<p>5. 将卡片与指定服务器绑定</p>\n<p>0. 返回卡片选择</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-has-bound-server": "<p>[{name}]</p>\n<p>已绑定服务器:{defaultServerName}</p>\n<p>1. 设为默认卡片</p>\n<p>2. 查看或修改卡号</p>\n<p>3. 删除该卡</p>\n<p>4. 重命名该卡片</p>\n<p>5. 将卡片与指定服务器绑定</p>\n<p>0. 返回卡片选择</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-1-success": "<p>设置成功!</p>", "menu-1-error-duplicate": "<p>选择的卡片与旧的默认卡片相同!</p>", "menu-2-prompt": "<p>卡号:{code}</p>\n<p>请输入新的卡号:</p>\n<p>0. 返回</p>\n<p>q. 退出</p>", "menu-2-success": "<p>修改成功!</p>", "menu-2-error-invalid-code": "<p>卡号不对哟,不记得的话去机台刷一下吧~</p>", "menu-3-success": "<p>已删除!</p>", "menu-4-prompt": "<p>输入一个新名字,不要带空格哦:</p>\n<p>q. 退出</p>", "menu-4-error-invalid-name": "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", "menu-4-success": "<p>修改成功!</p>", "menu-5": "<p>请选择一个服务器:</p>\n{server_list}\n<p>q. 退出</p>", "menu-5-success": "<p>设置成功!</p>", "menu-5-error-duplicate": "<p>选择的服务器与旧的默认服务器相同!</p>" } }, server: { description: "管理服务器", messages: { "no-channel": "<p>请在群聊中使用本功能哦~</p>", "invalid-select": "<p>没有该选项!</p>", "no-auth": "<p>只有群管理员能使用本功能哦~</p>", quit: "<p>已退出~</p>", "admin-menu-select": "<p>[群聊服务器管理]</p>\n{server_list}\n<p>0. 添加新服务器</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-select": "<p>[服务器管理]</p>\n{server_list}\n<p>0. 添加新服务器</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", menu: "<p>[{name}]</p>\n<p>类型:{type}</p>\n<p>1. 设为默认服务器</p>\n<p>2. 查看或修改 url</p>\n<p>3. 删除该服务器</p>\n<p>4. 重命名该服务器</p>\n<p>0. 返回服务器选择</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-1-success": "<p>设置成功!</p>", "menu-1-error-duplicate": "<p>选择的服务器与旧的默认服务器相同!</p>", "menu-2-prompt": "<p>该服务器的 url:{baseUrl}</p>\n<p>请输入新的服务器 url:</p>\n<p>0. 返回</p>\n<p>q. 退出</p>", "menu-2-success": "<p>修改成功!</p>", "menu-2-invalid-url": "<p>URL 格式不正确!请输入有效的 url 地址。</p>", "menu-2-too-many-attempts": "<p>尝试次数过多,操作已取消。</p>", "menu-3-success": "<p>已删除!</p>", "menu-4-prompt": "<p>输入一个新名字,不要带空格哦:</p>\n<p>0. 返回</p>\n<p>q. 退出</p>", "menu-4-error-invalid-name": "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", "menu-4-success": "<p>修改成功!</p>", "add-type": "<p>请选择服务器的类型:</p>\n{server_type_list}\n<p>q. 退出</p>", "add-url": "<p>请输入服务器的 url:</p>\n<p>q. 退出</p>", "add-invalid-url": "<p>URL 格式不正确!请输入有效的 url 地址。</p>", "add-too-many-attempts": "<p>尝试次数过多,操作已取消。</p>", "add-name": "<p>收到!为服务器取一个名字吧,不要带空格哦:</p>\n<p>q. 退出</p>", "add-invalid_name": "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", "add-success": "<p>添加成功啦,服务器信息如下:</p>\n<p>[{serverName}]</p>\n<p>类型:{serverType}</p>" } } } };
|
|
1946
|
+
var zh_CN_default2 = { _config: { $desc: "Core 模块设置", adminUsers: "**插件管理员** 的用户id (使用 inspect 指令获取)", guildNameCards: "**群聊卡片** 的名称列表", maoServerUrl: "**猫网服务器** 的 URL 地址", official_support_url: "**官方支持** 的 URL 地址" }, commands: { maintain: { description: "切换到维护模式", messages: { "no-auth": "<p>你没有权限使用本功能哦~</p>", start: "<p>正在进入维护模式</p>", "success-start": "<p>成功切换到维护模式</p>", stop: "<p>正在退出维护模式</p>", "success-stop": "<p>成功退出维护模式</p>" } }, timeout: "Noah 没等到你的回复,请重试!", noah: { help: { description: "显示 Noah 帮助信息", messages: { content: "<p>使用文档:</p>\n<a>https://docs.logthm.cn/noah</a>" } } }, locale: { description: "设置语言", messages: { "no-auth": "<p>只有群管理员能使用本功能哦~</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>", "reset-channel": "<p>重置成功!</p>", "reset-user": "<p>重置成功!</p>", success: "<p>设置成功!</p>", "set-channel": "<p>选择群聊默认使用的语言:</p>\n<p>1. 简体中文</p>\n<p>2. English</p>\n<p>q. 退出</p>", "set-user": "<p>选择你使用的语言:</p>\n<p>1. 简体中文</p>\n<p>2. English</p>\n<p>q. 退出</p>" } }, bind: { description: "绑定卡片", messages: { prompt: "<p>请输入你的卡号:</p>", "invalid-code": "<p>卡号不对哟,不记得的话去机台刷一下吧~</p>", duplicate: "<p>这张卡已经被绑定啦 (︶^︶)</p>", name: "<p>收到!为这张卡取一个名字吧,不要带空格哦:</p>", invalid_name: "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", success: "<p>绑好啦,你的卡片信息如下:</p>\n<p>[{cardName}]</p>\n<p>{cardCode}</p>" } }, card: { description: "管理卡片", options: { detail: "显示卡片详细信息" }, messages: { "invalid-code": "<p>卡号不对哟,不记得的话去机台刷一下吧~</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>", "lookup-error": "查询失败: {message}", "lookup-error-unknown": "查询失败: 未知错误", "menu-select": "<p>[卡片管理]</p>\n{card_list}\n<p>0. 添加新卡片</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", menu: "<p>[{name}]</p>\n<p>1. 设为默认卡片</p>\n<p>2. 查看或修改卡号</p>\n<p>3. 删除该卡</p>\n<p>4. 重命名该卡片</p>\n<p>5. 将卡片与指定服务器绑定</p>\n<p>0. 返回卡片选择</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-has-bound-server": "<p>[{name}]</p>\n<p>已绑定服务器:{defaultServerName}</p>\n<p>1. 设为默认卡片</p>\n<p>2. 查看或修改卡号</p>\n<p>3. 删除该卡</p>\n<p>4. 重命名该卡片</p>\n<p>5. 将卡片与指定服务器绑定</p>\n<p>0. 返回卡片选择</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-1-success": "<p>设置成功!</p>", "menu-1-error-duplicate": "<p>选择的卡片与旧的默认卡片相同!</p>", "menu-2-prompt": "<p>卡号:{code}</p>\n<p>请输入新的卡号:</p>\n<p>0. 返回</p>\n<p>q. 退出</p>", "menu-2-success": "<p>修改成功!</p>", "menu-2-error-invalid-code": "<p>卡号不对哟,不记得的话去机台刷一下吧~</p>", "menu-3-success": "<p>已删除!</p>", "menu-4-prompt": "<p>输入一个新名字,不要带空格哦:</p>\n<p>q. 退出</p>", "menu-4-error-invalid-name": "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", "menu-4-success": "<p>修改成功!</p>", "menu-5": "<p>请选择一个服务器:</p>\n{server_list}\n<p>q. 退出</p>", "menu-5-success": "<p>设置成功!</p>", "menu-5-error-duplicate": "<p>选择的服务器与旧的默认服务器相同!</p>" } }, server: { description: "管理服务器", messages: { "no-channel": "<p>请在群聊中使用本功能哦~</p>", "invalid-select": "<p>没有该选项!</p>", "no-auth": "<p>只有群管理员能使用本功能哦~</p>", quit: "<p>已退出~</p>", "admin-menu-select": "<p>[群聊服务器管理]</p>\n{server_list}\n<p>0. 添加新服务器</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-select": "<p>[服务器管理]</p>\n{server_list}\n<p>0. 添加新服务器</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", menu: "<p>[{name}]</p>\n<p>类型:{type}</p>\n<p>1. 设为默认服务器</p>\n<p>2. 查看或修改 url</p>\n<p>3. 删除该服务器</p>\n<p>4. 重命名该服务器</p>\n<p>0. 返回服务器选择</p>\n<p>q. 退出菜单</p>\n<p>请输入序号:</p>", "menu-1-success": "<p>设置成功!</p>", "menu-1-error-duplicate": "<p>选择的服务器与旧的默认服务器相同!</p>", "menu-2-prompt": "<p>该服务器的 url:{baseUrl}</p>\n<p>请输入新的服务器 url:</p>\n<p>0. 返回</p>\n<p>q. 退出</p>", "menu-2-success": "<p>修改成功!</p>", "menu-2-invalid-url": "<p>URL 格式不正确!请输入有效的 url 地址。</p>", "menu-2-too-many-attempts": "<p>尝试次数过多,操作已取消。</p>", "menu-3-success": "<p>已删除!</p>", "menu-4-prompt": "<p>输入一个新名字,不要带空格哦:</p>\n<p>0. 返回</p>\n<p>q. 退出</p>", "menu-4-error-invalid-name": "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", "menu-4-success": "<p>修改成功!</p>", "add-type": "<p>请选择服务器的类型:</p>\n{server_type_list}\n<p>q. 退出</p>", "add-url": "<p>请输入服务器的 url:</p>\n<p>q. 退出</p>", "add-invalid-url": "<p>URL 格式不正确!请输入有效的 url 地址。</p>", "add-too-many-attempts": "<p>尝试次数过多,操作已取消。</p>", "add-name": "<p>收到!为服务器取一个名字吧,不要带空格哦:</p>\n<p>q. 退出</p>", "add-invalid_name": "<p>名字不要带空格!重来重来 o(一︿一+)o</p>", "add-success": "<p>添加成功啦,服务器信息如下:</p>\n<p>[{serverName}]</p>\n<p>类型:{serverType}</p>" } } } };
|
|
1930
1947
|
|
|
1931
1948
|
// src/core/index.ts
|
|
1932
1949
|
var name5 = "Noah-Core";
|
|
@@ -3377,7 +3394,7 @@ __export(sdvx_exports, {
|
|
|
3377
3394
|
logger: () => logger4,
|
|
3378
3395
|
name: () => name13
|
|
3379
3396
|
});
|
|
3380
|
-
var
|
|
3397
|
+
var import_koishi16 = require("koishi");
|
|
3381
3398
|
|
|
3382
3399
|
// src/games/sdvx/command.ts
|
|
3383
3400
|
var command_exports2 = {};
|
|
@@ -4100,23 +4117,64 @@ var MusicService = class _MusicService {
|
|
|
4100
4117
|
return _MusicService.instance;
|
|
4101
4118
|
}
|
|
4102
4119
|
/**
|
|
4103
|
-
*
|
|
4120
|
+
* 获取音乐信息(支持数字和字符串 ID)
|
|
4104
4121
|
* @param ctx - Koishi 上下文对象
|
|
4105
|
-
* @param musicIds - 音乐 ID
|
|
4122
|
+
* @param musicIds - 音乐 ID 数组(数字或字符串)
|
|
4106
4123
|
* @returns 音乐信息数组
|
|
4107
4124
|
*/
|
|
4108
4125
|
async getMusic(ctx, musicIds) {
|
|
4109
|
-
const
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4126
|
+
const numericIds = musicIds.filter((id) => typeof id === "number");
|
|
4127
|
+
const stringTitles = musicIds.filter((id) => typeof id === "string");
|
|
4128
|
+
const results = [];
|
|
4129
|
+
if (numericIds.length > 0) {
|
|
4130
|
+
try {
|
|
4131
|
+
const response = await ctx.http.post(
|
|
4132
|
+
`/music`,
|
|
4133
|
+
{ ids: numericIds },
|
|
4134
|
+
{ baseURL: this.sdvx_data_url }
|
|
4135
|
+
);
|
|
4136
|
+
results.push(...response);
|
|
4137
|
+
} catch (error) {
|
|
4138
|
+
console.warn("Failed to fetch music data for numeric IDs:", error);
|
|
4116
4139
|
}
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4140
|
+
}
|
|
4141
|
+
if (stringTitles.length > 0) {
|
|
4142
|
+
try {
|
|
4143
|
+
const response = await ctx.http.post(
|
|
4144
|
+
`/external/music`,
|
|
4145
|
+
{ titles: stringTitles },
|
|
4146
|
+
{ baseURL: this.sdvx_data_url }
|
|
4147
|
+
);
|
|
4148
|
+
const converted = this.convertExternalToStandard(response);
|
|
4149
|
+
results.push(...converted);
|
|
4150
|
+
} catch (error) {
|
|
4151
|
+
console.warn("Failed to fetch music data for string IDs:", error);
|
|
4152
|
+
}
|
|
4153
|
+
}
|
|
4154
|
+
return results;
|
|
4155
|
+
}
|
|
4156
|
+
/**
|
|
4157
|
+
* 转换外部音乐数据到标准格式
|
|
4158
|
+
* @param externalData - 外部音乐数据数组
|
|
4159
|
+
* @returns 标准格式音乐数据数组
|
|
4160
|
+
*/
|
|
4161
|
+
convertExternalToStandard(externalData) {
|
|
4162
|
+
return externalData.map((data) => ({
|
|
4163
|
+
id: data.slug,
|
|
4164
|
+
title_name: data.ext_title_name,
|
|
4165
|
+
artist_name: data.ext_artist_name,
|
|
4166
|
+
genre: data.genre,
|
|
4167
|
+
genre_name: data.genre_name,
|
|
4168
|
+
inf_ver: data.difficulty[0]?.inf_ver || 0,
|
|
4169
|
+
difficulty: data.difficulty.map((diff) => ({
|
|
4170
|
+
difstr: diff.difstr,
|
|
4171
|
+
difnum: diff.difnum,
|
|
4172
|
+
illustrator: diff.ext_illustrator,
|
|
4173
|
+
effected_by: diff.ext_effected_by,
|
|
4174
|
+
cover_url: diff.cover_url,
|
|
4175
|
+
inf_ver: diff.inf_ver
|
|
4176
|
+
}))
|
|
4177
|
+
}));
|
|
4120
4178
|
}
|
|
4121
4179
|
/**
|
|
4122
4180
|
* 根据曲名查询歌曲
|
|
@@ -4348,7 +4406,7 @@ function chart(ctx, config, logger5) {
|
|
|
4348
4406
|
__name(chart, "chart");
|
|
4349
4407
|
|
|
4350
4408
|
// src/games/sdvx/commands/recent.ts
|
|
4351
|
-
var
|
|
4409
|
+
var import_koishi14 = require("koishi");
|
|
4352
4410
|
|
|
4353
4411
|
// src/servers/index.ts
|
|
4354
4412
|
var servers_exports = {};
|
|
@@ -4866,6 +4924,156 @@ var Mao = class {
|
|
|
4866
4924
|
}
|
|
4867
4925
|
};
|
|
4868
4926
|
|
|
4927
|
+
// src/servers/Official/index.ts
|
|
4928
|
+
var import_koishi13 = require("koishi");
|
|
4929
|
+
|
|
4930
|
+
// src/servers/Official/services/sdvx-service.ts
|
|
4931
|
+
var SDVXService3 = class _SDVXService {
|
|
4932
|
+
static {
|
|
4933
|
+
__name(this, "SDVXService");
|
|
4934
|
+
}
|
|
4935
|
+
static instance;
|
|
4936
|
+
logger;
|
|
4937
|
+
constructor(logger5) {
|
|
4938
|
+
this.logger = logger5;
|
|
4939
|
+
}
|
|
4940
|
+
static getInstance(logger5) {
|
|
4941
|
+
if (!_SDVXService.instance) {
|
|
4942
|
+
_SDVXService.instance = new _SDVXService(logger5);
|
|
4943
|
+
}
|
|
4944
|
+
return _SDVXService.instance;
|
|
4945
|
+
}
|
|
4946
|
+
/**
|
|
4947
|
+
* 映射难度缩写到完整名称
|
|
4948
|
+
*/
|
|
4949
|
+
getDifficultyString(diffShort) {
|
|
4950
|
+
const diffMap = {
|
|
4951
|
+
NOV: "novice",
|
|
4952
|
+
ADV: "advanced",
|
|
4953
|
+
EXH: "exhaust",
|
|
4954
|
+
INF: "infinite",
|
|
4955
|
+
MXM: "maximum"
|
|
4956
|
+
};
|
|
4957
|
+
return diffMap[diffShort.toUpperCase()] || diffShort.toLowerCase();
|
|
4958
|
+
}
|
|
4959
|
+
/**
|
|
4960
|
+
* 映射 mark 到 SDVXClearType
|
|
4961
|
+
*/
|
|
4962
|
+
mapClearType(mark) {
|
|
4963
|
+
const markMap = {
|
|
4964
|
+
"s-puc": "S-PUC",
|
|
4965
|
+
spuc: "S-PUC",
|
|
4966
|
+
puc: "PUC",
|
|
4967
|
+
uc: "UC",
|
|
4968
|
+
mc: "MC",
|
|
4969
|
+
hc: "HC",
|
|
4970
|
+
nc: "NC",
|
|
4971
|
+
none: "PLAYED"
|
|
4972
|
+
};
|
|
4973
|
+
return markMap[mark.toLowerCase()] || "PLAYED";
|
|
4974
|
+
}
|
|
4975
|
+
/**
|
|
4976
|
+
* Get the user name/ID from the server response
|
|
4977
|
+
* @param ctx Context object
|
|
4978
|
+
* @param url Base Official Support URL for the API
|
|
4979
|
+
* @param player_id Player ID of the player (SV-xxxx-xxxx format)
|
|
4980
|
+
* @returns The player name
|
|
4981
|
+
*/
|
|
4982
|
+
async getUserName(ctx, url, player_id) {
|
|
4983
|
+
const response = await ctx.http.get(`/api/sdvx/profile?id=${player_id}`, {
|
|
4984
|
+
baseURL: url,
|
|
4985
|
+
responseType: "json"
|
|
4986
|
+
});
|
|
4987
|
+
return response.player_name || player_id;
|
|
4988
|
+
}
|
|
4989
|
+
async getAllScore(ctx, url, player_id, config) {
|
|
4990
|
+
try {
|
|
4991
|
+
const response = await ctx.http.get(`/api/sdvx/scores?id=${player_id}`, {
|
|
4992
|
+
baseURL: url,
|
|
4993
|
+
responseType: "json"
|
|
4994
|
+
});
|
|
4995
|
+
const scoresData = response;
|
|
4996
|
+
const stringMusicTitles = [...new Set(scoresData.map((score) => score.title))];
|
|
4997
|
+
const musicService = MusicService.getInstance(config);
|
|
4998
|
+
const musicDataList = await musicService.getMusic(ctx, stringMusicTitles);
|
|
4999
|
+
const musicDataMap = new Map(musicDataList.map((music) => [music.title_name, music]));
|
|
5000
|
+
const sdvxScores = [];
|
|
5001
|
+
for (const scoreData of scoresData) {
|
|
5002
|
+
const musicData = musicDataMap.get(scoreData.title);
|
|
5003
|
+
const infVer = musicData?.inf_ver || 0;
|
|
5004
|
+
for (const [diffKey, diffScore] of Object.entries(scoreData.difficulties)) {
|
|
5005
|
+
const diffStr = this.getDifficultyString(diffKey);
|
|
5006
|
+
let difficultyData = null;
|
|
5007
|
+
if (musicData && musicData.difficulty) {
|
|
5008
|
+
difficultyData = musicData.difficulty.find(
|
|
5009
|
+
(d) => d.difstr.toLowerCase() === diffStr.toLowerCase()
|
|
5010
|
+
) || null;
|
|
5011
|
+
}
|
|
5012
|
+
const scoreObj = {
|
|
5013
|
+
music: {
|
|
5014
|
+
music_id: scoreData.music_id,
|
|
5015
|
+
music_diff: difficultyData?.difnum || 0,
|
|
5016
|
+
music_diff_name: getDiffName(diffStr, infVer),
|
|
5017
|
+
music_diff_full_name: getDiffFullName(diffStr, infVer),
|
|
5018
|
+
score: diffScore.score,
|
|
5019
|
+
exscore: 0,
|
|
5020
|
+
// Official 服务器不提供
|
|
5021
|
+
clear_type: this.mapClearType(diffScore.mark),
|
|
5022
|
+
score_grade: diffScore.grade,
|
|
5023
|
+
btn_rate: "0",
|
|
5024
|
+
long_rate: "0",
|
|
5025
|
+
vol_rate: "0"
|
|
5026
|
+
},
|
|
5027
|
+
extra: {
|
|
5028
|
+
volforce: 0,
|
|
5029
|
+
play_count: 0,
|
|
5030
|
+
update_at: ""
|
|
5031
|
+
},
|
|
5032
|
+
music_data: musicData || null,
|
|
5033
|
+
difficulty_data: difficultyData || null
|
|
5034
|
+
};
|
|
5035
|
+
scoreObj.extra.volforce = calculateVolforce(scoreObj);
|
|
5036
|
+
sdvxScores.push(scoreObj);
|
|
5037
|
+
}
|
|
5038
|
+
}
|
|
5039
|
+
return sdvxScores;
|
|
5040
|
+
} catch (error) {
|
|
5041
|
+
if (error.response?.status === 404) {
|
|
5042
|
+
return [];
|
|
5043
|
+
}
|
|
5044
|
+
throw error;
|
|
5045
|
+
}
|
|
5046
|
+
}
|
|
5047
|
+
async getScore(ctx, url, player_id, musicId, config) {
|
|
5048
|
+
const allScores = await this.getAllScore(ctx, url, player_id, config);
|
|
5049
|
+
const score = allScores.find((s) => s.music.music_id === musicId);
|
|
5050
|
+
if (!score) {
|
|
5051
|
+
throw new Error(`Score not found for music ID: ${musicId}`);
|
|
5052
|
+
}
|
|
5053
|
+
return score;
|
|
5054
|
+
}
|
|
5055
|
+
async getRecentScores(ctx, url, player_id, config, count = 1) {
|
|
5056
|
+
return [];
|
|
5057
|
+
}
|
|
5058
|
+
};
|
|
5059
|
+
|
|
5060
|
+
// src/servers/Official/index.ts
|
|
5061
|
+
var Official = class {
|
|
5062
|
+
static {
|
|
5063
|
+
__name(this, "Official");
|
|
5064
|
+
}
|
|
5065
|
+
name = "official";
|
|
5066
|
+
supportedGames = ["sdvx"];
|
|
5067
|
+
gameServices = {};
|
|
5068
|
+
logger = new import_koishi13.Logger("Noah-Official");
|
|
5069
|
+
/**
|
|
5070
|
+
* 初始化SDVX游戏服务实例
|
|
5071
|
+
*/
|
|
5072
|
+
constructor() {
|
|
5073
|
+
this.gameServices["sdvx"] = SDVXService3.getInstance(this.logger);
|
|
5074
|
+
}
|
|
5075
|
+
};
|
|
5076
|
+
|
|
4869
5077
|
// src/servers/ServerFactory.ts
|
|
4870
5078
|
var ServerFactory = class {
|
|
4871
5079
|
static {
|
|
@@ -4888,6 +5096,9 @@ var ServerFactory = class {
|
|
|
4888
5096
|
case "mao":
|
|
4889
5097
|
serverInstance = new Mao();
|
|
4890
5098
|
break;
|
|
5099
|
+
case "official":
|
|
5100
|
+
serverInstance = new Official();
|
|
5101
|
+
break;
|
|
4891
5102
|
default:
|
|
4892
5103
|
throw new Error(`Unsupported server type: ${serverType}`);
|
|
4893
5104
|
}
|
|
@@ -4969,7 +5180,7 @@ function recent(ctx, config, logger5) {
|
|
|
4969
5180
|
cardListMsg += `<p>${i + 1}. ${userCards[i].name}</p>`;
|
|
4970
5181
|
}
|
|
4971
5182
|
}
|
|
4972
|
-
const msg =
|
|
5183
|
+
const msg = import_koishi14.h.unescape(session.text(".menu-select", { card_list: cardListMsg })).replace("< 默认卡片", "< 默认卡片");
|
|
4973
5184
|
await session.send(msg);
|
|
4974
5185
|
const select = await session.prompt();
|
|
4975
5186
|
if (!select) return session.text("commands.timeout");
|
|
@@ -5026,9 +5237,9 @@ function recent(ctx, config, logger5) {
|
|
|
5026
5237
|
}
|
|
5027
5238
|
);
|
|
5028
5239
|
if (options.lossless) {
|
|
5029
|
-
return
|
|
5240
|
+
return import_koishi14.h.image(imageBuffer, "image/png");
|
|
5030
5241
|
}
|
|
5031
|
-
return
|
|
5242
|
+
return import_koishi14.h.image(imageBuffer, "image/jpg");
|
|
5032
5243
|
} catch (error) {
|
|
5033
5244
|
logger5.warn(error);
|
|
5034
5245
|
return session.text(".error");
|
|
@@ -5039,7 +5250,7 @@ __name(recent, "recent");
|
|
|
5039
5250
|
|
|
5040
5251
|
// src/games/sdvx/commands/vf.ts
|
|
5041
5252
|
var fs4 = __toESM(require("fs"), 1);
|
|
5042
|
-
var
|
|
5253
|
+
var import_koishi15 = require("koishi");
|
|
5043
5254
|
|
|
5044
5255
|
// src/games/sdvx/services/score-service.ts
|
|
5045
5256
|
var ScoreService = class _ScoreService {
|
|
@@ -5197,7 +5408,7 @@ function vf(ctx, config, logger5) {
|
|
|
5197
5408
|
cardListMsg += `<p>${i + 1}. ${userCards[i].name}</p>`;
|
|
5198
5409
|
}
|
|
5199
5410
|
}
|
|
5200
|
-
const msg =
|
|
5411
|
+
const msg = import_koishi15.h.unescape(session.text(".menu-select", { card_list: cardListMsg })).replace("< 默认卡片", "< 默认卡片");
|
|
5201
5412
|
await session.send(msg);
|
|
5202
5413
|
const select = await session.prompt();
|
|
5203
5414
|
if (!select) return session.text("commands.timeout");
|
|
@@ -5260,14 +5471,13 @@ function vf(ctx, config, logger5) {
|
|
|
5260
5471
|
}
|
|
5261
5472
|
);
|
|
5262
5473
|
if (options.lossless) {
|
|
5263
|
-
session.send(
|
|
5474
|
+
session.send(import_koishi15.h.file(imageBuffer, "image/png"));
|
|
5264
5475
|
} else {
|
|
5265
|
-
session.send(
|
|
5476
|
+
session.send(import_koishi15.h.image(imageBuffer, "image/jpg"));
|
|
5266
5477
|
}
|
|
5267
5478
|
const sortedScores = [...best50ScoreList].sort((a, b) => b.extra.volforce - a.extra.volforce).slice(0, 50);
|
|
5268
5479
|
const total = sortedScores.reduce((sum, score) => sum + score.extra.volforce, 0);
|
|
5269
5480
|
const totalVolforce = Math.round(total / 50 * 1e3) / 1e3;
|
|
5270
|
-
console.log(totalVolforce);
|
|
5271
5481
|
if (totalVolforce >= 20) {
|
|
5272
5482
|
try {
|
|
5273
5483
|
await new Promise((resolve3) => setTimeout(resolve3, 2e3));
|
|
@@ -5281,11 +5491,11 @@ function vf(ctx, config, logger5) {
|
|
|
5281
5491
|
);
|
|
5282
5492
|
if (fs4.existsSync(audioPath)) {
|
|
5283
5493
|
const audioBuffer = fs4.readFileSync(audioPath);
|
|
5284
|
-
session.send(
|
|
5494
|
+
session.send(import_koishi15.h.audio(audioBuffer, "audio/mpeg"));
|
|
5285
5495
|
}
|
|
5286
5496
|
if (fs4.existsSync(imagePath)) {
|
|
5287
5497
|
const imageBuffer2 = fs4.readFileSync(imagePath);
|
|
5288
|
-
session.send(
|
|
5498
|
+
session.send(import_koishi15.h.image(imageBuffer2, "image/png"));
|
|
5289
5499
|
}
|
|
5290
5500
|
} catch (error) {
|
|
5291
5501
|
logger5.warn(`Failed to send celebration files: ${error.message}`);
|
|
@@ -5334,15 +5544,15 @@ function apply12(ctx) {
|
|
|
5334
5544
|
__name(apply12, "apply");
|
|
5335
5545
|
|
|
5336
5546
|
// src/games/sdvx/locales/en-US.yml
|
|
5337
|
-
var en_US_default4 = { _config: { $desc: "SDVX Module Settings", default_model: "<p>Default model value (e.g. `2024110700`)</p>", sdvx_data_url: "<p>The URL of the SDVX data service</p>", sdvx_search_url: "<p>The URL of the SDVX search service</p>" }, commands: { vf: { description: "Show Noah help information", messages: { "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing {name} [{difstr}], please wait patiently~</p>", "menu-select": "<p>Please select the card you want to use:</p>\n{card_list}\n<p>q. Exit</p>", "invalid-select": "<p>No such option!</p>", quit: "<p>Exited~</p>" } }, sdvx: { recent: { description: "Show recent scores", messages: { "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>" } }, chart: { description: "Show SDVX chart", messages: { prompt: "<p>Which song's chart would you like to view?</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", "no-result": "<p>Aww, Noah couldn’t find that song~ try another keyword, okay?</p>" } }, calculate: { description: "Calculate volforce value or score", messages: { "invalid-query": "<p>Invalid query parameters, please check your input~</p>", "no-results": "<p>No results found~</p>", "too-many-results": "<p>Too many results! Found {0} results, please narrow down your query (current limit: 500 results)</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", error: "<p>An error occurred(っ °Д °;)っ</p>" } } } } };
|
|
5547
|
+
var en_US_default4 = { _config: { $desc: "SDVX Module Settings", default_model: "<p>Default model value (e.g. `2024110700`)</p>", sdvx_data_url: "<p>The URL of the SDVX data service</p>", sdvx_search_url: "<p>The URL of the SDVX search service</p>", official_support_url: "<p>The URL of the SDVX official support service</p>" }, commands: { vf: { description: "Show Noah help information", messages: { "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing {name} [{difstr}], please wait patiently~</p>", "menu-select": "<p>Please select the card you want to use:</p>\n{card_list}\n<p>q. Exit</p>", "invalid-select": "<p>No such option!</p>", quit: "<p>Exited~</p>" } }, sdvx: { recent: { description: "Show recent scores", messages: { "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>" } }, chart: { description: "Show SDVX chart", messages: { prompt: "<p>Which song's chart would you like to view?</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", "no-result": "<p>Aww, Noah couldn’t find that song~ try another keyword, okay?</p>" } }, calculate: { description: "Calculate volforce value or score", messages: { "invalid-query": "<p>Invalid query parameters, please check your input~</p>", "no-results": "<p>No results found~</p>", "too-many-results": "<p>Too many results! Found {0} results, please narrow down your query (current limit: 500 results)</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", error: "<p>An error occurred(っ °Д °;)っ</p>" } } } } };
|
|
5338
5548
|
|
|
5339
5549
|
// src/games/sdvx/locales/zh-CN.yml
|
|
5340
|
-
var zh_CN_default4 = { _config: { $desc: "SDVX 模块设置", default_model: "<p>默认的 model 值(如 `2024110700`)</p>", sdvx_data_url: "<p>SDVX 数据服务的 URL</p>", sdvx_search_url: "<p>SDVX 搜索服务的 URL</p>" }, commands: { vf: { description: "查询 SDVX VOLFORCE", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", "menu-select": "<p>请选择你要使用的卡片:</p>\n{card_list}\n<p>q. 退出</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>" } }, sdvx: { recent: { description: "查询最近分数", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>" } }, chart: { description: "查询 SDVX 谱面", messages: { prompt: "<p>要查哪首歌的铺面呢?</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在绘制 {name} [{difstr}],请耐心等待~</p>", "no-result": "<p>Noah 没有找到这首歌,换个关键词试试吧~</p>" } }, calculate: { description: "计算 volforce 值或分数", messages: { "invalid-query": "<p>查询参数无效,请检查你的输入~</p>", "no-results": "<p>没有找到符合条件的结果~</p>", "too-many-results": "<p>结果太多啦!共找到 {0} 条结果,请缩小查询范围(当前限制:500 条)</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>" } } } } };
|
|
5550
|
+
var zh_CN_default4 = { _config: { $desc: "SDVX 模块设置", default_model: "<p>默认的 model 值(如 `2024110700`)</p>", sdvx_data_url: "<p>SDVX 数据服务的 URL</p>", sdvx_search_url: "<p>SDVX 搜索服务的 URL</p>", official_support_url: "<p>SDVX 官方支持服务的 URL</p>" }, commands: { vf: { description: "查询 SDVX VOLFORCE", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", "menu-select": "<p>请选择你要使用的卡片:</p>\n{card_list}\n<p>q. 退出</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>" } }, sdvx: { recent: { description: "查询最近分数", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>" } }, chart: { description: "查询 SDVX 谱面", messages: { prompt: "<p>要查哪首歌的铺面呢?</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在绘制 {name} [{difstr}],请耐心等待~</p>", "no-result": "<p>Noah 没有找到这首歌,换个关键词试试吧~</p>" } }, calculate: { description: "计算 volforce 值或分数", messages: { "invalid-query": "<p>查询参数无效,请检查你的输入~</p>", "no-results": "<p>没有找到符合条件的结果~</p>", "too-many-results": "<p>结果太多啦!共找到 {0} 条结果,请缩小查询范围(当前限制:500 条)</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>" } } } } };
|
|
5341
5551
|
|
|
5342
5552
|
// src/games/sdvx/index.ts
|
|
5343
5553
|
var name13 = "Noah-SDVX";
|
|
5344
5554
|
var inject2 = ["database"];
|
|
5345
|
-
var logger4 = new
|
|
5555
|
+
var logger4 = new import_koishi16.Logger("Noah-SDVX");
|
|
5346
5556
|
async function apply13(ctx, config) {
|
|
5347
5557
|
;
|
|
5348
5558
|
[
|
|
@@ -5356,48 +5566,49 @@ async function apply13(ctx, config) {
|
|
|
5356
5566
|
__name(apply13, "apply");
|
|
5357
5567
|
|
|
5358
5568
|
// src/config.ts
|
|
5359
|
-
var
|
|
5569
|
+
var import_koishi22 = require("koishi");
|
|
5360
5570
|
|
|
5361
5571
|
// src/asset/config.ts
|
|
5362
|
-
var
|
|
5363
|
-
var assetConfig =
|
|
5364
|
-
data_path:
|
|
5365
|
-
auto_update:
|
|
5366
|
-
update_url:
|
|
5367
|
-
update_interval:
|
|
5572
|
+
var import_koishi17 = require("koishi");
|
|
5573
|
+
var assetConfig = import_koishi17.Schema.object({
|
|
5574
|
+
data_path: import_koishi17.Schema.string().default("noah_assets"),
|
|
5575
|
+
auto_update: import_koishi17.Schema.boolean().default(true),
|
|
5576
|
+
update_url: import_koishi17.Schema.string().default("https://github.com/logthm/noah/releases/latest/download/"),
|
|
5577
|
+
update_interval: import_koishi17.Schema.number().default(24 * 60 * 60 * 1e3),
|
|
5368
5578
|
// 24 hours in milliseconds
|
|
5369
|
-
github_token:
|
|
5579
|
+
github_token: import_koishi17.Schema.string().description("GitHub token for accessing private repositories").role("secret")
|
|
5370
5580
|
}).i18n({
|
|
5371
5581
|
"en-US": en_US_default._config,
|
|
5372
5582
|
"zh-CN": zh_CN_default._config
|
|
5373
5583
|
});
|
|
5374
5584
|
|
|
5375
5585
|
// src/core/config.ts
|
|
5376
|
-
var
|
|
5377
|
-
var coreConfig =
|
|
5378
|
-
adminUsers:
|
|
5379
|
-
guildNameCards:
|
|
5380
|
-
maoServerUrl:
|
|
5586
|
+
var import_koishi18 = require("koishi");
|
|
5587
|
+
var coreConfig = import_koishi18.Schema.object({
|
|
5588
|
+
adminUsers: import_koishi18.Schema.array(String).role("table"),
|
|
5589
|
+
guildNameCards: import_koishi18.Schema.array(String).role("table").default(["Noah | /help 获取食用指南"]),
|
|
5590
|
+
maoServerUrl: import_koishi18.Schema.string().default("http://maomani.cn:573"),
|
|
5591
|
+
official_support_url: import_koishi18.Schema.string().default("https://noah.logthm.com")
|
|
5381
5592
|
}).i18n({
|
|
5382
5593
|
"en-US": en_US_default2._config,
|
|
5383
5594
|
"zh-CN": zh_CN_default2._config
|
|
5384
5595
|
});
|
|
5385
5596
|
|
|
5386
5597
|
// src/fun/poke/config.ts
|
|
5387
|
-
var
|
|
5388
|
-
var pokeConfig =
|
|
5389
|
-
interval:
|
|
5390
|
-
warning:
|
|
5391
|
-
prompt:
|
|
5392
|
-
|
|
5393
|
-
content:
|
|
5394
|
-
weight:
|
|
5598
|
+
var import_koishi19 = require("koishi");
|
|
5599
|
+
var pokeConfig = import_koishi19.Schema.object({
|
|
5600
|
+
interval: import_koishi19.Schema.number().default(1e3).step(100),
|
|
5601
|
+
warning: import_koishi19.Schema.boolean().default(false),
|
|
5602
|
+
prompt: import_koishi19.Schema.array(
|
|
5603
|
+
import_koishi19.Schema.object({
|
|
5604
|
+
content: import_koishi19.Schema.string().required(),
|
|
5605
|
+
weight: import_koishi19.Schema.number().min(0).max(100).default(50)
|
|
5395
5606
|
})
|
|
5396
5607
|
).role("table"),
|
|
5397
|
-
messages:
|
|
5398
|
-
|
|
5399
|
-
content:
|
|
5400
|
-
weight:
|
|
5608
|
+
messages: import_koishi19.Schema.array(
|
|
5609
|
+
import_koishi19.Schema.object({
|
|
5610
|
+
content: import_koishi19.Schema.string().required(),
|
|
5611
|
+
weight: import_koishi19.Schema.number().min(0).max(100).default(50)
|
|
5401
5612
|
})
|
|
5402
5613
|
).role("table")
|
|
5403
5614
|
}).i18n({
|
|
@@ -5406,7 +5617,7 @@ var pokeConfig = import_koishi18.Schema.object({
|
|
|
5406
5617
|
});
|
|
5407
5618
|
|
|
5408
5619
|
// src/games/general/config.ts
|
|
5409
|
-
var
|
|
5620
|
+
var import_koishi20 = require("koishi");
|
|
5410
5621
|
|
|
5411
5622
|
// src/games/general/locales/en-US.yml
|
|
5412
5623
|
var en_US_default5 = { _config: { $desc: "General Module Settings", barcode_api_url: "<p>The URL of the barcode API</p>" } };
|
|
@@ -5415,26 +5626,27 @@ var en_US_default5 = { _config: { $desc: "General Module Settings", barcode_api_
|
|
|
5415
5626
|
var zh_CN_default5 = { _config: { $desc: "通用工具模块设置", barcode_api_url: "<p>条形码 API 地址</p>" } };
|
|
5416
5627
|
|
|
5417
5628
|
// src/games/general/config.ts
|
|
5418
|
-
var generalConfig =
|
|
5419
|
-
barcode_api_url:
|
|
5629
|
+
var generalConfig = import_koishi20.Schema.object({
|
|
5630
|
+
barcode_api_url: import_koishi20.Schema.string().required()
|
|
5420
5631
|
}).i18n({
|
|
5421
5632
|
"en-US": en_US_default5._config,
|
|
5422
5633
|
"zh-CN": zh_CN_default5._config
|
|
5423
5634
|
});
|
|
5424
5635
|
|
|
5425
5636
|
// src/games/sdvx/config.ts
|
|
5426
|
-
var
|
|
5427
|
-
var sdvxConfig =
|
|
5428
|
-
default_model:
|
|
5429
|
-
sdvx_data_url:
|
|
5430
|
-
sdvx_search_url:
|
|
5637
|
+
var import_koishi21 = require("koishi");
|
|
5638
|
+
var sdvxConfig = import_koishi21.Schema.object({
|
|
5639
|
+
default_model: import_koishi21.Schema.string().default("2025100700"),
|
|
5640
|
+
sdvx_data_url: import_koishi21.Schema.string().required(),
|
|
5641
|
+
sdvx_search_url: import_koishi21.Schema.string().required(),
|
|
5642
|
+
official_support_url: import_koishi21.Schema.string().required()
|
|
5431
5643
|
}).i18n({
|
|
5432
5644
|
"en-US": en_US_default4._config,
|
|
5433
5645
|
"zh-CN": zh_CN_default4._config
|
|
5434
5646
|
});
|
|
5435
5647
|
|
|
5436
5648
|
// src/config.ts
|
|
5437
|
-
var Config =
|
|
5649
|
+
var Config = import_koishi22.Schema.object({
|
|
5438
5650
|
core: coreConfig,
|
|
5439
5651
|
sdvx: sdvxConfig,
|
|
5440
5652
|
poke: pokeConfig,
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Logger } from 'koishi';
|
|
2
|
+
import { IServer, TGame, TServer, GameService } from '../../types';
|
|
3
|
+
export declare class Official implements IServer {
|
|
4
|
+
name: TServer;
|
|
5
|
+
supportedGames: TGame[];
|
|
6
|
+
gameServices: {
|
|
7
|
+
[key in TGame]?: GameService;
|
|
8
|
+
};
|
|
9
|
+
logger: Logger;
|
|
10
|
+
/**
|
|
11
|
+
* 初始化SDVX游戏服务实例
|
|
12
|
+
*/
|
|
13
|
+
constructor();
|
|
14
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Context, Logger } from 'koishi';
|
|
2
|
+
import { SDVXScore } from '../../../games/sdvx/types';
|
|
3
|
+
import { SDVXService as ISDVXService } from '../../../types';
|
|
4
|
+
import { SDVXConfig } from '../../../types/config';
|
|
5
|
+
export declare class SDVXService implements ISDVXService {
|
|
6
|
+
private static instance;
|
|
7
|
+
logger: Logger;
|
|
8
|
+
private constructor();
|
|
9
|
+
static getInstance(logger: Logger): SDVXService;
|
|
10
|
+
/**
|
|
11
|
+
* 映射难度缩写到完整名称
|
|
12
|
+
*/
|
|
13
|
+
private getDifficultyString;
|
|
14
|
+
/**
|
|
15
|
+
* 映射 mark 到 SDVXClearType
|
|
16
|
+
*/
|
|
17
|
+
private mapClearType;
|
|
18
|
+
/**
|
|
19
|
+
* Get the user name/ID from the server response
|
|
20
|
+
* @param ctx Context object
|
|
21
|
+
* @param url Base Official Support URL for the API
|
|
22
|
+
* @param player_id Player ID of the player (SV-xxxx-xxxx format)
|
|
23
|
+
* @returns The player name
|
|
24
|
+
*/
|
|
25
|
+
getUserName(ctx: Context, url: string, player_id: string): Promise<string>;
|
|
26
|
+
getAllScore(ctx: Context, url: string, player_id: string, config: SDVXConfig): Promise<SDVXScore[]>;
|
|
27
|
+
getScore(ctx: Context, url: string, player_id: string, musicId: number, config: SDVXConfig): Promise<SDVXScore>;
|
|
28
|
+
getRecentScores(ctx: Context, url: string, player_id: string, config: SDVXConfig, count?: number): Promise<SDVXScore[]>;
|
|
29
|
+
}
|
package/lib/types/config.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export interface CoreConfig extends BaseConfig {
|
|
|
16
16
|
guildNameCards?: string[];
|
|
17
17
|
/** 猫网服务器 URL */
|
|
18
18
|
maoServerUrl?: string;
|
|
19
|
+
/** Official Support URL */
|
|
20
|
+
official_support_url?: string;
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
21
23
|
* SDVX 游戏配置接口
|
|
@@ -28,6 +30,8 @@ export interface SDVXConfig extends BaseConfig {
|
|
|
28
30
|
sdvx_data_url: string;
|
|
29
31
|
/** SDVX 搜索 URL */
|
|
30
32
|
sdvx_search_url: string;
|
|
33
|
+
/** Official Support URL */
|
|
34
|
+
official_support_url: string;
|
|
31
35
|
}
|
|
32
36
|
/**
|
|
33
37
|
* 戳一戳功能配置接口
|
package/lib/types/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Context, Logger } from 'koishi';
|
|
|
2
2
|
import { SDVXScore } from '../games/sdvx/types';
|
|
3
3
|
import { SDVXConfig } from './config';
|
|
4
4
|
/** 服务器类型 */
|
|
5
|
-
export type TServer = 'asphyxia' | 'mao';
|
|
5
|
+
export type TServer = 'asphyxia' | 'mao' | 'official';
|
|
6
6
|
/** 服务器类型可选值列表 */
|
|
7
7
|
export declare const serverValues: TServer[];
|
|
8
8
|
/** 游戏类型 */
|
|
@@ -23,10 +23,10 @@ export interface GameService {
|
|
|
23
23
|
*/
|
|
24
24
|
export interface SDVXService extends GameService {
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* 获取指定卡片的所有分数记录
|
|
27
27
|
* @param ctx - Koishi 上下文对象
|
|
28
28
|
* @param url - SDVX 服务的基础 URL
|
|
29
|
-
* @param cardId -
|
|
29
|
+
* @param cardId - 玩家卡片 ID
|
|
30
30
|
* @param config - SDVX 配置设置
|
|
31
31
|
* @returns Promise 解析为 SDVX 分数记录数组
|
|
32
32
|
* @throws 当获取操作失败时抛出错误
|
|
@@ -36,7 +36,7 @@ export interface SDVXService extends GameService {
|
|
|
36
36
|
* 获取指定音乐 ID 的分数记录
|
|
37
37
|
* @param ctx - Koishi 上下文对象
|
|
38
38
|
* @param url - SDVX 服务的基础 URL
|
|
39
|
-
* @param cardId -
|
|
39
|
+
* @param cardId - 玩家卡片 ID
|
|
40
40
|
* @param musicId - 音乐曲目 ID
|
|
41
41
|
* @param config - SDVX 配置设置
|
|
42
42
|
* @returns Promise 解析为单个 SDVX 分数记录
|
|
@@ -44,10 +44,10 @@ export interface SDVXService extends GameService {
|
|
|
44
44
|
*/
|
|
45
45
|
getScore(ctx: Context, url: string, cardId: string, musicId: number, config: SDVXConfig): Promise<SDVXScore>;
|
|
46
46
|
/**
|
|
47
|
-
*
|
|
47
|
+
* 获取卡片的最近分数记录
|
|
48
48
|
* @param ctx - Koishi 上下文对象
|
|
49
49
|
* @param url - SDVX 服务的基础 URL
|
|
50
|
-
* @param cardId -
|
|
50
|
+
* @param cardId - 玩家卡片 ID
|
|
51
51
|
* @param config - SDVX 配置设置(可选)
|
|
52
52
|
* @param count - 要获取的最近分数记录数量(可选,默认为 1)
|
|
53
53
|
* @returns Promise 解析为最近 SDVX 分数记录数组
|
|
@@ -58,7 +58,7 @@ export interface SDVXService extends GameService {
|
|
|
58
58
|
* 从服务器响应中获取用户名/ID
|
|
59
59
|
* @param ctx - Koishi 上下文对象
|
|
60
60
|
* @param url - API 的基础 URL
|
|
61
|
-
* @param cardId -
|
|
61
|
+
* @param cardId - 玩家卡片 ID
|
|
62
62
|
* @returns 玩家 ID
|
|
63
63
|
*/
|
|
64
64
|
getUserName(ctx: Context, url: string, cardId: string): Promise<string>;
|