@yaoyuanchao/dingtalk 1.4.3 → 1.4.5

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/monitor.ts +41 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaoyuanchao/dingtalk",
3
- "version": "1.4.3",
3
+ "version": "1.4.5",
4
4
  "type": "module",
5
5
  "description": "DingTalk channel plugin for Clawdbot with Stream Mode support",
6
6
  "license": "MIT",
package/src/monitor.ts CHANGED
@@ -164,6 +164,7 @@ async function extractMessageContent(
164
164
  if (chatRecordStr && typeof chatRecordStr === 'string') {
165
165
  const records = JSON.parse(chatRecordStr) as Array<{
166
166
  senderId?: string;
167
+ senderStaffId?: string; // Non-encrypted userId (available when app is published)
167
168
  senderNick?: string;
168
169
  msgType?: string;
169
170
  content?: string;
@@ -171,11 +172,48 @@ async function extractMessageContent(
171
172
  }>;
172
173
 
173
174
  if (Array.isArray(records) && records.length > 0) {
174
- // Debug: log first record structure to understand available fields
175
- log?.info?.("[dingtalk] chatRecord first record structure: " + JSON.stringify(records[0]));
175
+ // Debug: log first record structure with all keys
176
+ const firstRecord = records[0];
177
+ log?.info?.("[dingtalk] chatRecord first record keys: " + Object.keys(firstRecord).join(', '));
178
+ log?.info?.("[dingtalk] chatRecord first record: " + JSON.stringify(firstRecord));
179
+
180
+ // Collect unique userIds for batch lookup
181
+ // Prefer senderStaffId (non-encrypted) over senderId
182
+ const senderIds = [...new Set(
183
+ records
184
+ .map(r => r.senderStaffId || (r.senderId && !r.senderId.startsWith('$:') ? r.senderId : null))
185
+ .filter((id): id is string => !!id)
186
+ )].slice(0, 10); // Limit to 10 users
187
+
188
+ log?.info?.("[dingtalk] chatRecord senderIds for lookup: " + JSON.stringify(senderIds));
189
+
190
+ // Try to resolve sender names via API
191
+ let senderNameMap = new Map<string, string>();
192
+ if (senderIds.length > 0 && account.clientId && account.clientSecret) {
193
+ try {
194
+ senderNameMap = await batchGetUserInfo(account.clientId, account.clientSecret, senderIds, 3000);
195
+ log?.info?.("[dingtalk] Resolved " + senderNameMap.size + " sender names from API");
196
+ } catch (err) {
197
+ log?.info?.("[dingtalk] Failed to resolve sender names: " + err);
198
+ }
199
+ }
176
200
 
177
201
  const formattedRecords = records.map((record, idx) => {
178
- const sender = record.senderNick || record.senderId || '未知';
202
+ // Try: senderNick > API resolved name (via staffId or senderId) > fallback
203
+ let sender = record.senderNick;
204
+ if (!sender) {
205
+ // Try to get name from API lookup
206
+ const lookupId = record.senderStaffId || record.senderId;
207
+ if (lookupId) {
208
+ sender = senderNameMap.get(lookupId);
209
+ }
210
+ // Fallback for encrypted IDs
211
+ if (!sender && record.senderId?.startsWith('$:')) {
212
+ sender = '成员';
213
+ }
214
+ }
215
+ sender = sender || '未知';
216
+
179
217
  const msgContent = record.content || '[不支持的消息类型]';
180
218
  const time = record.createAt ? new Date(record.createAt).toLocaleString('zh-CN') : '';
181
219
  return `[${idx + 1}] ${sender}${time ? ` (${time})` : ''}: ${msgContent}`;