lxns-rhythm-api 0.1.3 → 0.1.8
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/LICENSE +21 -0
- package/README.md +85 -53
- package/dist/index.d.ts +434 -87
- package/dist/index.js +452 -126
- package/package.json +25 -14
package/dist/index.js
CHANGED
|
@@ -4,153 +4,211 @@ var __export = (target, all) => {
|
|
|
4
4
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
// src/
|
|
7
|
+
// src/api/chunithm/models.ts
|
|
8
8
|
var models_exports = {};
|
|
9
9
|
__export(models_exports, {
|
|
10
10
|
LevelIndex: () => LevelIndex
|
|
11
11
|
});
|
|
12
|
-
var LevelIndex = /* @__PURE__ */ ((
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
var LevelIndex = /* @__PURE__ */ ((LevelIndex3) => {
|
|
13
|
+
LevelIndex3[LevelIndex3["BASIC"] = 0] = "BASIC";
|
|
14
|
+
LevelIndex3[LevelIndex3["ADVANCED"] = 1] = "ADVANCED";
|
|
15
|
+
LevelIndex3[LevelIndex3["EXPERT"] = 2] = "EXPERT";
|
|
16
|
+
LevelIndex3[LevelIndex3["MASTER"] = 3] = "MASTER";
|
|
17
|
+
LevelIndex3[LevelIndex3["ULTIMA"] = 4] = "ULTIMA";
|
|
18
|
+
LevelIndex3[LevelIndex3["WORLDS_END"] = 5] = "WORLDS_END";
|
|
19
|
+
return LevelIndex3;
|
|
19
20
|
})(LevelIndex || {});
|
|
20
21
|
|
|
21
|
-
// src/
|
|
22
|
+
// src/api/maimai/models.ts
|
|
23
|
+
var models_exports2 = {};
|
|
24
|
+
__export(models_exports2, {
|
|
25
|
+
LevelIndex: () => LevelIndex2
|
|
26
|
+
});
|
|
27
|
+
var LevelIndex2 = /* @__PURE__ */ ((LevelIndex3) => {
|
|
28
|
+
LevelIndex3[LevelIndex3["BASIC"] = 0] = "BASIC";
|
|
29
|
+
LevelIndex3[LevelIndex3["ADVANCED"] = 1] = "ADVANCED";
|
|
30
|
+
LevelIndex3[LevelIndex3["EXPERT"] = 2] = "EXPERT";
|
|
31
|
+
LevelIndex3[LevelIndex3["MASTER"] = 3] = "MASTER";
|
|
32
|
+
LevelIndex3[LevelIndex3["RE_MASTER"] = 4] = "RE_MASTER";
|
|
33
|
+
return LevelIndex3;
|
|
34
|
+
})(LevelIndex2 || {});
|
|
35
|
+
|
|
36
|
+
// src/client/lxns-api-client.ts
|
|
22
37
|
import ky from "ky";
|
|
23
38
|
|
|
24
|
-
// src/
|
|
25
|
-
var
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"expert",
|
|
29
|
-
"master",
|
|
30
|
-
"remaster"
|
|
31
|
-
];
|
|
32
|
-
function convertDifficulty(difficulty) {
|
|
33
|
-
return difficulty.reduce(
|
|
34
|
-
(acc, cur) => {
|
|
35
|
-
acc[LevelArray[cur.difficulty]] = cur;
|
|
36
|
-
return acc;
|
|
37
|
-
},
|
|
38
|
-
{}
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
var Song = class {
|
|
42
|
-
id;
|
|
43
|
-
title;
|
|
44
|
-
artist;
|
|
45
|
-
genre;
|
|
46
|
-
version;
|
|
47
|
-
bpm;
|
|
48
|
-
difficulties;
|
|
49
|
-
locked;
|
|
50
|
-
disabled;
|
|
51
|
-
rights;
|
|
52
|
-
constructor(song) {
|
|
53
|
-
this.id = song.id;
|
|
54
|
-
this.title = song.title;
|
|
55
|
-
this.artist = song.artist;
|
|
56
|
-
this.genre = song.genre;
|
|
57
|
-
this.version = song.version;
|
|
58
|
-
this.bpm = song.bpm;
|
|
59
|
-
this.difficulties = song.difficulties;
|
|
60
|
-
this.locked = song.locked ?? false;
|
|
61
|
-
this.disabled = song.disabled ?? false;
|
|
62
|
-
this.rights = song.rights;
|
|
39
|
+
// src/api/chunithm/dev.ts
|
|
40
|
+
var ChunithmDevApi = class {
|
|
41
|
+
constructor(http) {
|
|
42
|
+
this.http = http;
|
|
63
43
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
44
|
+
/**
|
|
45
|
+
* 创建或修改玩家信息
|
|
46
|
+
*/
|
|
47
|
+
async postPlayer(body) {
|
|
48
|
+
return this.http.post("player", { json: body }).json();
|
|
67
49
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
50
|
+
/**
|
|
51
|
+
* 获取玩家信息(通过好友码)
|
|
52
|
+
*/
|
|
53
|
+
async getPlayer(friendCode) {
|
|
54
|
+
return this.http.get(`player/${friendCode}`).json();
|
|
71
55
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
56
|
+
/**
|
|
57
|
+
* 获取玩家信息(通过 QQ 号)
|
|
58
|
+
*/
|
|
59
|
+
async getPlayerByQQ(qq) {
|
|
60
|
+
return this.http.get(`player/qq/${qq}`).json();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* 获取 Best 30(old 15 + new 15)
|
|
64
|
+
*/
|
|
65
|
+
async getBests(friendCode) {
|
|
66
|
+
return this.http.get(`player/${friendCode}/bests`).json();
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 获取玩家缓存谱面的最佳成绩
|
|
70
|
+
*/
|
|
71
|
+
async getBest(friendCode, options) {
|
|
72
|
+
return this.http.get(`player/${friendCode}/best`, {
|
|
73
|
+
searchParams: {
|
|
74
|
+
song_id: options.songId,
|
|
75
|
+
song_name: options.songName,
|
|
76
|
+
level_index: options.levelIndex
|
|
77
|
+
}
|
|
78
|
+
}).json();
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 获取玩家缓存的所有最佳成绩(简化)
|
|
82
|
+
*/
|
|
83
|
+
async getAllBestScores(friendCode) {
|
|
84
|
+
return this.http.get(`player/${friendCode}/scores`).json();
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 获取 Recent 50
|
|
88
|
+
*/
|
|
89
|
+
async getRecents(friendCode) {
|
|
90
|
+
return this.http.get(`player/${friendCode}/recents`).json();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* 获取成绩游玩历史记录
|
|
94
|
+
*/
|
|
95
|
+
async getScoreHistory(friendCode, options) {
|
|
96
|
+
return this.http.get(`player/${friendCode}/score/history`, {
|
|
97
|
+
searchParams: {
|
|
98
|
+
song_id: options?.songId,
|
|
99
|
+
level_index: options?.levelIndex
|
|
100
|
+
}
|
|
101
|
+
}).json();
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 成绩上传热力图
|
|
105
|
+
*/
|
|
106
|
+
async getHeatmap(friendCode) {
|
|
107
|
+
return this.http.get(`player/${friendCode}/heatmap`).json();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Rating 趋势
|
|
111
|
+
*/
|
|
112
|
+
async getTrend(friendCode, version) {
|
|
113
|
+
return this.http.get(`player/${friendCode}/trend`, { searchParams: { version } }).json();
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* 获取玩家收藏品进度
|
|
117
|
+
*/
|
|
118
|
+
async getCollectionProgress(friendCode, collectionType, collectionId) {
|
|
119
|
+
return this.http.get(`player/${friendCode}/${collectionType}/${collectionId}`).json();
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* 上传玩家成绩
|
|
123
|
+
*/
|
|
124
|
+
async postScores(friendCode, scores) {
|
|
125
|
+
const body = { scores };
|
|
126
|
+
return this.http.post(`player/${friendCode}/scores`, { json: body }).json();
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* 通过 NET 的 HTML 源代码上传玩家数据
|
|
130
|
+
*/
|
|
131
|
+
async postHtml(friendCode, htmlSource) {
|
|
132
|
+
return this.http.post(`player/${friendCode}/html`, {
|
|
133
|
+
body: htmlSource,
|
|
134
|
+
headers: { "content-type": "text/plain" }
|
|
135
|
+
}).json();
|
|
75
136
|
}
|
|
76
137
|
};
|
|
77
138
|
|
|
78
|
-
// src/
|
|
79
|
-
var
|
|
139
|
+
// src/api/chunithm/personal.ts
|
|
140
|
+
var ChunithmPersonalApi = class {
|
|
141
|
+
constructor(http) {
|
|
142
|
+
this.http = http;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* 获取玩家信息
|
|
146
|
+
* GET /api/v0/user/chunithm/player
|
|
147
|
+
*/
|
|
148
|
+
async getPlayer() {
|
|
149
|
+
return this.http.get("player").json();
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* 获取玩家所有成绩
|
|
153
|
+
* GET /api/v0/user/chunithm/player/scores
|
|
154
|
+
*/
|
|
155
|
+
async getScores() {
|
|
156
|
+
return this.http.get("scores").json();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* 上传玩家成绩
|
|
160
|
+
* POST /api/v0/user/chunithm/player/scores
|
|
161
|
+
*/
|
|
162
|
+
async postScores(scores) {
|
|
163
|
+
const body = { scores };
|
|
164
|
+
return this.http.post("scores", { json: body }).json();
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// src/api/chunithm/public.ts
|
|
169
|
+
var ChunithmPublicApi = class {
|
|
80
170
|
constructor(http) {
|
|
81
171
|
this.http = http;
|
|
82
172
|
}
|
|
83
173
|
/**
|
|
84
174
|
* 获取歌曲列表
|
|
85
|
-
* @param version 版本,不填写遵循api默认行为
|
|
86
|
-
* @param notes 是否包含谱面信息,不填写遵循api默认行为
|
|
87
|
-
* @returns 歌曲列表
|
|
88
175
|
*/
|
|
89
176
|
async getSongList(version, notes) {
|
|
90
|
-
return this.http.get("song/list
|
|
177
|
+
return this.http.get("song/list", { searchParams: { version, notes } }).json();
|
|
91
178
|
}
|
|
92
179
|
/**
|
|
93
180
|
* 获取歌曲信息
|
|
94
|
-
* @param id 歌曲 ID
|
|
95
|
-
* @returns 歌曲信息
|
|
96
181
|
*/
|
|
97
|
-
async getSong(id) {
|
|
98
|
-
|
|
99
|
-
return new Song(songInfo);
|
|
182
|
+
async getSong(id, version) {
|
|
183
|
+
return this.http.get(`song/${id}`, { searchParams: { version } }).json();
|
|
100
184
|
}
|
|
101
185
|
/**
|
|
102
186
|
* 获取歌曲别名列表
|
|
103
|
-
* @returns 歌曲别名列表
|
|
104
187
|
*/
|
|
105
188
|
async getAliasList() {
|
|
106
189
|
return this.http.get("alias/list").json();
|
|
107
190
|
}
|
|
108
191
|
/**
|
|
109
192
|
* 获取收藏品列表
|
|
110
|
-
* @param collectionType trophy | icon | plate | frame
|
|
111
|
-
* @param options.version 版本,不填写遵循api默认行为
|
|
112
|
-
* @param options.required 是否包含曲目需求,默认值为 false
|
|
113
|
-
* @returns 收藏品列表
|
|
114
193
|
*/
|
|
115
|
-
async getCollectionList(collectionType,
|
|
194
|
+
async getCollectionList(collectionType, version) {
|
|
116
195
|
const collectionMap = {
|
|
117
196
|
trophy: "trophies",
|
|
118
|
-
|
|
197
|
+
character: "characters",
|
|
119
198
|
plate: "plates",
|
|
120
|
-
|
|
199
|
+
icon: "icons"
|
|
121
200
|
};
|
|
122
|
-
return this.http.get(`${collectionType}/list`, { searchParams: {
|
|
201
|
+
return this.http.get(`${collectionType}/list`, { searchParams: { version } }).json().then((res) => res[collectionMap[collectionType]]);
|
|
123
202
|
}
|
|
124
203
|
/**
|
|
125
204
|
* 获取收藏品信息
|
|
126
|
-
* @param collectionType trophy | icon | plate | frame
|
|
127
|
-
* @param id 收藏品 ID
|
|
128
|
-
* @param options.version 版本,不填写遵循api默认行为
|
|
129
|
-
* @returns 收藏品信息
|
|
130
205
|
*/
|
|
131
|
-
async getCollectionInfo(collectionType, id,
|
|
132
|
-
return this.http.get(`${collectionType}/${id}`, { searchParams: {
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* 获取收藏品分类列表
|
|
136
|
-
* @param options.version 版本,不填写遵循api默认行为
|
|
137
|
-
* @returns 收藏品分类列表
|
|
138
|
-
*/
|
|
139
|
-
async getCollectionGenreList(options) {
|
|
140
|
-
return this.http.get("collection-genre/list", { searchParams: { ...options } }).json();
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* 获取收藏品分类信息
|
|
144
|
-
* @param id 收藏品分类 ID
|
|
145
|
-
* @param options.version 版本,不填写遵循api默认行为
|
|
146
|
-
* @returns 收藏品分类信息
|
|
147
|
-
*/
|
|
148
|
-
async getCollectionGenreInfo(id, options) {
|
|
149
|
-
return this.http.get(`collection-genre/${id}`, { searchParams: { ...options } }).json();
|
|
206
|
+
async getCollectionInfo(collectionType, id, version) {
|
|
207
|
+
return this.http.get(`${collectionType}/${id}`, { searchParams: { version } }).json();
|
|
150
208
|
}
|
|
151
209
|
};
|
|
152
210
|
|
|
153
|
-
// src/
|
|
211
|
+
// src/api/maimai/dev.ts
|
|
154
212
|
var MaimaiDevApi = class {
|
|
155
213
|
constructor(http) {
|
|
156
214
|
this.http = http;
|
|
@@ -269,7 +327,7 @@ var MaimaiDevApi = class {
|
|
|
269
327
|
}
|
|
270
328
|
};
|
|
271
329
|
|
|
272
|
-
// src/
|
|
330
|
+
// src/api/maimai/personal.ts
|
|
273
331
|
var MaimaiPersonalApi = class {
|
|
274
332
|
constructor(http) {
|
|
275
333
|
this.http = http;
|
|
@@ -302,50 +360,318 @@ var MaimaiPersonalApi = class {
|
|
|
302
360
|
}
|
|
303
361
|
};
|
|
304
362
|
|
|
305
|
-
// src/
|
|
306
|
-
var
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
363
|
+
// src/api/maimai/entities/song.ts
|
|
364
|
+
var LevelArray = [
|
|
365
|
+
"basic",
|
|
366
|
+
"advanced",
|
|
367
|
+
"expert",
|
|
368
|
+
"master",
|
|
369
|
+
"remaster"
|
|
370
|
+
];
|
|
371
|
+
function convertDifficulty(difficulty) {
|
|
372
|
+
return difficulty.reduce(
|
|
373
|
+
(acc, cur) => {
|
|
374
|
+
acc[LevelArray[cur.difficulty]] = cur;
|
|
375
|
+
return acc;
|
|
376
|
+
},
|
|
377
|
+
{}
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
var Song = class {
|
|
381
|
+
id;
|
|
382
|
+
title;
|
|
383
|
+
artist;
|
|
384
|
+
genre;
|
|
385
|
+
version;
|
|
386
|
+
bpm;
|
|
387
|
+
difficulties;
|
|
388
|
+
locked;
|
|
389
|
+
disabled;
|
|
390
|
+
rights;
|
|
391
|
+
constructor(song) {
|
|
392
|
+
this.id = song.id;
|
|
393
|
+
this.title = song.title;
|
|
394
|
+
this.artist = song.artist;
|
|
395
|
+
this.genre = song.genre;
|
|
396
|
+
this.version = song.version;
|
|
397
|
+
this.bpm = song.bpm;
|
|
398
|
+
this.difficulties = song.difficulties;
|
|
399
|
+
this.locked = song.locked ?? false;
|
|
400
|
+
this.disabled = song.disabled ?? false;
|
|
401
|
+
this.rights = song.rights;
|
|
402
|
+
}
|
|
403
|
+
get standard() {
|
|
404
|
+
if (this.difficulties.standard.length === 0) return null;
|
|
405
|
+
return convertDifficulty(this.difficulties.standard);
|
|
406
|
+
}
|
|
407
|
+
get dx() {
|
|
408
|
+
if (this.difficulties.dx.length === 0) return null;
|
|
409
|
+
return convertDifficulty(this.difficulties.dx);
|
|
410
|
+
}
|
|
411
|
+
get utage() {
|
|
412
|
+
if (!this.difficulties.utage) return null;
|
|
413
|
+
return convertDifficulty(this.difficulties.utage);
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
// src/api/maimai/public.ts
|
|
418
|
+
var MaimaiPublicApi = class {
|
|
419
|
+
constructor(http) {
|
|
420
|
+
this.http = http;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* 获取歌曲列表
|
|
424
|
+
* @param version 版本,不填写遵循api默认行为
|
|
425
|
+
* @param notes 是否包含谱面信息,不填写遵循api默认行为
|
|
426
|
+
* @returns 歌曲列表
|
|
427
|
+
*/
|
|
428
|
+
async getSongList(version, notes) {
|
|
429
|
+
return this.http.get("song/list?", { searchParams: { version, notes } }).json();
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* 获取歌曲信息
|
|
433
|
+
* @param id 歌曲 ID
|
|
434
|
+
* @returns 歌曲信息
|
|
435
|
+
*/
|
|
436
|
+
async getSong(id) {
|
|
437
|
+
const songInfo = await this.http.get(`song/${id}`).json();
|
|
438
|
+
return new Song(songInfo);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* 获取歌曲别名列表
|
|
442
|
+
* @returns 歌曲别名列表
|
|
443
|
+
*/
|
|
444
|
+
async getAliasList() {
|
|
445
|
+
return this.http.get("alias/list").json();
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* 获取收藏品列表
|
|
449
|
+
* @param collectionType trophy | icon | plate | frame
|
|
450
|
+
* @param options.version 版本,不填写遵循api默认行为
|
|
451
|
+
* @param options.required 是否包含曲目需求,默认值为 false
|
|
452
|
+
* @returns 收藏品列表
|
|
453
|
+
*/
|
|
454
|
+
async getCollectionList(collectionType, options) {
|
|
455
|
+
const collectionMap = {
|
|
456
|
+
trophy: "trophies",
|
|
457
|
+
icon: "icons",
|
|
458
|
+
plate: "plates",
|
|
459
|
+
frame: "frames"
|
|
460
|
+
};
|
|
461
|
+
return this.http.get(`${collectionType}/list`, { searchParams: { ...options } }).json().then((res) => res[collectionMap[collectionType]]);
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* 获取收藏品信息
|
|
465
|
+
* @param collectionType trophy | icon | plate | frame
|
|
466
|
+
* @param id 收藏品 ID
|
|
467
|
+
* @param options.version 版本,不填写遵循api默认行为
|
|
468
|
+
* @returns 收藏品信息
|
|
469
|
+
*/
|
|
470
|
+
async getCollectionInfo(collectionType, id, options) {
|
|
471
|
+
return this.http.get(`${collectionType}/${id}`, { searchParams: { ...options } }).json();
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* 获取收藏品分类列表
|
|
475
|
+
* @param options.version 版本,不填写遵循api默认行为
|
|
476
|
+
* @returns 收藏品分类列表
|
|
477
|
+
*/
|
|
478
|
+
async getCollectionGenreList(options) {
|
|
479
|
+
return this.http.get("collection-genre/list", { searchParams: { ...options } }).json();
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* 获取收藏品分类信息
|
|
483
|
+
* @param id 收藏品分类 ID
|
|
484
|
+
* @param options.version 版本,不填写遵循api默认行为
|
|
485
|
+
* @returns 收藏品分类信息
|
|
486
|
+
*/
|
|
487
|
+
async getCollectionGenreInfo(id, options) {
|
|
488
|
+
return this.http.get(`collection-genre/${id}`, { searchParams: { ...options } }).json();
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
// src/lxns-api-error.ts
|
|
493
|
+
var LxnsApiError = class extends Error {
|
|
494
|
+
code;
|
|
495
|
+
status;
|
|
496
|
+
success;
|
|
497
|
+
data;
|
|
498
|
+
constructor(payload, status) {
|
|
499
|
+
super(payload.message ?? `Lxns API unknown error (code: ${payload.code})`);
|
|
500
|
+
this.name = "LxnsApiError";
|
|
501
|
+
this.code = payload.code;
|
|
502
|
+
this.status = status;
|
|
503
|
+
this.success = payload.success;
|
|
504
|
+
this.data = payload.data;
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
function isLxnsApiError(error) {
|
|
508
|
+
return error instanceof LxnsApiError;
|
|
509
|
+
}
|
|
510
|
+
function isNotFoundError(error) {
|
|
511
|
+
return isLxnsApiError(error) && (error.status ?? error.code) === 404;
|
|
512
|
+
}
|
|
513
|
+
function isAuthError(error) {
|
|
514
|
+
const code = isLxnsApiError(error) ? error.status ?? error.code : void 0;
|
|
515
|
+
return code === 401 || code === 403;
|
|
516
|
+
}
|
|
517
|
+
function isRateLimitError(error) {
|
|
518
|
+
return isLxnsApiError(error) && (error.status ?? error.code) === 429;
|
|
519
|
+
}
|
|
520
|
+
function isServerError(error) {
|
|
521
|
+
const code = isLxnsApiError(error) ? error.status ?? error.code : void 0;
|
|
522
|
+
return typeof code === "number" && code >= 500;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// src/client/lxns-api-client.ts
|
|
526
|
+
function parseLxnsJson(text) {
|
|
527
|
+
const payload = JSON.parse(text);
|
|
528
|
+
if (payload.success === false) {
|
|
529
|
+
throw new LxnsApiError(payload);
|
|
530
|
+
}
|
|
531
|
+
if (payload.success === true) {
|
|
532
|
+
return payload.data;
|
|
533
|
+
}
|
|
534
|
+
return payload;
|
|
535
|
+
}
|
|
536
|
+
async function wrapKyError(error) {
|
|
537
|
+
const status = error.response.status;
|
|
538
|
+
try {
|
|
539
|
+
const payload = await error.response.clone().json();
|
|
540
|
+
if (typeof payload.success === "boolean") {
|
|
541
|
+
throw new LxnsApiError(
|
|
542
|
+
{
|
|
543
|
+
success: payload.success,
|
|
544
|
+
code: payload.code ?? status,
|
|
545
|
+
message: payload.message ?? error.message,
|
|
546
|
+
data: payload.data
|
|
547
|
+
},
|
|
548
|
+
status
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
} catch {
|
|
552
|
+
}
|
|
553
|
+
throw new LxnsApiError(
|
|
554
|
+
{
|
|
555
|
+
success: false,
|
|
556
|
+
code: status,
|
|
557
|
+
message: error.message
|
|
558
|
+
},
|
|
559
|
+
status
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
var LxnsApiClient = class _LxnsApiClient {
|
|
563
|
+
config;
|
|
310
564
|
/**
|
|
311
565
|
* maimai API
|
|
312
566
|
*/
|
|
313
567
|
maimai;
|
|
568
|
+
/**
|
|
569
|
+
* chunithm API
|
|
570
|
+
*/
|
|
571
|
+
chunithm;
|
|
572
|
+
static BASE_OPTIONS = {
|
|
573
|
+
parseJson: parseLxnsJson,
|
|
574
|
+
throwHttpErrors: true,
|
|
575
|
+
hooks: {
|
|
576
|
+
beforeError: [wrapKyError]
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
mountGameApi({
|
|
580
|
+
public: publicApi,
|
|
581
|
+
dev,
|
|
582
|
+
personal,
|
|
583
|
+
extra
|
|
584
|
+
}) {
|
|
585
|
+
const namespace = {
|
|
586
|
+
public: publicApi,
|
|
587
|
+
...extra ?? {}
|
|
588
|
+
};
|
|
589
|
+
if (dev) {
|
|
590
|
+
namespace.dev = dev;
|
|
591
|
+
}
|
|
592
|
+
if (personal) {
|
|
593
|
+
namespace.personal = personal;
|
|
594
|
+
}
|
|
595
|
+
return namespace;
|
|
596
|
+
}
|
|
314
597
|
constructor(config) {
|
|
315
598
|
this.config = {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
devAccessToken: config?.devAccessToken
|
|
599
|
+
...config,
|
|
600
|
+
baseURL: config?.baseURL ?? "https://maimai.lxns.net/api/v0/"
|
|
319
601
|
};
|
|
320
602
|
const { baseURL, devAccessToken, personalAccessToken } = this.config;
|
|
321
|
-
const
|
|
322
|
-
prefixUrl: new URL("maimai/", baseURL)
|
|
603
|
+
const maimaiHttpPublic = ky.create({
|
|
604
|
+
prefixUrl: new URL("maimai/", baseURL),
|
|
605
|
+
..._LxnsApiClient.BASE_OPTIONS
|
|
323
606
|
});
|
|
324
|
-
const
|
|
607
|
+
const maimaiHttpDev = devAccessToken ? ky.create({
|
|
325
608
|
prefixUrl: new URL("maimai/", baseURL),
|
|
326
609
|
headers: {
|
|
327
610
|
Authorization: devAccessToken
|
|
328
|
-
}
|
|
611
|
+
},
|
|
612
|
+
..._LxnsApiClient.BASE_OPTIONS
|
|
329
613
|
}) : void 0;
|
|
330
|
-
const
|
|
614
|
+
const maimaiHttpPersonal = personalAccessToken ? ky.create({
|
|
331
615
|
prefixUrl: new URL("user/maimai/", baseURL),
|
|
332
616
|
headers: {
|
|
333
617
|
"X-User-Token": personalAccessToken
|
|
618
|
+
},
|
|
619
|
+
..._LxnsApiClient.BASE_OPTIONS
|
|
620
|
+
}) : void 0;
|
|
621
|
+
this.maimai = this.mountGameApi({
|
|
622
|
+
public: new MaimaiPublicApi(maimaiHttpPublic),
|
|
623
|
+
dev: maimaiHttpDev ? new MaimaiDevApi(maimaiHttpDev) : void 0,
|
|
624
|
+
personal: maimaiHttpPersonal ? new MaimaiPersonalApi(maimaiHttpPersonal) : void 0,
|
|
625
|
+
extra: {
|
|
626
|
+
getAsset: async (type, id) => {
|
|
627
|
+
return new Uint8Array(
|
|
628
|
+
await ky.get(
|
|
629
|
+
`https://assets2.lxns.net/maimai/${type}/${id + (type === "music" ? ".mp3" : ".png")}`
|
|
630
|
+
).arrayBuffer()
|
|
631
|
+
);
|
|
632
|
+
}
|
|
334
633
|
}
|
|
634
|
+
});
|
|
635
|
+
const chunithmHttpPublic = ky.create({
|
|
636
|
+
prefixUrl: new URL("chunithm/", baseURL),
|
|
637
|
+
..._LxnsApiClient.BASE_OPTIONS
|
|
638
|
+
});
|
|
639
|
+
const chunithmHttpDev = devAccessToken ? ky.create({
|
|
640
|
+
prefixUrl: new URL("chunithm/", baseURL),
|
|
641
|
+
headers: {
|
|
642
|
+
Authorization: devAccessToken
|
|
643
|
+
},
|
|
644
|
+
..._LxnsApiClient.BASE_OPTIONS
|
|
335
645
|
}) : void 0;
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
646
|
+
const chunithmHttpPersonal = personalAccessToken ? ky.create({
|
|
647
|
+
prefixUrl: new URL("user/chunithm/", baseURL),
|
|
648
|
+
headers: {
|
|
649
|
+
"X-User-Token": personalAccessToken
|
|
650
|
+
},
|
|
651
|
+
..._LxnsApiClient.BASE_OPTIONS
|
|
652
|
+
}) : void 0;
|
|
653
|
+
this.chunithm = this.mountGameApi({
|
|
654
|
+
public: new ChunithmPublicApi(chunithmHttpPublic),
|
|
655
|
+
dev: chunithmHttpDev ? new ChunithmDevApi(chunithmHttpDev) : void 0,
|
|
656
|
+
personal: chunithmHttpPersonal ? new ChunithmPersonalApi(chunithmHttpPersonal) : void 0,
|
|
657
|
+
extra: {
|
|
658
|
+
getAsset: async (type, id) => {
|
|
659
|
+
return new Uint8Array(
|
|
660
|
+
await ky.get(`https://assets2.lxns.net/chunithm/${type}/${id}.png`).arrayBuffer()
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
});
|
|
346
665
|
}
|
|
347
666
|
};
|
|
348
667
|
export {
|
|
668
|
+
models_exports as ChunithmModels,
|
|
349
669
|
LxnsApiClient,
|
|
350
|
-
|
|
670
|
+
LxnsApiError,
|
|
671
|
+
models_exports2 as MaimaiModels,
|
|
672
|
+
isAuthError,
|
|
673
|
+
isLxnsApiError,
|
|
674
|
+
isNotFoundError,
|
|
675
|
+
isRateLimitError,
|
|
676
|
+
isServerError
|
|
351
677
|
};
|