Files
gateway-telegram/README.md

8.5 KiB

gw_telegram

Bramka Telegram do n8n i systemów agentów AI. Bot przyjmuje wiadomości tekstowe i głosowe od użytkowników i routuje je do odpowiednich workflow w n8n lub agentów AI.

Funkcje

  • Wiadomości tekstowe — routing oparty na regułach regex do dowolnego workflow n8n
  • Wiadomości głosowe — pipeline: pobieranie OGG → konwersja ffmpeg (WAV 16kHz) → transkrypcja Whisper API → routing jak tekst
  • Sesje użytkowników — historia konwersacji przechowywana w Redis z konfigurowalnym TTL
  • Graceful shutdown — obsługa sygnałów SIGINT/SIGTERM, bot kończy obsługę aktualnych wiadomości przed zatrzymaniem
  • Tryby pracy — polling (domyślny) lub webhook

Architektura

Projekt stosuje Clean Architecture z pełnym oddzieleniem warstw:

cmd/bot/main.go              # composition root — łączy wszystkie warstwy
internal/
  domain/                    # logika biznesowa, zero zależności zewnętrznych
    entity/                  # modele: Message, Session, Intent, Route, WorkflowRequest
    port/                    # interfejsy (bramy zależności)
    apperror/                # typowane błędy domenowe
  application/               # przypadki użycia
    usecase/                 # HandleTextMessage, HandleVoiceMessage
    dto/                     # obiekty transferu danych
  infrastructure/            # implementacje portów
    telegram/                # BotGateway, UpdatePoller, FileDownloader
    n8n/                     # WebhookDispatcher
    speech/                  # OpenAIWhisper, FFmpegConverter
    router/                  # RuleBasedRouter
    storage/                 # RedisSessionStore
  interfaces/                # warstwa wejściowa
    telegram_handler.go      # mapowanie update → use case
    health_handler.go        # endpointy /health i /ready
  config/                    # ładowanie konfiguracji z env
test/testutil/               # fake'i dla wszystkich portów (TDD)
deploy/                      # Dockerfile, docker-compose.yml

Pipeline wiadomości głosowej

Telegram Voice Update
       │
       ▼
TelegramHandler.Handle()
       │
       ▼
HandleVoiceMessage.Execute()
  1. SendTyping (wskaźnik pisania)
  2. FileDownloader.Download(fileID)  → OGG Opus bytes
  3. FFmpegConverter.Convert()        → WAV 16kHz mono
  4. OpenAIWhisper.Transcribe()       → tekst
       │
       ▼
HandleTextMessage.Execute()          → routing → n8n → odpowiedź

Kontrakt JSON z n8n

Bot wysyła do webhooka n8n:

{
  "request_id": "uuid-v4",
  "chat_id": 123456789,
  "user_id": 987654321,
  "username": "jankowalski",
  "message_text": "Gdzie jest moje zamówienie #12345?",
  "intent_name": "order_inquiry",
  "timestamp": "2026-04-16T10:00:00Z",
  "metadata": {
    "route_target_type": "n8n"
  }
}

n8n odpowiada:

{
  "reply": "Twoje zamówienie #12345 jest w drodze.",
  "actions": [],
  "next_workflow": null
}

Jeśli n8n zwróci surowy tekst (nie JSON), bot wyśle go bezpośrednio do użytkownika.

Wymagania

  • Go 1.22+
  • Redis 7+
  • ffmpeg (wymagany do obsługi wiadomości głosowych)
  • Task (go install github.com/go-task/task/v3/cmd/task@latest)
  • Token bota Telegram (@BotFather)
  • Klucz API OpenAI (do transkrypcji głosu)
  • Działająca instancja n8n

Konfiguracja

Konfiguracja odbywa się wyłącznie przez zmienne środowiskowe. Skopiuj .env.example jako punkt startowy:

cp .env.example .env

Zmienne środowiskowe

Bot Telegram (wymagane)

Zmienna Domyślna Opis
TELEGRAM_BOT_TOKEN Token bota z @BotFather
BOT_MODE polling Tryb pracy: polling lub webhook
TELEGRAM_WEBHOOK_URL URL webhooka (tylko dla BOT_MODE=webhook)
TELEGRAM_DEBUG false Włącza szczegółowe logi Telegram API

n8n (wymagane)

Zmienna Domyślna Opis
N8N_BASE_URL Bazowy URL instancji n8n, np. http://localhost:5678
N8N_AUTH_TOKEN Token Bearer do uwierzytelniania webhooka
N8N_TIMEOUT 30 Timeout żądania do n8n (sekundy)
N8N_RETRY_COUNT 3 Liczba ponownych prób przy błędzie

Speech-to-Text

