mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-19 05:50:47 +00:00
203 lines
6.7 KiB
TypeScript
203 lines
6.7 KiB
TypeScript
import { resolveLineAccount } from "openclaw/plugin-sdk/line";
|
|
import {
|
|
DEFAULT_ACCOUNT_ID,
|
|
formatDocsLink,
|
|
setSetupChannelEnabled,
|
|
setTopLevelChannelDmPolicyWithAllowFrom,
|
|
splitSetupEntries,
|
|
type ChannelSetupDmPolicy,
|
|
type ChannelSetupWizard,
|
|
} from "openclaw/plugin-sdk/setup";
|
|
import {
|
|
isLineConfigured,
|
|
listLineAccountIds,
|
|
parseLineAllowFromId,
|
|
patchLineAccountConfig,
|
|
} from "./setup-core.js";
|
|
|
|
const channel = "line" as const;
|
|
|
|
const LINE_SETUP_HELP_LINES = [
|
|
"1) Open the LINE Developers Console and create or pick a Messaging API channel",
|
|
"2) Copy the channel access token and channel secret",
|
|
"3) Enable Use webhook in the Messaging API settings",
|
|
"4) Point the webhook at https://<gateway-host>/line/webhook",
|
|
`Docs: ${formatDocsLink("/channels/line", "channels/line")}`,
|
|
];
|
|
|
|
const LINE_ALLOW_FROM_HELP_LINES = [
|
|
"Allowlist LINE DMs by user id.",
|
|
"LINE ids are case-sensitive.",
|
|
"Examples:",
|
|
"- U1234567890abcdef1234567890abcdef",
|
|
"- line:user:U1234567890abcdef1234567890abcdef",
|
|
"Multiple entries: comma-separated.",
|
|
`Docs: ${formatDocsLink("/channels/line", "channels/line")}`,
|
|
];
|
|
|
|
const lineDmPolicy: ChannelSetupDmPolicy = {
|
|
label: "LINE",
|
|
channel,
|
|
policyKey: "channels.line.dmPolicy",
|
|
allowFromKey: "channels.line.allowFrom",
|
|
getCurrent: (cfg) => cfg.channels?.line?.dmPolicy ?? "pairing",
|
|
setPolicy: (cfg, policy) =>
|
|
setTopLevelChannelDmPolicyWithAllowFrom({
|
|
cfg,
|
|
channel,
|
|
dmPolicy: policy,
|
|
}),
|
|
};
|
|
|
|
export { lineSetupAdapter } from "./setup-core.js";
|
|
|
|
export const lineSetupWizard: ChannelSetupWizard = {
|
|
channel,
|
|
status: {
|
|
configuredLabel: "configured",
|
|
unconfiguredLabel: "needs token + secret",
|
|
configuredHint: "configured",
|
|
unconfiguredHint: "needs token + secret",
|
|
configuredScore: 1,
|
|
unconfiguredScore: 0,
|
|
resolveConfigured: ({ cfg }) =>
|
|
listLineAccountIds(cfg).some((accountId) => isLineConfigured(cfg, accountId)),
|
|
resolveStatusLines: ({ cfg, configured }) => [
|
|
`LINE: ${configured ? "configured" : "needs token + secret"}`,
|
|
`Accounts: ${listLineAccountIds(cfg).length || 0}`,
|
|
],
|
|
},
|
|
introNote: {
|
|
title: "LINE Messaging API",
|
|
lines: LINE_SETUP_HELP_LINES,
|
|
shouldShow: ({ cfg, accountId }) => !isLineConfigured(cfg, accountId),
|
|
},
|
|
credentials: [
|
|
{
|
|
inputKey: "token",
|
|
providerHint: channel,
|
|
credentialLabel: "channel access token",
|
|
preferredEnvVar: "LINE_CHANNEL_ACCESS_TOKEN",
|
|
helpTitle: "LINE Messaging API",
|
|
helpLines: LINE_SETUP_HELP_LINES,
|
|
envPrompt: "LINE_CHANNEL_ACCESS_TOKEN detected. Use env var?",
|
|
keepPrompt: "LINE channel access token already configured. Keep it?",
|
|
inputPrompt: "Enter LINE channel access token",
|
|
allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID,
|
|
inspect: ({ cfg, accountId }) => {
|
|
const resolved = resolveLineAccount({ cfg, accountId });
|
|
return {
|
|
accountConfigured: Boolean(
|
|
resolved.channelAccessToken.trim() && resolved.channelSecret.trim(),
|
|
),
|
|
hasConfiguredValue: Boolean(
|
|
resolved.config.channelAccessToken?.trim() || resolved.config.tokenFile?.trim(),
|
|
),
|
|
resolvedValue: resolved.channelAccessToken.trim() || undefined,
|
|
envValue:
|
|
accountId === DEFAULT_ACCOUNT_ID
|
|
? process.env.LINE_CHANNEL_ACCESS_TOKEN?.trim() || undefined
|
|
: undefined,
|
|
};
|
|
},
|
|
applyUseEnv: ({ cfg, accountId }) =>
|
|
patchLineAccountConfig({
|
|
cfg,
|
|
accountId,
|
|
enabled: true,
|
|
clearFields: ["channelAccessToken", "tokenFile"],
|
|
patch: {},
|
|
}),
|
|
applySet: ({ cfg, accountId, resolvedValue }) =>
|
|
patchLineAccountConfig({
|
|
cfg,
|
|
accountId,
|
|
enabled: true,
|
|
clearFields: ["tokenFile"],
|
|
patch: { channelAccessToken: resolvedValue },
|
|
}),
|
|
},
|
|
{
|
|
inputKey: "password",
|
|
providerHint: "line-secret",
|
|
credentialLabel: "channel secret",
|
|
preferredEnvVar: "LINE_CHANNEL_SECRET",
|
|
helpTitle: "LINE Messaging API",
|
|
helpLines: LINE_SETUP_HELP_LINES,
|
|
envPrompt: "LINE_CHANNEL_SECRET detected. Use env var?",
|
|
keepPrompt: "LINE channel secret already configured. Keep it?",
|
|
inputPrompt: "Enter LINE channel secret",
|
|
allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID,
|
|
inspect: ({ cfg, accountId }) => {
|
|
const resolved = resolveLineAccount({ cfg, accountId });
|
|
return {
|
|
accountConfigured: Boolean(
|
|
resolved.channelAccessToken.trim() && resolved.channelSecret.trim(),
|
|
),
|
|
hasConfiguredValue: Boolean(
|
|
resolved.config.channelSecret?.trim() || resolved.config.secretFile?.trim(),
|
|
),
|
|
resolvedValue: resolved.channelSecret.trim() || undefined,
|
|
envValue:
|
|
accountId === DEFAULT_ACCOUNT_ID
|
|
? process.env.LINE_CHANNEL_SECRET?.trim() || undefined
|
|
: undefined,
|
|
};
|
|
},
|
|
applyUseEnv: ({ cfg, accountId }) =>
|
|
patchLineAccountConfig({
|
|
cfg,
|
|
accountId,
|
|
enabled: true,
|
|
clearFields: ["channelSecret", "secretFile"],
|
|
patch: {},
|
|
}),
|
|
applySet: ({ cfg, accountId, resolvedValue }) =>
|
|
patchLineAccountConfig({
|
|
cfg,
|
|
accountId,
|
|
enabled: true,
|
|
clearFields: ["secretFile"],
|
|
patch: { channelSecret: resolvedValue },
|
|
}),
|
|
},
|
|
],
|
|
allowFrom: {
|
|
helpTitle: "LINE allowlist",
|
|
helpLines: LINE_ALLOW_FROM_HELP_LINES,
|
|
message: "LINE allowFrom (user id)",
|
|
placeholder: "U1234567890abcdef1234567890abcdef",
|
|
invalidWithoutCredentialNote:
|
|
"LINE allowFrom requires raw user ids like U1234567890abcdef1234567890abcdef.",
|
|
parseInputs: splitSetupEntries,
|
|
parseId: parseLineAllowFromId,
|
|
resolveEntries: async ({ entries }) =>
|
|
entries.map((entry) => {
|
|
const id = parseLineAllowFromId(entry);
|
|
return {
|
|
input: entry,
|
|
resolved: Boolean(id),
|
|
id,
|
|
};
|
|
}),
|
|
apply: ({ cfg, accountId, allowFrom }) =>
|
|
patchLineAccountConfig({
|
|
cfg,
|
|
accountId,
|
|
enabled: true,
|
|
patch: { dmPolicy: "allowlist", allowFrom },
|
|
}),
|
|
},
|
|
dmPolicy: lineDmPolicy,
|
|
completionNote: {
|
|
title: "LINE webhook",
|
|
lines: [
|
|
"Enable Use webhook in the LINE console after saving credentials.",
|
|
"Default webhook URL: https://<gateway-host>/line/webhook",
|
|
"If you set channels.line.webhookPath, update the URL to match.",
|
|
`Docs: ${formatDocsLink("/channels/line", "channels/line")}`,
|
|
],
|
|
},
|
|
disable: (cfg) => setSetupChannelEnabled(cfg, channel, false),
|
|
};
|