@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/README.md +0 -228
- package/dist/index.cjs +336 -27
- package/dist/index.d.cts +115 -8
- package/dist/index.d.ts +115 -8
- package/dist/index.js +331 -28
- package/package.json +1 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
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
|
-
|
|
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
|
-
|
|
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(
|
|
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 {
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
this.
|
|
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
|
-
...
|
|
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
package/dist/index.cjs.map
DELETED
|
@@ -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"]}
|