@yaoyuanchao/dingtalk 1.7.7 → 1.7.8
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/package.json +1 -1
- package/src/api.ts +14 -4
- package/src/monitor.ts +12 -5
package/package.json
CHANGED
package/src/api.ts
CHANGED
|
@@ -116,11 +116,16 @@ export async function getDingTalkAccessToken(clientId: string, clientSecret: str
|
|
|
116
116
|
export async function sendViaSessionWebhook(
|
|
117
117
|
sessionWebhook: string,
|
|
118
118
|
text: string,
|
|
119
|
+
atUserIds?: string[],
|
|
119
120
|
): Promise<{ ok: boolean; errcode?: number; errmsg?: string; processQueryKey?: string }> {
|
|
120
|
-
const
|
|
121
|
+
const body: any = {
|
|
121
122
|
msgtype: "text",
|
|
122
123
|
text: { content: text },
|
|
123
|
-
}
|
|
124
|
+
};
|
|
125
|
+
if (atUserIds?.length) {
|
|
126
|
+
body.at = { atUserIds, isAtAll: false };
|
|
127
|
+
}
|
|
128
|
+
const res = await jsonPost(sessionWebhook, body);
|
|
124
129
|
const ok = res?.errcode === 0 || !res?.errcode;
|
|
125
130
|
if (!ok) {
|
|
126
131
|
console.warn(`[dingtalk] SessionWebhook text error: errcode=${res?.errcode}, errmsg=${res?.errmsg}`);
|
|
@@ -133,11 +138,16 @@ export async function sendMarkdownViaSessionWebhook(
|
|
|
133
138
|
sessionWebhook: string,
|
|
134
139
|
title: string,
|
|
135
140
|
text: string,
|
|
141
|
+
atUserIds?: string[],
|
|
136
142
|
): Promise<{ ok: boolean; errcode?: number; errmsg?: string; processQueryKey?: string }> {
|
|
137
|
-
const
|
|
143
|
+
const body: any = {
|
|
138
144
|
msgtype: "markdown",
|
|
139
145
|
markdown: { title, text },
|
|
140
|
-
}
|
|
146
|
+
};
|
|
147
|
+
if (atUserIds?.length) {
|
|
148
|
+
body.at = { atUserIds, isAtAll: false };
|
|
149
|
+
}
|
|
150
|
+
const res = await jsonPost(sessionWebhook, body);
|
|
141
151
|
const ok = res?.errcode === 0 || !res?.errcode;
|
|
142
152
|
if (!ok) {
|
|
143
153
|
console.warn(`[dingtalk] SessionWebhook markdown error: errcode=${res?.errcode}, errmsg=${res?.errmsg}`);
|
package/src/monitor.ts
CHANGED
|
@@ -369,8 +369,8 @@ export async function startDingTalkMonitor(ctx: DingTalkMonitorContext): Promise
|
|
|
369
369
|
});
|
|
370
370
|
|
|
371
371
|
// Reconnection configuration
|
|
372
|
-
const HEARTBEAT_CHECK_MS =
|
|
373
|
-
const HEARTBEAT_TIMEOUT_MS =
|
|
372
|
+
const HEARTBEAT_CHECK_MS = 30_000; // Check connectivity every 30s
|
|
373
|
+
const HEARTBEAT_TIMEOUT_MS = 5 * 60 * 1000; // 5 min no activity = force reconnect (safety net only)
|
|
374
374
|
const RECONNECT_BASE_MS = 1_000; // 1s initial backoff
|
|
375
375
|
const RECONNECT_CAP_MS = 30_000; // 30s max backoff
|
|
376
376
|
let reconnectAttempt = 0;
|
|
@@ -421,6 +421,7 @@ export async function startDingTalkMonitor(ctx: DingTalkMonitorContext): Promise
|
|
|
421
421
|
});
|
|
422
422
|
|
|
423
423
|
client.registerAllEventListener((msg: any) => {
|
|
424
|
+
touchActivity(); // SDK events (including ping/pong) count as activity
|
|
424
425
|
return { status: "SUCCESS", message: "OK" };
|
|
425
426
|
});
|
|
426
427
|
|
|
@@ -437,7 +438,7 @@ export async function startDingTalkMonitor(ctx: DingTalkMonitorContext): Promise
|
|
|
437
438
|
log?.info?.("[dingtalk:" + account.accountId + "] Stream connected");
|
|
438
439
|
setStatus?.({ running: true, lastStartAt: connectTime });
|
|
439
440
|
|
|
440
|
-
// Start heartbeat monitor: if no activity for
|
|
441
|
+
// Start heartbeat monitor: if no activity for 5 min, force disconnect to trigger reconnect.
|
|
441
442
|
// The SDK's keepAlive ping/pong (8s interval) handles socket-level liveness and sets
|
|
442
443
|
// client.connected=false on missed pongs, which our poll loop below detects.
|
|
443
444
|
// This heartbeat is a secondary safety net for higher-level silent failures where
|
|
@@ -2025,6 +2026,10 @@ async function deliverReply(target: any, text: string, log?: any): Promise<void>
|
|
|
2025
2026
|
}
|
|
2026
2027
|
}
|
|
2027
2028
|
|
|
2029
|
+
// Auto @mention sender in group chats (only on first chunk to avoid spam)
|
|
2030
|
+
const atUserIds = (!target.isDm && target.senderId) ? [target.senderId] : undefined;
|
|
2031
|
+
let atApplied = false; // Only @ on the first chunk
|
|
2032
|
+
|
|
2028
2033
|
for (const chunk of chunks) {
|
|
2029
2034
|
let webhookSuccess = false;
|
|
2030
2035
|
const maxRetries = 2;
|
|
@@ -2036,12 +2041,13 @@ async function deliverReply(target: any, text: string, log?: any): Promise<void>
|
|
|
2036
2041
|
await throttleSend();
|
|
2037
2042
|
log?.info?.("[dingtalk] Using sessionWebhook (attempt " + attempt + "/" + maxRetries + "), format=" + messageFormat);
|
|
2038
2043
|
log?.info?.("[dingtalk] Sending text (" + chunk.length + " chars): " + chunk.substring(0, 200));
|
|
2044
|
+
const currentAt = (!atApplied && atUserIds) ? atUserIds : undefined;
|
|
2039
2045
|
let sendResult: { ok: boolean; errcode?: number; errmsg?: string; processQueryKey?: string };
|
|
2040
2046
|
if (isMarkdown) {
|
|
2041
2047
|
const markdownTitle = buildMarkdownPreviewTitle(chunk, "Jax");
|
|
2042
|
-
sendResult = await sendMarkdownViaSessionWebhook(target.sessionWebhook, markdownTitle, chunk);
|
|
2048
|
+
sendResult = await sendMarkdownViaSessionWebhook(target.sessionWebhook, markdownTitle, chunk, currentAt);
|
|
2043
2049
|
} else {
|
|
2044
|
-
sendResult = await sendViaSessionWebhook(target.sessionWebhook, chunk);
|
|
2050
|
+
sendResult = await sendViaSessionWebhook(target.sessionWebhook, chunk, currentAt);
|
|
2045
2051
|
}
|
|
2046
2052
|
if (!sendResult.ok) {
|
|
2047
2053
|
throw new Error(`SessionWebhook rejected: errcode=${sendResult.errcode}, errmsg=${sendResult.errmsg}`);
|
|
@@ -2055,6 +2061,7 @@ async function deliverReply(target: any, text: string, log?: any): Promise<void>
|
|
|
2055
2061
|
// so interactiveCard quotes can resolve via repliedMsg.createdAt
|
|
2056
2062
|
cacheOutboundMessageByTime(chunk);
|
|
2057
2063
|
}
|
|
2064
|
+
if (currentAt) atApplied = true;
|
|
2058
2065
|
webhookSuccess = true;
|
|
2059
2066
|
break;
|
|
2060
2067
|
} catch (err) {
|