Бот-переводчик в Telegram на Go с использованием n8n
- четверг, 8 мая 2025 г. в 00:00:08
 
Привет! Сегодня мы создадим простейшего бота-переводчика для Telegram на Golang с использованием библиотеки telego и нейросети Mistral через платформу n8n.
Цель — показать возможную связку n8n, бота и LLM.
Создаем папку для проекта и открываем ее в терминале
Инициализируем Go-модуль:
go mod init bot-translateУстанавливаем необходимые библиотеки:
go get github.com/mymmrac/telegoСоздаем файл main.go для основного кода бота
n8n мы развернем в Amvera Cloud, так как
В Amvera n8n есть как преднастроенный сервис. Это сильно упрощает развертывание.
Предоставляется бесплатный домен с SSL, что необходимо для работы с n8n.
Есть встроенное проксирование до API ведущих LLM, что пригодится, если мы хотим подключить OpenAI, Gemini или подобный сервис.
При регистрации получаем 111₽ на тестирование. Начать бесплатно всегда приятно.
Идем в раздел «Преднастроенные сервисы», «Создать преднастроенный сервис». Вводим название проекта и выбираем тариф, в моем случае будет тариф «Начальный Плюс». При создании нам предложат настроить конфигурацию, но я оставлю так как есть. Нажимаем «Завершить» и ждем когда приложение получит статус запущенного. После запуска переходим во вкладку «Домены». Создаем бесплатное доменное имя Amvera и выбираем тип подключения https. В дополнительных настройках пути и порта выбираем как на скриншоте:

Во вкладке «Переменные» добавляем переменную WEBHOOK_URL, в значение которой вставляем домен. Нам это необходимо для использования Webhook в дальнейшем. Примерно он будет выглядеть так: https://имя_проекта-ник.amvera.io/
Перезапускаем проект для применения изменений.
Переходим по созданному домену и регистрируем аккаунт владельца (email, имя, пароль).
Первым делом нам надо подключить Mistral. В меню создаем новый Credential → Mist API. Получаем API-токен на официальном сайте Mistral. В настроках вводим полученный токен, а регион можно оставить Европейским.
После подключения создаем новый Workflow. Первым шагом (Add first step) добавляем триггер "On webhook call"

И вводим следующие данные:
HTTP Method: POST
Path: /translate
В Workflow добавляем шаг (плюсик идущий от вебхука) AI → "AI Agent"

И указываем:
Source for Prompt: Define below
Prompt: {{ $json.body.text }}
Respond: Using 'Respond to Webhook' Node
Подключаем модель к агенту (плюсик у Chat Model → Mistral Cloud Chat Model):
Выбираем созданный Credential
Модель: mistral-large2411
Последним шагом добавляем Respond to Webhook (плюсик от агента → Core → в самом низу Respond to Webhook):
В Respond With вписываем - Text
А в Response Body - {{ $json.output }}
Примерно вот так будет выглядеть Workflow:

Осталось создать аккаунт бота.
Находим @BotFather в Telegram
Вводим команду /newbot
Указываем:
Имя бота (например, «Переводчик»)
Юзернейм, например translate_golang_bot (должен заканчиваться на bot)
Сохраняем полученный токен.
Теперь у нас есть все компоненты для создания бота.
Открываем файл main.go. Первым делом импортируем все необходимые зависимости:
package main
import (
	"context"
	"fmt"
	"net/http"
	"bytes"
	"time"
	"io"
	"strings"
	"github.com/mymmrac/telego"
	th "github.com/mymmrac/telego/telegohandler"
	tu "github.com/mymmrac/telego/telegoutil"
)Создаем основную функцию и инициализируем переменные:
func main() {
	ctx := context.Background()
	bot, _ := telego.NewBot("TOKEN")
	updates, _ := bot.UpdatesViaLongPolling(ctx, nil)
	bh, _ := th.NewBotHandler(bot, updates)
	fmt.Print("Бот запущен!") // Уведомление об успешном запуске
}Теперь добавим обработчики команд. Начнем с команды /start:
	bh.Handle(func(ctx *th.Context, update telego.Update) error {
		_, _ = ctx.Bot().SendMessage(ctx, tu.Message(tu.ID(update.Message.Chat.ID), 
			"Привет! Я бот-переводчик, написанный на Golang."))
		return nil
	}, th.CommandEqual("start"))
