2 Commits

Author SHA1 Message Date
sliverp
d36182beed chore: 添加日志输出以调试图片发送流程 2026-02-03 14:52:53 +08:00
sliverp
1a5b866f20 refactor: 重命名 imageServerBaseUrl 为 imageServerPublicIp 2026-02-03 14:17:17 +08:00
7 changed files with 25 additions and 19 deletions

View File

@@ -390,7 +390,9 @@ export async function sendGroupImageMessage(
content?: string content?: string
): Promise<{ id: string; timestamp: string }> { ): Promise<{ id: string; timestamp: string }> {
// 先上传图片获取 file_info // 先上传图片获取 file_info
console.log(`[qqbot-api] sendGroupImageMessage: uploading image from URL: ${imageUrl}`);
const uploadResult = await uploadGroupMedia(accessToken, groupOpenid, MediaFileType.IMAGE, imageUrl, false); const uploadResult = await uploadGroupMedia(accessToken, groupOpenid, MediaFileType.IMAGE, imageUrl, false);
console.log(`[qqbot-api] sendGroupImageMessage: upload success, file_info: ${uploadResult.file_info?.slice(0, 50)}...`);
// 再发送富媒体消息 // 再发送富媒体消息
return sendGroupMediaMessage(accessToken, groupOpenid, uploadResult.file_info, msgId, content); return sendGroupMediaMessage(accessToken, groupOpenid, uploadResult.file_info, msgId, content);
} }

View File

@@ -83,7 +83,7 @@ export const qqbotPlugin: ChannelPlugin<ResolvedQQBotAccount> = {
clientSecret, clientSecret,
clientSecretFile: input.tokenFile, clientSecretFile: input.tokenFile,
name: input.name, name: input.name,
imageServerBaseUrl: input.imageServerBaseUrl, imageServerPublicIp: input.imageServerPublicIp,
}); });
}, },
}, },

View File

@@ -63,7 +63,7 @@ export function resolveQQBotAccount(
dmPolicy: qqbot?.dmPolicy, dmPolicy: qqbot?.dmPolicy,
allowFrom: qqbot?.allowFrom, allowFrom: qqbot?.allowFrom,
systemPrompt: qqbot?.systemPrompt, systemPrompt: qqbot?.systemPrompt,
imageServerBaseUrl: qqbot?.imageServerBaseUrl, imageServerPublicIp: qqbot?.imageServerPublicIp,
}; };
appId = qqbot?.appId ?? ""; appId = qqbot?.appId ?? "";
} else { } else {
@@ -98,7 +98,7 @@ export function resolveQQBotAccount(
clientSecret, clientSecret,
secretSource, secretSource,
systemPrompt: accountConfig.systemPrompt, systemPrompt: accountConfig.systemPrompt,
imageServerBaseUrl: accountConfig.imageServerBaseUrl || process.env.QQBOT_IMAGE_SERVER_BASE_URL, imageServerPublicIp: accountConfig.imageServerPublicIp || process.env.QQBOT_IMAGE_SERVER_PUBLIC_IP,
config: accountConfig, config: accountConfig,
}; };
} }
@@ -109,7 +109,7 @@ export function resolveQQBotAccount(
export function applyQQBotAccountConfig( export function applyQQBotAccountConfig(
cfg: MoltbotConfig, cfg: MoltbotConfig,
accountId: string, accountId: string,
input: { appId?: string; clientSecret?: string; clientSecretFile?: string; name?: string; imageServerBaseUrl?: string } input: { appId?: string; clientSecret?: string; clientSecretFile?: string; name?: string; imageServerPublicIp?: string }
): MoltbotConfig { ): MoltbotConfig {
const next = { ...cfg }; const next = { ...cfg };
@@ -126,7 +126,7 @@ export function applyQQBotAccountConfig(
? { clientSecretFile: input.clientSecretFile } ? { clientSecretFile: input.clientSecretFile }
: {}), : {}),
...(input.name ? { name: input.name } : {}), ...(input.name ? { name: input.name } : {}),
...(input.imageServerBaseUrl ? { imageServerBaseUrl: input.imageServerBaseUrl } : {}), ...(input.imageServerPublicIp ? { imageServerPublicIp: input.imageServerPublicIp } : {}),
}, },
}; };
} else { } else {
@@ -147,7 +147,7 @@ export function applyQQBotAccountConfig(
? { clientSecretFile: input.clientSecretFile } ? { clientSecretFile: input.clientSecretFile }
: {}), : {}),
...(input.name ? { name: input.name } : {}), ...(input.name ? { name: input.name } : {}),
...(input.imageServerBaseUrl ? { imageServerBaseUrl: input.imageServerBaseUrl } : {}), ...(input.imageServerPublicIp ? { imageServerPublicIp: input.imageServerPublicIp } : {}),
}, },
}, },
}, },

