mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 05:47:28 +00:00
refactor: dedupe discord account inspect config merge
This commit is contained in:
126
src/discord/account-inspect.test.ts
Normal file
126
src/discord/account-inspect.test.ts
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import type { OpenClawConfig } from "../config/config.js";
|
||||||
|
import { inspectDiscordAccount } from "./account-inspect.js";
|
||||||
|
|
||||||
|
function asConfig(value: unknown): OpenClawConfig {
|
||||||
|
return value as OpenClawConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("inspectDiscordAccount", () => {
|
||||||
|
it("prefers account token over channel token and strips Bot prefix", () => {
|
||||||
|
const inspected = inspectDiscordAccount({
|
||||||
|
cfg: asConfig({
|
||||||
|
channels: {
|
||||||
|
discord: {
|
||||||
|
token: "Bot channel-token",
|
||||||
|
accounts: {
|
||||||
|
work: {
|
||||||
|
token: "Bot account-token",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
accountId: "work",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(inspected.token).toBe("account-token");
|
||||||
|
expect(inspected.tokenSource).toBe("config");
|
||||||
|
expect(inspected.tokenStatus).toBe("available");
|
||||||
|
expect(inspected.configured).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reports configured_unavailable for unresolved configured secret input", () => {
|
||||||
|
const inspected = inspectDiscordAccount({
|
||||||
|
cfg: asConfig({
|
||||||
|
channels: {
|
||||||
|
discord: {
|
||||||
|
accounts: {
|
||||||
|
work: {
|
||||||
|
token: { source: "env", id: "DISCORD_TOKEN" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
accountId: "work",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(inspected.token).toBe("");
|
||||||
|
expect(inspected.tokenSource).toBe("config");
|
||||||
|
expect(inspected.tokenStatus).toBe("configured_unavailable");
|
||||||
|
expect(inspected.configured).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not fall back when account token key exists but is missing", () => {
|
||||||
|
const inspected = inspectDiscordAccount({
|
||||||
|
cfg: asConfig({
|
||||||
|
channels: {
|
||||||
|
discord: {
|
||||||
|
token: "Bot channel-token",
|
||||||
|
accounts: {
|
||||||
|
work: {
|
||||||
|
token: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
accountId: "work",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(inspected.token).toBe("");
|
||||||
|
expect(inspected.tokenSource).toBe("none");
|
||||||
|
expect(inspected.tokenStatus).toBe("missing");
|
||||||
|
expect(inspected.configured).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("falls back to channel token when account token is absent", () => {
|
||||||
|
const inspected = inspectDiscordAccount({
|
||||||
|
cfg: asConfig({
|
||||||
|
channels: {
|
||||||
|
discord: {
|
||||||
|
token: "Bot channel-token",
|
||||||
|
accounts: {
|
||||||
|
work: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
accountId: "work",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(inspected.token).toBe("channel-token");
|
||||||
|
expect(inspected.tokenSource).toBe("config");
|
||||||
|
expect(inspected.tokenStatus).toBe("available");
|
||||||
|
expect(inspected.configured).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("allows env token only for default account", () => {
|
||||||
|
const defaultInspected = inspectDiscordAccount({
|
||||||
|
cfg: asConfig({}),
|
||||||
|
accountId: "default",
|
||||||
|
envToken: "Bot env-default",
|
||||||
|
});
|
||||||
|
const namedInspected = inspectDiscordAccount({
|
||||||
|
cfg: asConfig({
|
||||||
|
channels: {
|
||||||
|
discord: {
|
||||||
|
accounts: {
|
||||||
|
work: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
accountId: "work",
|
||||||
|
envToken: "Bot env-work",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(defaultInspected.token).toBe("env-default");
|
||||||
|
expect(defaultInspected.tokenSource).toBe("env");
|
||||||
|
expect(defaultInspected.configured).toBe(true);
|
||||||
|
expect(namedInspected.token).toBe("");
|
||||||
|
expect(namedInspected.tokenSource).toBe("none");
|
||||||
|
expect(namedInspected.configured).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
import type { OpenClawConfig } from "../config/config.js";
|
import type { OpenClawConfig } from "../config/config.js";
|
||||||
import type { DiscordAccountConfig } from "../config/types.discord.js";
|
import type { DiscordAccountConfig } from "../config/types.discord.js";
|
||||||
import { hasConfiguredSecretInput, normalizeSecretInputString } from "../config/types.secrets.js";
|
import { hasConfiguredSecretInput, normalizeSecretInputString } from "../config/types.secrets.js";
|
||||||
import { resolveAccountEntry } from "../routing/account-lookup.js";
|
|
||||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js";
|
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js";
|
||||||
import { resolveDefaultDiscordAccountId } from "./accounts.js";
|
import {
|
||||||
|
mergeDiscordAccountConfig,
|
||||||
|
resolveDefaultDiscordAccountId,
|
||||||
|
resolveDiscordAccountConfig,
|
||||||
|
} from "./accounts.js";
|
||||||
|
|
||||||
export type DiscordCredentialStatus = "available" | "configured_unavailable" | "missing";
|
export type DiscordCredentialStatus = "available" | "configured_unavailable" | "missing";
|
||||||
|
|
||||||
@@ -18,21 +21,6 @@ export type InspectedDiscordAccount = {
|
|||||||
config: DiscordAccountConfig;
|
config: DiscordAccountConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
function resolveDiscordAccountConfig(
|
|
||||||
cfg: OpenClawConfig,
|
|
||||||
accountId: string,
|
|
||||||
): DiscordAccountConfig | undefined {
|
|
||||||
return resolveAccountEntry(cfg.channels?.discord?.accounts, accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
function mergeDiscordAccountConfig(cfg: OpenClawConfig, accountId: string): DiscordAccountConfig {
|
|
||||||
const { accounts: _ignored, ...base } = (cfg.channels?.discord ?? {}) as DiscordAccountConfig & {
|
|
||||||
accounts?: unknown;
|
|
||||||
};
|
|
||||||
const account = resolveDiscordAccountConfig(cfg, accountId) ?? {};
|
|
||||||
return { ...base, ...account };
|
|
||||||
}
|
|
||||||
|
|
||||||
function inspectDiscordTokenValue(value: unknown): {
|
function inspectDiscordTokenValue(value: unknown): {
|
||||||
token: string;
|
token: string;
|
||||||
tokenSource: "config";
|
tokenSource: "config";
|
||||||
|
|||||||
@@ -19,18 +19,21 @@ const { listAccountIds, resolveDefaultAccountId } = createAccountListHelpers("di
|
|||||||
export const listDiscordAccountIds = listAccountIds;
|
export const listDiscordAccountIds = listAccountIds;
|
||||||
export const resolveDefaultDiscordAccountId = resolveDefaultAccountId;
|
export const resolveDefaultDiscordAccountId = resolveDefaultAccountId;
|
||||||
|
|
||||||
function resolveAccountConfig(
|
export function resolveDiscordAccountConfig(
|
||||||
cfg: OpenClawConfig,
|
cfg: OpenClawConfig,
|
||||||
accountId: string,
|
accountId: string,
|
||||||
): DiscordAccountConfig | undefined {
|
): DiscordAccountConfig | undefined {
|
||||||
return resolveAccountEntry(cfg.channels?.discord?.accounts, accountId);
|
return resolveAccountEntry(cfg.channels?.discord?.accounts, accountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeDiscordAccountConfig(cfg: OpenClawConfig, accountId: string): DiscordAccountConfig {
|
export function mergeDiscordAccountConfig(
|
||||||
|
cfg: OpenClawConfig,
|
||||||
|
accountId: string,
|
||||||
|
): DiscordAccountConfig {
|
||||||
const { accounts: _ignored, ...base } = (cfg.channels?.discord ?? {}) as DiscordAccountConfig & {
|
const { accounts: _ignored, ...base } = (cfg.channels?.discord ?? {}) as DiscordAccountConfig & {
|
||||||
accounts?: unknown;
|
accounts?: unknown;
|
||||||
};
|
};
|
||||||
const account = resolveAccountConfig(cfg, accountId) ?? {};
|
const account = resolveDiscordAccountConfig(cfg, accountId) ?? {};
|
||||||
return { ...base, ...account };
|
return { ...base, ...account };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +44,7 @@ export function createDiscordActionGate(params: {
|
|||||||
const accountId = normalizeAccountId(params.accountId);
|
const accountId = normalizeAccountId(params.accountId);
|
||||||
return createAccountActionGate({
|
return createAccountActionGate({
|
||||||
baseActions: params.cfg.channels?.discord?.actions,
|
baseActions: params.cfg.channels?.discord?.actions,
|
||||||
accountActions: resolveAccountConfig(params.cfg, accountId)?.actions,
|
accountActions: resolveDiscordAccountConfig(params.cfg, accountId)?.actions,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user