mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-07 15:21:06 +00:00
138 lines
4.4 KiB
TypeScript
138 lines
4.4 KiB
TypeScript
import { RequestClient } from "@buape/carbon";
|
|
import { loadConfig } from "openclaw/plugin-sdk/config-runtime";
|
|
import type { RetryConfig, RetryRunner } from "openclaw/plugin-sdk/retry-runtime";
|
|
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
|
|
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
|
|
import {
|
|
mergeDiscordAccountConfig,
|
|
resolveDiscordAccount,
|
|
type ResolvedDiscordAccount,
|
|
} from "./accounts.js";
|
|
import { resolveDiscordProxyFetchForAccount } from "./proxy-fetch.js";
|
|
import { createDiscordRetryRunner } from "./retry.js";
|
|
import type { DiscordRuntimeAccountContext } from "./send.types.js";
|
|
import { normalizeDiscordToken } from "./token.js";
|
|
|
|
export type DiscordClientOpts = {
|
|
cfg?: ReturnType<typeof loadConfig>;
|
|
token?: string;
|
|
accountId?: string;
|
|
rest?: RequestClient;
|
|
retry?: RetryConfig;
|
|
verbose?: boolean;
|
|
};
|
|
|
|
export function createDiscordRuntimeAccountContext(params: {
|
|
cfg: ReturnType<typeof loadConfig>;
|
|
accountId: string;
|
|
}): DiscordRuntimeAccountContext {
|
|
return {
|
|
cfg: params.cfg,
|
|
accountId: normalizeAccountId(params.accountId),
|
|
};
|
|
}
|
|
|
|
export function resolveDiscordClientAccountContext(
|
|
opts: Pick<DiscordClientOpts, "cfg" | "accountId">,
|
|
cfg?: ReturnType<typeof loadConfig>,
|
|
runtime?: Pick<RuntimeEnv, "error">,
|
|
) {
|
|
const resolvedCfg = opts.cfg ?? cfg ?? loadConfig();
|
|
const account = resolveAccountWithoutToken({
|
|
cfg: resolvedCfg,
|
|
accountId: opts.accountId,
|
|
});
|
|
return {
|
|
cfg: resolvedCfg,
|
|
account,
|
|
proxyFetch: resolveDiscordProxyFetchForAccount(account, resolvedCfg, runtime),
|
|
};
|
|
}
|
|
|
|
function resolveToken(params: { accountId: string; fallbackToken?: string }) {
|
|
const fallback = normalizeDiscordToken(params.fallbackToken, "channels.discord.token");
|
|
if (!fallback) {
|
|
throw new Error(
|
|
`Discord bot token missing for account "${params.accountId}" (set discord.accounts.${params.accountId}.token or DISCORD_BOT_TOKEN for default).`,
|
|
);
|
|
}
|
|
return fallback;
|
|
}
|
|
|
|
export function resolveDiscordProxyFetch(
|
|
opts: Pick<DiscordClientOpts, "cfg" | "accountId">,
|
|
cfg?: ReturnType<typeof loadConfig>,
|
|
runtime?: Pick<RuntimeEnv, "error">,
|
|
): typeof fetch | undefined {
|
|
return resolveDiscordClientAccountContext(opts, cfg, runtime).proxyFetch;
|
|
}
|
|
|
|
function resolveRest(
|
|
token: string,
|
|
account: ResolvedDiscordAccount,
|
|
cfg: ReturnType<typeof loadConfig>,
|
|
rest?: RequestClient,
|
|
proxyFetch?: typeof fetch,
|
|
) {
|
|
if (rest) {
|
|
return rest;
|
|
}
|
|
const resolvedProxyFetch = proxyFetch ?? resolveDiscordProxyFetchForAccount(account, cfg);
|
|
return new RequestClient(token, resolvedProxyFetch ? { fetch: resolvedProxyFetch } : undefined);
|
|
}
|
|
|
|
function resolveAccountWithoutToken(params: {
|
|
cfg: ReturnType<typeof loadConfig>;
|
|
accountId?: string;
|
|
}): ResolvedDiscordAccount {
|
|
const accountId = normalizeAccountId(params.accountId);
|
|
const merged = mergeDiscordAccountConfig(params.cfg, accountId);
|
|
const baseEnabled = params.cfg.channels?.discord?.enabled !== false;
|
|
const accountEnabled = merged.enabled !== false;
|
|
return {
|
|
accountId,
|
|
enabled: baseEnabled && accountEnabled,
|
|
name: merged.name?.trim() || undefined,
|
|
token: "",
|
|
tokenSource: "none",
|
|
config: merged,
|
|
};
|
|
}
|
|
|
|
export function createDiscordRestClient(
|
|
opts: DiscordClientOpts,
|
|
cfg?: ReturnType<typeof loadConfig>,
|
|
) {
|
|
const explicitToken = normalizeDiscordToken(opts.token, "channels.discord.token");
|
|
const proxyContext = resolveDiscordClientAccountContext(opts, cfg);
|
|
const resolvedCfg = proxyContext.cfg;
|
|
const account = explicitToken
|
|
? proxyContext.account
|
|
: resolveDiscordAccount({ cfg: resolvedCfg, accountId: opts.accountId });
|
|
const token =
|
|
explicitToken ??
|
|
resolveToken({
|
|
accountId: account.accountId,
|
|
fallbackToken: account.token,
|
|
});
|
|
const rest = resolveRest(token, account, resolvedCfg, opts.rest, proxyContext.proxyFetch);
|
|
return { token, rest, account };
|
|
}
|
|
|
|
export function createDiscordClient(
|
|
opts: DiscordClientOpts,
|
|
cfg?: ReturnType<typeof loadConfig>,
|
|
): { token: string; rest: RequestClient; request: RetryRunner } {
|
|
const { token, rest, account } = createDiscordRestClient(opts, opts.cfg ?? cfg);
|
|
const request = createDiscordRetryRunner({
|
|
retry: opts.retry,
|
|
configRetry: account.config.retry,
|
|
verbose: opts.verbose,
|
|
});
|
|
return { token, rest, request };
|
|
}
|
|
|
|
export function resolveDiscordRest(opts: DiscordClientOpts) {
|
|
return createDiscordRestClient(opts, opts.cfg).rest;
|
|
}
|