diff --git a/wecom-api.js b/wecom-api.js index 029f7e9..ebdee94 100755 --- a/wecom-api.js +++ b/wecom-api.js @@ -37,6 +37,7 @@ async uploadMedia(corpId, corpSecret, type, filePath, fileName) { const { readFile } = await import("fs/promises"); const { Buffer } = await import("buffer"); + const path = await import("path"); logger.debug("WeCom API: Uploading media", { corpId, type, filePath }); const token = await this.getAccessToken(corpId, corpSecret); @@ -44,7 +45,9 @@ const fileBuffer = await readFile(filePath); const formData = new FormData(); const blob = new Blob([fileBuffer]); - formData.append('media', blob, fileName || 'file'); + + const actualFileName = fileName || path.basename(filePath) || 'file.mp3'; + formData.append('media', blob, actualFileName); const res = await fetch(`https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=${token}&type=${type}`, { method: "POST", diff --git a/wecom-message-processor.js b/wecom-message-processor.js index 1a730ae..f8b73ad 100755 --- a/wecom-message-processor.js +++ b/wecom-message-processor.js @@ -538,10 +538,28 @@ for (const media of mediaMatches) { const type = getWecomMediaType(media.path); - processedText = processedText.replace(media.fullMatch, `[${type === 'voice' ? '语音' : type === 'video' ? '视频' : type === 'image' ? '图片' : '文件'}: ${media.path}]`).trim(); + try { + const uploadRes = await wecomApi.uploadMedia(account.corpId, account.corpSecret, type, media.path); + const mediaId = uploadRes.media_id; + const agentId = message.agentId || account.agentId || 1000002; + if (type === 'image') { + await wecomApi.sendImageMessage?.(account.corpId, account.corpSecret, agentId, senderId, mediaId); + } else if (type === 'voice') { + await wecomApi.sendVoiceMessage?.(account.corpId, account.corpSecret, agentId, senderId, mediaId); + } else if (type === 'video') { + await wecomApi.sendVideoMessage?.(account.corpId, account.corpSecret, agentId, senderId, mediaId); + } else { + await wecomApi.sendFileMessage?.(account.corpId, account.corpSecret, agentId, senderId, mediaId); + } + logger.info("WeCom Self-Built (Async): sent active media message (mixed with text)", { mediaId, type }); + processedText = processedText.replace(media.fullMatch, "").trim(); + } catch (err) { + logger.error("WeCom Self-Built (Async): Failed to upload/send media actively", { error: err.message, path: media.path }); + processedText = processedText.replace(media.fullMatch, `[${type === 'voice' ? '语音' : type === 'video' ? '视频' : type === 'image' ? '图片' : '文件'}: ${media.path}]`).trim(); + } } - if (processedText.trim() || mediaMatches.length > 0) { + if (processedText.trim()) { try { await wecomApi.sendTextMessage(account.corpId, account.corpSecret, message.agentId || account.agentId || 1000002, senderId, processedText); } catch (e) { @@ -766,8 +784,27 @@ } } else if (isSelfBuiltAppRequest) { const type = getWecomMediaType(media.path); - processedText = processedText.replace(media.fullMatch, `[${type === 'voice' ? '语音' : type === 'video' ? '视频' : type === 'image' ? '图片' : '文件'}: ${media.path}]`).trim(); - logger.warn("WeCom Self-Built: converting local media to text for passive reply (multi-item or text mixed)", { mediaPath: media.path, type }); + try { + const uploadRes = await wecomApi.uploadMedia(account.corpId, account.corpSecret, type, media.path); + const mediaId = uploadRes.media_id; + const toUser = originalMessage.fromUser || originalMessage.chatId || originalMessage.ToUserName; + const agentId = originalMessage.agentId || account.agentId || 1000002; + + if (type === 'image') { + await wecomApi.sendImageMessage?.(account.corpId, account.corpSecret, agentId, toUser, mediaId); + } else if (type === 'voice') { + await wecomApi.sendVoiceMessage?.(account.corpId, account.corpSecret, agentId, toUser, mediaId); + } else if (type === 'video') { + await wecomApi.sendVideoMessage?.(account.corpId, account.corpSecret, agentId, toUser, mediaId); + } else { + await wecomApi.sendFileMessage?.(account.corpId, account.corpSecret, agentId, toUser, mediaId); + } + logger.info("WeCom Self-Built: sent active media message (mixed with text)", { mediaId, type }); + processedText = processedText.replace(media.fullMatch, "").trim(); + } catch (err) { + logger.error("Failed to upload/send media actively", { error: err.message, path: media.path }); + processedText = processedText.replace(media.fullMatch, `[${type === 'voice' ? '语音' : type === 'video' ? '视频' : type === 'image' ? '图片' : '文件'}: ${media.path}]`).trim(); + } } } }