mirror of https://github.com/openclaw/openclaw.git
refactor: share delimited channel entry parsing
This commit is contained in:
parent
e8a80cfbd8
commit
d55fa78e40
|
|
@ -81,6 +81,32 @@ describe("resolveDefaultIrcAccountId", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("resolveIrcAccount", () => {
|
describe("resolveIrcAccount", () => {
|
||||||
|
it("parses delimited IRC_CHANNELS env values for the default account", () => {
|
||||||
|
const previousChannels = process.env.IRC_CHANNELS;
|
||||||
|
process.env.IRC_CHANNELS = "alpha, beta\ngamma; delta";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const account = resolveIrcAccount({
|
||||||
|
cfg: asConfig({
|
||||||
|
channels: {
|
||||||
|
irc: {
|
||||||
|
host: "irc.example.com",
|
||||||
|
nick: "claw",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(account.config.channels).toEqual(["alpha", "beta", "gamma", "delta"]);
|
||||||
|
} finally {
|
||||||
|
if (previousChannels === undefined) {
|
||||||
|
delete process.env.IRC_CHANNELS;
|
||||||
|
} else {
|
||||||
|
process.env.IRC_CHANNELS = previousChannels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it.runIf(process.platform !== "win32")("rejects symlinked password files", () => {
|
it.runIf(process.platform !== "win32")("rejects symlinked password files", () => {
|
||||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-irc-account-"));
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-irc-account-"));
|
||||||
const passwordFile = path.join(dir, "password.txt");
|
const passwordFile = path.join(dir, "password.txt");
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { tryReadSecretFileSync } from "openclaw/plugin-sdk/core";
|
||||||
import {
|
import {
|
||||||
createAccountListHelpers,
|
createAccountListHelpers,
|
||||||
normalizeResolvedSecretInputString,
|
normalizeResolvedSecretInputString,
|
||||||
|
parseOptionalDelimitedEntries,
|
||||||
} from "openclaw/plugin-sdk/irc";
|
} from "openclaw/plugin-sdk/irc";
|
||||||
import type { CoreConfig, IrcAccountConfig, IrcNickServConfig } from "./types.js";
|
import type { CoreConfig, IrcAccountConfig, IrcNickServConfig } from "./types.js";
|
||||||
|
|
||||||
|
|
@ -42,17 +43,6 @@ function parseIntEnv(value?: string): number | undefined {
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseListEnv(value?: string): string[] | undefined {
|
|
||||||
if (!value?.trim()) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
const parsed = value
|
|
||||||
.split(/[\n,;]+/g)
|
|
||||||
.map((entry) => entry.trim())
|
|
||||||
.filter(Boolean);
|
|
||||||
return parsed.length > 0 ? parsed : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { listAccountIds: listIrcAccountIds, resolveDefaultAccountId: resolveDefaultIrcAccountId } =
|
const { listAccountIds: listIrcAccountIds, resolveDefaultAccountId: resolveDefaultIrcAccountId } =
|
||||||
createAccountListHelpers("irc", { normalizeAccountId });
|
createAccountListHelpers("irc", { normalizeAccountId });
|
||||||
export { listIrcAccountIds, resolveDefaultIrcAccountId };
|
export { listIrcAccountIds, resolveDefaultIrcAccountId };
|
||||||
|
|
@ -174,7 +164,9 @@ export function resolveIrcAccount(params: {
|
||||||
accountId === DEFAULT_ACCOUNT_ID ? parseIntEnv(process.env.IRC_PORT) : undefined;
|
accountId === DEFAULT_ACCOUNT_ID ? parseIntEnv(process.env.IRC_PORT) : undefined;
|
||||||
const port = merged.port ?? envPort ?? (tls ? 6697 : 6667);
|
const port = merged.port ?? envPort ?? (tls ? 6697 : 6667);
|
||||||
const envChannels =
|
const envChannels =
|
||||||
accountId === DEFAULT_ACCOUNT_ID ? parseListEnv(process.env.IRC_CHANNELS) : undefined;
|
accountId === DEFAULT_ACCOUNT_ID
|
||||||
|
? parseOptionalDelimitedEntries(process.env.IRC_CHANNELS)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const host = (
|
const host = (
|
||||||
merged.host?.trim() ||
|
merged.host?.trim() ||
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import type { OpenClawConfig } from "../../config/config.js";
|
import type { OpenClawConfig } from "../../config/config.js";
|
||||||
import { buildAccountScopedDmSecurityPolicy, formatPairingApproveHint } from "./helpers.js";
|
import {
|
||||||
|
buildAccountScopedDmSecurityPolicy,
|
||||||
|
formatPairingApproveHint,
|
||||||
|
parseOptionalDelimitedEntries,
|
||||||
|
} from "./helpers.js";
|
||||||
|
|
||||||
function cfgWithChannel(channelKey: string, accounts?: Record<string, unknown>): OpenClawConfig {
|
function cfgWithChannel(channelKey: string, accounts?: Record<string, unknown>): OpenClawConfig {
|
||||||
return {
|
return {
|
||||||
|
|
@ -93,3 +97,18 @@ describe("buildAccountScopedDmSecurityPolicy", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("parseOptionalDelimitedEntries", () => {
|
||||||
|
it("returns undefined for empty input", () => {
|
||||||
|
expect(parseOptionalDelimitedEntries(" ")).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("splits comma, newline, and semicolon separated entries", () => {
|
||||||
|
expect(parseOptionalDelimitedEntries("alpha, beta\ngamma; delta")).toEqual([
|
||||||
|
"alpha",
|
||||||
|
"beta",
|
||||||
|
"gamma",
|
||||||
|
"delta",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,17 @@ export function formatPairingApproveHint(channelId: string): string {
|
||||||
return `Approve via: ${listCmd} / ${approveCmd}`;
|
return `Approve via: ${listCmd} / ${approveCmd}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function parseOptionalDelimitedEntries(value?: string): string[] | undefined {
|
||||||
|
if (!value?.trim()) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const parsed = value
|
||||||
|
.split(/[\n,;]+/g)
|
||||||
|
.map((entry) => entry.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
return parsed.length > 0 ? parsed : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export function buildAccountScopedDmSecurityPolicy(params: {
|
export function buildAccountScopedDmSecurityPolicy(params: {
|
||||||
cfg: OpenClawConfig;
|
cfg: OpenClawConfig;
|
||||||
channelKey: string;
|
channelKey: string;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/agent-scope.js";
|
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/agent-scope.js";
|
||||||
import { listChannelPluginCatalogEntries } from "../../channels/plugins/catalog.js";
|
import { listChannelPluginCatalogEntries } from "../../channels/plugins/catalog.js";
|
||||||
|
import { parseOptionalDelimitedEntries } from "../../channels/plugins/helpers.js";
|
||||||
import { getChannelPlugin, normalizeChannelId } from "../../channels/plugins/index.js";
|
import { getChannelPlugin, normalizeChannelId } from "../../channels/plugins/index.js";
|
||||||
import { moveSingleAccountChannelSectionToDefaultAccount } from "../../channels/plugins/setup-helpers.js";
|
import { moveSingleAccountChannelSectionToDefaultAccount } from "../../channels/plugins/setup-helpers.js";
|
||||||
import type { ChannelId, ChannelSetupInput } from "../../channels/plugins/types.js";
|
import type { ChannelId, ChannelSetupInput } from "../../channels/plugins/types.js";
|
||||||
|
|
@ -28,17 +29,6 @@ export type ChannelsAddOptions = {
|
||||||
dmAllowlist?: string;
|
dmAllowlist?: string;
|
||||||
} & Omit<ChannelSetupInput, "groupChannels" | "dmAllowlist" | "initialSyncLimit">;
|
} & Omit<ChannelSetupInput, "groupChannels" | "dmAllowlist" | "initialSyncLimit">;
|
||||||
|
|
||||||
function parseList(value: string | undefined): string[] | undefined {
|
|
||||||
if (!value?.trim()) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
const parsed = value
|
|
||||||
.split(/[\n,;]+/g)
|
|
||||||
.map((entry) => entry.trim())
|
|
||||||
.filter(Boolean);
|
|
||||||
return parsed.length > 0 ? parsed : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveCatalogChannelEntry(raw: string, cfg: OpenClawConfig | null) {
|
function resolveCatalogChannelEntry(raw: string, cfg: OpenClawConfig | null) {
|
||||||
const trimmed = raw.trim().toLowerCase();
|
const trimmed = raw.trim().toLowerCase();
|
||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
|
|
@ -225,8 +215,8 @@ export async function channelsAddCommand(
|
||||||
: typeof opts.initialSyncLimit === "string" && opts.initialSyncLimit.trim()
|
: typeof opts.initialSyncLimit === "string" && opts.initialSyncLimit.trim()
|
||||||
? Number.parseInt(opts.initialSyncLimit, 10)
|
? Number.parseInt(opts.initialSyncLimit, 10)
|
||||||
: undefined;
|
: undefined;
|
||||||
const groupChannels = parseList(opts.groupChannels);
|
const groupChannels = parseOptionalDelimitedEntries(opts.groupChannels);
|
||||||
const dmAllowlist = parseList(opts.dmAllowlist);
|
const dmAllowlist = parseOptionalDelimitedEntries(opts.dmAllowlist);
|
||||||
|
|
||||||
const input: ChannelSetupInput = {
|
const input: ChannelSetupInput = {
|
||||||
name: opts.name,
|
name: opts.name,
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,10 @@ export {
|
||||||
} from "../channels/plugins/config-helpers.js";
|
} from "../channels/plugins/config-helpers.js";
|
||||||
export { createAccountListHelpers } from "../channels/plugins/account-helpers.js";
|
export { createAccountListHelpers } from "../channels/plugins/account-helpers.js";
|
||||||
export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
||||||
export { formatPairingApproveHint } from "../channels/plugins/helpers.js";
|
export {
|
||||||
|
formatPairingApproveHint,
|
||||||
|
parseOptionalDelimitedEntries,
|
||||||
|
} from "../channels/plugins/helpers.js";
|
||||||
export type {
|
export type {
|
||||||
ChannelOnboardingAdapter,
|
ChannelOnboardingAdapter,
|
||||||
ChannelOnboardingDmPolicy,
|
ChannelOnboardingDmPolicy,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue