修复死循环问题 - 添加状态记忆功能

问题:
选择路径后重新发送文件,又显示选择卡片,导致死循环

解决方案:
1. 添加用户状态临时存储(内存)
2. 选择存储桶/路径后保存状态(5 分钟有效)
3. 重新发送文件时,检测是否有保存的状态
4. 有状态则直接上传,无状态则显示选择卡片

使用流程:
1. 发送文件 → 显示选择卡片
2. 选择存储桶 → 保存状态,提示重新发送
3. 选择路径 → 保存状态,提示重新发送
4. 重新发送文件 → 使用保存的状态直接上传
5. 上传完成后清除状态

状态有效期:5 分钟
This commit is contained in:
饭团
2026-03-06 09:12:18 +08:00
parent bf5b79c62b
commit e13b86fcd0

View File

@@ -30,6 +30,25 @@ function loadFullConfig() {
return JSON.parse(fs.readFileSync(configPath, 'utf-8')); return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
} }
// 用户临时状态存储(内存)
const userStates = {};
function getUserState(chatId) {
return userStates[chatId] || {};
}
function setUserState(chatId, state) {
userStates[chatId] = { ...userStates[chatId], ...state };
// 5 分钟后清除状态
setTimeout(() => {
delete userStates[chatId];
}, 5 * 60 * 1000);
}
function clearUserState(chatId) {
delete userStates[chatId];
}
async function handleFeishuEvent(req, res) { async function handleFeishuEvent(req, res) {
const event = req.body; const event = req.body;
log('📩 收到飞书请求'); log('📩 收到飞书请求');
@@ -99,8 +118,16 @@ async function handleMessage(event) {
} else if (text.startsWith('/help') || text.startsWith('/qh')) { } else if (text.startsWith('/help') || text.startsWith('/qh')) {
await handleHelpCommandV2(chatId, feishu); await handleHelpCommandV2(chatId, feishu);
} else if (messageType === 'file' || messageContent.file_key) { } else if (messageType === 'file' || messageContent.file_key) {
log('🔍 收到文件消息 - 发送配置卡片'); // 检查是否有已保存的配置
await handleFileReceivedWithCard(messageData, feishu, uploader); const state = getUserState(chatId);
if (state.bucket || state.upload_path) {
log('🔍 收到文件消息 - 使用已保存的配置');
await handleFileUploadWithState(messageData, feishu, uploader, state);
clearUserState(chatId);
} else {
log('🔍 收到文件消息 - 发送配置卡片');
await handleFileReceivedWithCard(messageData, feishu, uploader);
}
} else { } else {
await sendWelcomeCard(chatId, feishu); await sendWelcomeCard(chatId, feishu);
} }
@@ -192,9 +219,11 @@ async function handleCardInteraction(event) {
const { bucket } = actionData.value; const { bucket } = actionData.value;
log('🪣 选择存储桶:', bucket); log('🪣 选择存储桶:', bucket);
setUserState(chatId, { bucket });
await feishu.sendMessage(chatId, { await feishu.sendMessage(chatId, {
msg_type: 'text', msg_type: 'text',
content: { text: `✅ 已选择存储桶:**${bucket}**\n\n请重新发送文件开始上传` } content: { text: `✅ 已选择存储桶:**${bucket}**\n\n请重新发送文件开始上传(配置 5 分钟内有效)` }
}); });
break; break;
} }
@@ -204,9 +233,11 @@ async function handleCardInteraction(event) {
const pathDesc = path_label || '原文件名'; const pathDesc = path_label || '原文件名';
log('📁 选择路径:', pathDesc); log('📁 选择路径:', pathDesc);
setUserState(chatId, { upload_path, path_label });
await feishu.sendMessage(chatId, { await feishu.sendMessage(chatId, {
msg_type: 'text', msg_type: 'text',
content: { text: `✅ 已选择路径:**${pathDesc}**\n\n请重新发送文件开始上传` } content: { text: `✅ 已选择路径:**${pathDesc}**\n\n请重新发送文件开始上传(配置 5 分钟内有效)` }
}); });
break; break;
} }
@@ -371,6 +402,66 @@ async function handleFileReceivedWithCard(messageData, feishu, uploader) {
await feishu.sendCard(chatId, card); await feishu.sendCard(chatId, card);
} }
// 使用已保存的状态直接上传文件
async function handleFileUploadWithState(messageData, feishu, uploader, state) {
const chatId = messageData.chat_id;
const messageId = messageData.message_id;
const messageContent = JSON.parse(messageData.content);
const fileKey = messageContent.file_key;
const fileName = messageContent.file_name;
if (!fileKey) return;
const targetBucket = state.bucket || 'default';
let targetKey = state.upload_path || fileName;
const pathLabel = state.path_label || '原文件名';
if (targetKey.startsWith('/')) targetKey = targetKey.substring(1);
log('📤 使用已保存配置上传:', fileName, 'bucket:', targetBucket, 'path:', targetKey);
try {
await feishu.sendMessage(chatId, {
msg_type: 'text',
content: { text: `📥 正在下载:${fileName}` }
});
const tempFile = await feishu.downloadFile(fileKey, messageId, chatId);
log('✅ 文件下载完成:', tempFile);
await feishu.sendMessage(chatId, {
msg_type: 'text',
content: { text: `📤 上传中:${targetKey}${targetBucket} (路径:${pathLabel})` }
});
const result = await uploader.upload(tempFile, targetKey, targetBucket);
await uploader.refreshCDN(targetBucket, targetKey);
await feishu.sendMessage(chatId, {
msg_type: 'text',
content: {
text: `✅ 上传成功!\n\n` +
`📦 文件:${targetKey}\n` +
`🔗 链接:${result.url}\n` +
`💾 原文件:${fileName}\n` +
`🪣 存储桶:${targetBucket}\n` +
`📁 路径:${pathLabel}`
}
});
fs.unlinkSync(tempFile);
log('🗑️ 临时文件已清理:', tempFile);
} catch (error) {
log('上传失败:', error.message);
await feishu.sendMessage(chatId, {
msg_type: 'text',
content: { text: `❌ 上传失败:${error.message}` }
});
}
}
async function handleConfigCommandV2(message, content, feishu, uploader) { async function handleConfigCommandV2(message, content, feishu, uploader) {
const chatId = message.chat_id; const chatId = message.chat_id;
const text = content.text || ''; const text = content.text || '';