mirror of https://github.com/openclaw/openclaw.git
149 lines
4.5 KiB
TypeScript
149 lines
4.5 KiB
TypeScript
import { deleteTelegramUpdateOffset } from "../../../extensions/telegram/src/update-offset-store.js";
|
|
import { resolveChannelDefaultAccountId } from "../../channels/plugins/helpers.js";
|
|
import {
|
|
getChannelPlugin,
|
|
listChannelPlugins,
|
|
normalizeChannelId,
|
|
} from "../../channels/plugins/index.js";
|
|
import { type OpenClawConfig, writeConfigFile } from "../../config/config.js";
|
|
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../routing/session-key.js";
|
|
import { defaultRuntime, type RuntimeEnv } from "../../runtime.js";
|
|
import { createClackPrompter } from "../../wizard/clack-prompter.js";
|
|
import { type ChatChannel, channelLabel, requireValidConfig, shouldUseWizard } from "./shared.js";
|
|
|
|
export type ChannelsRemoveOptions = {
|
|
channel?: string;
|
|
account?: string;
|
|
delete?: boolean;
|
|
};
|
|
|
|
function listAccountIds(cfg: OpenClawConfig, channel: ChatChannel): string[] {
|
|
const plugin = getChannelPlugin(channel);
|
|
if (!plugin) {
|
|
return [];
|
|
}
|
|
return plugin.config.listAccountIds(cfg);
|
|
}
|
|
|
|
export async function channelsRemoveCommand(
|
|
opts: ChannelsRemoveOptions,
|
|
runtime: RuntimeEnv = defaultRuntime,
|
|
params?: { hasFlags?: boolean },
|
|
) {
|
|
const cfg = await requireValidConfig(runtime);
|
|
if (!cfg) {
|
|
return;
|
|
}
|
|
|
|
const useWizard = shouldUseWizard(params);
|
|
const prompter = useWizard ? createClackPrompter() : null;
|
|
let channel: ChatChannel | null = normalizeChannelId(opts.channel);
|
|
let accountId = normalizeAccountId(opts.account);
|
|
const deleteConfig = Boolean(opts.delete);
|
|
|
|
if (useWizard && prompter) {
|
|
await prompter.intro("Remove channel account");
|
|
const selectedChannel = await prompter.select({
|
|
message: "Channel",
|
|
options: listChannelPlugins().map((plugin) => ({
|
|
value: plugin.id,
|
|
label: plugin.meta.label,
|
|
})),
|
|
});
|
|
channel = selectedChannel;
|
|
|
|
accountId = await (async () => {
|
|
const ids = listAccountIds(cfg, selectedChannel);
|
|
const choice = await prompter.select({
|
|
message: "Account",
|
|
options: ids.map((id) => ({
|
|
value: id,
|
|
label: id === DEFAULT_ACCOUNT_ID ? "default (primary)" : id,
|
|
})),
|
|
initialValue: ids[0] ?? DEFAULT_ACCOUNT_ID,
|
|
});
|
|
return normalizeAccountId(choice);
|
|
})();
|
|
|
|
const wantsDisable = await prompter.confirm({
|
|
message: `Disable ${channelLabel(selectedChannel)} account "${accountId}"? (keeps config)`,
|
|
initialValue: true,
|
|
});
|
|
if (!wantsDisable) {
|
|
await prompter.outro("Cancelled.");
|
|
return;
|
|
}
|
|
} else {
|
|
if (!channel) {
|
|
runtime.error("Channel is required. Use --channel <name>.");
|
|
runtime.exit(1);
|
|
return;
|
|
}
|
|
if (!deleteConfig) {
|
|
const confirm = createClackPrompter();
|
|
const ok = await confirm.confirm({
|
|
message: `Disable ${channelLabel(channel)} account "${accountId}"? (keeps config)`,
|
|
initialValue: true,
|
|
});
|
|
if (!ok) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
const plugin = getChannelPlugin(channel);
|
|
if (!plugin) {
|
|
runtime.error(`Unknown channel: ${channel}`);
|
|
runtime.exit(1);
|
|
return;
|
|
}
|
|
|
|
const resolvedAccountId =
|
|
normalizeAccountId(accountId) ?? resolveChannelDefaultAccountId({ plugin, cfg });
|
|
const accountKey = resolvedAccountId || DEFAULT_ACCOUNT_ID;
|
|
|
|
let next = { ...cfg };
|
|
if (deleteConfig) {
|
|
if (!plugin.config.deleteAccount) {
|
|
runtime.error(`Channel ${channel} does not support delete.`);
|
|
runtime.exit(1);
|
|
return;
|
|
}
|
|
next = plugin.config.deleteAccount({
|
|
cfg: next,
|
|
accountId: resolvedAccountId,
|
|
});
|
|
|
|
// Clean up Telegram polling offset to prevent stale offset on bot token change (#18233)
|
|
if (channel === "telegram") {
|
|
await deleteTelegramUpdateOffset({ accountId: resolvedAccountId });
|
|
}
|
|
} else {
|
|
if (!plugin.config.setAccountEnabled) {
|
|
runtime.error(`Channel ${channel} does not support disable.`);
|
|
runtime.exit(1);
|
|
return;
|
|
}
|
|
next = plugin.config.setAccountEnabled({
|
|
cfg: next,
|
|
accountId: resolvedAccountId,
|
|
enabled: false,
|
|
});
|
|
}
|
|
|
|
await writeConfigFile(next);
|
|
if (useWizard && prompter) {
|
|
await prompter.outro(
|
|
deleteConfig
|
|
? `Deleted ${channelLabel(channel)} account "${accountKey}".`
|
|
: `Disabled ${channelLabel(channel)} account "${accountKey}".`,
|
|
);
|
|
} else {
|
|
runtime.log(
|
|
deleteConfig
|
|
? `Deleted ${channelLabel(channel)} account "${accountKey}".`
|
|
: `Disabled ${channelLabel(channel)} account "${accountKey}".`,
|
|
);
|
|
}
|
|
}
|