lxns-rhythm-api 0.1.1 → 0.1.3
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/README.md +11 -12
- package/package.json +3 -4
- package/dist/index.cjs +0 -383
package/README.md
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
# lxns-
|
|
1
|
+
# lxns-rhythm-api
|
|
2
2
|
|
|
3
3
|
一个用于访问 Lxns API 的轻量 TypeScript SDK。
|
|
4
4
|
|
|
5
5
|
- 零运行时依赖(仅使用 `ky` 发起请求)。
|
|
6
6
|
- 类型安全:根据传入的 token 自动在 `maimai` 命名空间上暴露 `public` / `dev` / `personal` 子 API。
|
|
7
|
-
-
|
|
7
|
+
- 现代构建
|
|
8
8
|
|
|
9
9
|
## 安装
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
# npm
|
|
13
|
-
npm i lxns-
|
|
13
|
+
npm i lxns-rhythm-api
|
|
14
14
|
|
|
15
15
|
# pnpm
|
|
16
|
-
pnpm add lxns-
|
|
16
|
+
pnpm add lxns-rhythm-api
|
|
17
17
|
|
|
18
18
|
# yarn
|
|
19
|
-
yarn add lxns-
|
|
19
|
+
yarn add lxns-rhythm-api
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
## 快速开始
|
|
23
23
|
|
|
24
24
|
```ts
|
|
25
|
-
import { LxnsApiClient } from "lxns-
|
|
25
|
+
import { LxnsApiClient } from "lxns-rhythm-api";
|
|
26
26
|
|
|
27
27
|
// 无 token:仅可用 public API
|
|
28
28
|
const client = new LxnsApiClient();
|
|
@@ -44,12 +44,6 @@ const me = await personalClient.maimai.personal.getPlayer();
|
|
|
44
44
|
console.log(me);
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
CommonJS 引用:
|
|
48
|
-
|
|
49
|
-
```js
|
|
50
|
-
const { LxnsApiClient } = require("lxns-sdk");
|
|
51
|
-
```
|
|
52
|
-
|
|
53
47
|
## 配置项
|
|
54
48
|
|
|
55
49
|
构造函数签名:
|
|
@@ -75,6 +69,11 @@ new LxnsApiClient(options?: {
|
|
|
75
69
|
|
|
76
70
|
> 注意:`baseURL` 默认值为 `https://maimai.lxns.net/api/v0/`。
|
|
77
71
|
|
|
72
|
+
## TODO
|
|
73
|
+
|
|
74
|
+
- [ ] 支持 Chuni API
|
|
75
|
+
- [x] 支持 Maimai API
|
|
76
|
+
|
|
78
77
|
## API 概览
|
|
79
78
|
|
|
80
79
|
- `maimai.public`
|
package/package.json
CHANGED
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
"name": "lxns-rhythm-api",
|
|
3
3
|
"description": "A simple SDK for lxns api.",
|
|
4
4
|
"author": "amatsuka <amatsukamao@qq.com>",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.3",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/wsyzxjn/lxns-rhythm-api.git"
|
|
9
9
|
},
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
|
-
"import": "./dist/index.js"
|
|
13
|
-
"require": "./dist/index.cjs"
|
|
12
|
+
"import": "./dist/index.js"
|
|
14
13
|
},
|
|
15
14
|
"./package.json": "./package.json"
|
|
16
15
|
},
|
|
@@ -21,7 +20,7 @@
|
|
|
21
20
|
"LICENSE"
|
|
22
21
|
],
|
|
23
22
|
"type": "module",
|
|
24
|
-
"main": "./dist/index.
|
|
23
|
+
"main": "./dist/index.js",
|
|
25
24
|
"module": "./dist/index.js",
|
|
26
25
|
"types": "./dist/index.d.ts",
|
|
27
26
|
"devDependencies": {
|
package/dist/index.cjs
DELETED
|
@@ -1,383 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
// src/index.ts
|
|
31
|
-
var index_exports = {};
|
|
32
|
-
__export(index_exports, {
|
|
33
|
-
LxnsApiClient: () => LxnsApiClient,
|
|
34
|
-
MaimaiModels: () => models_exports
|
|
35
|
-
});
|
|
36
|
-
module.exports = __toCommonJS(index_exports);
|
|
37
|
-
|
|
38
|
-
// src/apis/maimai/models.ts
|
|
39
|
-
var models_exports = {};
|
|
40
|
-
__export(models_exports, {
|
|
41
|
-
LevelIndex: () => LevelIndex
|
|
42
|
-
});
|
|
43
|
-
var LevelIndex = /* @__PURE__ */ ((LevelIndex2) => {
|
|
44
|
-
LevelIndex2[LevelIndex2["BASIC"] = 0] = "BASIC";
|
|
45
|
-
LevelIndex2[LevelIndex2["ADVANCED"] = 1] = "ADVANCED";
|
|
46
|
-
LevelIndex2[LevelIndex2["EXPERT"] = 2] = "EXPERT";
|
|
47
|
-
LevelIndex2[LevelIndex2["MASTER"] = 3] = "MASTER";
|
|
48
|
-
LevelIndex2[LevelIndex2["RE_MASTER"] = 4] = "RE_MASTER";
|
|
49
|
-
return LevelIndex2;
|
|
50
|
-
})(LevelIndex || {});
|
|
51
|
-
|
|
52
|
-
// src/client/LxnsApiCLient.ts
|
|
53
|
-
var import_ky = __toESM(require("ky"), 1);
|
|
54
|
-
|
|
55
|
-
// src/apis/maimai/entities/Song.ts
|
|
56
|
-
var LevelArray = [
|
|
57
|
-
"basic",
|
|
58
|
-
"advanced",
|
|
59
|
-
"expert",
|
|
60
|
-
"master",
|
|
61
|
-
"remaster"
|
|
62
|
-
];
|
|
63
|
-
function convertDifficulty(difficulty) {
|
|
64
|
-
return difficulty.reduce(
|
|
65
|
-
(acc, cur) => {
|
|
66
|
-
acc[LevelArray[cur.difficulty]] = cur;
|
|
67
|
-
return acc;
|
|
68
|
-
},
|
|
69
|
-
{}
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
var Song = class {
|
|
73
|
-
id;
|
|
74
|
-
title;
|
|
75
|
-
artist;
|
|
76
|
-
genre;
|
|
77
|
-
version;
|
|
78
|
-
bpm;
|
|
79
|
-
difficulties;
|
|
80
|
-
locked;
|
|
81
|
-
disabled;
|
|
82
|
-
rights;
|
|
83
|
-
constructor(song) {
|
|
84
|
-
this.id = song.id;
|
|
85
|
-
this.title = song.title;
|
|
86
|
-
this.artist = song.artist;
|
|
87
|
-
this.genre = song.genre;
|
|
88
|
-
this.version = song.version;
|
|
89
|
-
this.bpm = song.bpm;
|
|
90
|
-
this.difficulties = song.difficulties;
|
|
91
|
-
this.locked = song.locked ?? false;
|
|
92
|
-
this.disabled = song.disabled ?? false;
|
|
93
|
-
this.rights = song.rights;
|
|
94
|
-
}
|
|
95
|
-
get standard() {
|
|
96
|
-
if (this.difficulties.standard.length === 0) return null;
|
|
97
|
-
return convertDifficulty(this.difficulties.standard);
|
|
98
|
-
}
|
|
99
|
-
get dx() {
|
|
100
|
-
if (this.difficulties.dx.length === 0) return null;
|
|
101
|
-
return convertDifficulty(this.difficulties.dx);
|
|
102
|
-
}
|
|
103
|
-
get utage() {
|
|
104
|
-
if (!this.difficulties.utage) return null;
|
|
105
|
-
return convertDifficulty(this.difficulties.utage);
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
// src/apis/maimai/public.ts
|
|
110
|
-
var MaimaiPublicApi = class {
|
|
111
|
-
constructor(http) {
|
|
112
|
-
this.http = http;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* 获取歌曲列表
|
|
116
|
-
* @param version 版本,不填写遵循api默认行为
|
|
117
|
-
* @param notes 是否包含谱面信息,不填写遵循api默认行为
|
|
118
|
-
* @returns 歌曲列表
|
|
119
|
-
*/
|
|
120
|
-
async getSongList(version, notes) {
|
|
121
|
-
return this.http.get("song/list?", { searchParams: { version, notes } }).json();
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* 获取歌曲信息
|
|
125
|
-
* @param id 歌曲 ID
|
|
126
|
-
* @returns 歌曲信息
|
|
127
|
-
*/
|
|
128
|
-
async getSong(id) {
|
|
129
|
-
const songInfo = await this.http.get(`song/${id}`).json();
|
|
130
|
-
return new Song(songInfo);
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* 获取歌曲别名列表
|
|
134
|
-
* @returns 歌曲别名列表
|
|
135
|
-
*/
|
|
136
|
-
async getAliasList() {
|
|
137
|
-
return this.http.get("alias/list").json();
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* 获取收藏品列表
|
|
141
|
-
* @param collectionType trophy | icon | plate | frame
|
|
142
|
-
* @param options.version 版本,不填写遵循api默认行为
|
|
143
|
-
* @param options.required 是否包含曲目需求,默认值为 false
|
|
144
|
-
* @returns 收藏品列表
|
|
145
|
-
*/
|
|
146
|
-
async getCollectionList(collectionType, options) {
|
|
147
|
-
const collectionMap = {
|
|
148
|
-
trophy: "trophies",
|
|
149
|
-
icon: "icons",
|
|
150
|
-
plate: "plates",
|
|
151
|
-
frame: "frames"
|
|
152
|
-
};
|
|
153
|
-
return this.http.get(`${collectionType}/list`, { searchParams: { ...options } }).json().then((res) => res[collectionMap[collectionType]]);
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* 获取收藏品信息
|
|
157
|
-
* @param collectionType trophy | icon | plate | frame
|
|
158
|
-
* @param id 收藏品 ID
|
|
159
|
-
* @param options.version 版本,不填写遵循api默认行为
|
|
160
|
-
* @returns 收藏品信息
|
|
161
|
-
*/
|
|
162
|
-
async getCollectionInfo(collectionType, id, options) {
|
|
163
|
-
return this.http.get(`${collectionType}/${id}`, { searchParams: { ...options } }).json();
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* 获取收藏品分类列表
|
|
167
|
-
* @param options.version 版本,不填写遵循api默认行为
|
|
168
|
-
* @returns 收藏品分类列表
|
|
169
|
-
*/
|
|
170
|
-
async getCollectionGenreList(options) {
|
|
171
|
-
return this.http.get("collection-genre/list", { searchParams: { ...options } }).json();
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* 获取收藏品分类信息
|
|
175
|
-
* @param id 收藏品分类 ID
|
|
176
|
-
* @param options.version 版本,不填写遵循api默认行为
|
|
177
|
-
* @returns 收藏品分类信息
|
|
178
|
-
*/
|
|
179
|
-
async getCollectionGenreInfo(id, options) {
|
|
180
|
-
return this.http.get(`collection-genre/${id}`, { searchParams: { ...options } }).json();
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
// src/apis/maimai/dev.ts
|
|
185
|
-
var MaimaiDevApi = class {
|
|
186
|
-
constructor(http) {
|
|
187
|
-
this.http = http;
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* 创建或修改玩家信息
|
|
191
|
-
* @param body 玩家信息
|
|
192
|
-
* @returns 玩家信息
|
|
193
|
-
*/
|
|
194
|
-
async postPlayer(body) {
|
|
195
|
-
return this.http.post("player", { json: body }).json();
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* 获取玩家信息(通过好友码)
|
|
199
|
-
* @param friendCode 好友码
|
|
200
|
-
* @returns 玩家信息
|
|
201
|
-
*/
|
|
202
|
-
async getPlayer(friendCode) {
|
|
203
|
-
return this.http.get(`player/${friendCode}`).json();
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* 获取玩家信息(通过 QQ 号)
|
|
207
|
-
* @param qq QQ 号
|
|
208
|
-
* @returns 玩家信息
|
|
209
|
-
*/
|
|
210
|
-
async getPlayerByQQ(qq) {
|
|
211
|
-
return this.http.get(`player/qq/${qq}`).json();
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* 获取 Best 50(standard 35 + dx 15)
|
|
215
|
-
* @param friendCode 好友码
|
|
216
|
-
* @returns Best 50
|
|
217
|
-
*/
|
|
218
|
-
async getBests(friendCode) {
|
|
219
|
-
return this.http.get(`player/${friendCode}/bests`).json();
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* 获取 AP 50
|
|
223
|
-
* @param friendCode 好友码
|
|
224
|
-
* @returns AP 50
|
|
225
|
-
*/
|
|
226
|
-
async getApBests(friendCode) {
|
|
227
|
-
return this.http.get(`player/${friendCode}/bests/ap`).json();
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* 获取 Recent 50(仅增量爬取可用)
|
|
231
|
-
* @param friendCode 好友码
|
|
232
|
-
* @returns Recent 50
|
|
233
|
-
*/
|
|
234
|
-
async getRecents(friendCode) {
|
|
235
|
-
return this.http.get(`player/${friendCode}/recents`).json();
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* 获取玩家缓存的所有最佳成绩(简化)
|
|
239
|
-
* @param friendCode 好友码
|
|
240
|
-
* @returns BestScoreList
|
|
241
|
-
*/
|
|
242
|
-
async getAllBestScores(friendCode) {
|
|
243
|
-
return this.http.get(`player/${friendCode}/scores`).json();
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* 成绩上传热力图(YYYY-MM-DD -> 数量)
|
|
247
|
-
* @param friendCode 好友码
|
|
248
|
-
* @returns Heatmap
|
|
249
|
-
*/
|
|
250
|
-
async getHeatmap(friendCode) {
|
|
251
|
-
return this.http.get(`player/${friendCode}/heatmap`).json();
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* DX Rating 趋势
|
|
255
|
-
* @param friendCode 好友码
|
|
256
|
-
* @returns TrendList
|
|
257
|
-
*/
|
|
258
|
-
async getTrend(friendCode) {
|
|
259
|
-
return this.http.get(`player/${friendCode}/trend`).json();
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* 成绩游玩历史记录(仅返回带有 play_time 的成绩)
|
|
263
|
-
* @param friendCode 好友码
|
|
264
|
-
* @returns 游玩历史记录
|
|
265
|
-
*/
|
|
266
|
-
async getScoreHistory(friendCode) {
|
|
267
|
-
return this.http.get(`player/${friendCode}/score/history`).json();
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* 获取玩家收藏品进度
|
|
271
|
-
* @param friendCode 好友码
|
|
272
|
-
* @param collectionType 收藏品类型
|
|
273
|
-
* @param collectionId 收藏品 ID
|
|
274
|
-
* @returns 收藏品进度
|
|
275
|
-
*/
|
|
276
|
-
async getCollectionProgress(friendCode, collectionType, collectionId) {
|
|
277
|
-
return this.http.get(`player/${friendCode}/${collectionType}/${collectionId}`).json();
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* 上传玩家成绩
|
|
281
|
-
* @param friendCode 好友码
|
|
282
|
-
* @param scores 成绩列表
|
|
283
|
-
* @returns 上传结果
|
|
284
|
-
*/
|
|
285
|
-
async postScores(friendCode, scores) {
|
|
286
|
-
const body = { scores };
|
|
287
|
-
return this.http.post(`player/${friendCode}/scores`, { json: body }).json();
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* 通过 NET 的 HTML 源代码上传玩家数据
|
|
291
|
-
* @param friendCode 好友码
|
|
292
|
-
* @param htmlSource HTML 源代码
|
|
293
|
-
* @returns 上传结果
|
|
294
|
-
*/
|
|
295
|
-
async postHtml(friendCode, htmlSource) {
|
|
296
|
-
return this.http.post(`player/${friendCode}/html`, {
|
|
297
|
-
body: htmlSource,
|
|
298
|
-
headers: { "content-type": "text/plain" }
|
|
299
|
-
}).json();
|
|
300
|
-
}
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
// src/apis/maimai/personal.ts
|
|
304
|
-
var MaimaiPersonalApi = class {
|
|
305
|
-
constructor(http) {
|
|
306
|
-
this.http = http;
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* 获取玩家信息
|
|
310
|
-
* GET /api/v0/user/maimai/player
|
|
311
|
-
* @returns PlayerInfo
|
|
312
|
-
*/
|
|
313
|
-
async getPlayer() {
|
|
314
|
-
return this.http.get("player").json();
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* 获取玩家所有成绩
|
|
318
|
-
* GET /api/v0/user/maimai/player/scores
|
|
319
|
-
* @returns PlayerScores
|
|
320
|
-
*/
|
|
321
|
-
async getScores() {
|
|
322
|
-
return this.http.get("scores").json();
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* 上传玩家成绩
|
|
326
|
-
* POST /api/v0/user/maimai/player/scores
|
|
327
|
-
* @param scores 成绩列表
|
|
328
|
-
* @returns 上传结果
|
|
329
|
-
*/
|
|
330
|
-
async postScores(scores) {
|
|
331
|
-
const body = { scores };
|
|
332
|
-
return this.http.post("scores", { json: body }).json();
|
|
333
|
-
}
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
// src/client/LxnsApiCLient.ts
|
|
337
|
-
var LxnsApiClient = class {
|
|
338
|
-
config = {
|
|
339
|
-
baseURL: "https://maimai.lxns.net/api/v0/"
|
|
340
|
-
};
|
|
341
|
-
/**
|
|
342
|
-
* maimai API
|
|
343
|
-
*/
|
|
344
|
-
maimai;
|
|
345
|
-
constructor(config) {
|
|
346
|
-
this.config = {
|
|
347
|
-
baseURL: config?.baseURL ?? this.config.baseURL,
|
|
348
|
-
personalAccessToken: config?.personalAccessToken,
|
|
349
|
-
devAccessToken: config?.devAccessToken
|
|
350
|
-
};
|
|
351
|
-
const { baseURL, devAccessToken, personalAccessToken } = this.config;
|
|
352
|
-
const httpPublic = import_ky.default.create({
|
|
353
|
-
prefixUrl: new URL("maimai/", baseURL)
|
|
354
|
-
});
|
|
355
|
-
const httpDev = devAccessToken ? import_ky.default.create({
|
|
356
|
-
prefixUrl: new URL("maimai/", baseURL),
|
|
357
|
-
headers: {
|
|
358
|
-
Authorization: devAccessToken
|
|
359
|
-
}
|
|
360
|
-
}) : void 0;
|
|
361
|
-
const httpPersonal = personalAccessToken ? import_ky.default.create({
|
|
362
|
-
prefixUrl: new URL("user/maimai/", baseURL),
|
|
363
|
-
headers: {
|
|
364
|
-
"X-User-Token": personalAccessToken
|
|
365
|
-
}
|
|
366
|
-
}) : void 0;
|
|
367
|
-
const maimai = {
|
|
368
|
-
public: new MaimaiPublicApi(httpPublic)
|
|
369
|
-
};
|
|
370
|
-
if (httpDev) {
|
|
371
|
-
maimai.dev = new MaimaiDevApi(httpDev);
|
|
372
|
-
}
|
|
373
|
-
if (httpPersonal) {
|
|
374
|
-
maimai.personal = new MaimaiPersonalApi(httpPersonal);
|
|
375
|
-
}
|
|
376
|
-
this.maimai = maimai;
|
|
377
|
-
}
|
|
378
|
-
};
|
|
379
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
380
|
-
0 && (module.exports = {
|
|
381
|
-
LxnsApiClient,
|
|
382
|
-
MaimaiModels
|
|
383
|
-
});
|