openclaw/docs/architecture/telegram-integration.md
Arne Moor 69608fd305 feat: add telegram provider with CLI integration
Add Telegram as a third messaging provider alongside web and twilio.

Core Features:
- Interactive login flow with phone/SMS/2FA authentication
- Send text and media messages (images, videos, audio, documents)
- Monitor incoming messages with auto-reply support
- Session management at ~/.clawdis/telegram/session/
- Full CLI integration (login, logout, status, send, relay commands)

Implementation Details:
- Uses telegram npm package for MTProto API access
- Supports both URL and local file media sending
- Cross-platform path handling (Windows/Unix)
- Optional Twilio env vars (supports Telegram-only usage)
- Minimal provider abstraction pattern
- Comprehensive test coverage (440 tests passing)

Changes:
- Add Telegram module (client, login, monitor, inbound, outbound, session)
- Add provider factory and base interfaces
- Wire Telegram functions into CLI deps
- Update env validation to make Twilio fields optional
- Add telegram to all CLI commands (login, logout, status, send, relay)
- Add null checks in Twilio code for optional env fields
- Fix send command to properly load session and connect
- Add local file support with cross-platform path handling
- Update login message to show correct ~/.clawdis path
- Add comprehensive tests and documentation

Basic Usage:
  warelay login --provider telegram
  warelay send --provider telegram --to "@user" --message "Hi"
  warelay send --provider telegram --to "@user" --media "/path/to/file.jpg"
  warelay relay --provider telegram

All tests pass (63 files, 440 tests). Zero TypeScript errors.
2025-12-05 18:59:38 +01:00

27 KiB

Telegram Integration Architecture

Executive Summary

This document provides architectural guidance for adding Telegram as a third messaging provider to warelay. Like the WhatsApp Web provider, Telegram uses the user's personal account via MTProto client for 1-on-1 conversation automation.

Key architecture decisions:

  1. MTProto client: Users log in with their personal Telegram account (phone + 2FA)
  2. Same security model: allowFrom whitelist controls who can trigger auto-replies
  3. Provider abstraction: Unified interface across Twilio, Web, and Telegram providers
  4. Session storage: File-based session like WhatsApp Web (~/.warelay/telegram/session/)

Table of Contents

  1. Current Provider Architecture
  2. Provider Analysis: Web vs Telegram
  3. Telegram MTProto Design
  4. Provider Abstraction Improvements
  5. Configuration Schema Design
  6. Implementation Roadmap
  7. User Experience Design
  8. Design Decisions

1. Current Provider Architecture

1.1 System Context

flowchart LR
  subgraph Warelay["warelay CLI (Container)"]
    CLI[[CLI / Commander]]
    Send[[Send Command]]
    Relay[[Relay Command]]
    AutoReply[[Auto-Reply Engine]]
    Config[(Config / Sessions)]
  end

  User["Developer / Agent"]
  Twilio["Twilio API"]
  WhatsApp["WhatsApp Web"]
  IDP["WhatsApp IDP"]

  User -->|CLI commands| CLI
  CLI --> Send
  CLI --> Relay
  Relay --> AutoReply
  Send --> Twilio
  Send --> WhatsApp
  Relay --> Twilio
  Relay --> WhatsApp
  AutoReply --> Config
  WhatsApp -->|Baileys| IDP

Caption: warelay system context showing CLI entry points and provider connections.

Evidence: src/cli/program.ts:L1-L50, src/commands/send.ts:L1-L150

1.2 Current Provider Type Definition

The provider abstraction is currently a simple type union:

// src/utils.ts:L9
export type Provider = "wa-twilio" | "wa-web";

// src/utils.ts:L11-L14
export function assertProvider(input: string): asserts input is Provider {
  if (input !== "wa-twilio" && input !== "wa-web") {
    throw new Error("Provider must be 'wa-twilio' or 'wa-web'");
  }
}

Evidence: src/utils.ts:L9-L14

Interpretation: There is no formal provider interface or contract. Each provider has its own module structure with different function signatures.

1.3 Provider Module Structure

