feat: complete DM pairing codes with channel adapters, gateway handlers, and TUI command (Tier 4 feature 4)

This commit is contained in:
William Valentin
2026-02-09 18:28:10 -08:00
parent 9d4d440ecf
commit 1e29da4da2
11 changed files with 270 additions and 7 deletions
+27 -4
View File
@@ -12,6 +12,7 @@ import type {
import { isAllowedChat } from '../../frontends/telegram/handlers.js';
import { parseConfirmationCallback } from '../../frontends/telegram/confirmations.js';
import { splitMessage } from '../utils.js';
import type { PairingManager } from '../pairing.js';
/** Configuration for the Telegram channel adapter. */
export interface TelegramAdapterConfig {
@@ -20,6 +21,8 @@ export interface TelegramAdapterConfig {
/** Require bot mention or reply-to-bot to respond in group chats (default: true). */
requireMention?: boolean;
hookEngine?: HookEngine;
/** Optional pairing manager for DM pairing codes. */
pairingManager?: PairingManager;
}
/**
@@ -76,14 +79,34 @@ export class TelegramAdapter implements ChannelAdapter {
this.bot = new Bot(this.config.botToken);
this._status = 'connecting';
// ── Auth middleware — reject messages from unknown chats ──
// ── Auth middleware — reject messages from unknown chats (with pairing fallback) ──
this.bot.use(async (ctx, next) => {
const chatId = ctx.chat?.id;
if (chatId === undefined || !isAllowedChat(chatId, this.config.allowedChatIds)) {
console.log(`Rejected message from unauthorized chat: ${chatId}`);
if (chatId === undefined) return;
// Allowlist check
if (isAllowedChat(chatId, this.config.allowedChatIds)) {
await next();
return;
}
await next();
// Pairing fallback — check if sender is already approved or sending a valid code
const pm = this.config.pairingManager;
if (pm?.enabled) {
const senderId = String(chatId);
if (pm.isApproved('telegram', senderId)) {
await next();
return;
}
// Check if the message text is a valid pairing code
const text = ctx.message?.text?.trim();
if (text && pm.validateCode('telegram', senderId, text)) {
await ctx.reply('Pairing successful! You can now chat with Flynn.');
return;
}
}
console.log(`Rejected message from unauthorized chat: ${chatId}`);
});
// ── Confirmation callback handler (requires hookEngine) ──