koishi-plugin-bind-bot 2.1.1 → 2.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.
@@ -197,7 +197,7 @@ class MCIDBINDRepository {
197
197
  */
198
198
  async deleteAll() {
199
199
  try {
200
- this.logger.debug('数据库', `删除所有绑定记录`);
200
+ this.logger.debug('数据库', '删除所有绑定记录');
201
201
  const result = await this.ctx.database.remove('mcidbind', {});
202
202
  this.logger.info('数据库', `成功删除所有绑定记录(删除${result.removed}条)`, true);
203
203
  return result.removed;
@@ -324,7 +324,7 @@ class MCIDBINDRepository {
324
324
  */
325
325
  async findAllAdmins() {
326
326
  try {
327
- this.logger.debug('数据库', `获取所有管理员`);
327
+ this.logger.debug('数据库', '获取所有管理员');
328
328
  const allRecords = await this.ctx.database.get('mcidbind', {});
329
329
  return allRecords.filter(record => record.isAdmin);
330
330
  }
@@ -50,7 +50,7 @@ class ScheduleMuteRepository {
50
50
  */
51
51
  async findAll() {
52
52
  try {
53
- this.logger.debug('数据库', `获取所有定时禁言任务`);
53
+ this.logger.debug('数据库', '获取所有定时禁言任务');
54
54
  const tasks = await this.ctx.database.get('schedule_mute_tasks', {});
55
55
  return tasks;
56
56
  }
@@ -65,7 +65,7 @@ class ScheduleMuteRepository {
65
65
  */
66
66
  async findAllEnabled() {
67
67
  try {
68
- this.logger.debug('数据库', `获取所有已启用的定时禁言任务`);
68
+ this.logger.debug('数据库', '获取所有已启用的定时禁言任务');
69
69
  const tasks = await this.ctx.database.get('schedule_mute_tasks', { enabled: true });
70
70
  return tasks;
71
71
  }
@@ -28,7 +28,7 @@ class ApiService {
28
28
  const response = await axios_1.default.get(`https://api.mojang.com/users/profiles/minecraft/${username}`, {
29
29
  timeout: 10000, // 添加10秒超时
30
30
  headers: {
31
- 'User-Agent': 'KoishiMCVerifier/1.0', // 添加User-Agent头
31
+ 'User-Agent': 'KoishiMCVerifier/1.0' // 添加User-Agent头
32
32
  }
33
33
  });
34
34
  if (response.status === 200 && response.data) {
@@ -54,13 +54,15 @@ class ApiService {
54
54
  : error.message || '未知错误';
55
55
  this.logger.error('Mojang API', `验证用户名"${username}"时发生错误: ${errorMessage}`);
56
56
  // 如果是网络相关错误,尝试使用备用API检查
57
- if (axios_1.default.isAxiosError(error) && (error.code === 'ENOTFOUND' ||
58
- error.code === 'ETIMEDOUT' ||
59
- error.code === 'ECONNRESET' ||
60
- error.code === 'ECONNREFUSED' ||
61
- error.code === 'ECONNABORTED' ||
62
- error.response?.status === 429 || // 添加429 (Too Many Requests)
63
- error.response?.status === 403)) { // 添加403 (Forbidden)
57
+ if (axios_1.default.isAxiosError(error) &&
58
+ (error.code === 'ENOTFOUND' ||
59
+ error.code === 'ETIMEDOUT' ||
60
+ error.code === 'ECONNRESET' ||
61
+ error.code === 'ECONNREFUSED' ||
62
+ error.code === 'ECONNABORTED' ||
63
+ error.response?.status === 429 || // 添加429 (Too Many Requests)
64
+ error.response?.status === 403)) {
65
+ // 添加403 (Forbidden)
64
66
  // 尝试使用playerdb.co作为备用API
65
67
  this.logger.info('Mojang API', `遇到错误(${error.code || error.response?.status}),将尝试使用备用API`);
66
68
  return this.tryBackupAPI(username);
@@ -84,7 +86,7 @@ class ApiService {
84
86
  'User-Agent': 'KoishiMCVerifier/1.0'
85
87
  }
86
88
  });
87
- if (backupResponse.status === 200 && backupResponse.data?.code === "player.found") {
89
+ if (backupResponse.status === 200 && backupResponse.data?.code === 'player.found') {
88
90
  const playerData = backupResponse.data.data.player;
89
91
  const rawId = playerData.raw_id || playerData.id.replace(/-/g, ''); // 确保使用不带连字符的UUID
90
92
  this.logger.info('备用API', `用户名"${username}"验证成功,UUID: ${rawId},标准名称: ${playerData.username}`);
@@ -117,7 +119,7 @@ class ApiService {
117
119
  const response = await axios_1.default.get(`https://api.mojang.com/user/profile/${cleanUuid}`, {
118
120
  timeout: 10000,
119
121
  headers: {
120
- 'User-Agent': 'KoishiMCVerifier/1.0',
122
+ 'User-Agent': 'KoishiMCVerifier/1.0'
121
123
  }
122
124
  });
123
125
  if (response.status === 200 && response.data) {
@@ -131,13 +133,15 @@ class ApiService {
131
133
  }
132
134
  catch (error) {
133
135
  // 如果是网络相关错误,尝试使用备用API
134
- if (axios_1.default.isAxiosError(error) && (error.code === 'ENOTFOUND' ||
135
- error.code === 'ETIMEDOUT' ||
136
- error.code === 'ECONNRESET' ||
137
- error.code === 'ECONNREFUSED' ||
138
- error.code === 'ECONNABORTED' ||
139
- error.response?.status === 429 || // 添加429 (Too Many Requests)
140
- error.response?.status === 403)) { // 添加403 (Forbidden)
136
+ if (axios_1.default.isAxiosError(error) &&
137
+ (error.code === 'ENOTFOUND' ||
138
+ error.code === 'ETIMEDOUT' ||
139
+ error.code === 'ECONNRESET' ||
140
+ error.code === 'ECONNREFUSED' ||
141
+ error.code === 'ECONNABORTED' ||
142
+ error.response?.status === 429 || // 添加429 (Too Many Requests)
143
+ error.response?.status === 403)) {
144
+ // 添加403 (Forbidden)
141
145
  this.logger.info('Mojang API', `通过UUID查询用户名时遇到错误(${error.code || error.response?.status}),将尝试使用备用API`);
142
146
  return this.getUsernameByUuidBackupAPI(uuid);
143
147
  }
@@ -161,10 +165,10 @@ class ApiService {
161
165
  const response = await axios_1.default.get(`https://playerdb.co/api/player/minecraft/${formattedUuid}`, {
162
166
  timeout: 10000,
163
167
  headers: {
164
- 'User-Agent': 'KoishiMCVerifier/1.0',
168
+ 'User-Agent': 'KoishiMCVerifier/1.0'
165
169
  }
166
170
  });
167
- if (response.status === 200 && response.data?.code === "player.found") {
171
+ if (response.status === 200 && response.data?.code === 'player.found') {
168
172
  const playerData = response.data.data.player;
169
173
  this.logger.debug('备用API', `UUID "${formattedUuid}" 当前用户名: ${playerData.username}`);
170
174
  return playerData.username;
@@ -193,13 +197,13 @@ class ApiService {
193
197
  return null;
194
198
  }
195
199
  this.logger.debug('B站官方API', `开始查询UID ${uid} 的官方信息`);
196
- const response = await axios_1.default.get(`https://api.bilibili.com/x/space/acc/info`, {
200
+ const response = await axios_1.default.get('https://api.bilibili.com/x/space/acc/info', {
197
201
  params: { mid: uid },
198
202
  timeout: 10000,
199
203
  headers: {
200
204
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
201
- 'Referer': 'https://space.bilibili.com/',
202
- 'Origin': 'https://space.bilibili.com'
205
+ Referer: 'https://space.bilibili.com/',
206
+ Origin: 'https://space.bilibili.com'
203
207
  }
204
208
  });
205
209
  if (response.data.code === 0 && response.data.data) {
@@ -314,7 +318,7 @@ class ApiService {
314
318
  'dungeons', // 地下城风格
315
319
  'facepalm', // 捂脸
316
320
  'mojavatar', // Mojave姿态
317
- 'head', // 头部特写
321
+ 'head' // 头部特写
318
322
  ];
319
323
  // 随机选择一个动作
320
324
  const randomPose = poses[Math.floor(Math.random() * poses.length)];
@@ -27,7 +27,7 @@ class DatabaseService {
27
27
  try {
28
28
  // 处理空值
29
29
  if (!qqId) {
30
- this.logger.warn('MCIDBIND', `尝试查询空QQ号`);
30
+ this.logger.warn('MCIDBIND', '尝试查询空QQ号');
31
31
  return null;
32
32
  }
33
33
  const normalizedQQId = this.normalizeQQId(qqId);
@@ -45,7 +45,7 @@ class DatabaseService {
45
45
  async getMcBindByUsername(mcUsername) {
46
46
  // 处理空值
47
47
  if (!mcUsername) {
48
- this.logger.warn('MCIDBIND', `尝试查询空MC用户名`);
48
+ this.logger.warn('MCIDBIND', '尝试查询空MC用户名');
49
49
  return null;
50
50
  }
51
51
  // 使用 Repository 查询
@@ -58,16 +58,16 @@ class DatabaseService {
58
58
  try {
59
59
  // 验证输入参数
60
60
  if (!userId) {
61
- this.logger.error('MCIDBIND', `创建/更新绑定失败: 无效的用户ID`);
61
+ this.logger.error('MCIDBIND', '创建/更新绑定失败: 无效的用户ID');
62
62
  return false;
63
63
  }
64
64
  if (!mcUsername) {
65
- this.logger.error('MCIDBIND', `创建/更新绑定失败: 无效的MC用户名`);
65
+ this.logger.error('MCIDBIND', '创建/更新绑定失败: 无效的MC用户名');
66
66
  return false;
67
67
  }
68
68
  const normalizedQQId = this.normalizeQQId(userId);
69
69
  if (!normalizedQQId) {
70
- this.logger.error('MCIDBIND', `创建/更新绑定失败: 无法提取有效的QQ号`);
70
+ this.logger.error('MCIDBIND', '创建/更新绑定失败: 无法提取有效的QQ号');
71
71
  return false;
72
72
  }
73
73
  // 查询是否已存在绑定记录
@@ -118,12 +118,12 @@ class DatabaseService {
118
118
  try {
119
119
  // 验证输入参数
120
120
  if (!userId) {
121
- this.logger.error('MCIDBIND', `删除绑定失败: 无效的用户ID`);
121
+ this.logger.error('MCIDBIND', '删除绑定失败: 无效的用户ID');
122
122
  return false;
123
123
  }
124
124
  const normalizedQQId = this.normalizeQQId(userId);
125
125
  if (!normalizedQQId) {
126
- this.logger.error('MCIDBIND', `删除绑定失败: 无法提取有效的QQ号`);
126
+ this.logger.error('MCIDBIND', '删除绑定失败: 无法提取有效的QQ号');
127
127
  return false;
128
128
  }
129
129
  // 查询是否存在绑定记录
@@ -161,7 +161,7 @@ class DatabaseService {
161
161
  try {
162
162
  // 验证输入参数
163
163
  if (!username) {
164
- this.logger.warn('绑定检查', `尝试检查空MC用户名`);
164
+ this.logger.warn('绑定检查', '尝试检查空MC用户名');
165
165
  return false;
166
166
  }
167
167
  // 跳过临时用户名的检查
@@ -207,7 +207,7 @@ class DatabaseService {
207
207
  async getBuidBindByBuid(buid) {
208
208
  try {
209
209
  if (!buid) {
210
- this.logger.warn('B站账号绑定', `尝试查询空B站UID`);
210
+ this.logger.warn('B站账号绑定', '尝试查询空B站UID');
211
211
  return null;
212
212
  }
213
213
  const bind = await this.mcidbindRepo.findByBuidUid(buid);
@@ -245,7 +245,7 @@ class DatabaseService {
245
245
  try {
246
246
  const normalizedQQId = this.normalizeQQId(userId);
247
247
  if (!normalizedQQId) {
248
- this.logger.error('B站账号绑定', `创建/更新绑定失败: 无法提取有效的QQ号`);
248
+ this.logger.error('B站账号绑定', '创建/更新绑定失败: 无法提取有效的QQ号');
249
249
  return false;
250
250
  }
251
251
  // 检查该UID是否已被其他用户绑定(安全检查)
@@ -266,7 +266,9 @@ class DatabaseService {
266
266
  medalName: buidUser.medal?.name || '',
267
267
  medalLevel: buidUser.medal?.level || 0,
268
268
  wealthMedalLevel: buidUser.wealthMedalLevel || 0,
269
- lastActiveTime: buidUser.last_active_time ? new Date(buidUser.last_active_time) : new Date(),
269
+ lastActiveTime: buidUser.last_active_time
270
+ ? new Date(buidUser.last_active_time)
271
+ : new Date(),
270
272
  lastModified: new Date()
271
273
  };
272
274
  if (bind) {
@@ -302,7 +304,7 @@ class DatabaseService {
302
304
  try {
303
305
  const normalizedQQId = this.normalizeQQId(userId);
304
306
  if (!normalizedQQId) {
305
- this.logger.error('B站账号信息更新', `更新失败: 无法提取有效的QQ号`);
307
+ this.logger.error('B站账号信息更新', '更新失败: 无法提取有效的QQ号');
306
308
  return false;
307
309
  }
308
310
  // 查询是否已存在绑定记录
@@ -339,7 +341,7 @@ class DatabaseService {
339
341
  async checkAndUpdateUsername(bind) {
340
342
  try {
341
343
  if (!bind || !bind.mcUuid) {
342
- this.logger.warn('用户名更新', `无法检查用户名更新: 空绑定或空UUID`);
344
+ this.logger.warn('用户名更新', '无法检查用户名更新: 空绑定或空UUID');
343
345
  return bind;
344
346
  }
345
347
  // 通过UUID查询最新用户名
@@ -377,7 +379,7 @@ class DatabaseService {
377
379
  async checkAndUpdateUsernameWithCache(bind) {
378
380
  try {
379
381
  if (!bind || !bind.mcUuid) {
380
- this.logger.warn('改名检测缓存', `无法检查用户名更新: 空绑定或空UUID`);
382
+ this.logger.warn('改名检测缓存', '无法检查用户名更新: 空绑定或空UUID');
381
383
  return bind;
382
384
  }
383
385
  const now = new Date();
@@ -28,7 +28,7 @@ class NicknameService {
28
28
  if (!nickname || !buidUsername)
29
29
  return false;
30
30
  // 期望格式:B站名称(ID:MC用户名)或 B站名称(ID:未绑定)
31
- const mcInfo = mcUsername && !mcUsername.startsWith('_temp_') ? mcUsername : "未绑定";
31
+ const mcInfo = mcUsername && !mcUsername.startsWith('_temp_') ? mcUsername : '未绑定';
32
32
  const expectedFormat = `${buidUsername}(ID:${mcInfo})`;
33
33
  return nickname === expectedFormat;
34
34
  }
@@ -40,14 +40,14 @@ class NicknameService {
40
40
  // 1. 尝试获取B站官方API的用户信息(最权威)
41
41
  let officialUsername = null;
42
42
  try {
43
- this.logger.debug('群昵称设置', `正在查询B站官方API...`);
43
+ this.logger.debug('群昵称设置', '正在查询B站官方API...');
44
44
  const officialInfo = await this.getBilibiliOfficialUserInfo(buidUid);
45
45
  if (officialInfo && officialInfo.name) {
46
46
  officialUsername = officialInfo.name;
47
47
  this.logger.info('群昵称设置', `[层1-官方API] ✅ "${officialUsername}"`, true);
48
48
  }
49
49
  else {
50
- this.logger.warn('群昵称设置', `[层1-官方API] ❌ 查询失败`);
50
+ this.logger.warn('群昵称设置', '[层1-官方API] ❌ 查询失败');
51
51
  }
52
52
  }
53
53
  catch (officialError) {
@@ -56,13 +56,13 @@ class NicknameService {
56
56
  // 2. 尝试获取ZMINFO API的用户信息(可能有缓存)
57
57
  let zminfoUserData = null;
58
58
  try {
59
- this.logger.debug('群昵称设置', `正在查询ZMINFO API...`);
59
+ this.logger.debug('群昵称设置', '正在查询ZMINFO API...');
60
60
  zminfoUserData = await this.validateBUID(buidUid);
61
61
  if (zminfoUserData && zminfoUserData.username) {
62
62
  this.logger.debug('群昵称设置', `[层2-ZMINFO] "${zminfoUserData.username}"`);
63
63
  }
64
64
  else {
65
- this.logger.warn('群昵称设置', `[层2-ZMINFO] 查询失败`);
65
+ this.logger.warn('群昵称设置', '[层2-ZMINFO] 查询失败');
66
66
  }
67
67
  }
68
68
  catch (zminfoError) {
@@ -101,7 +101,7 @@ class NicknameService {
101
101
  return; // 无需更新
102
102
  }
103
103
  if (!zminfoData) {
104
- this.logger.debug('群昵称设置', `无ZMINFO数据,跳过数据库同步`);
104
+ this.logger.debug('群昵称设置', '无ZMINFO数据,跳过数据库同步');
105
105
  return;
106
106
  }
107
107
  try {
@@ -136,7 +136,7 @@ class NicknameService {
136
136
  else {
137
137
  this.logger.warn('群昵称设置', `⚠️ 验证失败,期望"${nickname}",实际"${verifyNickname}",可能是权限不足或API延迟`);
138
138
  if (!currentNickname) {
139
- this.logger.warn('群昵称设置', `建议检查: 1.机器人是否为群管理员 2.群设置是否允许管理员修改昵称 3.OneBot实现是否支持该功能`);
139
+ this.logger.warn('群昵称设置', '建议检查: 1.机器人是否为群管理员 2.群设置是否允许管理员修改昵称 3.OneBot实现是否支持该功能');
140
140
  }
141
141
  }
142
142
  }
@@ -159,7 +159,7 @@ class NicknameService {
159
159
  const actualUserId = targetUserId || session.userId;
160
160
  const normalizedUserId = this.normalizeQQId(actualUserId);
161
161
  const targetGroupId = specifiedGroupId || this.config.autoNicknameGroupId;
162
- const mcInfo = (mcUsername && !mcUsername.startsWith('_temp_')) ? mcUsername : "未绑定";
162
+ const mcInfo = mcUsername && !mcUsername.startsWith('_temp_') ? mcUsername : '未绑定';
163
163
  this.logger.debug('群昵称设置', `开始处理QQ(${normalizedUserId})的群昵称设置,目标群: ${targetGroupId}`);
164
164
  // 检查前置条件
165
165
  if (!session.bot.internal) {
@@ -173,7 +173,7 @@ class NicknameService {
173
173
  // 获取最新的B站用户名
174
174
  let latestBuidUsername = buidUsername;
175
175
  if (buidUid) {
176
- this.logger.debug('群昵称设置', `开始四层判断获取最新B站用户名...`);
176
+ this.logger.debug('群昵称设置', '开始四层判断获取最新B站用户名...');
177
177
  this.logger.debug('群昵称设置', `[层3-数据库] "${buidUsername}"`);
178
178
  const result = await this.getLatestBuidUsername(buidUid, buidUsername);
179
179
  latestBuidUsername = result.username;
@@ -189,16 +189,12 @@ class NicknameService {
189
189
  const currentGroupInfo = await session.bot.internal.getGroupMemberInfo(targetGroupId, normalizedUserId);
190
190
  const currentNickname = currentGroupInfo.card || currentGroupInfo.nickname || '';
191
191
  this.logger.debug('群昵称设置', `当前昵称: "${currentNickname}"`);
192
- // 智能判断:如果当前昵称已包含最新用户名,跳过修改
192
+ // 【调试信息】提取当前昵称中的BUID用户名(仅用于日志)
193
193
  if (buidUid && currentNickname) {
194
194
  const currentNicknameUsername = (0, helpers_1.extractBuidUsernameFromNickname)(currentNickname);
195
195
  this.logger.debug('群昵称设置', `[层4-群昵称] "${currentNicknameUsername || '(无法提取)'}"`);
196
- if (currentNicknameUsername && currentNicknameUsername === latestBuidUsername) {
197
- this.logger.info('群昵称设置', `✅ 群昵称已包含最新名称"${latestBuidUsername}",跳过修改`, true);
198
- return;
199
- }
200
196
  }
201
- // 如果昵称完全一致,也跳过
197
+ // 如果昵称完全一致,跳过修改
202
198
  if (currentNickname === targetNickname) {
203
199
  this.logger.info('群昵称设置', `QQ(${normalizedUserId})群昵称已经是"${targetNickname}",跳过修改`, true);
204
200
  return;
@@ -210,7 +206,7 @@ class NicknameService {
210
206
  catch (getInfoError) {
211
207
  // 无法获取当前昵称,直接设置新昵称
212
208
  this.logger.warn('群昵称设置', `获取QQ(${normalizedUserId})当前群昵称失败: ${getInfoError.message}`);
213
- this.logger.debug('群昵称设置', `将直接尝试设置新昵称...`);
209
+ this.logger.debug('群昵称设置', '将直接尝试设置新昵称...');
214
210
  await this.setAndVerifyNickname(session, targetGroupId, normalizedUserId, targetNickname);
215
211
  }
216
212
  }
@@ -5,59 +5,149 @@
5
5
  /**
6
6
  * Mojang API 响应接口
7
7
  * 用于获取MC用户UUID和用户名
8
+ *
9
+ * @see https://api.mojang.com/users/profiles/minecraft/{username}
10
+ * @see https://api.mojang.com/user/profile/{uuid}
11
+ *
12
+ * @example
13
+ * ```json
14
+ * {
15
+ * "id": "069a79f444e94726a5befca90e38aaf5",
16
+ * "name": "Notch"
17
+ * }
18
+ * ```
8
19
  */
9
20
  export interface MojangProfile {
21
+ /** UUID (不带连字符,32位十六进制字符串) */
10
22
  id: string;
23
+ /** 玩家名称 (Mojang返回的标准大小写) */
11
24
  name: string;
12
25
  }
13
26
  /**
14
27
  * ZMINFO API - 用户信息接口
28
+ *
29
+ * @see {zminfoApiUrl}/api/user/{uid}
30
+ *
31
+ * @example
32
+ * ```json
33
+ * {
34
+ * "uid": "12345678",
35
+ * "username": "用户名",
36
+ * "avatar_url": "https://...",
37
+ * "guard_level": 3,
38
+ * "guard_level_text": "总督",
39
+ * "max_guard_level": 3,
40
+ * "max_guard_level_text": "总督",
41
+ * "medal": {
42
+ * "name": "粉丝牌",
43
+ * "level": 20,
44
+ * "uid": "87654321",
45
+ * "room": 123456
46
+ * },
47
+ * "wealthMedalLevel": 15,
48
+ * "last_active_time": "2025-10-23T12:00:00Z"
49
+ * }
50
+ * ```
15
51
  */
16
52
  export interface ZminfoUser {
53
+ /** B站用户UID */
17
54
  uid: string;
55
+ /** B站用户名 */
18
56
  username: string;
57
+ /** 用户头像URL */
19
58
  avatar_url: string;
59
+ /** 当前舰长等级 (0=无, 1=总督, 2=提督, 3=舰长) */
20
60
  guard_level: number;
61
+ /** 当前舰长等级文本描述 */
21
62
  guard_level_text: string;
63
+ /** 历史最高舰长等级 */
22
64
  max_guard_level: number;
65
+ /** 历史最高舰长等级文本描述 */
23
66
  max_guard_level_text: string;
67
+ /** 粉丝牌信息 (如果用户拥有) */
24
68
  medal: {
69
+ /** 粉丝牌名称 */
25
70
  name: string;
71
+ /** 粉丝牌等级 */
26
72
  level: number;
73
+ /** UP主UID */
27
74
  uid: string;
75
+ /** 直播间房间号 */
28
76
  room: number;
29
77
  } | null;
78
+ /** 荣耀等级 (财富勋章等级) */
30
79
  wealthMedalLevel: number;
80
+ /** 最后活跃时间 (ISO 8601格式) */
31
81
  last_active_time: string;
32
82
  }
33
83
  /**
34
84
  * ZMINFO API 响应接口
85
+ *
86
+ * @example 成功响应
87
+ * ```json
88
+ * {
89
+ * "success": true,
90
+ * "message": "success",
91
+ * "data": {
92
+ * "user": { ... }
93
+ * }
94
+ * }
95
+ * ```
96
+ *
97
+ * @example 失败响应
98
+ * ```json
99
+ * {
100
+ * "success": false,
101
+ * "message": "User not found"
102
+ * }
103
+ * ```
35
104
  */
36
105
  export interface ZminfoApiResponse {
106
+ /** 请求是否成功 */
37
107
  success: boolean;
108
+ /** 响应消息 */
38
109
  message: string;
110
+ /** 响应数据 (仅成功时存在) */
39
111
  data?: {
112
+ /** 用户信息 */
40
113
  user?: ZminfoUser;
41
114
  };
42
115
  }
43
116
  /**
44
117
  * Bilibili Live API - 粉丝勋章信息接口
118
+ *
119
+ * @see https://api.live.bilibili.com/xlive/app-ucenter/v1/user/GetMyMedals
45
120
  */
46
121
  export interface MedalInfo {
122
+ /** UP主UID */
47
123
  target_id: number;
124
+ /** 粉丝牌等级 */
48
125
  level: number;
126
+ /** 粉丝牌名称 */
49
127
  medal_name: string;
128
+ /** 粉丝牌渐变色起始颜色 */
50
129
  medal_color_start: number;
130
+ /** 粉丝牌渐变色结束颜色 */
51
131
  medal_color_end: number;
132
+ /** 粉丝牌边框颜色 */
52
133
  medal_color_border: number;
134
+ /** 舰长等级 (0=无, 1=总督, 2=提督, 3=舰长) */
53
135
  guard_level: number;
136
+ /** 佩戴状态 (0=未佩戴, 1=已佩戴) */
54
137
  wearing_status: number;
138
+ /** 粉丝牌ID */
55
139
  medal_id: number;
140
+ /** 当前亲密度 */
56
141
  intimacy: number;
142
+ /** 下一级所需亲密度 */
57
143
  next_intimacy: number;
144
+ /** 今日亲密度 */
58
145
  today_feed: number;
146
+ /** 每日亲密度上限 */
59
147
  day_limit: number;
148
+ /** 舰长图标URL */
60
149
  guard_icon: string;
150
+ /** 荣耀图标URL */
61
151
  honor_icon: string;
62
152
  }
63
153
  /**
@@ -38,3 +38,48 @@ export interface LotteryResult {
38
38
  host_uid: number;
39
39
  host_username: string;
40
40
  }
41
+ /**
42
+ * 待审批的入群申请信息
43
+ */
44
+ export interface PendingRequest {
45
+ /** 播报消息的ID(用于监听表情回应) */
46
+ broadcastMessageId: string;
47
+ /** OneBot的请求标识(用于批准/拒绝) */
48
+ requestFlag: string;
49
+ /** 申请人QQ号 */
50
+ applicantQQ: string;
51
+ /** 申请人昵称 */
52
+ applicantNickname: string;
53
+ /** 申请人头像URL */
54
+ applicantAvatar: string;
55
+ /** 目标群号 */
56
+ targetGroupId: string;
57
+ /** 申请人回答的内容(UID) */
58
+ answer: string;
59
+ /** 申请时间戳 */
60
+ timestamp: number;
61
+ /** 审批状态 */
62
+ status: 'pending' | 'approved' | 'rejected' | 'processing';
63
+ }
64
+ /**
65
+ * 拒绝流程状态
66
+ */
67
+ export interface RejectFlow {
68
+ /** 对应的待审批申请 */
69
+ pendingRequest: PendingRequest;
70
+ /** 发起拒绝的管理员QQ号 */
71
+ operatorId: string;
72
+ /** 询问消息ID */
73
+ askMessageId: string;
74
+ /** 超时时间戳 */
75
+ timeout: number;
76
+ }
77
+ /**
78
+ * 管理员权限缓存
79
+ */
80
+ export interface AdminCache {
81
+ /** 管理员QQ号列表 */
82
+ admins: string[];
83
+ /** 最后更新时间戳 */
84
+ lastUpdate: number;
85
+ }