flowchart TB
  subgraph Providers["Provider Modules"]
    subgraph TwilioMod["Twilio Provider"]
      TClient[[client.ts]]
      TSend[[send.ts]]
      TMonitor[[monitor.ts]]
      TWebhook[[webhook.ts]]
    end
    subgraph WebMod["Web Provider"]
      WSession[[session.ts]]
      WOutbound[[outbound.ts]]
      WInbound[[inbound.ts]]
      WLogin[[login.ts]]
      WMedia[[media.ts]]
      WAutoReply[[auto-reply.ts]]
      WIPC[[ipc.ts]]
    end
  end

  CLI[[CLI Commands]]
  CLI --> TwilioMod
  CLI --> WebMod

Caption: Current provider module organization showing asymmetric implementations.

Evidence:

  • Twilio: src/providers/twilio/index.ts, src/twilio/*.ts
  • Web: src/providers/web/index.ts, src/web/*.ts, src/provider-web.ts

1.4 Provider Selection Logic

flowchart TB
  Start([Provider Selection])
  Check{Provider Flag?}
  Auto{Auto Mode?}
  WebAuth{Web Auth Exists?}

  Start --> Check
  Check -->|wa-twilio| UseTwilio[Use WhatsApp Twilio]
  Check -->|wa-web| UseWeb[Use WhatsApp Web]
  Check -->|auto| Auto
  Auto --> WebAuth
  WebAuth -->|yes| UseWeb
  WebAuth -->|no| UseTwilio

Caption: Provider auto-selection prioritizes Web when credentials exist.

Evidence: src/web/session.ts:L220-L226

export async function pickProvider(pref: Provider | "auto"): Promise<Provider> {
  if (pref !== "auto") return pref;
  const hasWeb = await webAuthExists();
  if (hasWeb) return "wa-web";
  return "wa-twilio";
}

2. Provider Analysis: Web vs Telegram

2.1 Comparison Matrix

Aspect WhatsApp Web Provider Telegram MTProto Provider
Auth Model QR code scan Phone + code + 2FA
Connection Type Persistent WebSocket Persistent TCP/WebSocket
Library Baileys GramJS
Session Storage ~/.warelay/credentials/ ~/.warelay/telegram/session/
Message Send Socket message MTProto request
Inbound Handling Event listener Event listener
Delivery Status Limited (receipts) Full (receipts + read)
Media Handling Buffer-based Buffer-based
Session Management Multi-file auth state String session
Reconnection Exponential backoff Exponential backoff

2.2 Web Provider Architecture

sequenceDiagram
  participant U as User/Agent
  participant C as CLI
  participant S as WA Socket
  participant WA as WhatsApp

  U->>C: warelay send --provider wa-web
  C->>S: createWaSocket()
  S->>WA: Connect (auth state)
  WA-->>S: Connection open
  S->>WA: sendMessage(jid, payload)
  WA-->>S: Message key
  S-->>C: {messageId, toJid}
  C->>S: ws.close()

Caption: Web send flow using persistent Baileys socket.

Evidence: src/web/outbound.ts:L12-L65

Key characteristics:

  • Persistent connection with session state
  • QR-based authentication stored at ~/.warelay/credentials/
  • Media sent as buffers with automatic optimization
  • IPC server for relay mode to prevent session corruption

2.3 Telegram MTProto Architecture (Proposed)

sequenceDiagram
  participant U as User/Agent
  participant C as CLI
  participant T as TelegramClient
  participant TG as Telegram

  U->>C: warelay send --provider telegram
  C->>T: createTelegramClient()
  T->>TG: Connect (session)
  TG-->>T: Connection open
  T->>TG: sendMessage(peer, payload)
  TG-->>T: Message object
  T-->>C: {messageId, peerId}
  C->>T: disconnect()

Caption: Telegram send flow using GramJS MTProto client.

Key characteristics:

  • Persistent connection with session state (like WhatsApp Web)
  • Phone-based authentication stored at ~/.warelay/telegram/session/
  • Media sent as buffers
  • Same patterns as Baileys for session management

2.4 Inbound Message Handling

flowchart TB
  subgraph Twilio["Twilio Inbound"]
    direction TB
    TW[Webhook] --> TA[Auto-Reply]
    TP[Polling] --> TA
  end

  subgraph Web["Web Inbound"]
    direction TB
    WS[Socket Event] --> WA[Auto-Reply]
    WU[messages.upsert] --> WS
  end

  subgraph Telegram["Telegram Inbound"]
    direction TB
    TE[NewMessage Event] --> TGA[Auto-Reply]
  end

  AutoReply[[Auto-Reply Engine]]
  TA --> AutoReply
  WA --> AutoReply
  TGA --> AutoReply
  AutoReply --> Config[(Config)]
  AutoReply --> Session[(Session Store)]

Caption: All providers converge at the provider-agnostic auto-reply engine.

Evidence:

  • Twilio: src/twilio/monitor.ts:L52-L101
  • Web: src/web/inbound.ts:L43-L274

3. Telegram MTProto Design

3.1 MTProto Client Architecture

flowchart TB
  subgraph TelegramProvider["Telegram Provider"]
    Client[[GramJS Client]]
    Session[[Session Manager]]
    Login[[Login Handler]]
    Media[[Media Handler]]
    Events[[Event Handler]]
  end

  subgraph External["Telegram"]
    API["Telegram MTProto\nDC Servers"]
  end

  subgraph Storage["Local Storage"]
    SessionFile[("~/.warelay/telegram/session/")]
  end

  Login -->|phone + code| Client
  Client --> API
  API --> Events
  Client --> Session
  Session --> SessionFile
  Client --> Media

Caption: Telegram provider internal architecture using MTProto.

3.2 Telegram Login Flow

sequenceDiagram
  participant U as User
  participant C as CLI
  participant T as TelegramClient
  participant TG as Telegram

  U->>C: warelay login --provider telegram
  C->>T: createClient(apiId, apiHash)
  T->>TG: Connect
  C->>U: Enter phone number
  U->>C: +15551234567
  T->>TG: sendCode(phone)
  TG-->>T: Code sent
  C->>U: Enter code
  U->>C: 12345
  T->>TG: signIn(phone, code)

  alt 2FA Enabled
    TG-->>T: Password required
    C->>U: Enter 2FA password
    U->>C: ********
    T->>TG: checkPassword(hash)
  end

  TG-->>T: Authorized
  T->>T: saveSession()
  C->>U: Logged in as @username

Caption: Interactive Telegram login flow with optional 2FA.

3.3 Telegram Send Flow

sequenceDiagram
  participant C as CLI
  participant P as TelegramProvider
  participant G as GramJS
  participant A as Telegram API

  C->>P: send(userId, text)
  P->>P: resolveUser(userId)
  P->>G: client.sendMessage()
  G->>A: MTProto Request
  A-->>G: Message response
  G-->>P: Message object
  P-->>C: SendResult

Caption: Telegram outbound message sequence.

3.4 Telegram Relay Flow

sequenceDiagram
  participant U as Contact
  participant TG as Telegram
  participant C as TelegramClient
  participant AR as Auto-Reply
  participant A as Agent (Claude)

  Note over C: Persistent Connection

  U->>TG: Send message
  TG->>C: NewMessage event
  C->>C: Check allowFrom
  C->>AR: Process message
  AR->>A: Execute command
  A-->>AR: Response
  AR->>C: Reply payload
  C->>TG: sendMessage()
  TG->>U: Deliver reply

Caption: Telegram relay mode with auto-reply using persistent connection.

3.5 Security Model

flowchart TB
  Inbound[Incoming Message]
  Check{Sender in allowFrom?}
  Allow[Process Message]
  Deny[Ignore Message]

  Inbound --> Check
  Check -->|yes| Allow
  Check -->|no| Deny
  Allow --> AutoReply[Auto-Reply Engine]

Caption: allowFrom whitelist filtering for Telegram (same as WhatsApp).

Configuration:

{
  telegram: {
    allowFrom: ["@alice", "@bob", "123456789"]
  }
}
  • Usernames must include @ prefix
  • User IDs are numeric strings
  • Empty array [] blocks all
  • Omit entirely to allow all (use with caution)

4. Provider Abstraction Improvements

4.1 Proposed Provider Interface

// src/providers/types.ts (proposed)

export type ProviderKind = "wa-twilio" | "wa-web" | "telegram";

export interface ProviderMessage {
  id: string;
  from: string;           // Normalized identifier
  to: string;             // Normalized identifier
  body: string;
  timestamp: number;
  media?: ProviderMedia[];
  raw?: unknown;          // Provider-specific payload
}

export interface ProviderMedia {
  type: "image" | "video" | "audio" | "document" | "voice";
  url?: string;           // Remote URL
  buffer?: Buffer;        // Local buffer
  mimeType?: string;
  fileName?: string;
  size?: number;
}

export interface SendOptions {
  media?: ProviderMedia[];
  replyTo?: string;       // Message ID to reply to
  typing?: boolean;       // Send typing indicator first
}

export interface SendResult {
  messageId: string;
  status: "sent" | "queued" | "failed";
  providerMeta?: unknown; // Provider-specific (SID, user_id, etc.)
}

export interface DeliveryStatus {
  messageId: string;
  status: "sent" | "delivered" | "read" | "failed" | "unknown";
  timestamp?: number;
  error?: string;
}

export interface ProviderCapabilities {
  supportsDeliveryReceipts: boolean;
  supportsReadReceipts: boolean;
  supportsTypingIndicator: boolean;
  supportsReactions: boolean;
  supportsReplies: boolean;
  supportsEditing: boolean;
  supportsDeleting: boolean;
  maxMediaSize: number;
  supportedMediaTypes: string[];
  canInitiateConversation: boolean;
}

export interface Provider {
  readonly kind: ProviderKind;
  readonly capabilities: ProviderCapabilities;

  // Lifecycle
  initialize(config: ProviderConfig): Promise<void>;
  isConnected(): boolean;
  disconnect(): Promise<void>;

  // Outbound
  send(to: string, body: string, options?: SendOptions): Promise<SendResult>;
  sendTyping(to: string): Promise<void>;

  // Inbound (relay mode)
  onMessage(handler: (msg: ProviderMessage) => Promise<void>): void;
  startListening(): Promise<void>;
  stopListening(): Promise<void>;

  // Status (optional)
  getDeliveryStatus?(messageId: string): Promise<DeliveryStatus>;
}

4.2 Provider Factory Pattern

flowchart TB
  subgraph Factory["Provider Factory"]
    Create[[createProvider]]
    Registry[(Provider Registry)]
  end

  subgraph Providers["Provider Implementations"]
    Twilio[[TwilioProvider]]
    Web[[WebProvider]]
    Telegram[[TelegramProvider]]
  end

  Config[(Config / Env)]

  Config --> Create
  Create --> Registry
  Registry --> Twilio
  Registry --> Web
  Registry --> Telegram
// src/providers/factory.ts (proposed)

import type { Provider, ProviderConfig, ProviderKind } from "./types.js";

const providerRegistry = new Map<ProviderKind, new () => Provider>();

export function registerProvider(kind: ProviderKind, ctor: new () => Provider) {
  providerRegistry.set(kind, ctor);
}

export async function createProvider(config: ProviderConfig): Promise<Provider> {
  const ProviderClass = providerRegistry.get(config.kind);
  if (!ProviderClass) {
    throw new Error(`Unknown provider: ${config.kind}`);
  }
  const provider = new ProviderClass();
  await provider.initialize(config);
  return provider;
}

export function getAvailableProviders(): ProviderKind[] {
  return [...providerRegistry.keys()];
}

4.3 Unified Message Model

flowchart LR
  subgraph Inbound["Inbound Normalization"]
    TwilioIn[Twilio Message]
    WebIn[Baileys Message]
    TelegramIn[Telegram Message]
  end

  Normalize[[Normalize to ProviderMessage]]

  subgraph Unified["Unified Processing"]
    AutoReply[[Auto-Reply]]
    Session[[Session Management]]
    Logging[[Logging]]
  end

  TwilioIn --> Normalize
  WebIn --> Normalize
  TelegramIn --> Normalize
  Normalize --> AutoReply
  AutoReply --> Session
  AutoReply --> Logging

Caption: All provider messages normalized to common format before processing.

4.4 Identifier Normalization

// src/providers/identifiers.ts (proposed)

export interface NormalizedIdentifier {
  provider: ProviderKind;
  raw: string;            // Original identifier
  normalized: string;     // Provider-specific normalized form
  display: string;        // Human-readable form
}

export function normalizeIdentifier(
  provider: ProviderKind,
  raw: string
): NormalizedIdentifier {
  switch (provider) {
    case "wa-twilio":
    case "wa-web":
      // WhatsApp: E.164 phone number
      const e164 = raw.replace(/^whatsapp:/, "").replace(/[^\d+]/g, "");
      return {
        provider,
        raw,
        normalized: e164.startsWith("+") ? e164 : `+${e164}`,
        display: e164.startsWith("+") ? e164 : `+${e164}`,
      };

    case "telegram":
      // Telegram: numeric user ID or @username
      if (/^\d+$/.test(raw)) {
        return {
          provider,
          raw,
          normalized: raw,
          display: `user:${raw}`,
        };
      }
      if (raw.startsWith("@")) {
        return {
          provider,
          raw,
          normalized: raw.toLowerCase(),
          display: raw,
        };
      }
      return { provider, raw, normalized: raw, display: raw };

    default:
      return { provider, raw, normalized: raw, display: raw };
  }
}

5. Configuration Schema Design

5.1 Extended Environment Variables

# .env.example (extended)

# =============================================================================
# TWILIO (WhatsApp Business API)
# =============================================================================
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=your_auth_token_here
TWILIO_WHATSAPP_FROM=whatsapp:+17343367101

# =============================================================================
# TELEGRAM (MTProto Client)
# =============================================================================
# Get from https://my.telegram.org/apps
TELEGRAM_API_ID=12345678
TELEGRAM_API_HASH=0123456789abcdef0123456789abcdef

5.2 Extended warelay.json Schema

// Extended WarelayConfig type

export type TelegramConfig = {
  // Security whitelist (same model as WhatsApp)
  allowFrom?: string[];     // Usernames (@user) or user IDs (123456789)
};

export type WarelayConfig = {
  logging?: LoggingConfig;

  // Provider-specific settings
  web?: WebConfig;
  telegram?: TelegramConfig;

  inbound?: {
    allowFrom?: string[];   // WhatsApp E.164 numbers
    messagePrefix?: string;
    responsePrefix?: string;
    timestampPrefix?: boolean | string;
    transcribeAudio?: { ... };
    reply?: { ... };
  };
};

5.3 Sample warelay.json with Telegram

{
  "logging": {
    "level": "info",
    "file": "~/.warelay/logs/warelay.log"
  },

  // Telegram-specific settings
  "telegram": {
    "allowFrom": ["@alice", "@bob", "123456789"]
  },

  // Web relay settings
  "wa-web": {
    "heartbeatSeconds": 300,
    "reconnect": {
      "maxAttempts": 10,
      "initialMs": 1000,
      "maxMs": 30000
    }
  },

  // Shared inbound settings (apply to WhatsApp)
  "inbound": {
    "allowFrom": ["+15551234567"],
    "responsePrefix": "",
    "timestampPrefix": "America/Los_Angeles",
    "reply": {
      "mode": "command",
      "command": ["claude", "-p", "{{Body}}"],
      "timeoutSeconds": 300,
      "session": {
        "scope": "per-sender",
        "idleMinutes": 30,
        "resetTriggers": ["/new", "/reset"]
      }
    }
  }
}

5.4 Provider Selection Logic (Extended)

flowchart TB
  Start([Provider Selection])
  Flag{--provider flag?}

  Flag -->|telegram| CheckTG{Telegram session exists?}
  Flag -->|wa-twilio| CheckTwilio{Twilio env set?}
  Flag -->|wa-web| CheckWeb{WhatsApp Web auth exists?}
  Flag -->|auto| AutoSelect

  CheckTG -->|yes| UseTelegram[Use Telegram]
  CheckTG -->|no| Error[Error: Run warelay login --provider telegram]

  CheckTwilio -->|yes| UseTwilio[Use WhatsApp Twilio]
  CheckTwilio -->|no| Error2[Error: Set Twilio env]

  CheckWeb -->|yes| UseWeb[Use WhatsApp Web]
  CheckWeb -->|no| Error3[Error: Run warelay login]

  AutoSelect --> WebAuth{Web auth exists?}
  WebAuth -->|yes| UseWeb
  WebAuth -->|no| TelegramAuth{Telegram session?}
  TelegramAuth -->|yes| UseTelegram
  TelegramAuth -->|no| TwilioAuth{Twilio env?}
  TwilioAuth -->|yes| UseTwilio
  TwilioAuth -->|no| NoProvider[Error: No provider available]

Caption: Extended provider selection with Telegram priority between Web and Twilio.


6. Implementation Roadmap

6.1 Phase Overview

flowchart LR
  P1[Phase 1\nAbstraction]
  P2[Phase 2\nTelegram MTProto]
  P3[Phase 3\nFeature Parity]
  P4[Phase 4\nPolish]

  P1 --> P2 --> P3 --> P4

6.2 Phase 1: Provider Abstraction Refactoring (Week 1-2)

Goal: Introduce formal provider interface without breaking existing functionality.

Tasks

  1. Create provider interface types

    • src/providers/types.ts - Interface definitions
    • src/providers/factory.ts - Provider factory
    • src/providers/identifiers.ts - ID normalization
  2. Wrap existing providers

    • src/providers/twilio/provider.ts - TwilioProvider class
    • src/providers/web/provider.ts - WebProvider class
  3. Update CLI deps

    • Modify src/cli/deps.ts to use provider factory
    • Keep backward compatibility during transition
  4. Add provider tests

    • Unit tests for provider interface compliance
    • Integration tests for existing functionality

File Structure After Phase 1

src/providers/
  types.ts              # NEW: Interface definitions
  factory.ts            # NEW: Provider factory
  identifiers.ts        # NEW: ID normalization
  twilio/
    index.ts            # Existing: Re-exports
    provider.ts         # NEW: TwilioProvider class
  web/
    index.ts            # Existing: Re-exports
    provider.ts         # NEW: WebProvider class

6.3 Phase 2: Telegram MTProto Provider (Week 3-4)

Goal: Implement Telegram MTProto client provider.

Tasks

  1. Add Telegram dependencies

    pnpm add telegram  # GramJS
    pnpm add input     # For interactive login
    
  2. Create Telegram provider

    • src/providers/telegram/client.ts - GramJS client wrapper
    • src/providers/telegram/provider.ts - TelegramProvider class
    • src/providers/telegram/session.ts - Session management
    • src/providers/telegram/login.ts - Interactive login flow
  3. Implement core functionality

    • Send messages (text + media)
    • Receive via persistent connection
    • Session persistence
  4. Add Telegram-specific features

    • User ID / username resolution
    • allowFrom filtering

Telegram Provider Structure

src/providers/telegram/
  index.ts              # Re-exports
  provider.ts           # TelegramProvider class
  client.ts             # GramJS wrapper
  session.ts            # Session storage
  login.ts              # Interactive login
  media.ts              # Telegram media handling

6.4 Phase 3: Feature Parity (Week 5)

Goal: Full feature parity with WhatsApp Web provider.

Tasks

  1. Media support - Images, audio, video, documents
  2. Auto-reply integration - Test with Claude agent
  3. Relay mode - Persistent connection with reconnection
  4. CLI commands - login, send, relay, status

6.5 Phase 4: Documentation and Polish (Week 6)

Goal: Complete documentation and edge case handling.

Tasks

  1. Documentation - User guides, API docs, examples
  2. Error handling - Session expiry, rate limits, network errors
  3. Testing - Unit, integration, E2E tests

7. User Experience Design

7.1 CLI Command Changes

Current Commands (Unchanged)

# Send (add --provider telegram)
warelay send --to <id> --message "text" --provider telegram

# Relay (add --provider telegram)
warelay relay --provider telegram --verbose

New Telegram-Specific Commands

# Login with phone + code + 2FA
warelay login --provider telegram
# Interactive: prompts for phone, code, 2FA password

7.2 Example Workflows

Workflow 1: Send via Telegram

# One-time setup
export TELEGRAM_API_ID="12345678"
export TELEGRAM_API_HASH="0123456789abcdef..."

# Login (once)
warelay login --provider telegram
# Enter phone: +15551234567
# Enter code: 12345
# Enter 2FA password: ********

# Send message
warelay send --provider telegram --to @john_doe --message "Hello from warelay!"

# Send with media
warelay send --provider telegram --to @john_doe --message "Check this" --media ./photo.jpg

Workflow 2: Telegram Relay Mode

# Start relay (persistent connection)
warelay relay --provider telegram --verbose

# Output:
# warelay 1.4.0 - Telegram @yourusername listening
# logs: /tmp/warelay/warelay.log (level info)
# Ready to receive messages!

7.3 Provider Comparison Guide

Scenario Provider Command
Personal WhatsApp wa-web --provider wa-web
Business WhatsApp wa-twilio --provider wa-twilio
Personal Telegram telegram --provider telegram
Auto (prefer personal) auto --provider auto

7.4 Migration Guide for Existing Users

  1. No changes required for existing WhatsApp Twilio or WhatsApp Web users (legacy names twilio and web still work)
  2. To add Telegram:
    • Get API credentials from https://my.telegram.org/apps
    • Set TELEGRAM_API_ID and TELEGRAM_API_HASH environment variables
    • Run warelay login --provider telegram
    • Use --provider telegram flag
  3. Configuration file is backward compatible
  4. Auto mode will include Telegram in priority chain

8. Design Decisions

ADR-001: MTProto Client Approach

Status: Accepted

Context: warelay is a personal automation tool - a butler for the user's own account. Users want to automate their personal Telegram conversations, not run a bot.

Decision: Use MTProto client (GramJS) for personal account access.

Consequences:

  • Matches WhatsApp Web provider pattern exactly
  • Can initiate conversations
  • Full access to personal DMs
  • Same allowFrom security model works
  • Requires phone + code + 2FA login

ADR-002: GramJS Library Selection

Status: Accepted

Context: Multiple Node.js libraries exist for Telegram MTProto.

Library TypeScript Active Pattern
telegram (GramJS) Native Yes Similar to Baileys
mtproto-core Types available Moderate Low-level

Decision: Use GramJS (telegram npm package) for native TypeScript support and similarity to Baileys patterns.

Consequences:

  • Clean TypeScript integration
  • Familiar patterns for Baileys users
  • Active maintenance
  • Good documentation

ADR-003: Session Storage Location

Status: Accepted

Context: Need to store Telegram session like WhatsApp Web credentials.

Decision: Store at ~/.warelay/telegram/session/ following existing patterns.

Consequences:

  • Consistent with ~/.warelay/credentials/ for WhatsApp
  • User-specific storage
  • Easy to backup/restore
  • Clear separation between providers

ADR-004: Security Model Consistency

Status: Accepted

Context: WhatsApp uses allowFrom whitelist. Telegram needs same model.

Decision: Use telegram.allowFrom in config with usernames and user IDs.

Consequences:

  • Consistent security model across providers
  • Users understand the pattern already
  • Supports both @username and numeric IDs
  • Same behavior: whitelist = only listed users trigger auto-reply

Appendix A: File Evidence Index

Section Files Referenced
Provider Types src/utils.ts:L9-L14, src/providers/provider.types.ts:L1-L2
Twilio Implementation src/twilio/send.ts, src/twilio/monitor.ts, src/twilio/client.ts
Web Implementation src/web/session.ts, src/web/outbound.ts, src/web/inbound.ts
CLI Commands src/cli/program.ts, src/commands/send.ts, src/commands/status.ts
Configuration src/config/config.ts, src/env.ts, .env.example
Dependencies src/cli/deps.ts

Appendix B: Glossary

Term Definition
Baileys Open-source WhatsApp Web client library
GramJS TypeScript Telegram MTProto client library
MTProto Telegram's native binary protocol for user clients
User ID Telegram's numeric identifier for users
E.164 International phone number format (+1234567890)
JID Jabber/WhatsApp ID format (number@s.whatsapp.net)
Provider Messaging backend (Twilio, Web, Telegram)
Session Authenticated state stored on disk