@meet-im/meet-bot-jssdk 0.0.7 → 1.1.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 {
@@ -122,6 +140,11 @@ var CHUNK_RULES = [
122
140
  { maxSize: Infinity, chunks: 50 }
123
141
  // > 100MB: 50 片
124
142
  ];
143
+ var SESSION_TYPE = {
144
+ PRIVATE: 1,
145
+ GROUP: 3,
146
+ CHANNEL: 4
147
+ };
125
148
  function getChunkNum(size) {
126
149
  for (const rule of CHUNK_RULES) {
127
150
  if (size < rule.maxSize) {
@@ -130,6 +153,31 @@ function getChunkNum(size) {
130
153
  }
131
154
  return 50;
132
155
  }
156
+ function getConvID(firstID, secondID, sessionType, companyID = 1) {
157
+ let convID;
158
+ if (sessionType === SESSION_TYPE.PRIVATE) {
159
+ const min = Math.min(firstID, secondID);
160
+ const max = Math.max(firstID, secondID);
161
+ convID = `${min}:${max}`;
162
+ if (companyID > 1) {
163
+ convID += `:${companyID}`;
164
+ }
165
+ } else if (sessionType === SESSION_TYPE.GROUP) {
166
+ convID = `${firstID}+${secondID}`;
167
+ if (companyID > 1) {
168
+ convID += `+${companyID}`;
169
+ }
170
+ } else {
171
+ convID = `${firstID}_${secondID}`;
172
+ if (companyID > 1) {
173
+ convID += `_${companyID}`;
174
+ }
175
+ }
176
+ return convID;
177
+ }
178
+ function getQuoteMsgKey(convID, seqID) {
179
+ return `${convID}:${seqID}`;
180
+ }
133
181
 
134
182
  // src/utils/logger.ts
135
183
  var Logger = class {
@@ -166,8 +214,8 @@ function extractBotToken(token) {
166
214
  const parts = token.split(":");
167
215
  return parts.length >= 2 ? parts.slice(1).join(":") : token;
168
216
  }
169
- function buildUrl(baseUrl, path, params) {
170
- const url = new URL(`/im/bot/${path}`, baseUrl);
217
+ function buildUrl(baseUrl, path, pathPrefix, params) {
218
+ const url = new URL(`${pathPrefix}${path}`, baseUrl);
171
219
  if (params) {
172
220
  for (const [key, value] of Object.entries(params)) {
173
221
  if (value !== void 0) {
@@ -178,9 +226,19 @@ function buildUrl(baseUrl, path, params) {
178
226
  return url.toString();
179
227
  }
180
228
  async function request(options) {
181
- const { token, baseUrl, method = "GET", path, params, body, timeout = HTTP.DEFAULT_TIMEOUT } = options;
229
+ const {
230
+ token,
231
+ baseUrl,
232
+ method = "GET",
233
+ path,
234
+ pathPrefix = "/im/bot/",
235
+ params,
236
+ body,
237
+ timeout = HTTP.DEFAULT_TIMEOUT,
238
+ raw = false
239
+ } = options;
182
240
  validateToken(token);
183
- const url = buildUrl(baseUrl || DEFAULT_BASE_URL, path, method === "GET" ? params : void 0);
241
+ const url = buildUrl(baseUrl || DEFAULT_BASE_URL, path, pathPrefix, method === "GET" ? params : void 0);
184
242
  const controller = new AbortController();
185
243
  const timeoutId = setTimeout(() => controller.abort(), timeout);
186
244
  const headers = {
@@ -209,18 +267,40 @@ async function request(options) {
209
267
  const responseText = await response.text();
210
268
  if (!contentType.includes("application/json")) {
211
269
  logger.error("[Response] Non-JSON response:", responseText.substring(0, 500));
212
- throw new NetworkError(`Server returned non-JSON response (status ${response.status})`, void 0);
270
+ if (response.status === 504) {
271
+ throw new TimeoutError(`Gateway timeout (status ${response.status})`, false);
272
+ }
273
+ throw new NetworkError(
274
+ `Server returned non-JSON response (status ${response.status})`,
275
+ void 0,
276
+ response.status,
277
+ responseText.substring(0, 200)
278
+ );
213
279
  }
214
280
  let data;
215
281
  try {
216
282
  data = JSON.parse(responseText);
217
283
  } catch {
218
284
  logger.error("[Response] Failed to parse JSON:", responseText.substring(0, 500));
219
- throw new NetworkError("Failed to parse server response", void 0);
285
+ throw new NetworkError(
286
+ "Failed to parse server response",
287
+ void 0,
288
+ response.status,
289
+ responseText.substring(0, 200)
290
+ );
220
291
  }
221
292
  logger.info("[Response Body]", JSON.stringify(data));
293
+ if (raw) {
294
+ return data;
295
+ }
222
296
  if (!response.ok || !data.ok) {
223
297
  const errorData = data;
298
+ if (response.status === 504) {
299
+ throw new TimeoutError(
300
+ errorData.description || `Gateway timeout (status ${response.status})`,
301
+ false
302
+ );
303
+ }
224
304
  throw new ApiError(
225
305
  errorData.description || `HTTP ${response.status}`,
226
306
  response.status,
@@ -236,7 +316,7 @@ async function request(options) {
236
316
  }
237
317
  if (error instanceof Error) {
238
318
  if (error.name === "AbortError") {
239
- throw new TimeoutError(`Request timeout after ${timeout}ms`);
319
+ throw new TimeoutError(`Request timeout after ${timeout}ms`, true);
240
320
  }
241
321
  throw new NetworkError(`Network error: ${error.message}`, error);
242
322
  }
@@ -331,9 +411,8 @@ async function getAccessURL(params) {
331
411
  sessionType: queryParams.sessionType,
332
412
  seqId: queryParams.seqId,
333
413
  fileId: queryParams.fileId,
414
+ companyId: queryParams.companyId,
334
415
  "x-oss-process": queryParams["x-oss-process"],
335
- origin: queryParams.origin,
336
- bestDomain: queryParams.bestDomain,
337
416
  printResult: queryParams.printResult ?? "1"
338
417
  }
339
418
  });
@@ -512,6 +591,25 @@ async function sendMediaMessage(token, sessionInfo, options, baseUrl) {
512
591
  });
513
592
  }
514
593
 
594
+ // src/api/user.ts
595
+ async function getUsers(params) {
596
+ const { token, baseUrl } = params;
597
+ const result = await request({
598
+ token,
599
+ baseUrl,
600
+ method: "POST",
601
+ path: "general/SyncCompanyUser",
602
+ pathPrefix: "/",
603
+ body: { syncAt: 0 },
604
+ timeout: HTTP.DEFAULT_TIMEOUT,
605
+ raw: true
606
+ });
607
+ return Object.values(result.users).map((user) => ({
608
+ userID: user.userID,
609
+ nickName: user.nickName
610
+ }));
611
+ }
612
+
515
613
  // src/api/index.ts
516
614
  async function getUpdates(params) {
517
615
  const { token, baseUrl, timeout = API.DEFAULT_TIMEOUT, offset, limit = API.DEFAULT_LIMIT } = params;
@@ -528,6 +626,20 @@ async function getUpdates(params) {
528
626
  timeout: (timeout || 0) * 1e3 + HTTP.POLLING_TIMEOUT_BUFFER
529
627
  });
530
628
  }
629
+ async function getUpdatesV2(params) {
630
+ const { token, baseUrl, timeout = API.DEFAULT_TIMEOUT, limit = API.DEFAULT_LIMIT } = params;
631
+ return request({
632
+ token,
633
+ baseUrl,
634
+ method: "POST",
635
+ path: "getUpdatesV2",
636
+ body: {
637
+ timeout,
638
+ limit
639
+ },
640
+ timeout: (timeout || 0) * 1e3 + HTTP.POLLING_TIMEOUT_BUFFER
641
+ });
642
+ }
531
643
  async function sendMessage(params) {
532
644
  const { token, baseUrl, sessionInfo, msgContent } = params;
533
645
  const hasContent = msgContent.content && msgContent.content.trim() !== "";
@@ -550,15 +662,126 @@ async function sendMessage(params) {
550
662
 
551
663
  // src/client.ts
552
664
  init_error();
665
+
666
+ // src/user-cache.ts
667
+ var UserCache = class {
668
+ byId = /* @__PURE__ */ new Map();
669
+ byNickName = /* @__PURE__ */ new Map();
670
+ byAliasName = /* @__PURE__ */ new Map();
671
+ loadedAt = 0;
672
+ ttl;
673
+ loading = null;
674
+ constructor(options) {
675
+ this.ttl = options?.ttl ?? 60 * 60 * 1e3;
676
+ }
677
+ isExpired() {
678
+ return this.byId.size === 0 || this.ttl > 0 && Date.now() - this.loadedAt > this.ttl;
679
+ }
680
+ async load(fetchAll) {
681
+ if (this.loading) {
682
+ return this.loading;
683
+ }
684
+ this.loading = (async () => {
685
+ try {
686
+ const users = await fetchAll();
687
+ this.rebuild(users);
688
+ logger.info(`\u7528\u6237\u7F13\u5B58\u5DF2\u52A0\u8F7D\uFF0C\u5171 ${users.length} \u4E2A\u7528\u6237`);
689
+ } finally {
690
+ this.loading = null;
691
+ }
692
+ })();
693
+ return this.loading;
694
+ }
695
+ rebuild(users) {
696
+ this.byId.clear();
697
+ this.byNickName.clear();
698
+ this.byAliasName.clear();
699
+ for (const user of users) {
700
+ this.byId.set(user.userID, user);
701
+ const nickKey = user.nickName.toLowerCase();
702
+ let nickList = this.byNickName.get(nickKey);
703
+ if (!nickList) {
704
+ nickList = [];
705
+ this.byNickName.set(nickKey, nickList);
706
+ }
707
+ nickList.push(user);
708
+ if (user.aliasName) {
709
+ const aliasKey = user.aliasName.toLowerCase();
710
+ let aliasList = this.byAliasName.get(aliasKey);
711
+ if (!aliasList) {
712
+ aliasList = [];
713
+ this.byAliasName.set(aliasKey, aliasList);
714
+ }
715
+ aliasList.push(user);
716
+ }
717
+ }
718
+ this.loadedAt = Date.now();
719
+ }
720
+ async ensureLoaded(fetchAll) {
721
+ if (!this.isExpired()) return;
722
+ await this.load(fetchAll);
723
+ }
724
+ getById(userId) {
725
+ return this.byId.get(userId);
726
+ }
727
+ getByIds(userIds) {
728
+ const result = /* @__PURE__ */ new Map();
729
+ for (const id of userIds) {
730
+ const user = this.byId.get(id);
731
+ if (user) {
732
+ result.set(id, user);
733
+ }
734
+ }
735
+ return result;
736
+ }
737
+ getByName(name) {
738
+ const key = name.toLowerCase();
739
+ const byNick = this.byNickName.get(key);
740
+ const byAlias = this.byAliasName.get(key);
741
+ if (!byNick && !byAlias) return [];
742
+ if (!byNick) return [...byAlias];
743
+ if (!byAlias) return [...byNick];
744
+ const seen = /* @__PURE__ */ new Set();
745
+ const result = [];
746
+ for (const u of [...byNick, ...byAlias]) {
747
+ if (!seen.has(u.userID)) {
748
+ seen.add(u.userID);
749
+ result.push(u);
750
+ }
751
+ }
752
+ return result;
753
+ }
754
+ searchByName(query) {
755
+ const q = query.toLowerCase();
756
+ const result = [];
757
+ const seen = /* @__PURE__ */ new Set();
758
+ for (const user of this.byId.values()) {
759
+ 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)) {
760
+ if (!seen.has(user.userID)) {
761
+ seen.add(user.userID);
762
+ result.push(user);
763
+ }
764
+ }
765
+ }
766
+ return result;
767
+ }
768
+ get size() {
769
+ return this.byId.size;
770
+ }
771
+ };
772
+
773
+ // src/client.ts
553
774
  var MeetBot = class {
554
775
  token;
555
776
  baseUrl;
556
777
  pollingLimit;
557
778
  longPollingTimeout;
779
+ useV2;
558
780
  eventHandlers = /* @__PURE__ */ new Map();
559
781
  polling = false;
560
782
  offset = 0;
561
783
  abortController = null;
784
+ userCache;
562
785
  constructor(config) {
563
786
  if (config.token) {
564
787
  if (!config.token.includes(":")) {
@@ -573,6 +796,8 @@ var MeetBot = class {
573
796
  this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
574
797
  this.pollingLimit = config.pollingLimit ?? POLLING.DEFAULT_LIMIT;
575
798
  this.longPollingTimeout = config.longPollingTimeout ?? POLLING.DEFAULT_TIMEOUT;
799
+ this.useV2 = config.useV2 ?? false;
800
+ this.userCache = new UserCache(config.userCacheOptions);
576
801
  logger.setLevel(config.logLevel ?? "silent");
577
802
  }
578
803
  on(event, handler) {
@@ -612,7 +837,7 @@ var MeetBot = class {
612
837
  this.abortController = new AbortController();
613
838
  const limit = options?.limit ?? this.pollingLimit;
614
839
  const timeout = options?.timeout ?? this.longPollingTimeout;
615
- logger.info(`\u5F00\u59CB\u957F\u8F6E\u8BE2\u6D88\u606F... (\u6761\u6570: ${limit}, \u8D85\u65F6: ${timeout}s)`);
840
+ logger.info(`\u5F00\u59CB\u957F\u8F6E\u8BE2\u6D88\u606F... (\u6761\u6570: ${limit}, \u8D85\u65F6: ${timeout}s, V2: ${this.useV2})`);
616
841
  this.emit("polling_start", void 0);
617
842
  const retryDelay = options?.retryDelay ?? POLLING.DEFAULT_RETRY_DELAY;
618
843
  const maxRetries = options?.maxRetries ?? POLLING.DEFAULT_MAX_RETRIES;
@@ -620,20 +845,35 @@ var MeetBot = class {
620
845
  let retryCount = 0;
621
846
  while (this.polling) {
622
847
  try {
623
- const updates = await getUpdates({
624
- token: this.token,
625
- baseUrl: this.baseUrl,
626
- timeout,
627
- offset: this.offset,
628
- limit
629
- });
630
- retryCount = 0;
631
- for (const update of updates) {
632
- if (update.message) {
633
- this.emit("message", update.message);
634
- this.offset = (update.message.seqId || 0) + 1;
848
+ if (this.useV2) {
849
+ const result = await getUpdatesV2({
850
+ token: this.token,
851
+ baseUrl: this.baseUrl,
852
+ timeout,
853
+ limit
854
+ });
855
+ retryCount = 0;
856
+ for (const msgUpdate of result.msgs) {
857
+ this.emit("message", { message: msgUpdate.message, quoteMsgMap: result.quoteMsgMap });
858
+ this.offset = (msgUpdate.message.seqId || 0) + 1;
635
859
  onOffsetUpdate?.(this.offset);
636
860
  }
861
+ } else {
862
+ const updates = await getUpdates({
863
+ token: this.token,
864
+ baseUrl: this.baseUrl,
865
+ timeout,
866
+ offset: this.offset,
867
+ limit
868
+ });
869
+ retryCount = 0;
870
+ for (const update of updates) {
871
+ if (update.message) {
872
+ this.emit("message", { message: update.message, quoteMsgMap: {} });
873
+ this.offset = (update.message.seqId || 0) + 1;
874
+ onOffsetUpdate?.(this.offset);
875
+ }
876
+ }
637
877
  }
638
878
  await this.sleep(POLLING.SUCCESS_DELAY);
639
879
  } catch (error) {
@@ -664,6 +904,13 @@ var MeetBot = class {
664
904
  ...options
665
905
  });
666
906
  }
907
+ async getUpdatesV2(options) {
908
+ return getUpdatesV2({
909
+ token: this.token,
910
+ baseUrl: this.baseUrl,
911
+ ...options
912
+ });
913
+ }
667
914
  async sendMessage(sessionInfo, msgContent) {
668
915
  return sendMessage({
669
916
  token: this.token,
@@ -706,10 +953,18 @@ var MeetBot = class {
706
953
  * 获取文件下载地址
707
954
  */
708
955
  async getAccessURL(params) {
956
+ const apiParams = "sessionInfo" in params ? {
957
+ firstId: params.sessionInfo.firstID,
958
+ secondId: params.sessionInfo.secondID,
959
+ sessionType: params.sessionInfo.sessionType,
960
+ seqId: params.seqId,
961
+ fileId: params.fileId,
962
+ printResult: params.printResult
963
+ } : params;
709
964
  return getAccessURL({
710
965
  token: this.token,
711
966
  baseUrl: this.baseUrl,
712
- ...params
967
+ ...apiParams
713
968
  });
714
969
  }
715
970
  /**
@@ -724,6 +979,56 @@ var MeetBot = class {
724
979
  async sendMedia(sessionInfo, options) {
725
980
  return sendMediaMessage(this.token, sessionInfo, options, this.baseUrl);
726
981
  }
982
+ /**
983
+ * 刷新用户缓存
984
+ */
985
+ async refreshUserCache() {
986
+ await this.userCache.load(async () => {
987
+ return getUsers({ token: this.token, baseUrl: this.baseUrl });
988
+ });
989
+ }
990
+ /**
991
+ * 根据用户 ID 获取用户信息
992
+ */
993
+ async getUserById(userId) {
994
+ await this.userCache.ensureLoaded(async () => {
995
+ return getUsers({ token: this.token, baseUrl: this.baseUrl });
996
+ });
997
+ return this.userCache.getById(userId);
998
+ }
999
+ /**
1000
+ * 批量根据用户 ID 获取用户信息
1001
+ */
1002
+ async getUserByIds(userIds) {
1003
+ await this.userCache.ensureLoaded(async () => {
1004
+ return getUsers({ token: this.token, baseUrl: this.baseUrl });
1005
+ });
1006
+ return this.userCache.getByIds(userIds);
1007
+ }
1008
+ /**
1009
+ * 根据昵称或别名精确查找用户
1010
+ */
1011
+ async getUserByName(name) {
1012
+ await this.userCache.ensureLoaded(async () => {
1013
+ return getUsers({ token: this.token, baseUrl: this.baseUrl });
1014
+ });
1015
+ return this.userCache.getByName(name);
1016
+ }
1017
+ /**
1018
+ * 根据昵称或别名模糊搜索用户
1019
+ */
1020
+ async searchUserByName(query) {
1021
+ await this.userCache.ensureLoaded(async () => {
1022
+ return getUsers({ token: this.token, baseUrl: this.baseUrl });
1023
+ });
1024
+ return this.userCache.searchByName(query);
1025
+ }
1026
+ /**
1027
+ * 获取缓存用户数
1028
+ */
1029
+ get userCacheSize() {
1030
+ return this.userCache.size;
1031
+ }
727
1032
  sleep(ms) {
728
1033
  return new Promise((resolve) => setTimeout(resolve, ms));
729
1034
  }
@@ -732,6 +1037,4 @@ var MeetBot = class {
732
1037
  // src/index.ts
733
1038
  init_error();
734
1039
 
735
- export { API, ApiError, CHUNK_RULES, DEFAULT_BASE_URL, HTTP, MeetBot, MeetBotError, NetworkError, POLLING, TimeoutError, UPLOAD, ValidationError, completeMultipartUpload, computeMD5, getAccessURL, getChunkNum, getMultiPartUploadURL, getUpdates, getUploadURL, sendMediaMessage, sendMessage, uploadFile };
736
- //# sourceMappingURL=index.js.map
737
- //# sourceMappingURL=index.js.map
1040
+ 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": "0.0.7",
3
+ "version": "1.1.0",
4
4
  "description": "MeetIM Chatbot JavaScript SDK - 支持 Long Polling 消息获取和消息发送",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/types/error.ts","../src/types/index.ts","../src/constants.ts","../src/utils/logger.ts","../src/http/request.ts","../src/api/file.ts","../src/api/upload.ts","../src/api/index.ts","../src/client.ts","../src/index.ts"],"names":["ApiError","MeetBotError","NetworkError","TimeoutError","ValidationError","crypto"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ErrorCode } from './api'\n\nexport class MeetBotError extends Error {\n public readonly code: ErrorCode\n\n constructor(message: string, code: ErrorCode) {\n super(message)\n this.name = 'MeetBotError'\n this.code = code\n Error.captureStackTrace?.(this, this.constructor)\n }\n}\n\nexport class ApiError extends MeetBotError {\n public readonly statusCode: number\n public readonly retryAfter?: number\n\n constructor(message: string, statusCode: number, code: ErrorCode, retryAfter?: number) {\n super(message, code)\n this.name = 'ApiError'\n this.statusCode = statusCode\n this.retryAfter = retryAfter\n }\n}\n\nexport class NetworkError extends MeetBotError {\n public readonly cause?: Error\n\n constructor(message: string, cause?: Error) {\n super(message, 'NETWORK_ERROR')\n this.name = 'NetworkError'\n this.cause = cause\n }\n}\n\nexport class TimeoutError extends MeetBotError {\n constructor(message: string) {\n super(message, 'TIMEOUT_ERROR')\n this.name = 'TimeoutError'\n }\n}\n\nexport class ValidationError extends MeetBotError {\n public readonly field: string\n public readonly value: unknown\n\n constructor(message: string, field: string, value: unknown) {\n super(message, 'VALIDATION_ERROR')\n this.name = 'ValidationError'\n this.field = field\n this.value = value\n }\n}\n","export type {\n BotUser,\n BotChat,\n BotFile,\n BotMsg,\n BotUpdate,\n ChatType,\n SessionInfo,\n SessionType,\n MsgContent,\n MsgType,\n ExtraInfo,\n AttachmentInfo,\n} from './bot'\nexport type { ErrorCode, ApiErrorResponse, ApiResponse } from './api'\nexport type {\n MeetBotConfig,\n GetUpdatesOptions,\n SendMessageOptions,\n SendMessageResult,\n PollingOptions,\n LogLevel,\n} from './client'\nexport type {\n GetUploadURLParams,\n UploadURLResult,\n GetMultiPartUploadURLParams,\n MultiPartUploadURLResult,\n UploadPart,\n CompleteMultipartUploadParams,\n CompleteMultipartUploadResult,\n GetAccessURLParams,\n AccessURLResult,\n UploadProgress,\n UploadFileOptions,\n UploadFileResult,\n SendMediaOptions,\n ReceivedAttachmentInfo,\n} from './file'\n\nexport { MeetBotError, ApiError, NetworkError, TimeoutError, ValidationError } from './error'\n","/**\n * Bot API 默认基础 URL\n */\nexport const DEFAULT_BASE_URL = 'https://staging-meet-api.miyachat.com'\n\n/**\n * 轮询相关常量\n */\nexport const POLLING = {\n /** 每次拉取消息条数上限,默认 100 条 */\n DEFAULT_LIMIT: 100,\n /** 长轮询超时时间(秒),默认 30 秒 */\n DEFAULT_TIMEOUT: 30,\n /** 成功返回后等待时间(毫秒),默认 1 秒 */\n SUCCESS_DELAY: 1000,\n /** 重试延迟基础时间(毫秒),默认 1000ms */\n DEFAULT_RETRY_DELAY: 1000,\n /** 重试延迟最大时间(毫秒),默认 30000ms */\n MAX_RETRY_DELAY: 30000,\n /** 最大重试次数,默认无限(0 表示不限制) */\n DEFAULT_MAX_RETRIES: 0,\n} as const\n\n/**\n * HTTP 请求相关常量\n */\nexport const HTTP = {\n /** 请求超时时间(毫秒),默认 60000ms */\n DEFAULT_TIMEOUT: 60000,\n /** 长轮询额外超时缓冲时间(毫秒),默认 10000ms */\n POLLING_TIMEOUT_BUFFER: 10000,\n /** 上传超时时间(毫秒),默认 1 小时 */\n UPLOAD_TIMEOUT: 3600 * 1000,\n} as const\n\n/**\n * API 接口相关常量\n */\nexport const API = {\n /** getUpdates 默认超时时间(秒),默认 30(long polling) */\n DEFAULT_TIMEOUT: 30,\n /** getUpdates 默认拉取条数,默认 100 条 */\n DEFAULT_LIMIT: 100,\n} as const\n\n/**\n * 文件上传相关常量\n */\nexport const UPLOAD = {\n /** 分片上传阈值,>= 5MB 使用分片上传 */\n MULTIPART_THRESHOLD: 5 * 1024 * 1024,\n /** 分片上传最大重试次数 */\n MAX_RETRY_COUNT: 3,\n /** 分片上传重试间隔(毫秒) */\n RETRY_DELAY: 1000,\n /** 最大并发上传数 */\n MAX_CONCURRENCY: 4,\n} as const\n\n/**\n * 分片规则\n */\nexport const CHUNK_RULES = [\n { maxSize: 1 * 1024 * 1024, chunks: 1 }, // < 1MB: 1 片\n { maxSize: 20 * 1024 * 1024, chunks: 5 }, // 1-20MB: 5 片\n { maxSize: 100 * 1024 * 1024, chunks: 20 }, // 20-100MB: 20 片\n { maxSize: Infinity, chunks: 50 }, // > 100MB: 50 片\n] as const\n\n/**\n * 根据文件大小计算分片数量\n */\nexport function getChunkNum(size: number): number {\n for (const rule of CHUNK_RULES) {\n if (size < rule.maxSize) {\n return rule.chunks\n }\n }\n return 50\n}\n","export type LogLevel = 'silent' | 'info'\n\nexport class Logger {\n private level: LogLevel = 'silent'\n\n setLevel(level: LogLevel): void {\n this.level = level\n }\n\n getLevel(): LogLevel {\n return this.level\n }\n\n info(...args: unknown[]): void {\n if (this.level === 'info') {\n console.log('[meetBotSDK]', ...args)\n }\n }\n\n error(...args: unknown[]): void {\n if (this.level === 'info') {\n console.error('[meetBotSDK]', ...args)\n }\n }\n}\n\nexport const logger = new Logger()\n","import type { ApiResponse, ApiErrorResponse } from '../types'\nimport { ApiError, NetworkError, TimeoutError } from '../types'\nimport { DEFAULT_BASE_URL, HTTP } from '../constants'\nimport { logger } from '../utils/logger'\n\nexport interface RequestOptions {\n token: string\n baseUrl?: string\n method?: 'GET' | 'POST'\n path: string\n params?: Record<string, string | number | undefined>\n body?: Record<string, unknown>\n timeout?: number\n}\n\nfunction validateToken(token: string): void {\n if (!token || typeof token !== 'string') {\n throw new NetworkError('Token is required', undefined)\n }\n if (!token.includes(':')) {\n throw new NetworkError('Invalid token format. Expected \"bot_id:secret\"', undefined)\n }\n}\n\nfunction extractBotToken(token: string): string {\n const parts = token.split(':')\n return parts.length >= 2 ? parts.slice(1).join(':') : token\n}\n\nfunction buildUrl(baseUrl: string, path: string, params?: Record<string, string | number | undefined>): string {\n const url = new URL(`/im/bot/${path}`, baseUrl || DEFAULT_BASE_URL)\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n url.searchParams.append(key, String(value))\n }\n }\n }\n return url.toString()\n}\n\nexport async function request<T>(options: RequestOptions): Promise<T> {\n const { token, baseUrl, method = 'GET', path, params, body, timeout = HTTP.DEFAULT_TIMEOUT } = options\n\n validateToken(token)\n\n const url = buildUrl(baseUrl || DEFAULT_BASE_URL, path, method === 'GET' ? params : undefined)\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `Bot ${extractBotToken(token)}`,\n }\n\n logger.info('[Request]', method, url)\n if (body) {\n logger.info('[Body]', JSON.stringify(body))\n }\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n })\n clearTimeout(timeoutId)\n\n const responseHeaders: Record<string, string> = {}\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value\n })\n logger.info('[Response Status]', response.status)\n\n const contentType = response.headers.get('content-type') || ''\n const responseText = await response.text()\n\n if (!contentType.includes('application/json')) {\n logger.error('[Response] Non-JSON response:', responseText.substring(0, 500))\n throw new NetworkError(`Server returned non-JSON response (status ${response.status})`, undefined)\n }\n\n let data: ApiResponse<T> | ApiErrorResponse\n try {\n data = JSON.parse(responseText) as ApiResponse<T> | ApiErrorResponse\n } catch {\n logger.error('[Response] Failed to parse JSON:', responseText.substring(0, 500))\n throw new NetworkError('Failed to parse server response', undefined)\n }\n logger.info('[Response Body]', JSON.stringify(data))\n\n if (!response.ok || !data.ok) {\n const errorData = data as ApiErrorResponse\n throw new ApiError(\n errorData.description || `HTTP ${response.status}`,\n response.status,\n mapStatusCodeToErrorCode(response.status),\n errorData.retry_after\n )\n }\n\n return (data as ApiResponse<T>).result as T\n } catch (error) {\n clearTimeout(timeoutId)\n\n if (error instanceof ApiError) {\n throw error\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new TimeoutError(`Request timeout after ${timeout}ms`)\n }\n throw new NetworkError(`Network error: ${error.message}`, error)\n }\n\n throw new NetworkError('Unknown network error', undefined)\n }\n}\n\nfunction mapStatusCodeToErrorCode(status: number): import('../types').ErrorCode {\n switch (status) {\n case 401:\n return 'UNAUTHORIZED'\n case 403:\n return 'UNAUTHORIZED'\n case 404:\n return 'CHAT_NOT_FOUND'\n case 429:\n return 'RATE_LIMIT'\n case 500:\n case 502:\n case 503:\n return 'INTERNAL_ERROR'\n default:\n return 'INTERNAL_ERROR'\n }\n}\n","import { request } from '../http/request'\nimport { HTTP } from '../constants'\nimport type {\n GetUploadURLParams,\n UploadURLResult,\n GetMultiPartUploadURLParams,\n MultiPartUploadURLResult,\n CompleteMultipartUploadParams,\n CompleteMultipartUploadResult,\n GetAccessURLParams,\n AccessURLResult,\n} from '../types/file'\n\nexport interface GetUploadURLApiParams extends GetUploadURLParams {\n token: string\n baseUrl?: string\n}\n\nexport async function getUploadURL(params: GetUploadURLApiParams): Promise<UploadURLResult> {\n const { token, baseUrl, ...body } = params\n return request<UploadURLResult>({\n token,\n baseUrl,\n method: 'POST',\n path: 'getUploadURL',\n body: {\n originFileName: body.originFileName,\n contentType: body.contentType,\n md5: body.md5,\n size: body.size,\n fullImage: body.fullImage,\n videoLength: body.videoLength,\n bestDomain: body.bestDomain,\n uploadId: body.uploadId,\n chunkNum: body.chunkNum,\n },\n timeout: HTTP.UPLOAD_TIMEOUT,\n })\n}\n\nexport interface GetMultiPartUploadURLApiParams extends GetMultiPartUploadURLParams {\n token: string\n baseUrl?: string\n}\n\nexport async function getMultiPartUploadURL(\n params: GetMultiPartUploadURLApiParams\n): Promise<MultiPartUploadURLResult> {\n const { token, baseUrl, ...body } = params\n return request<MultiPartUploadURLResult>({\n token,\n baseUrl,\n method: 'POST',\n path: 'getMultiPartUploadURL',\n body: {\n originFileName: body.originFileName,\n contentType: body.contentType,\n md5: body.md5,\n size: body.size,\n fullImage: body.fullImage,\n videoLength: body.videoLength,\n bestDomain: body.bestDomain,\n },\n timeout: HTTP.UPLOAD_TIMEOUT,\n })\n}\n\nexport interface CompleteMultipartUploadApiParams extends CompleteMultipartUploadParams {\n token: string\n baseUrl?: string\n}\n\nexport async function completeMultipartUpload(\n params: CompleteMultipartUploadApiParams\n): Promise<CompleteMultipartUploadResult> {\n const { token, baseUrl, ...body } = params\n return request<CompleteMultipartUploadResult>({\n token,\n baseUrl,\n method: 'POST',\n path: 'completeMultipartUpload',\n body: {\n originFileName: body.originFileName,\n md5: body.md5,\n UploadParts: body.UploadParts,\n },\n timeout: HTTP.UPLOAD_TIMEOUT,\n })\n}\n\nexport interface GetAccessURLApiParams extends GetAccessURLParams {\n token: string\n baseUrl?: string\n}\n\nexport async function getAccessURL(params: GetAccessURLApiParams): Promise<AccessURLResult> {\n const { token, baseUrl, ...queryParams } = params\n return request<AccessURLResult>({\n token,\n baseUrl,\n method: 'GET',\n path: 'getAccessURL',\n params: {\n firstId: queryParams.firstId,\n secondId: queryParams.secondId,\n sessionType: queryParams.sessionType,\n seqId: queryParams.seqId,\n fileId: queryParams.fileId,\n 'x-oss-process': queryParams['x-oss-process'],\n origin: queryParams.origin,\n bestDomain: queryParams.bestDomain,\n printResult: queryParams.printResult ?? '1',\n },\n })\n}","/**\n * TODO: 浏览器兼容性改造\n * - MD5 计算: 使用 Web Crypto API (`crypto.subtle.digest('MD5', buffer)`) 或第三方库\n * - 文件输入: 支持 Blob/File/ArrayBuffer,内部转换为 Uint8Array\n * - Buffer 类型: 检测环境,Node.js 使用 Buffer,浏览器使用 Uint8Array\n */\nimport crypto from 'node:crypto'\nimport type {\n UploadFileOptions,\n UploadFileResult,\n UploadProgress,\n SendMediaOptions,\n SendMessageResult,\n SessionInfo,\n} from '../types'\nimport { getUploadURL, getMultiPartUploadURL, completeMultipartUpload, sendMessage } from './index'\nimport { UPLOAD, getChunkNum } from '../constants'\nimport { logger } from '../utils/logger'\n\n/**\n * 计算文件 MD5\n * @param buffer 文件 Buffer\n * @returns MD5 字符串\n */\nexport async function computeMD5(buffer: Buffer): Promise<string> {\n return crypto.createHash('md5').update(buffer).digest('hex')\n}\n\n/**\n * 上传文件到 OSS\n */\nasync function uploadToOSS(\n signedUrl: string,\n buffer: Buffer,\n contentType: string,\n callback: string,\n onProgress?: (progress: UploadProgress) => void\n): Promise<{ id: number; path: string; size: number }> {\n const startTime = Date.now()\n const total = buffer.length\n\n const response = await fetch(signedUrl, {\n method: 'PUT',\n headers: {\n 'Content-Type': contentType,\n 'X-Oss-Callback': callback,\n },\n body: buffer,\n })\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => '')\n logger.error(`OSS upload failed: ${response.status} ${response.statusText}`)\n logger.error(`OSS error body: ${errorBody}`)\n throw new Error(`OSS upload failed: ${response.status} - ${errorBody}`)\n }\n\n const responseText = await response.text()\n logger.info(`[uploadToOSS] OSS response status: ${response.status}`)\n logger.info(`[uploadToOSS] OSS response: ${responseText}`)\n\n let result: { id: number; path: string; size: number }\n\n try {\n const parsed = JSON.parse(responseText)\n result = {\n id: parsed.id || parsed.ID || 0,\n path: parsed.path || '',\n size: parsed.size || 0,\n }\n } catch {\n const idMatch = responseText.match(/<id>(\\d+)<\\/id>/i)\n const pathMatch = responseText.match(/<path>([^<]*)<\\/path>/i)\n const sizeMatch = responseText.match(/<size>(\\d+)<\\/size>/i)\n\n result = {\n id: idMatch?.[1] ? parseInt(idMatch[1], 10) : 0,\n path: pathMatch?.[1] || '',\n size: sizeMatch?.[1] ? parseInt(sizeMatch[1], 10) : 0,\n }\n }\n\n if (onProgress) {\n const seconds = Math.round((Date.now() - startTime) / 1000) || 1\n const speedPerSecond = formatSpeed(total / seconds)\n onProgress({\n percent: '100%',\n loaded: total,\n total,\n speedPerSecond,\n percentRate: 1,\n })\n }\n\n return result\n}\n\n/**\n * 格式化速度\n */\nfunction formatSpeed(bytesPerSecond: number): string {\n if (bytesPerSecond < 1024) {\n return `${bytesPerSecond.toFixed(0)}B/s`\n } else if (bytesPerSecond < 1024 * 1024) {\n return `${(bytesPerSecond / 1024).toFixed(2)}KB/s`\n } else {\n return `${(bytesPerSecond / 1024 / 1024).toFixed(2)}MB/s`\n }\n}\n\n/**\n * 上传单个文件(自动选择单文件或分片上传)\n */\nexport async function uploadFile(\n token: string,\n buffer: Buffer,\n options: UploadFileOptions,\n baseUrl?: string\n): Promise<UploadFileResult> {\n const { fileName, contentType, onProgress } = options\n const size = buffer.length\n const md5 = await computeMD5(buffer)\n\n logger.info(`[uploadFile] Starting upload: ${fileName}, size: ${size}, md5: ${md5}`)\n\n if (size < UPLOAD.MULTIPART_THRESHOLD) {\n return uploadSingleFile(token, buffer, fileName, contentType, md5, baseUrl, onProgress)\n } else {\n return uploadMultipartFile(token, buffer, fileName, contentType, md5, baseUrl, onProgress)\n }\n}\n\n/**\n * 单文件上传\n */\nasync function uploadSingleFile(\n token: string,\n buffer: Buffer,\n fileName: string,\n contentType: string,\n md5: string,\n baseUrl?: string,\n onProgress?: (progress: UploadProgress) => void\n): Promise<UploadFileResult> {\n const result = await getUploadURL({\n token,\n baseUrl,\n originFileName: fileName,\n contentType,\n md5,\n size: buffer.length,\n })\n\n if (result.id > 0 && !result.signedUrl) {\n logger.info(`[uploadFile] Instant upload (MD5 match): ${result.id}`)\n return { fileID: result.id, path: result.path, size: result.size }\n }\n\n const ossResult = await uploadToOSS(result.signedUrl, buffer, contentType, result.callback || '', onProgress)\n\n return { fileID: ossResult.id, path: ossResult.path, size: ossResult.size }\n}\n\n/**\n * 分片上传\n */\nasync function uploadMultipartFile(\n token: string,\n buffer: Buffer,\n fileName: string,\n contentType: string,\n md5: string,\n baseUrl?: string,\n onProgress?: (progress: UploadProgress) => void\n): Promise<UploadFileResult> {\n const size = buffer.length\n const chunkNum = getChunkNum(size)\n\n logger.info(`[uploadMultipartFile] Starting multipart upload: ${chunkNum} chunks`)\n\n const result = await getMultiPartUploadURL({\n token,\n baseUrl,\n originFileName: fileName,\n contentType,\n md5,\n size,\n })\n\n if (result.ID && result.ID > 0) {\n logger.info(`[uploadMultipartFile] Instant upload (MD5 match): ${result.ID}`)\n return { fileID: result.ID, path: result.path!, size: result.size }\n }\n\n const uploadParts: { partNumber: number; eTag: string }[] = []\n const chunkSize = Math.ceil(size / chunkNum)\n const startTime = Date.now()\n let totalUploaded = 0\n\n for (let i = 1; i <= chunkNum; i++) {\n const start = (i - 1) * chunkSize\n const end = Math.min(start + chunkSize, size)\n const chunk = buffer.subarray(start, end)\n const signedUrl = result.mapSignURLs[String(i)]\n\n if (!signedUrl) {\n throw new Error(`Missing signed URL for chunk ${i}`)\n }\n\n const resp = await fetch(signedUrl, {\n method: 'PUT',\n headers: { 'Content-Type': contentType },\n body: chunk,\n })\n\n if (!resp.ok) {\n throw new Error(`Chunk ${i} upload failed: ${resp.status}`)\n }\n\n const eTag = resp.headers.get('ETag') || ''\n uploadParts.push({ partNumber: i, eTag: JSON.parse(eTag) })\n\n totalUploaded += chunk.length\n\n if (onProgress) {\n const seconds = Math.round((Date.now() - startTime) / 1000) || 1\n const speedPerSecond = formatSpeed(totalUploaded / seconds)\n onProgress({\n percent: `${Math.round((totalUploaded / size) * 100)}%`,\n loaded: totalUploaded,\n total: size,\n speedPerSecond,\n percentRate: totalUploaded / size,\n })\n }\n }\n\n const complete = await completeMultipartUpload({\n token,\n baseUrl,\n originFileName: fileName,\n md5,\n UploadParts: uploadParts,\n })\n\n logger.info(`[uploadMultipartFile] Upload complete: ${complete.ID}`)\n\n return { fileID: complete.ID, path: complete.path, size }\n}\n\n/**\n * 发送媒体消息(上传并发送)\n */\nexport async function sendMediaMessage(\n token: string,\n sessionInfo: SessionInfo,\n options: SendMediaOptions,\n baseUrl?: string\n): Promise<SendMessageResult> {\n const { buffer, fileName, contentType, content, onProgress } = options\n\n const { fileID, path } = await uploadFile(token, buffer, { fileName, contentType, onProgress }, baseUrl)\n\n logger.info(`[sendMediaMessage] fileID=${fileID}, path=${path}`)\n\n return sendMessage({\n token,\n baseUrl,\n sessionInfo,\n msgContent: {\n content: content || '',\n extraInfo: {\n attechmentInfo: {\n fileID: String(fileID),\n fileName,\n filePath: path,\n fileSize: buffer.length,\n mimeType: contentType,\n },\n },\n },\n })\n}\n","import type { BotUpdate, SendMessageResult, SessionInfo, MsgContent } from '../types'\nimport { request } from '../http/request'\nimport { API, HTTP } from '../constants'\n\nexport interface GetUpdatesParams {\n token: string\n baseUrl?: string\n timeout?: number\n offset?: number\n limit?: number\n}\n\nexport async function getUpdates(params: GetUpdatesParams): Promise<BotUpdate[]> {\n const { token, baseUrl, timeout = API.DEFAULT_TIMEOUT, offset, limit = API.DEFAULT_LIMIT } = params\n\n return request<BotUpdate[]>({\n token,\n baseUrl,\n method: 'POST',\n path: 'getUpdates',\n body: {\n timeout,\n offset,\n limit,\n },\n timeout: (timeout || 0) * 1000 + HTTP.POLLING_TIMEOUT_BUFFER,\n })\n}\n\nexport interface SendMessageParams {\n token: string\n baseUrl?: string\n sessionInfo: SessionInfo\n msgContent: MsgContent\n}\n\nexport async function sendMessage(params: SendMessageParams): Promise<SendMessageResult> {\n const { token, baseUrl, sessionInfo, msgContent } = params\n\n const hasContent = msgContent.content && msgContent.content.trim() !== ''\n const hasAttachment =\n msgContent.extraInfo?.attechmentInfo || (msgContent.extraInfo?.attechmentInfos && msgContent.extraInfo.attechmentInfos.length > 0)\n\n if (!hasContent && !hasAttachment) {\n const { ValidationError } = await import('../types/error.js')\n throw new ValidationError('Message content or attachment is required', 'msgContent', msgContent)\n }\n\n return request<SendMessageResult>({\n token,\n baseUrl,\n method: 'POST',\n path: 'sendMessage',\n body: {\n sessionInfo,\n msgContent,\n },\n })\n}\n\nexport {\n getUploadURL,\n getMultiPartUploadURL,\n completeMultipartUpload,\n getAccessURL,\n} from './file'\n\nexport type {\n GetUploadURLApiParams,\n GetMultiPartUploadURLApiParams,\n CompleteMultipartUploadApiParams,\n GetAccessURLApiParams,\n} from './file'\n\nexport { uploadFile, sendMediaMessage, computeMD5 } from './upload'\n","import type {\n BotUpdate,\n MeetBotConfig,\n PollingOptions,\n SessionInfo,\n MsgContent,\n SendMessageResult,\n GetUploadURLParams,\n UploadURLResult,\n GetMultiPartUploadURLParams,\n MultiPartUploadURLResult,\n CompleteMultipartUploadParams,\n CompleteMultipartUploadResult,\n GetAccessURLParams,\n AccessURLResult,\n UploadFileOptions,\n UploadFileResult,\n SendMediaOptions,\n} from './types'\nimport {\n getUpdates,\n sendMessage,\n getUploadURL,\n getMultiPartUploadURL,\n completeMultipartUpload,\n getAccessURL,\n uploadFile,\n sendMediaMessage,\n} from './api'\nimport { MeetBotError } from './types/error'\nimport { DEFAULT_BASE_URL, POLLING } from './constants'\nimport { logger } from './utils/logger'\n\ntype EventHandler<T = unknown> = (data: T) => void\n\ninterface Events {\n message: BotUpdate['message']\n error: Error\n polling_start: void\n polling_stop: void\n}\n\nexport class MeetBot {\n private readonly token: string\n private readonly baseUrl: string\n private readonly pollingLimit: number\n private readonly longPollingTimeout: number\n private readonly eventHandlers: Map<keyof Events, Set<EventHandler>> = new Map()\n private polling = false\n private offset = 0\n private abortController: AbortController | null = null\n\n constructor(config: MeetBotConfig) {\n if (config.token) {\n if (!config.token.includes(':')) {\n throw new MeetBotError('Invalid token format. Expected \"bot_id:secret\"', 'INVALID_TOKEN')\n }\n this.token = config.token\n } else if (config.botId && config.botToken) {\n this.token = `${config.botId}:${config.botToken}`\n } else {\n throw new MeetBotError('Token or (botId + botToken) is required', 'INVALID_TOKEN')\n }\n\n this.baseUrl = config.baseUrl || DEFAULT_BASE_URL\n this.pollingLimit = config.pollingLimit ?? POLLING.DEFAULT_LIMIT\n this.longPollingTimeout = config.longPollingTimeout ?? POLLING.DEFAULT_TIMEOUT\n logger.setLevel(config.logLevel ?? 'silent')\n }\n\n on<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): this {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, new Set())\n }\n this.eventHandlers.get(event)!.add(handler as EventHandler)\n return this\n }\n\n off<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): this {\n const handlers = this.eventHandlers.get(event)\n if (handlers) {\n handlers.delete(handler as EventHandler)\n }\n return this\n }\n\n private emit<K extends keyof Events>(event: K, data: Events[K]): void {\n const handlers = this.eventHandlers.get(event)\n if (handlers) {\n for (const handler of handlers) {\n try {\n handler(data)\n } catch (e) {\n logger.error(`Error in ${event} handler:`, e)\n }\n }\n }\n }\n\n isPolling(): boolean {\n return this.polling\n }\n\n async startPolling(options?: PollingOptions): Promise<void> {\n if (this.polling) {\n return\n }\n\n this.polling = true\n this.abortController = new AbortController()\n\n const limit = options?.limit ?? this.pollingLimit\n const timeout = options?.timeout ?? this.longPollingTimeout\n\n logger.info(`开始长轮询消息... (条数: ${limit}, 超时: ${timeout}s)`)\n\n this.emit('polling_start', undefined)\n const retryDelay = options?.retryDelay ?? POLLING.DEFAULT_RETRY_DELAY\n const maxRetries = options?.maxRetries ?? POLLING.DEFAULT_MAX_RETRIES\n const onOffsetUpdate = options?.onOffsetUpdate\n\n let retryCount = 0\n\n while (this.polling) {\n try {\n const updates = await getUpdates({\n token: this.token,\n baseUrl: this.baseUrl,\n timeout,\n offset: this.offset,\n limit,\n })\n\n retryCount = 0\n\n for (const update of updates) {\n if (update.message) {\n this.emit('message', update.message)\n this.offset = (update.message.seqId || 0) + 1\n onOffsetUpdate?.(this.offset)\n }\n }\n\n await this.sleep(POLLING.SUCCESS_DELAY)\n } catch (error) {\n if (!this.polling) break\n\n retryCount++\n this.emit('error', error instanceof Error ? error : new Error(String(error)))\n\n if (maxRetries > 0 && retryCount >= maxRetries) {\n this.stopPolling()\n break\n }\n\n const delay = Math.min(retryDelay * Math.pow(2, retryCount - 1), POLLING.MAX_RETRY_DELAY)\n await this.sleep(delay)\n }\n }\n }\n\n stopPolling(): void {\n this.polling = false\n if (this.abortController) {\n this.abortController.abort()\n this.abortController = null\n }\n this.emit('polling_stop', undefined)\n }\n\n async getUpdates(options?: { timeout?: number; offset?: number; limit?: number }): Promise<BotUpdate[]> {\n return getUpdates({\n token: this.token,\n baseUrl: this.baseUrl,\n ...options,\n })\n }\n\n async sendMessage(sessionInfo: SessionInfo, msgContent: MsgContent): Promise<SendMessageResult> {\n return sendMessage({\n token: this.token,\n baseUrl: this.baseUrl,\n sessionInfo,\n msgContent,\n })\n }\n\n /**\n * 获取单文件上传签名地址\n */\n async getUploadURL(params: Omit<GetUploadURLParams, 'fileType'>): Promise<UploadURLResult> {\n return getUploadURL({\n token: this.token,\n baseUrl: this.baseUrl,\n ...params,\n })\n }\n\n /**\n * 获取分片上传签名地址\n */\n async getMultiPartUploadURL(params: Omit<GetMultiPartUploadURLParams, 'fileType'>): Promise<MultiPartUploadURLResult> {\n return getMultiPartUploadURL({\n token: this.token,\n baseUrl: this.baseUrl,\n ...params,\n })\n }\n\n /**\n * 完成分片上传\n */\n async completeMultipartUpload(params: CompleteMultipartUploadParams): Promise<CompleteMultipartUploadResult> {\n return completeMultipartUpload({\n token: this.token,\n baseUrl: this.baseUrl,\n ...params,\n })\n }\n\n /**\n * 获取文件下载地址\n */\n async getAccessURL(params: GetAccessURLParams): Promise<AccessURLResult> {\n return getAccessURL({\n token: this.token,\n baseUrl: this.baseUrl,\n ...params,\n })\n }\n\n /**\n * 上传文件(自动选择单文件或分片上传)\n */\n async uploadFile(buffer: Buffer, options: UploadFileOptions): Promise<UploadFileResult> {\n return uploadFile(this.token, buffer, options, this.baseUrl)\n }\n\n /**\n * 发送媒体消息(上传并发送)\n */\n async sendMedia(sessionInfo: SessionInfo, options: SendMediaOptions): Promise<SendMessageResult> {\n return sendMediaMessage(this.token, sessionInfo, options, this.baseUrl)\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n }\n}\n","export { MeetBot } from './client'\nexport {\n getUpdates,\n sendMessage,\n getUploadURL,\n getMultiPartUploadURL,\n completeMultipartUpload,\n getAccessURL,\n uploadFile,\n sendMediaMessage,\n computeMD5,\n} from './api'\nexport * from './constants'\nexport type {\n BotUser,\n BotChat,\n BotFile,\n BotMsg,\n BotUpdate,\n ChatType,\n SessionInfo,\n SessionType,\n MsgContent,\n MsgType,\n ExtraInfo,\n AttachmentInfo,\n MeetBotConfig,\n GetUpdatesOptions,\n SendMessageOptions,\n SendMessageResult,\n PollingOptions,\n ErrorCode,\n ApiErrorResponse,\n ApiResponse,\n LogLevel,\n GetUploadURLParams,\n UploadURLResult,\n GetMultiPartUploadURLParams,\n MultiPartUploadURLResult,\n UploadPart,\n CompleteMultipartUploadParams,\n CompleteMultipartUploadResult,\n GetAccessURLParams,\n AccessURLResult,\n UploadProgress,\n UploadFileOptions,\n UploadFileResult,\n SendMediaOptions,\n ReceivedAttachmentInfo,\n} from './types'\nexport { MeetBotError, ApiError, NetworkError, TimeoutError, ValidationError } from './types/error'\n"]}