fix: 增加 token 过期重试机制和 URL 替换规则优化
This commit is contained in:
@@ -209,17 +209,37 @@ export async function startGateway(ctx: GatewayContext): Promise<void> {
|
|||||||
QQGroupOpenid: event.groupOpenid,
|
QQGroupOpenid: event.groupOpenid,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 发送消息的辅助函数,带 token 过期重试
|
||||||
|
const sendWithTokenRetry = async (sendFn: (token: string) => Promise<unknown>) => {
|
||||||
|
try {
|
||||||
|
const token = await getAccessToken(account.appId, account.clientSecret);
|
||||||
|
await sendFn(token);
|
||||||
|
} catch (err) {
|
||||||
|
const errMsg = String(err);
|
||||||
|
// 如果是 token 相关错误,清除缓存重试一次
|
||||||
|
if (errMsg.includes("401") || errMsg.includes("token") || errMsg.includes("access_token")) {
|
||||||
|
log?.info(`[qqbot:${account.accountId}] Token may be expired, refreshing...`);
|
||||||
|
clearTokenCache();
|
||||||
|
const newToken = await getAccessToken(account.appId, account.clientSecret);
|
||||||
|
await sendFn(newToken);
|
||||||
|
} else {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 发送错误提示的辅助函数
|
// 发送错误提示的辅助函数
|
||||||
const sendErrorMessage = async (errorText: string) => {
|
const sendErrorMessage = async (errorText: string) => {
|
||||||
try {
|
try {
|
||||||
const token = await getAccessToken(account.appId, account.clientSecret);
|
await sendWithTokenRetry(async (token) => {
|
||||||
if (event.type === "c2c") {
|
if (event.type === "c2c") {
|
||||||
await sendC2CMessage(token, event.senderId, errorText, event.messageId);
|
await sendC2CMessage(token, event.senderId, errorText, event.messageId);
|
||||||
} else if (event.type === "group" && event.groupOpenid) {
|
} else if (event.type === "group" && event.groupOpenid) {
|
||||||
await sendGroupMessage(token, event.groupOpenid, errorText, event.messageId);
|
await sendGroupMessage(token, event.groupOpenid, errorText, event.messageId);
|
||||||
} else if (event.channelId) {
|
} else if (event.channelId) {
|
||||||
await sendChannelMessage(token, event.channelId, errorText, event.messageId);
|
await sendChannelMessage(token, event.channelId, errorText, event.messageId);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
} catch (sendErr) {
|
} catch (sendErr) {
|
||||||
log?.error(`[qqbot:${account.accountId}] Failed to send error message: ${sendErr}`);
|
log?.error(`[qqbot:${account.accountId}] Failed to send error message: ${sendErr}`);
|
||||||
}
|
}
|
||||||
@@ -228,9 +248,6 @@ export async function startGateway(ctx: GatewayContext): Promise<void> {
|
|||||||
try {
|
try {
|
||||||
const messagesConfig = pluginRuntime.channel.reply.resolveEffectiveMessagesConfig(cfg, route.agentId);
|
const messagesConfig = pluginRuntime.channel.reply.resolveEffectiveMessagesConfig(cfg, route.agentId);
|
||||||
|
|
||||||
// 每次发消息前刷新 token
|
|
||||||
const freshToken = await getAccessToken(account.appId, account.clientSecret);
|
|
||||||
|
|
||||||
// 追踪是否有响应
|
// 追踪是否有响应
|
||||||
let hasResponse = false;
|
let hasResponse = false;
|
||||||
const responseTimeout = 30000; // 30秒超时
|
const responseTimeout = 30000; // 30秒超时
|
||||||
@@ -260,22 +277,27 @@ export async function startGateway(ctx: GatewayContext): Promise<void> {
|
|||||||
if (!replyText.trim()) return;
|
if (!replyText.trim()) return;
|
||||||
|
|
||||||
// 处理回复内容,避免被 QQ 识别为 URL
|
// 处理回复内容,避免被 QQ 识别为 URL
|
||||||
// 把文件扩展名中的点替换为下划线,如 README.md -> README_md
|
|
||||||
const originalText = replyText;
|
const originalText = replyText;
|
||||||
replyText = replyText.replace(/(\w+)\.(\w{2,4})\b/g, "$1_$2");
|
|
||||||
|
// 把所有可能被识别为 URL 的点替换为下划线
|
||||||
|
// 匹配:字母/数字.字母/数字 的模式
|
||||||
|
replyText = replyText.replace(/([a-zA-Z0-9])\.([a-zA-Z0-9])/g, "$1_$2");
|
||||||
|
|
||||||
const hasReplacement = replyText !== originalText;
|
const hasReplacement = replyText !== originalText;
|
||||||
if (hasReplacement) {
|
if (hasReplacement) {
|
||||||
replyText += "\n\n(由于平台限制,回复中的部分符号已被替换)";
|
replyText += "\n\n(由于平台限制,回复中的部分符号已被替换)";
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (event.type === "c2c") {
|
await sendWithTokenRetry(async (token) => {
|
||||||
await sendC2CMessage(freshToken, event.senderId, replyText, event.messageId);
|
if (event.type === "c2c") {
|
||||||
} else if (event.type === "group" && event.groupOpenid) {
|
await sendC2CMessage(token, event.senderId, replyText, event.messageId);
|
||||||
await sendGroupMessage(freshToken, event.groupOpenid, replyText, event.messageId);
|
} else if (event.type === "group" && event.groupOpenid) {
|
||||||
} else if (event.channelId) {
|
await sendGroupMessage(token, event.groupOpenid, replyText, event.messageId);
|
||||||
await sendChannelMessage(freshToken, event.channelId, replyText, event.messageId);
|
} else if (event.channelId) {
|
||||||
}
|
await sendChannelMessage(token, event.channelId, replyText, event.messageId);
|
||||||
|
}
|
||||||
|
});
|
||||||
log?.info(`[qqbot:${account.accountId}] Sent reply`);
|
log?.info(`[qqbot:${account.accountId}] Sent reply`);
|
||||||
|
|
||||||
pluginRuntime.channel.activity.record({
|
pluginRuntime.channel.activity.record({
|
||||||
|
|||||||
Reference in New Issue
Block a user