Zmienna Domyślna Opis
STT_PROVIDER openai Dostawca transkrypcji: openai
OPENAI_API_KEY Klucz API OpenAI (wymagany jeśli STT_PROVIDER=openai)
WHISPER_MODEL whisper-1 Model Whisper
WHISPER_LANGUAGE Kod języka BCP-47 (np. pl, en). Puste = autodetekcja
FFMPEG_PATH ffmpeg Ścieżka do binarki ffmpeg

Redis

Zmienna Domyślna Opis
REDIS_URL redis://localhost:6379 URL połączenia z Redis
SESSION_TTL 24 Czas życia sesji użytkownika (godziny)

Serwer HTTP

Zmienna Domyślna Opis
SERVER_PORT 8080 Port serwera HTTP (/health, /ready)

Logowanie

Zmienna Domyślna Opis
LOG_LEVEL info Poziom logów: debug, info, warn, error
LOG_FORMAT json Format logów: json lub text

Uruchomienie

Lokalne (bez Dockera)

Wymagania: Go 1.22+, Redis, ffmpeg zainstalowane lokalnie.

# 1. Sklonuj i przejdź do katalogu
git clone <repo-url>
cd gw_telegram

# 2. Pobierz zależności
go mod download

# 3. Skonfiguruj zmienne środowiskowe
cp .env.example .env
# edytuj .env — uzupełnij TELEGRAM_BOT_TOKEN, N8N_BASE_URL, OPENAI_API_KEY

# 4. Eksportuj zmienne
export $(grep -v '^#' .env | xargs)

# 5. Uruchom
task run

Docker Compose (zalecane)

# 1. Skonfiguruj zmienne
cp .env.example .env
# uzupełnij .env

# 2. Zbuduj i uruchom
task docker:up

# 3. Sprawdź logi
docker compose -f deploy/docker-compose.yml logs -f bot

# 4. Zatrzymaj
task docker:down

Docker Compose uruchamia bota razem z Redisem. Redis automatycznie persystuje dane sesji w woluminie redis_data.

Binarka produkcyjna

task build
# binarka: ./bin/bot

TELEGRAM_BOT_TOKEN=xxx N8N_BASE_URL=http://n8n:5678 ./bin/bot

Routing wiadomości

Routing jest oparty na regułach regex z priorytetem. Reguły są definiowane w kodzie (cmd/bot/main.go) i dopasowywane od najwyższego priorytetu. Pierwsza pasująca reguła wygrywa.

Domyślne reguły

Pattern Intent Target Priorytet
^/start start builtin 100
^/help help builtin 100
.* general_query n8n: default 0

Dodawanie nowego workflow n8n

  1. Dodaj regułę w cmd/bot/main.go:
{
    Pattern:    regexp.MustCompile(`(?i)zamówienie|order`),
    IntentName: "order_inquiry",
    Target: entity.RouteTarget{
        Type:       entity.RouteTargetN8n,
        WorkflowID: "order-webhook",
    },
    Priority: 50,
},
  1. Dodaj konfigurację workflow w mapie workflows:
workflows := map[string]n8n.WorkflowConfig{
    "default": {
        WebhookURL: cfg.N8n.BaseURL + "/webhook/default",
        AuthToken:  cfg.N8n.AuthToken,
    },
    "order-webhook": {
        WebhookURL: cfg.N8n.BaseURL + "/webhook/order-inquiry",
        AuthToken:  cfg.N8n.AuthToken,
    },
}

Testy

# Testy jednostkowe
task test

# Testy z raportem pokrycia (HTML)
task test:cover
# otwórz coverage.html

# Testy integracyjne (wymaga Dockera)
task test:int

Projekt stosuje TDD. Każdy przypadek użycia ma testy oparte na ręcznie pisanych fake'ach portów (test/testutil/), bez generowanych mocków.

Pokrycie testami

Pakiet Testowane scenariusze
HandleTextMessage Happy path, pusty tekst, brak trasy, błąd dispatchera, persystencja sesji
HandleVoiceMessage Happy path, błąd pobierania pliku, błąd transkrypcji, konwersja audio

Linting

task lint

Projekt używa golangci-lint. Konfiguracja w .golangci.yml.

Health Check

Serwer HTTP (SERVER_PORT) udostępnia:

  • GET /health — zawsze zwraca 200 OK jeśli proces działa
  • GET /ready — zwraca 200 OK gdy połączenie z Telegram API i Redis jest aktywne

Przydatne do probes w Kubernetes i healthcheck w Docker Compose.

Zależności

Biblioteka Zastosowanie
go-telegram-bot-api/v5 Telegram Bot API (polling + wysyłanie wiadomości)
kelseyhightower/envconfig Ładowanie konfiguracji ze zmiennych środowiskowych
redis/go-redis/v9 Klient Redis do przechowywania sesji
google/uuid Generowanie RequestID
stretchr/testify Asercje w testach
log/slog (stdlib) Strukturalne logowanie JSON