Основная функциональность реализована в команде /translate:
	bh.Handle(func(ctx *th.Context, update telego.Update) error {
		args := strings.SplitN(update.Message.Text, " ", 3)
		if len(args) < 3 {
			_, _ = ctx.Bot().SendMessage(ctx, 
				tu.Message(tu.ID(update.Message.Chat.ID), 
					"Использование: /translate <язык> <текст>"))
			return nil
		}
		language := args[1]
		text := args[2]
		req, _ := http.NewRequest("POST", "https://0.0.0.0:5678/webhook/translate", // Локальный хост используется только для разработки
			bytes.NewBufferString(fmt.Sprintf(`{"text":"Переведи на %s язык: %s. Строго без контекста"}`, language, text)))
		req.Header.Set("Content-Type", "application/json")
		client := &http.Client{Timeout: 10 * time.Second}
		resp, _ := client.Do(req)
		defer resp.Body.Close()
		body, _ := io.ReadAll(resp.Body)
		_, _ = ctx.Bot().SendMessage(ctx, tu.Message(tu.ID(update.Message.Chat.ID), string(body)))
		return nil
	}, th.CommandEqual("translate"))
Итоговый вариант файла main.go:
package main
import (
	"context"
	"fmt"
	"net/http"
	"bytes"
	"time"
	"io"
	"strings"
	"github.com/mymmrac/telego"
	th "github.com/mymmrac/telego/telegohandler"
	tu "github.com/mymmrac/telego/telegoutil"
)
func main() {
	ctx := context.Background()
	bot, _ := telego.NewBot(TOKEN)
	updates, _ := bot.UpdatesViaLongPolling(ctx, nil)
	bh, _ := th.NewBotHandler(bot, updates)
	fmt.Print("Бот запущен!")
	defer func() { _ = bh.Stop() }()
	bh.Handle(func(ctx *th.Context, update telego.Update) error {
		_, _ = ctx.Bot().SendMessage(ctx, tu.Message(tu.ID(update.Message.Chat.ID), 
			"Привет! Я бот-переводчик, написанный на Golang."))
		return nil
	}, th.CommandEqual("start"))
	bh.Handle(func(ctx *th.Context, update telego.Update) error {
		args := strings.SplitN(update.Message.Text, " ", 3)
		if len(args) < 3 {
			_, _ = ctx.Bot().SendMessage(ctx, 
				tu.Message(tu.ID(update.Message.Chat.ID), 
					"Использование: /translate <язык> <текст>"))
			return nil
		}
		language := args[1]
		text := args[2]
		req, _ := http.NewRequest("POST", "https://0.0.0.0:5678/webhook/translate",
			bytes.NewBufferString(fmt.Sprintf(`{"text":"Переведи на %s язык: %s. Строго без контекста"}`, language, text)))
		req.Header.Set("Content-Type", "application/json")
		client := &http.Client{Timeout: 10 * time.Second}
		resp, _ := client.Do(req)
		defer resp.Body.Close()
		body, _ := io.ReadAll(resp.Body)
		_, _ = ctx.Bot().SendMessage(ctx, tu.Message(tu.ID(update.Message.Chat.ID), string(body)))
		return nil
	}, th.CommandEqual("translate"))
	bh.Start()
}
Перед запуском бота на локальном компьютере необходимо настроить переадресацию запросов к вашему n8n серверу. Для этого замените адрес локального хоста в коде.
Исходная строка:
req, _ := http.NewRequest("POST", "https://0.0.0.0:5678/webhook/translate",Замените на:
req, _ := http.NewRequest("POST", "https://<ваш-домен>/webhook/translate",Далее:
Сохраните изменения в файле main.go
Откройте терминал в папке с проектом
Выполните команду запуска:
go run main.goДеплоить мы все на тот же Amvera Cloud. Для этого в разделе Приложения нажимаем создать приложение. Вводим название и выбираем тариф. Далее загружаем файлы нашего бота, а именно: go.mod, go.sum, main.go. После загрузки файлов нам потребуется создать секрет TOKEN, где будет храниться токен от бота. Это создано для безопасности. Для этого нажимаем «Создать секрет». В поле названия пишем TOKEN в значение указываем токен.

Теперь осталось создать файл конфигурации. Для этого выбираем все как на скриншоте:

Нажимаем Завершить и ждем окончания сборки приложения. После упешной сборки, приложение начнет запускаться.
Поздравляю! Наше приложение перешло в статус запущенного:

Стартовая команда

Перевод текста



3. Обработка ошибок

Особенности работы:
Бот поддерживает перевод на все основные языки.
Сообщения обрабатываются в течение 2-3 секунд.
При ошибках соединения бот автоматически пытается восстановить связь.
Результат
Мы написали простого бота на Go, который в связке с n8n и LLM, позволяет переводить сообщения с любых языков на любые. И развернули его в облаке Amvera Cloud вместе с преднастроенным n8n, заполнив несколько полей в разделе конфигурация и перетянув необходимые файлы в интерфейсе.
Исходный код проекта доступен по ссылке на GitHub.