@openclaw/line 2026.5.2-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api.ts +11 -0
- package/channel-plugin-api.ts +1 -0
- package/contract-api.ts +5 -0
- package/index.ts +54 -0
- package/openclaw.plugin.json +342 -0
- package/package.json +58 -0
- package/runtime-api.ts +187 -0
- package/secret-contract-api.ts +4 -0
- package/setup-api.ts +2 -0
- package/setup-entry.ts +9 -0
- package/src/account-helpers.ts +16 -0
- package/src/accounts.test.ts +290 -0
- package/src/accounts.ts +187 -0
- package/src/actions.ts +61 -0
- package/src/auto-reply-delivery.test.ts +248 -0
- package/src/auto-reply-delivery.ts +200 -0
- package/src/bindings.ts +65 -0
- package/src/bot-access.ts +48 -0
- package/src/bot-handlers.test.ts +1089 -0
- package/src/bot-handlers.ts +642 -0
- package/src/bot-message-context.test.ts +405 -0
- package/src/bot-message-context.ts +581 -0
- package/src/bot.ts +70 -0
- package/src/card-command.ts +347 -0
- package/src/channel-access-token.ts +14 -0
- package/src/channel-api.ts +17 -0
- package/src/channel-setup-status.contract.test.ts +70 -0
- package/src/channel-shared.ts +48 -0
- package/src/channel.logout.test.ts +145 -0
- package/src/channel.runtime.ts +3 -0
- package/src/channel.sendPayload.test.ts +514 -0
- package/src/channel.setup.ts +11 -0
- package/src/channel.status.test.ts +63 -0
- package/src/channel.ts +154 -0
- package/src/config-adapter.ts +29 -0
- package/src/config-schema.ts +57 -0
- package/src/download.test.ts +133 -0
- package/src/download.ts +87 -0
- package/src/flex-templates/basic-cards.ts +395 -0
- package/src/flex-templates/common.ts +20 -0
- package/src/flex-templates/media-control-cards.ts +555 -0
- package/src/flex-templates/message.ts +13 -0
- package/src/flex-templates/schedule-cards.ts +467 -0
- package/src/flex-templates/types.ts +22 -0
- package/src/flex-templates.ts +32 -0
- package/src/gateway.ts +129 -0
- package/src/group-keys.test.ts +123 -0
- package/src/group-keys.ts +65 -0
- package/src/group-policy.ts +22 -0
- package/src/markdown-to-line.test.ts +348 -0
- package/src/markdown-to-line.ts +416 -0
- package/src/message-cards.test.ts +204 -0
- package/src/monitor.lifecycle.test.ts +421 -0
- package/src/monitor.runtime.ts +1 -0
- package/src/monitor.ts +506 -0
- package/src/outbound-media.test.ts +189 -0
- package/src/outbound-media.ts +120 -0
- package/src/outbound.runtime.ts +12 -0
- package/src/outbound.ts +356 -0
- package/src/probe.contract.test.ts +9 -0
- package/src/probe.runtime.ts +1 -0
- package/src/probe.ts +34 -0
- package/src/quick-reply-fallback.ts +10 -0
- package/src/reply-chunks.test.ts +179 -0
- package/src/reply-chunks.ts +110 -0
- package/src/reply-payload-transform.test.ts +387 -0
- package/src/reply-payload-transform.ts +317 -0
- package/src/rich-menu.test.ts +310 -0
- package/src/rich-menu.ts +326 -0
- package/src/runtime.ts +32 -0
- package/src/send.test.ts +346 -0
- package/src/send.ts +489 -0
- package/src/setup-core.ts +149 -0
- package/src/setup-runtime-api.ts +9 -0
- package/src/setup-surface.test.ts +474 -0
- package/src/setup-surface.ts +227 -0
- package/src/signature.test.ts +34 -0
- package/src/signature.ts +24 -0
- package/src/status.ts +37 -0
- package/src/template-messages.ts +333 -0
- package/src/types.ts +128 -0
- package/src/webhook-node.test.ts +513 -0
- package/src/webhook-node.ts +131 -0
- package/src/webhook-utils.ts +10 -0
- package/src/webhook.ts +111 -0
- package/tsconfig.json +16 -0
package/src/webhook.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { webhook } from "@line/bot-sdk";
|
|
2
|
+
import type { NextFunction, Request, Response } from "express";
|
|
3
|
+
import { danger, logVerbose, type RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
|
|
4
|
+
import { parseLineWebhookBody, validateLineSignature } from "./webhook-utils.js";
|
|
5
|
+
|
|
6
|
+
const LINE_WEBHOOK_MAX_RAW_BODY_BYTES = 64 * 1024;
|
|
7
|
+
|
|
8
|
+
export interface LineWebhookOptions {
|
|
9
|
+
channelSecret: string;
|
|
10
|
+
onEvents: (body: webhook.CallbackRequest) => Promise<void>;
|
|
11
|
+
runtime?: RuntimeEnv;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function readRawBody(req: Request): string | null {
|
|
15
|
+
const rawBody =
|
|
16
|
+
(req as { rawBody?: string | Buffer }).rawBody ??
|
|
17
|
+
(typeof req.body === "string" || Buffer.isBuffer(req.body) ? req.body : null);
|
|
18
|
+
if (!rawBody) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return Buffer.isBuffer(rawBody) ? rawBody.toString("utf-8") : rawBody;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function parseWebhookBody(rawBody?: string | null): webhook.CallbackRequest | null {
|
|
25
|
+
if (!rawBody) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return parseLineWebhookBody(rawBody);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function createLineWebhookMiddleware(
|
|
32
|
+
options: LineWebhookOptions,
|
|
33
|
+
): (req: Request, res: Response, _next: NextFunction) => Promise<void> {
|
|
34
|
+
const { channelSecret, onEvents, runtime } = options;
|
|
35
|
+
|
|
36
|
+
return async (req: Request, res: Response, _next: NextFunction): Promise<void> => {
|
|
37
|
+
try {
|
|
38
|
+
const signature = req.headers["x-line-signature"];
|
|
39
|
+
|
|
40
|
+
if (!signature || typeof signature !== "string") {
|
|
41
|
+
res.status(400).json({ error: "Missing X-Line-Signature header" });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const rawBody = readRawBody(req);
|
|
46
|
+
|
|
47
|
+
if (!rawBody) {
|
|
48
|
+
res.status(400).json({ error: "Missing raw request body for signature verification" });
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (Buffer.byteLength(rawBody, "utf-8") > LINE_WEBHOOK_MAX_RAW_BODY_BYTES) {
|
|
52
|
+
res.status(413).json({ error: "Payload too large" });
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!validateLineSignature(rawBody, signature, channelSecret)) {
|
|
57
|
+
logVerbose("line: webhook signature validation failed");
|
|
58
|
+
res.status(401).json({ error: "Invalid signature" });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const body = parseWebhookBody(rawBody);
|
|
63
|
+
|
|
64
|
+
if (!body) {
|
|
65
|
+
res.status(400).json({ error: "Invalid webhook payload" });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (body.events && body.events.length > 0) {
|
|
70
|
+
logVerbose(`line: received ${body.events.length} webhook events`);
|
|
71
|
+
await onEvents(body);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
res.status(200).json({ status: "ok" });
|
|
75
|
+
} catch (err) {
|
|
76
|
+
runtime?.error?.(danger(`line webhook error: ${String(err)}`));
|
|
77
|
+
if (!res.headersSent) {
|
|
78
|
+
res.status(500).json({ error: "Internal server error" });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface StartLineWebhookOptions {
|
|
85
|
+
channelSecret: string;
|
|
86
|
+
onEvents: (body: webhook.CallbackRequest) => Promise<void>;
|
|
87
|
+
runtime?: RuntimeEnv;
|
|
88
|
+
path?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function startLineWebhook(options: StartLineWebhookOptions): {
|
|
92
|
+
path: string;
|
|
93
|
+
handler: (req: Request, res: Response, _next: NextFunction) => Promise<void>;
|
|
94
|
+
} {
|
|
95
|
+
const channelSecret =
|
|
96
|
+
typeof options.channelSecret === "string" ? options.channelSecret.trim() : "";
|
|
97
|
+
if (!channelSecret) {
|
|
98
|
+
throw new Error(
|
|
99
|
+
"LINE webhook mode requires a non-empty channel secret. " +
|
|
100
|
+
"Set channels.line.channelSecret in your config.",
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
const path = options.path ?? "/line/webhook";
|
|
104
|
+
const middleware = createLineWebhookMiddleware({
|
|
105
|
+
channelSecret,
|
|
106
|
+
onEvents: options.onEvents,
|
|
107
|
+
runtime: options.runtime,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
return { path, handler: middleware };
|
|
111
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../tsconfig.package-boundary.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"rootDir": "."
|
|
5
|
+
},
|
|
6
|
+
"include": ["./*.ts", "./src/**/*.ts"],
|
|
7
|
+
"exclude": [
|
|
8
|
+
"./**/*.test.ts",
|
|
9
|
+
"./dist/**",
|
|
10
|
+
"./node_modules/**",
|
|
11
|
+
"./src/test-support/**",
|
|
12
|
+
"./src/**/*test-helpers.ts",
|
|
13
|
+
"./src/**/*test-harness.ts",
|
|
14
|
+
"./src/**/*test-support.ts"
|
|
15
|
+
]
|
|
16
|
+
}
|