View File

@@ -98,15 +98,16 @@ export async function startGateway(ctx: GatewayContext): Promise<void> {
throw new Error("QQBot not configured (missing appId or clientSecret)"); throw new Error("QQBot not configured (missing appId or clientSecret)");
} }
// 如果配置了公网 URL,启动图床服务器 // 如果配置了公网 IP,启动图床服务器
let imageServerBaseUrl: string | null = null; let imageServerBaseUrl: string | null = null;
if (account.imageServerBaseUrl) { if (account.imageServerPublicIp) {
// 使用用户配置的公网地址作为 baseUrl // 内部组装完整 URL
await ensureImageServer(log, account.imageServerBaseUrl); const publicBaseUrl = `http://${account.imageServerPublicIp}:${IMAGE_SERVER_PORT}`;
imageServerBaseUrl = account.imageServerBaseUrl; await ensureImageServer(log, publicBaseUrl);
imageServerBaseUrl = publicBaseUrl;
log?.info(`[qqbot:${account.accountId}] Image server enabled with URL: ${imageServerBaseUrl}`); log?.info(`[qqbot:${account.accountId}] Image server enabled with URL: ${imageServerBaseUrl}`);
} else { } else {
log?.info(`[qqbot:${account.accountId}] Image server disabled (no imageServerBaseUrl configured)`); log?.info(`[qqbot:${account.accountId}] Image server disabled (no imageServerPublicIp configured)`);
} }
let reconnectAttempts = 0; let reconnectAttempts = 0;
@@ -540,6 +541,7 @@ export async function startGateway(ctx: GatewayContext): Promise<void> {
try { try {
// 先发送图片(如果有) // 先发送图片(如果有)
log?.info(`[qqbot:${account.accountId}] imageUrls to send: ${JSON.stringify(imageUrls)}, imageServerBaseUrl: ${imageServerBaseUrl}`);
for (const imageUrl of imageUrls) { for (const imageUrl of imageUrls) {
try { try {
await sendWithTokenRetry(async (token) => { await sendWithTokenRetry(async (token) => {

View File

@@ -335,7 +335,9 @@ export function saveImage(
// 返回访问 URL // 返回访问 URL
const baseUrl = currentConfig.baseUrl || `http://localhost:${currentConfig.port}`; const baseUrl = currentConfig.baseUrl || `http://localhost:${currentConfig.port}`;
return `${baseUrl}/images/${imageId}.${ext}`; const resultUrl = `${baseUrl}/images/${imageId}.${ext}`;
console.log(`[image-server] saveImage: generated URL: ${resultUrl} (baseUrl: ${baseUrl})`);
return resultUrl;
} }
/** /**

View File

@@ -29,14 +29,14 @@ interface QQBotChannelConfig {
clientSecret?: string; clientSecret?: string;
clientSecretFile?: string; clientSecretFile?: string;
name?: string; name?: string;
imageServerBaseUrl?: string; imageServerPublicIp?: string;
accounts?: Record<string, { accounts?: Record<string, {
enabled?: boolean; enabled?: boolean;
appId?: string; appId?: string;
clientSecret?: string; clientSecret?: string;
clientSecretFile?: string; clientSecretFile?: string;
name?: string; name?: string;
imageServerBaseUrl?: string; imageServerPublicIp?: string;
}>; }>;
} }

View File

@@ -19,8 +19,8 @@ export interface ResolvedQQBotAccount {
secretSource: "config" | "file" | "env" | "none"; secretSource: "config" | "file" | "env" | "none";
/** 系统提示词 */ /** 系统提示词 */
systemPrompt?: string; systemPrompt?: string;
/** 图床服务器公网地址 */ /** 图床服务器公网 IP内部自动组装成 http://IP:18765 */
imageServerBaseUrl?: string; imageServerPublicIp?: string;
config: QQBotAccountConfig; config: QQBotAccountConfig;
} }
@@ -37,8 +37,8 @@ export interface QQBotAccountConfig {
allowFrom?: string[]; allowFrom?: string[];
/** 系统提示词,会添加在用户消息前面 */ /** 系统提示词,会添加在用户消息前面 */
systemPrompt?: string; systemPrompt?: string;
/** 图床服务器公网地址,用于发送图片,例如 http://your-ip:18765 */ /** 图床服务器公网 IP,用于发送图片,例如 1.2.3.4(内部自动组装成 http://IP:18765 */
imageServerBaseUrl?: string; imageServerPublicIp?: string;
} }
/** /**