@meet-im/meet-bot-jssdk 1.0.0 → 1.2.0

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/dist/index.js CHANGED
@@ -44,16 +44,34 @@ var init_error = __esm({
44
44
  };
45
45
  NetworkError = class extends MeetBotError {
46
46
  cause;
47
- constructor(message, cause) {
47
+ /**
48
+ * HTTP 状态码(如果有的话)
49
+ * 例如:504 表示网关超时,0 表示无 HTTP 响应
50
+ */
51
+ httpStatus;
52
+ /**
53
+ * 响应内容片段(用于调试)
54
+ */
55
+ responseSnippet;
56
+ constructor(message, cause, httpStatus, responseSnippet) {
48
57
  super(message, "NETWORK_ERROR");
49
58
  this.name = "NetworkError";
50
59
  this.cause = cause;
60
+ this.httpStatus = httpStatus;
61
+ this.responseSnippet = responseSnippet;
51
62
  }
52
63
  };
53
64
  TimeoutError = class extends MeetBotError {
54
- constructor(message) {
65
+ /**
66
+ * 是否为本地客户端超时(AbortController 触发)
67
+ * true: 本地 HTTP 请求超时
68
+ * false: 服务端/网关返回的超时(如 504 Gateway Timeout)
69
+ */
70
+ isLocal;
71
+ constructor(message, isLocal = true) {
55
72
  super(message, "TIMEOUT_ERROR");
56
73
  this.name = "TimeoutError";
74
+ this.isLocal = isLocal;
57
75
  }
58
76
  };
59
77
  ValidationError = class extends MeetBotError {
@@ -196,8 +214,8 @@ function extractBotToken(token) {
196
214
  const parts = token.split(":");
197
215
  return parts.length >= 2 ? parts.slice(1).join(":") : token;
198
216
  }
199
- function buildUrl(baseUrl, path, params) {
200
- const url = new URL(`/im/bot/${path}`, baseUrl);
217
+ function buildUrl(baseUrl, path, pathPrefix, params) {
218
+ const url = new URL(`${pathPrefix}${path}`, baseUrl);
201
219
  if (params) {
202
220
  for (const [key, value] of Object.entries(params)) {
203
221
  if (value !== void 0) {
@@ -207,10 +225,27 @@ function buildUrl(baseUrl, path, params) {
207
225
  }
208
226
  return url.toString();
209
227
  }
228
+ function sanitizeHeaders(headers) {
229
+ return {
230
+ ...headers,
231
+ Authorization: headers.Authorization ? "Bot ***" : ""
232
+ };
233
+ }
210
234
  async function request(options) {
211
- const { token, baseUrl, method = "GET", path, params, body, timeout = HTTP.DEFAULT_TIMEOUT } = options;
235
+ const {
236
+ token,
237
+ baseUrl,
238
+ method = "GET",
239
+ path,
240
+ pathPrefix = "/im/bot/",
241
+ params,
242
+ body,
243
+ timeout = HTTP.DEFAULT_TIMEOUT,
244
+ userAgent,
245
+ raw = false
246
+ } = options;
212
247
  validateToken(token);
213
- const url = buildUrl(baseUrl || DEFAULT_BASE_URL, path, method === "GET" ? params : void 0);
248
+ const url = buildUrl(baseUrl || DEFAULT_BASE_URL, path, pathPrefix, method === "GET" ? params : void 0);
214
249
  const controller = new AbortController();
215
250
  const timeoutId = setTimeout(() => controller.abort(), timeout);
216
251
  const headers = {
@@ -218,7 +253,11 @@ async function request(options) {
218
253
  Accept: "application/json",
219
254
  Authorization: `Bot ${extractBotToken(token)}`
220
255
  };
256
+ if (userAgent) {
257
+ headers["User-Agent"] = userAgent;
258
+ }
221
259
  logger.info("[Request]", method, url);
260
+ logger.info("[Headers]", sanitizeHeaders(headers));
222
261
  if (body) {
223
262
  logger.info("[Body]", JSON.stringify(body));
224
263
  }
@@ -239,18 +278,40 @@ async function request(options) {
239
278
  const responseText = await response.text();
240
279
  if (!contentType.includes("application/json")) {
241
280
  logger.error("[Response] Non-JSON response:", responseText.substring(0, 500));
242
- throw new NetworkError(`Server returned non-JSON response (status ${response.status})`, void 0);
281
+ if (response.status === 504) {
282
+ throw new TimeoutError(`Gateway timeout (status ${response.status})`, false);
283
+ }
284
+ throw new NetworkError(
285
+ `Server returned non-JSON response (status ${response.status})`,
286
+ void 0,
287
+ response.status,
288
+ responseText.substring(0, 200)
289
+ );
243
290
  }
244
291
  let data;
245
292
  try {
246
293
  data = JSON.parse(responseText);
247
294
  } catch {
248
295
  logger.error("[Response] Failed to parse JSON:", responseText.substring(0, 500));
249
- throw new NetworkError("Failed to parse server response", void 0);
296
+ throw new NetworkError(
297
+ "Failed to parse server response",
298
+ void 0,
299
+ response.status,
300
+ responseText.substring(0, 200)
301
+ );
250
302
  }
251
303
  logger.info("[Response Body]", JSON.stringify(data));
304
+ if (raw) {
305
+ return data;
306
+ }
252
307
  if (!response.ok || !data.ok) {
253
308
  const errorData = data;
309
+ if (response.status === 504) {
310
+ throw new TimeoutError(
311
+ errorData.description || `Gateway timeout (status ${response.status})`,
312
+ false
313
+ );
314
+ }
254
315
  throw new ApiError(
255
316
  errorData.description || `HTTP ${response.status}`,
256
317
  response.status,
@@ -266,7 +327,7 @@ async function request(options) {
266
327
  }
267
328
  if (error instanceof Error) {
268
329
  if (error.name === "AbortError") {
269
- throw new TimeoutError(`Request timeout after ${timeout}ms`);
330
+ throw new TimeoutError(`Request timeout after ${timeout}ms`, true);
270
331
  }
271
332
  throw new NetworkError(`Network error: ${error.message}`, error);
272
333
  }
@@ -294,10 +355,11 @@ function mapStatusCodeToErrorCode(status) {
294
355
 
295
356
  // src/api/file.ts
296
357
  async function getUploadURL(params) {
297
- const { token, baseUrl, ...body } = params;
358
+ const { token, baseUrl, userAgent, ...body } = params;
298
359
  return request({
299
360
  token,
300
361
  baseUrl,
362
+ userAgent,
301
363
  method: "POST",
302
364
  path: "getUploadURL",
303
365
  body: {
@@ -315,10 +377,11 @@ async function getUploadURL(params) {
315
377
  });
316
378
  }
317
379
  async function getMultiPartUploadURL(params) {
318
- const { token, baseUrl, ...body } = params;
380
+ const { token, baseUrl, userAgent, ...body } = params;
319
381
  return request({
320
382
  token,
321
383
  baseUrl,
384
+ userAgent,
322
385
  method: "POST",
323
386
  path: "getMultiPartUploadURL",
324
387
  body: {
@@ -334,10 +397,11 @@ async function getMultiPartUploadURL(params) {
334
397
  });
335
398
  }
336
399
  async function completeMultipartUpload(params) {
337
- const { token, baseUrl, ...body } = params;
400
+ const { token, baseUrl, userAgent, ...body } = params;
338
401
  return request({
339
402
  token,
340
403
  baseUrl,
404
+ userAgent,
341
405
  method: "POST",
342
406
  path: "completeMultipartUpload",
343
407
  body: {
@@ -349,10 +413,11 @@ async function completeMultipartUpload(params) {
349
413
  });
350
414
  }
351
415
  async function getAccessURL(params) {
352
- const { token, baseUrl, ...queryParams } = params;
416
+ const { token, baseUrl, userAgent, ...queryParams } = params;
353
417
  return request({
354
418
  token,
355
419
  baseUrl,
420
+ userAgent,
356
421
  method: "GET",
357
422
  path: "getAccessURL",
358
423
  params: {
@@ -430,21 +495,22 @@ function formatSpeed(bytesPerSecond) {
430
495
  return `${(bytesPerSecond / 1024 / 1024).toFixed(2)}MB/s`;
431
496
  }
432
497
  }
433
- async function uploadFile(token, buffer, options, baseUrl) {
498
+ async function uploadFile(token, buffer, options, baseUrl, userAgent) {
434
499
  const { fileName, contentType, onProgress } = options;
435
500
  const size = buffer.length;
436
501
  const md5 = await computeMD5(buffer);
437
502
  logger.info(`[uploadFile] Starting upload: ${fileName}, size: ${size}, md5: ${md5}`);
438
503
  if (size < UPLOAD.MULTIPART_THRESHOLD) {
439
- return uploadSingleFile(token, buffer, fileName, contentType, md5, baseUrl, onProgress);
504
+ return uploadSingleFile(token, buffer, fileName, contentType, md5, baseUrl, userAgent, onProgress);
440
505
  } else {
441
- return uploadMultipartFile(token, buffer, fileName, contentType, md5, baseUrl, onProgress);
506
+ return uploadMultipartFile(token, buffer, fileName, contentType, md5, baseUrl, userAgent, onProgress);
442
507
  }
443
508
  }
444
- async function uploadSingleFile(token, buffer, fileName, contentType, md5, baseUrl, onProgress) {
509
+ async function uploadSingleFile(token, buffer, fileName, contentType, md5, baseUrl, userAgent, onProgress) {
445
510
  const result = await getUploadURL({
446
511
  token,
447
512
  baseUrl,
513
+ userAgent,
448
514
  originFileName: fileName,
449
515
  contentType,
450
516
  md5,
@@ -457,13 +523,14 @@ async function uploadSingleFile(token, buffer, fileName, contentType, md5, baseU
457
523
  const ossResult = await uploadToOSS(result.signedUrl, buffer, contentType, result.callback || "", onProgress);
458
524
  return { fileID: ossResult.id, path: ossResult.path, size: ossResult.size };
459
525
  }
460
- async function uploadMultipartFile(token, buffer, fileName, contentType, md5, baseUrl, onProgress) {
526
+ async function uploadMultipartFile(token, buffer, fileName, contentType, md5, baseUrl, userAgent, onProgress) {
461
527
  const size = buffer.length;
462
528
  const chunkNum = getChunkNum(size);
463
529
  logger.info(`[uploadMultipartFile] Starting multipart upload: ${chunkNum} chunks`);
464
530
  const result = await getMultiPartUploadURL({
465
531
  token,
466
532
  baseUrl,
533
+ userAgent,
467
534
  originFileName: fileName,
468
535
  contentType,
469
536
  md5,
@@ -511,6 +578,7 @@ async function uploadMultipartFile(token, buffer, fileName, contentType, md5, ba
511
578
  const complete = await completeMultipartUpload({
512
579
  token,
513
580
  baseUrl,
581
+ userAgent,
514
582
  originFileName: fileName,
515
583
  md5,
516
584
  UploadParts: uploadParts
@@ -518,13 +586,14 @@ async function uploadMultipartFile(token, buffer, fileName, contentType, md5, ba
518
586
  logger.info(`[uploadMultipartFile] Upload complete: ${complete.ID}`);
519
587
  return { fileID: complete.ID, path: complete.path, size };
520
588
  }
521
- async function sendMediaMessage(token, sessionInfo, options, baseUrl) {
589
+ async function sendMediaMessage(token, sessionInfo, options, baseUrl, userAgent) {
522
590
  const { buffer, fileName, contentType, content, onProgress } = options;
523
- const { fileID, path } = await uploadFile(token, buffer, { fileName, contentType, onProgress }, baseUrl);
591
+ const { fileID, path } = await uploadFile(token, buffer, { fileName, contentType, onProgress }, baseUrl, userAgent);
524
592
  logger.info(`[sendMediaMessage] fileID=${fileID}, path=${path}`);
525
593
  return sendMessage({
526
594
  token,
527
595
  baseUrl,
596
+ userAgent,
528
597
  sessionInfo,
529
598
  msgContent: {
530
599
  content: content || "",
@@ -541,12 +610,33 @@ async function sendMediaMessage(token, sessionInfo, options, baseUrl) {
541
610
  });
542
611
  }
543
612
 
613
+ // src/api/user.ts
614
+ async function getUsers(params) {
615
+ const { token, baseUrl, userAgent } = params;
616
+ const result = await request({
617
+ token,
618
+ baseUrl,
619
+ userAgent,
620
+ method: "POST",
621
+ path: "general/SyncCompanyUser",
622
+ pathPrefix: "/",
623
+ body: { syncAt: 0 },
624
+ timeout: HTTP.DEFAULT_TIMEOUT,
625
+ raw: true
626
+ });
627
+ return Object.values(result.users).map((user) => ({
628
+ userID: user.userID,
629
+ nickName: user.nickName
630
+ }));
631
+ }
632
+
544
633
  // src/api/index.ts
545
634
  async function getUpdates(params) {
546
- const { token, baseUrl, timeout = API.DEFAULT_TIMEOUT, offset, limit = API.DEFAULT_LIMIT } = params;
635
+ const { token, baseUrl, userAgent, timeout = API.DEFAULT_TIMEOUT, offset, limit = API.DEFAULT_LIMIT } = params;
547
636
  return request({
548
637
  token,
549
638
  baseUrl,
639
+ userAgent,
550
640
  method: "POST",
551
641
  path: "getUpdates",
552
642
  body: {
@@ -558,10 +648,11 @@ async function getUpdates(params) {
558
648
  });
559
649
  }
560
650
  async function getUpdatesV2(params) {
561
- const { token, baseUrl, timeout = API.DEFAULT_TIMEOUT, limit = API.DEFAULT_LIMIT } = params;
651
+ const { token, baseUrl, userAgent, timeout = API.DEFAULT_TIMEOUT, limit = API.DEFAULT_LIMIT } = params;
562
652
  return request({
563
653
  token,
564
654
  baseUrl,
655
+ userAgent,
565
656
  method: "POST",
566
657
  path: "getUpdatesV2",
567
658
  body: {
@@ -572,7 +663,7 @@ async function getUpdatesV2(params) {
572
663
  });
573
664
  }
574
665
  async function sendMessage(params) {
575
- const { token, baseUrl, sessionInfo, msgContent } = params;
666
+ const { token, baseUrl, userAgent, sessionInfo, msgContent } = params;
576
667
  const hasContent = msgContent.content && msgContent.content.trim() !== "";
577
668
  const hasAttachment = msgContent.extraInfo?.attechmentInfo || msgContent.extraInfo?.attechmentInfos && msgContent.extraInfo.attechmentInfos.length > 0;
578
669
  if (!hasContent && !hasAttachment) {
@@ -582,6 +673,7 @@ async function sendMessage(params) {
582
673
  return request({
583
674
  token,
584
675
  baseUrl,
676
+ userAgent,
585
677
  method: "POST",
586
678
  path: "sendMessage",
587
679
  body: {
@@ -593,16 +685,127 @@ async function sendMessage(params) {
593
685
 
594
686
  // src/client.ts
595
687
  init_error();
688
+
689
+ // src/user-cache.ts
690
+ var UserCache = class {
691
+ byId = /* @__PURE__ */ new Map();
692
+ byNickName = /* @__PURE__ */ new Map();
693
+ byAliasName = /* @__PURE__ */ new Map();
694
+ loadedAt = 0;
695
+ ttl;
696
+ loading = null;
697
+ constructor(options) {
698
+ this.ttl = options?.ttl ?? 60 * 60 * 1e3;
699
+ }
700
+ isExpired() {
701
+ return this.byId.size === 0 || this.ttl > 0 && Date.now() - this.loadedAt > this.ttl;
702
+ }
703
+ async load(fetchAll) {
704
+ if (this.loading) {
705
+ return this.loading;
706
+ }
707
+ this.loading = (async () => {
708
+ try {
709
+ const users = await fetchAll();
710
+ this.rebuild(users);
711
+ logger.info(`\u7528\u6237\u7F13\u5B58\u5DF2\u52A0\u8F7D\uFF0C\u5171 ${users.length} \u4E2A\u7528\u6237`);
712
+ } finally {
713
+ this.loading = null;
714
+ }
715
+ })();
716
+ return this.loading;
717
+ }
718
+ rebuild(users) {
719
+ this.byId.clear();
720
+ this.byNickName.clear();
721
+ this.byAliasName.clear();
722
+ for (const user of users) {
723
+ this.byId.set(user.userID, user);
724
+ const nickKey = user.nickName.toLowerCase();
725
+ let nickList = this.byNickName.get(nickKey);
726
+ if (!nickList) {
727
+ nickList = [];
728
+ this.byNickName.set(nickKey, nickList);
729
+ }
730
+ nickList.push(user);
731
+ if (user.aliasName) {
732
+ const aliasKey = user.aliasName.toLowerCase();
733
+ let aliasList = this.byAliasName.get(aliasKey);
734
+ if (!aliasList) {
735
+ aliasList = [];
736
+ this.byAliasName.set(aliasKey, aliasList);
737
+ }
738
+ aliasList.push(user);
739
+ }
740
+ }
741
+ this.loadedAt = Date.now();
742
+ }
743
+ async ensureLoaded(fetchAll) {
744
+ if (!this.isExpired()) return;
745
+ await this.load(fetchAll);
746
+ }
747
+ getById(userId) {
748
+ return this.byId.get(userId);
749
+ }
750
+ getByIds(userIds) {
751
+ const result = /* @__PURE__ */ new Map();
752
+ for (const id of userIds) {
753
+ const user = this.byId.get(id);
754
+ if (user) {
755
+ result.set(id, user);
756
+ }
757
+ }
758
+ return result;
759
+ }
760
+ getByName(name) {
761
+ const key = name.toLowerCase();
762
+ const byNick = this.byNickName.get(key);
763
+ const byAlias = this.byAliasName.get(key);
764
+ if (!byNick && !byAlias) return [];
765
+ if (!byNick) return [...byAlias];
766
+ if (!byAlias) return [...byNick];
767
+ const seen = /* @__PURE__ */ new Set();
768
+ const result = [];
769
+ for (const u of [...byNick, ...byAlias]) {
770
+ if (!seen.has(u.userID)) {
771
+ seen.add(u.userID);
772
+ result.push(u);
773
+ }
774
+ }
775
+ return result;
776
+ }
777
+ searchByName(query) {
778
+ const q = query.toLowerCase();
779
+ const result = [];
780
+ const seen = /* @__PURE__ */ new Set();
781
+ for (const user of this.byId.values()) {
782
+ if (user.nickName.toLowerCase().includes(q) || user.aliasName && user.aliasName.toLowerCase().includes(q) || user.nickNamePinyin && user.nickNamePinyin.toLowerCase().includes(q) || user.aliasNamePinyin && user.aliasNamePinyin.toLowerCase().includes(q)) {
783
+ if (!seen.has(user.userID)) {
784
+ seen.add(user.userID);
785
+ result.push(user);
786
+ }
787
+ }
788
+ }
789
+ return result;
790
+ }
791
+ get size() {
792
+ return this.byId.size;
793
+ }
794
+ };
795
+
796
+ // src/client.ts
596
797
  var MeetBot = class {
597
798
  token;
598
799
  baseUrl;
599
800
  pollingLimit;
600
801
  longPollingTimeout;
601
802
  useV2;
803
+ userAgent;
602
804
  eventHandlers = /* @__PURE__ */ new Map();
603
805
  polling = false;
604
806
  offset = 0;
605
807
  abortController = null;
808
+ userCache;
606
809
  constructor(config) {
607
810
  if (config.token) {
608
811
  if (!config.token.includes(":")) {
@@ -618,6 +821,8 @@ var MeetBot = class {
618
821
  this.pollingLimit = config.pollingLimit ?? POLLING.DEFAULT_LIMIT;
619
822
  this.longPollingTimeout = config.longPollingTimeout ?? POLLING.DEFAULT_TIMEOUT;
620
823
  this.useV2 = config.useV2 ?? false;
824
+ this.userAgent = config.userAgent;
825
+ this.userCache = new UserCache(config.userCacheOptions);
621
826
  logger.setLevel(config.logLevel ?? "silent");
622
827
  }
623
828
  on(event, handler) {
@@ -669,6 +874,7 @@ var MeetBot = class {
669
874
  const result = await getUpdatesV2({
670
875
  token: this.token,
671
876
  baseUrl: this.baseUrl,
877
+ userAgent: this.userAgent,
672
878
  timeout,
673
879
  limit
674
880
  });
@@ -682,6 +888,7 @@ var MeetBot = class {
682
888
  const updates = await getUpdates({
683
889
  token: this.token,
684
890
  baseUrl: this.baseUrl,
891
+ userAgent: this.userAgent,
685
892
  timeout,
686
893
  offset: this.offset,
687
894
  limit
@@ -721,6 +928,7 @@ var MeetBot = class {
721
928
  return getUpdates({
722
929
  token: this.token,
723
930
  baseUrl: this.baseUrl,
931
+ userAgent: this.userAgent,
724
932
  ...options
725
933
  });
726
934
  }
@@ -728,6 +936,7 @@ var MeetBot = class {
728
936
  return getUpdatesV2({
729
937
  token: this.token,
730
938
  baseUrl: this.baseUrl,
939
+ userAgent: this.userAgent,
731
940
  ...options
732
941
  });
733
942
  }
@@ -735,6 +944,7 @@ var MeetBot = class {
735
944
  return sendMessage({
736
945
  token: this.token,
737
946
  baseUrl: this.baseUrl,
947
+ userAgent: this.userAgent,
738
948
  sessionInfo,
739
949
  msgContent
740
950
  });
@@ -746,6 +956,7 @@ var MeetBot = class {
746
956
  return getUploadURL({
747
957
  token: this.token,
748
958
  baseUrl: this.baseUrl,
959
+ userAgent: this.userAgent,
749
960
  ...params
750
961
  });
751
962
  }
@@ -756,6 +967,7 @@ var MeetBot = class {
756
967
  return getMultiPartUploadURL({
757
968
  token: this.token,
758
969
  baseUrl: this.baseUrl,
970
+ userAgent: this.userAgent,
759
971
  ...params
760
972
  });
761
973
  }
@@ -766,6 +978,7 @@ var MeetBot = class {
766
978
  return completeMultipartUpload({
767
979
  token: this.token,
768
980
  baseUrl: this.baseUrl,
981
+ userAgent: this.userAgent,
769
982
  ...params
770
983
  });
771
984
  }
@@ -784,6 +997,7 @@ var MeetBot = class {
784
997
  return getAccessURL({
785
998
  token: this.token,
786
999
  baseUrl: this.baseUrl,
1000
+ userAgent: this.userAgent,
787
1001
  ...apiParams
788
1002
  });
789
1003
  }
@@ -791,13 +1005,63 @@ var MeetBot = class {
791
1005
  * 上传文件(自动选择单文件或分片上传)
792
1006
  */
793
1007
  async uploadFile(buffer, options) {
794
- return uploadFile(this.token, buffer, options, this.baseUrl);
1008
+ return uploadFile(this.token, buffer, options, this.baseUrl, this.userAgent);
795
1009
  }
796
1010
  /**
797
1011
  * 发送媒体消息(上传并发送)
798
1012
  */
799
1013
  async sendMedia(sessionInfo, options) {
800
- return sendMediaMessage(this.token, sessionInfo, options, this.baseUrl);
1014
+ return sendMediaMessage(this.token, sessionInfo, options, this.baseUrl, this.userAgent);
1015
+ }
1016
+ /**
1017
+ * 刷新用户缓存
1018
+ */
1019
+ async refreshUserCache() {
1020
+ await this.userCache.load(async () => {
1021
+ return getUsers({ token: this.token, baseUrl: this.baseUrl, userAgent: this.userAgent });
1022
+ });
1023
+ }
1024
+ /**
1025
+ * 根据用户 ID 获取用户信息
1026
+ */
1027
+ async getUserById(userId) {
1028
+ await this.userCache.ensureLoaded(async () => {
1029
+ return getUsers({ token: this.token, baseUrl: this.baseUrl, userAgent: this.userAgent });
1030
+ });
1031
+ return this.userCache.getById(userId);
1032
+ }
1033
+ /**
1034
+ * 批量根据用户 ID 获取用户信息
1035
+ */
1036
+ async getUserByIds(userIds) {
1037
+ await this.userCache.ensureLoaded(async () => {
1038
+ return getUsers({ token: this.token, baseUrl: this.baseUrl, userAgent: this.userAgent });
1039
+ });
1040
+ return this.userCache.getByIds(userIds);
1041
+ }
1042
+ /**
1043
+ * 根据昵称或别名精确查找用户
1044
+ */
1045
+ async getUserByName(name) {
1046
+ await this.userCache.ensureLoaded(async () => {
1047
+ return getUsers({ token: this.token, baseUrl: this.baseUrl, userAgent: this.userAgent });
1048
+ });
1049
+ return this.userCache.getByName(name);
1050
+ }
1051
+ /**
1052
+ * 根据昵称或别名模糊搜索用户
1053
+ */
1054
+ async searchUserByName(query) {
1055
+ await this.userCache.ensureLoaded(async () => {
1056
+ return getUsers({ token: this.token, baseUrl: this.baseUrl, userAgent: this.userAgent });
1057
+ });
1058
+ return this.userCache.searchByName(query);
1059
+ }
1060
+ /**
1061
+ * 获取缓存用户数
1062
+ */
1063
+ get userCacheSize() {
1064
+ return this.userCache.size;
801
1065
  }
802
1066
  sleep(ms) {
803
1067
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -807,6 +1071,4 @@ var MeetBot = class {
807
1071
  // src/index.ts
808
1072
  init_error();
809
1073
 
810
- export { API, ApiError, CHUNK_RULES, DEFAULT_BASE_URL, HTTP, MeetBot, MeetBotError, NetworkError, POLLING, SESSION_TYPE, TimeoutError, UPLOAD, ValidationError, completeMultipartUpload, computeMD5, getAccessURL, getChunkNum, getConvID, getMultiPartUploadURL, getQuoteMsgKey, getUpdates, getUpdatesV2, getUploadURL, sendMediaMessage, sendMessage, uploadFile };
811
- //# sourceMappingURL=index.js.map
812
- //# sourceMappingURL=index.js.map
1074
+ export { API, ApiError, CHUNK_RULES, DEFAULT_BASE_URL, HTTP, MeetBot, MeetBotError, NetworkError, POLLING, SESSION_TYPE, TimeoutError, UPLOAD, UserCache, ValidationError, completeMultipartUpload, computeMD5, getAccessURL, getChunkNum, getConvID, getMultiPartUploadURL, getQuoteMsgKey, getUpdates, getUpdatesV2, getUploadURL, getUsers, sendMediaMessage, sendMessage, uploadFile };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meet-im/meet-bot-jssdk",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "MeetIM Chatbot JavaScript SDK - 支持 Long Polling 消息获取和消息发送",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",