@yaoyuanchao/dingtalk 1.4.13 → 1.4.15

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaoyuanchao/dingtalk",
3
- "version": "1.4.13",
3
+ "version": "1.4.15",
4
4
  "type": "module",
5
5
  "description": "DingTalk channel plugin for Clawdbot with Stream Mode support",
6
6
  "license": "MIT",
package/src/api.ts CHANGED
@@ -167,18 +167,26 @@ export async function sendDingTalkRestMessage(params: {
167
167
  userId?: string;
168
168
  conversationId?: string;
169
169
  text: string;
170
+ format?: 'text' | 'markdown';
170
171
  }): Promise<{ ok: boolean }> {
171
172
  const token = await getDingTalkAccessToken(params.clientId, params.clientSecret);
172
173
  const headers = { "x-acs-dingtalk-access-token": token };
173
174
 
175
+ // Use markdown format by default for better rendering
176
+ const useMarkdown = params.format !== 'text';
177
+ const msgKey = useMarkdown ? 'sampleMarkdown' : 'sampleText';
178
+ const msgParam = useMarkdown
179
+ ? JSON.stringify({ title: 'AI', text: params.text })
180
+ : JSON.stringify({ content: params.text });
181
+
174
182
  if (params.userId) {
175
183
  const res = await jsonPost(
176
184
  `${DINGTALK_API_BASE}/robot/oToMessages/batchSend`,
177
185
  {
178
186
  robotCode: params.robotCode,
179
187
  userIds: [params.userId],
180
- msgKey: "sampleText",
181
- msgParam: JSON.stringify({ content: params.text }),
188
+ msgKey,
189
+ msgParam,
182
190
  },
183
191
  headers,
184
192
  );
@@ -194,8 +202,8 @@ export async function sendDingTalkRestMessage(params: {
194
202
  {
195
203
  robotCode: params.robotCode,
196
204
  openConversationId: params.conversationId,
197
- msgKey: "sampleText",
198
- msgParam: JSON.stringify({ content: params.text }),
205
+ msgKey,
206
+ msgParam,
199
207
  },
200
208
  headers,
201
209
  );
package/src/channel.ts CHANGED
@@ -38,6 +38,7 @@ export const dingtalkPlugin = {
38
38
  capabilities: {
39
39
  chatTypes: ['direct', 'group'],
40
40
  media: true, // Supports images via markdown in sessionWebhook replies
41
+ files: true, // Supports file upload and sending
41
42
  threads: false,
42
43
  reactions: false,
43
44
  mentions: true,
@@ -251,6 +252,56 @@ export const dingtalkPlugin = {
251
252
  return { channel: 'dingtalk', ok: true };
252
253
  },
253
254
 
255
+ async sendFile({ to, content, fileName, accountId, cfg }) {
256
+ const account = resolveDingTalkAccount({ cfg, accountId });
257
+ const { type, id } = parseOutboundTo(to);
258
+
259
+ // Convert content to buffer if it's a string
260
+ let fileBuffer: Buffer;
261
+ if (typeof content === 'string') {
262
+ // Add UTF-8 BOM for text files (better Chinese display)
263
+ const bom = Buffer.from([0xEF, 0xBB, 0xBF]);
264
+ const textContent = Buffer.from(content, 'utf-8');
265
+ fileBuffer = Buffer.concat([bom, textContent]);
266
+ } else if (Buffer.isBuffer(content)) {
267
+ fileBuffer = content;
268
+ } else {
269
+ throw new Error('content must be a string or Buffer');
270
+ }
271
+
272
+ // Upload file to DingTalk
273
+ const uploadResult = await uploadMediaFile({
274
+ clientId: account.clientId,
275
+ clientSecret: account.clientSecret,
276
+ robotCode: account.robotCode || account.clientId,
277
+ fileBuffer,
278
+ fileName: fileName || 'file.txt',
279
+ fileType: 'file',
280
+ });
281
+
282
+ if (!uploadResult.mediaId) {
283
+ throw new Error(`File upload failed: ${uploadResult.error}`);
284
+ }
285
+
286
+ // Send file message
287
+ const sendResult = await sendFileMessage({
288
+ clientId: account.clientId,
289
+ clientSecret: account.clientSecret,
290
+ robotCode: account.robotCode || account.clientId,
291
+ userId: type === 'dm' ? id : undefined,
292
+ conversationId: type === 'group' ? id : undefined,
293
+ mediaId: uploadResult.mediaId,
294
+ fileName: fileName || 'file.txt',
295
+ });
296
+
297
+ if (!sendResult.ok) {
298
+ throw new Error(`File send failed: ${sendResult.error}`);
299
+ }
300
+
301
+ console.log(`[dingtalk] File sent via outbound.sendFile: ${fileName}`);
302
+ return { channel: 'dingtalk', ok: true };
303
+ },
304
+
254
305
  async sendMedia({ to, text, mediaUrl, accountId, cfg }) {
255
306
  // Note: DingTalk REST API (oToMessages/groupMessages) doesn't support markdown or images
256
307
  // Images can only be sent via sessionWebhook (when replying to messages)