openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
355 lines (354 loc) • 13.4 kB
JavaScript
import { t as formatCliCommand } from "./command-format-CKGmlpAQ.js";
import { t as formatDocsLink } from "./links-CsLBrRff.js";
import { l as normalizeStringEntries } from "./string-normalization-WNUDCpXX.js";
import { n as normalizeAccountId } from "./account-id-Df9e41E6.js";
import "./string-coerce-runtime-CEGJWkQ_.js";
import { l as patchScopedAccountConfig } from "./setup-helpers-DO5nSeNy.js";
import { t as createSetupTranslator } from "./i18n-7g_f4oaD.js";
import { t as addWildcardAllowFrom, v as mergeAllowFromEntries } from "./setup-wizard-helpers-Dv-t1nb8.js";
import { t as formatResolvedUnresolvedNote } from "./setup-DHfdBmUU.js";
import { a as listZalouserAccountIds, i as checkZcaAuthenticated, o as resolveDefaultZalouserAccountId, r as writeQrDataUrlToTempFile, s as resolveZalouserAccountSync } from "./setup-core-kty7gX4X.js";
import { b as waitForZaloQrLogin, c as logoutZaloProfile, d as resolveZaloGroupsByEntries, l as resolveZaloAllowFromEntries, y as startZaloQrLogin } from "./zalo-js-B1zE_Wyq.js";
//#region extensions/zalouser/src/setup-surface.ts
const t = createSetupTranslator();
const channel = "zalouser";
const ZALOUSER_ALLOW_FROM_PLACEHOLDER = t("wizard.zalouser.allowFromPlaceholder");
const ZALOUSER_GROUPS_PLACEHOLDER = t("wizard.zalouser.groupsPlaceholder");
const ZALOUSER_DM_ACCESS_TITLE = t("wizard.zalouser.dmAccessTitle");
const ZALOUSER_ALLOWLIST_TITLE = t("wizard.zalouser.allowlistTitle");
const ZALOUSER_GROUPS_TITLE = t("wizard.zalouser.groupsTitle");
function parseZalouserEntries(raw) {
return normalizeStringEntries(raw.split(/[\n,;]+/g));
}
function setZalouserAccountScopedConfig(cfg, accountId, defaultPatch, accountPatch = defaultPatch) {
return patchScopedAccountConfig({
cfg,
channelKey: channel,
accountId,
patch: defaultPatch,
accountPatch
});
}
function setZalouserDmPolicy(cfg, accountId, policy) {
const resolvedAccountId = normalizeAccountId(accountId) ?? "default";
const resolved = resolveZalouserAccountSync({
cfg,
accountId: resolvedAccountId
});
return setZalouserAccountScopedConfig(cfg, resolvedAccountId, {
dmPolicy: policy,
...policy === "open" ? { allowFrom: addWildcardAllowFrom(resolved.config.allowFrom) } : {}
}, {
dmPolicy: policy,
...policy === "open" ? { allowFrom: addWildcardAllowFrom(resolved.config.allowFrom) } : {}
});
}
function setZalouserGroupPolicy(cfg, accountId, groupPolicy) {
return setZalouserAccountScopedConfig(cfg, accountId, { groupPolicy });
}
function setZalouserGroupAllowlist(cfg, accountId, groupKeys) {
return setZalouserAccountScopedConfig(cfg, accountId, { groups: Object.fromEntries(groupKeys.map((key) => [key, {
enabled: true,
requireMention: true
}])) });
}
function ensureZalouserPluginEnabled(cfg) {
const next = {
...cfg,
plugins: {
...cfg.plugins,
entries: {
...cfg.plugins?.entries,
zalouser: {
...cfg.plugins?.entries?.zalouser,
enabled: true
}
}
}
};
const allow = next.plugins?.allow;
if (!Array.isArray(allow) || allow.includes(channel)) return next;
return {
...next,
plugins: {
...next.plugins,
allow: [...allow, channel]
}
};
}
async function noteZalouserHelp(prompter) {
await prompter.note([
t("wizard.zalouser.helpQrLogin"),
"",
t("wizard.zalouser.helpZcaJs"),
"",
`Docs: ${formatDocsLink("/channels/zalouser", "zalouser")}`
].join("\n"), t("wizard.zalouser.setupTitle"));
}
async function promptZalouserAllowFrom(params) {
const { cfg, prompter, accountId } = params;
const resolved = resolveZalouserAccountSync({
cfg,
accountId
});
const existingAllowFrom = resolved.config.allowFrom ?? [];
while (true) {
const parts = parseZalouserEntries(await prompter.text({
message: t("wizard.zalouser.allowFromPrompt"),
placeholder: ZALOUSER_ALLOW_FROM_PLACEHOLDER,
initialValue: existingAllowFrom.length > 0 ? existingAllowFrom.join(", ") : void 0
}));
if (parts.length === 0) {
await prompter.note([
t("wizard.zalouser.noDmAllowlist"),
t("wizard.zalouser.directChatsBlocked"),
t("wizard.zalouser.peersLookupTip", { command: formatCliCommand("openclaw directory peers list --channel zalouser") })
].join("\n"), ZALOUSER_ALLOWLIST_TITLE);
return setZalouserAccountScopedConfig(cfg, accountId, {
dmPolicy: "allowlist",
allowFrom: []
});
}
const resolvedEntries = await resolveZaloAllowFromEntries({
profile: resolved.profile,
entries: parts
});
const unresolved = resolvedEntries.filter((item) => !item.resolved).map((item) => item.input);
if (unresolved.length > 0) {
await prompter.note(t("wizard.zalouser.couldNotResolve", { entries: unresolved.join(", ") }), ZALOUSER_ALLOWLIST_TITLE);
continue;
}
const unique = mergeAllowFromEntries(existingAllowFrom, resolvedEntries.filter((item) => item.resolved && item.id).map((item) => item.id));
const notes = resolvedEntries.filter((item) => item.note).map((item) => `${item.input} -> ${item.id} (${item.note})`);
if (notes.length > 0) await prompter.note(notes.join("\n"), ZALOUSER_ALLOWLIST_TITLE);
return setZalouserAccountScopedConfig(cfg, accountId, {
dmPolicy: "allowlist",
allowFrom: unique
});
}
}
const zalouserDmPolicy = {
label: "Zalo Personal",
channel,
policyKey: "channels.zalouser.dmPolicy",
allowFromKey: "channels.zalouser.allowFrom",
resolveConfigKeys: (cfg, accountId) => (accountId ?? resolveDefaultZalouserAccountId(cfg)) !== "default" ? {
policyKey: `channels.zalouser.accounts.${accountId ?? resolveDefaultZalouserAccountId(cfg)}.dmPolicy`,
allowFromKey: `channels.zalouser.accounts.${accountId ?? resolveDefaultZalouserAccountId(cfg)}.allowFrom`
} : {
policyKey: "channels.zalouser.dmPolicy",
allowFromKey: "channels.zalouser.allowFrom"
},
getCurrent: (cfg, accountId) => resolveZalouserAccountSync({
cfg,
accountId: accountId ?? resolveDefaultZalouserAccountId(cfg)
}).config.dmPolicy ?? "pairing",
setPolicy: (cfg, policy, accountId) => setZalouserDmPolicy(cfg, accountId ?? resolveDefaultZalouserAccountId(cfg), policy),
promptAllowFrom: async ({ cfg, prompter, accountId }) => {
return await promptZalouserAllowFrom({
cfg,
prompter,
accountId: accountId && normalizeAccountId(accountId) ? normalizeAccountId(accountId) ?? "default" : resolveDefaultZalouserAccountId(cfg)
});
}
};
async function promptZalouserQuickstartDmPolicy(params) {
const { cfg, prompter, accountId } = params;
const resolved = resolveZalouserAccountSync({
cfg,
accountId
});
const existingPolicy = resolved.config.dmPolicy ?? "pairing";
const existingAllowFrom = resolved.config.allowFrom ?? [];
const existingLabel = existingAllowFrom.length > 0 ? existingAllowFrom.join(", ") : "unset";
await prompter.note([
t("wizard.zalouser.dmHelpSeparate"),
t("wizard.zalouser.dmHelpPairing"),
t("wizard.zalouser.dmHelpAllowlist"),
t("wizard.zalouser.dmHelpOpen"),
t("wizard.zalouser.dmHelpDisabled"),
"",
`Current: dmPolicy=${existingPolicy}, allowFrom=${existingLabel}`,
t("wizard.zalouser.dmHelpAllowlistEmpty")
].join("\n"), ZALOUSER_DM_ACCESS_TITLE);
const policy = await prompter.select({
message: t("wizard.zalouser.dmPolicyPrompt"),
options: [
{
value: "pairing",
label: t("wizard.channels.dmPolicyPairing")
},
{
value: "allowlist",
label: t("wizard.channels.dmPolicyAllowlistOption")
},
{
value: "open",
label: t("wizard.channels.dmPolicyOpenOption")
},
{
value: "disabled",
label: t("wizard.channels.dmPolicyDisabledOption")
}
],
initialValue: existingPolicy
});
if (policy === "allowlist") return await promptZalouserAllowFrom({
cfg,
prompter,
accountId
});
return setZalouserDmPolicy(cfg, accountId, policy);
}
const zalouserSetupWizard = {
channel,
status: {
configuredLabel: t("wizard.channels.statusLoggedIn"),
unconfiguredLabel: t("wizard.channels.statusNeedsQrLogin"),
configuredHint: t("wizard.channels.statusRecommendedLoggedIn"),
unconfiguredHint: t("wizard.channels.statusRecommendedQrLogin"),
configuredScore: 1,
unconfiguredScore: 15,
resolveConfigured: async ({ cfg, accountId }) => {
const ids = accountId ? [accountId] : listZalouserAccountIds(cfg);
for (const resolvedAccountId of ids) if (await checkZcaAuthenticated(resolveZalouserAccountSync({
cfg,
accountId: resolvedAccountId
}).profile)) return true;
return false;
},
resolveStatusLines: async ({ cfg, accountId, configured }) => {
return [`${accountId && accountId !== "default" ? `Zalo Personal (${accountId})` : "Zalo Personal"}: ${configured ? "logged in" : "needs QR login"}`];
}
},
prepare: async ({ cfg, accountId, prompter, options }) => {
let next = cfg;
const account = resolveZalouserAccountSync({
cfg: next,
accountId
});
if (!await checkZcaAuthenticated(account.profile)) {
await noteZalouserHelp(prompter);
if (await prompter.confirm({
message: t("wizard.zalouser.loginQrPrompt"),
initialValue: true
})) {
const start = await startZaloQrLogin({
profile: account.profile,
timeoutMs: 35e3
});
if (start.qrDataUrl) {
const qrPath = await writeQrDataUrlToTempFile(start.qrDataUrl, account.profile);
await prompter.note([
start.message,
qrPath ? t("wizard.zalouser.qrImageSaved", { path: qrPath }) : t("wizard.zalouser.qrImageWriteFailed"),
t("wizard.zalouser.scanApproveContinue")
].join("\n"), t("wizard.zalouser.qrLoginTitle"));
if (await prompter.confirm({
message: t("wizard.zalouser.qrScannedPrompt"),
initialValue: true
})) {
const waited = await waitForZaloQrLogin({
profile: account.profile,
timeoutMs: 12e4
});
await prompter.note(waited.message, waited.connected ? t("common.done") : t("wizard.zalouser.loginPendingTitle"));
}
} else await prompter.note(start.message, t("wizard.zalouser.loginPendingTitle"));
}
} else if (!await prompter.confirm({
message: t("wizard.zalouser.keepSessionPrompt"),
initialValue: true
})) {
await logoutZaloProfile(account.profile);
const start = await startZaloQrLogin({
profile: account.profile,
force: true,
timeoutMs: 35e3
});
if (start.qrDataUrl) {
const qrPath = await writeQrDataUrlToTempFile(start.qrDataUrl, account.profile);
await prompter.note([start.message, qrPath ? t("wizard.zalouser.qrImageSaved", { path: qrPath }) : void 0].filter(Boolean).join("\n"), t("wizard.zalouser.qrLoginTitle"));
const waited = await waitForZaloQrLogin({
profile: account.profile,
timeoutMs: 12e4
});
await prompter.note(waited.message, waited.connected ? t("common.done") : t("wizard.zalouser.loginPendingTitle"));
}
}
next = setZalouserAccountScopedConfig(next, accountId, { profile: account.profile !== "default" ? account.profile : void 0 }, {
profile: account.profile,
enabled: true
});
if (options?.quickstartDefaults) next = await promptZalouserQuickstartDmPolicy({
cfg: next,
prompter,
accountId
});
return { cfg: next };
},
credentials: [],
groupAccess: {
label: "Zalo groups",
placeholder: ZALOUSER_GROUPS_PLACEHOLDER,
currentPolicy: ({ cfg, accountId }) => resolveZalouserAccountSync({
cfg,
accountId
}).config.groupPolicy ?? "allowlist",
currentEntries: ({ cfg, accountId }) => Object.keys(resolveZalouserAccountSync({
cfg,
accountId
}).config.groups ?? {}),
updatePrompt: ({ cfg, accountId }) => Boolean(resolveZalouserAccountSync({
cfg,
accountId
}).config.groups),
setPolicy: ({ cfg, accountId, policy }) => setZalouserGroupPolicy(cfg, accountId, policy),
resolveAllowlist: async ({ cfg, accountId, entries, prompter }) => {
if (entries.length === 0) {
await prompter.note([
t("wizard.zalouser.noGroupAllowlist"),
t("wizard.zalouser.groupChatsBlocked"),
t("wizard.zalouser.groupsLookupTip", { command: formatCliCommand("openclaw directory groups list --channel zalouser") }),
t("wizard.zalouser.groupMentionRequirement")
].join("\n"), ZALOUSER_GROUPS_TITLE);
return [];
}
const updatedAccount = resolveZalouserAccountSync({
cfg,
accountId
});
try {
const resolved = await resolveZaloGroupsByEntries({
profile: updatedAccount.profile,
entries
});
const resolvedIds = resolved.filter((entry) => entry.resolved && entry.id).map((entry) => entry.id);
const unresolved = resolved.filter((entry) => !entry.resolved).map((entry) => entry.input);
const keys = [...resolvedIds, ...normalizeStringEntries(unresolved)];
const resolution = formatResolvedUnresolvedNote({
resolved: resolvedIds,
unresolved
});
if (resolution) await prompter.note(resolution, ZALOUSER_GROUPS_TITLE);
return keys;
} catch (err) {
await prompter.note(t("wizard.zalouser.groupLookupFailed", { error: String(err) }), ZALOUSER_GROUPS_TITLE);
return normalizeStringEntries(entries);
}
},
applyAllowlist: ({ cfg, accountId, resolved }) => setZalouserGroupAllowlist(cfg, accountId, resolved)
},
finalize: async ({ cfg, accountId, forceAllowFrom, options, prompter }) => {
let next = cfg;
if (forceAllowFrom && !options?.quickstartDefaults) next = await promptZalouserAllowFrom({
cfg: next,
prompter,
accountId
});
return { cfg: ensureZalouserPluginEnabled(next) };
},
dmPolicy: zalouserDmPolicy
};
//#endregion
export { zalouserSetupWizard as t };