feat: support wecom (#372)

Co-authored-by: DigHuang <114602213+DigHuang@users.noreply.github.com>
This commit is contained in:
paisley
2026-03-10 12:06:37 +08:00
committed by GitHub
Unverified
parent 905ce02b0b
commit b86f47171b
13 changed files with 326 additions and 54 deletions

View File

@@ -16,6 +16,14 @@ import { whatsAppLoginManager } from '../../utils/whatsapp-login';
import type { HostApiContext } from '../context';
import { parseJsonBody, sendJson } from '../route-utils';
function scheduleGatewayChannelRestart(ctx: HostApiContext, reason: string): void {
if (ctx.gatewayManager.getStatus().state === 'stopped') {
return;
}
ctx.gatewayManager.debouncedRestart();
void reason;
}
async function ensureDingTalkPluginInstalled(): Promise<{ installed: boolean; warning?: string }> {
const targetDir = join(homedir(), '.openclaw', 'extensions', 'dingtalk');
const targetManifest = join(targetDir, 'openclaw.plugin.json');
@@ -57,6 +65,47 @@ async function ensureDingTalkPluginInstalled(): Promise<{ installed: boolean; wa
}
}
async function ensureWeComPluginInstalled(): Promise<{ installed: boolean; warning?: string }> {
const targetDir = join(homedir(), '.openclaw', 'extensions', 'wecom');
const targetManifest = join(targetDir, 'openclaw.plugin.json');
if (existsSync(targetManifest)) {
return { installed: true };
}
const candidateSources = app.isPackaged
? [
join(process.resourcesPath, 'openclaw-plugins', 'wecom'),
join(process.resourcesPath, 'app.asar.unpacked', 'build', 'openclaw-plugins', 'wecom'),
join(process.resourcesPath, 'app.asar.unpacked', 'openclaw-plugins', 'wecom'),
]
: [
join(app.getAppPath(), 'build', 'openclaw-plugins', 'wecom'),
join(process.cwd(), 'build', 'openclaw-plugins', 'wecom'),
join(__dirname, '../../../build/openclaw-plugins/wecom'),
];
const sourceDir = candidateSources.find((dir) => existsSync(join(dir, 'openclaw.plugin.json')));
if (!sourceDir) {
return {
installed: false,
warning: `Bundled WeCom plugin mirror not found. Checked: ${candidateSources.join(' | ')}`,
};
}
try {
mkdirSync(join(homedir(), '.openclaw', 'extensions'), { recursive: true });
rmSync(targetDir, { recursive: true, force: true });
cpSync(sourceDir, targetDir, { recursive: true, dereference: true });
if (!existsSync(targetManifest)) {
return { installed: false, warning: 'Failed to install WeCom plugin mirror (manifest missing).' };
}
return { installed: true };
} catch {
return { installed: false, warning: 'Failed to install bundled WeCom plugin mirror' };
}
}
export async function handleChannelRoutes(
req: IncomingMessage,
res: ServerResponse,
@@ -119,7 +168,15 @@ export async function handleChannelRoutes(
return true;
}
}
if (body.channelType === 'wecom') {
const installResult = await ensureWeComPluginInstalled();
if (!installResult.installed) {
sendJson(res, 500, { success: false, error: installResult.warning || 'WeCom plugin install failed' });
return true;
}
}
await saveChannelConfig(body.channelType, body.config);
scheduleGatewayChannelRestart(ctx, `channel:saveConfig:${body.channelType}`);
sendJson(res, 200, { success: true });
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
@@ -131,6 +188,7 @@ export async function handleChannelRoutes(
try {
const body = await parseJsonBody<{ channelType: string; enabled: boolean }>(req);
await setChannelEnabled(body.channelType, body.enabled);
scheduleGatewayChannelRestart(ctx, `channel:setEnabled:${body.channelType}`);
sendJson(res, 200, { success: true });
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
@@ -155,6 +213,7 @@ export async function handleChannelRoutes(
try {
const channelType = decodeURIComponent(url.pathname.slice('/api/channels/config/'.length));
await deleteChannelConfig(channelType);
scheduleGatewayChannelRestart(ctx, `channel:deleteConfig:${channelType}`);
sendJson(res, 200, { success: true });
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });