Add LINE channel adapter with webhook ingress and gating
This commit is contained in:
@@ -35,6 +35,7 @@ function makeBaseConfig(): Config {
|
||||
teams: undefined,
|
||||
google_chat: undefined,
|
||||
bluebubbles: undefined,
|
||||
line: undefined,
|
||||
} as unknown as Config;
|
||||
}
|
||||
|
||||
@@ -53,6 +54,7 @@ describe('discoverServices', () => {
|
||||
expect.objectContaining({ name: 'teams', status: 'not_configured' }),
|
||||
expect.objectContaining({ name: 'google_chat', status: 'not_configured' }),
|
||||
expect.objectContaining({ name: 'bluebubbles', status: 'not_configured' }),
|
||||
expect.objectContaining({ name: 'line', status: 'not_configured' }),
|
||||
expect.objectContaining({ name: 'cron', status: 'not_configured' }),
|
||||
expect.objectContaining({ name: 'mcp', status: 'not_configured' }),
|
||||
expect.objectContaining({ name: 'web_search', status: 'configured' }),
|
||||
|
||||
@@ -58,6 +58,7 @@ export function discoverServices(
|
||||
{ key: 'teams', name: 'teams', description: 'Microsoft Teams bot' },
|
||||
{ key: 'google_chat', name: 'google_chat', description: 'Google Chat bot' },
|
||||
{ key: 'bluebubbles', name: 'bluebubbles', description: 'iMessage via BlueBubbles' },
|
||||
{ key: 'line', name: 'line', description: 'LINE Messaging API bot' },
|
||||
];
|
||||
|
||||
for (const { key, name, description } of channelConfigs) {
|
||||
|
||||
@@ -51,6 +51,7 @@ import { RequestBodyTooLargeError, readRequestBody } from '../utils/httpBody.js'
|
||||
import type { TeamsAdapter } from '../channels/teams/adapter.js';
|
||||
import type { GoogleChatAdapter } from '../channels/googleChat/adapter.js';
|
||||
import type { BlueBubblesAdapter } from '../channels/bluebubbles/adapter.js';
|
||||
import type { LineAdapter } from '../channels/line/adapter.js';
|
||||
|
||||
export interface GatewayServerConfig {
|
||||
port: number;
|
||||
@@ -120,6 +121,8 @@ export interface GatewayServerConfig {
|
||||
googleChatHandler?: Pick<GoogleChatAdapter, 'handleRequest'>;
|
||||
/** Optional BlueBubbles adapter for inbound iMessage event webhooks. */
|
||||
blueBubblesHandler?: Pick<BlueBubblesAdapter, 'handleRequest'>;
|
||||
/** Optional LINE adapter for inbound webhook events. */
|
||||
lineHandler?: Pick<LineAdapter, 'handleRequest'>;
|
||||
}
|
||||
|
||||
export class GatewayServer {
|
||||
@@ -724,6 +727,12 @@ export class GatewayServer {
|
||||
return;
|
||||
}
|
||||
|
||||
// LINE events route — bypass gateway auth (LINE webhook posts directly)
|
||||
if (this.config.lineHandler && req.method === 'POST' && req.url?.startsWith('/line/events')) {
|
||||
await this.config.lineHandler.handleRequest(req, res);
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply auth to HTTP requests when configured
|
||||
const authConfig = this.config.auth ?? {};
|
||||
if (this.config.authHttp !== false && authConfig.token) {
|
||||
@@ -842,6 +851,11 @@ export class GatewayServer {
|
||||
this.config.blueBubblesHandler = handler;
|
||||
}
|
||||
|
||||
/** Set the LINE handler for inbound webhook HTTP routes (late binding). */
|
||||
setLineHandler(handler: Pick<LineAdapter, 'handleRequest'>): void {
|
||||
this.config.lineHandler = handler;
|
||||
}
|
||||
|
||||
private async startDiscovery(host: string, port: number): Promise<void> {
|
||||
const discovery = this.config.discovery;
|
||||
if (!discovery?.enabled) {
|
||||
|
||||
Reference in New Issue
Block a user