Find a file
decrypt-mm 0ee0263f24
Some checks failed
Build / build (push) Has been cancelled
Fix TG album captions: drop double attribution, keep caption on later photo
Album items reach the media-group buffer with the sender attribution already
applied by telegram.go, so item.caption is non-empty even for parts that carry
no caption. formatTgMediaGroupCaption selected the caption by that field, which
had two consequences:

- a caption attached to a later photo was ignored (the first part always won);
- the attribution was applied a second time, so MAX rendered "Name: Name:"
  with the actual caption gone.

Take the caption from the raw Telegram message instead: the entity offsets refer
to it, not to the attributed string. Crossposts keep using item.caption, which is
prepared HTML without author attribution.

The existing test passed the raw caption in item.caption, a shape production
never produces, which is why the bug went unnoticed; the fixture now builds items
the way telegram.go does.
2026-08-18 12:04:59 +04:00
.github/workflows v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
docs Preserve Telegram video documents as MAX files 2026-08-01 13:56:53 +04:00
migrations Retain mappings for pinned Telegram messages 2026-08-01 15:19:33 +04:00
scripts support channel crosspost accumulators 2026-07-26 14:41:05 +04:00
.env.example v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
.gitignore v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
addon.go Relay Telegram inline bot media 2026-08-10 14:31:25 +04:00
addon_entitlements_test.go fix: resolve workspace PRO entitlements 2026-07-29 21:46:47 +04:00
addon_errs_test.go v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
addon_local_billing_test.go Expose workspace switching in bot help 2026-08-01 18:04:34 +04:00
addon_stub.go add secure browser cabinet command 2026-07-27 14:44:10 +04:00
addressbook.go Add per-chat participant address book 2026-08-01 14:47:53 +04:00
addressbook_test.go Retain mappings for pinned Telegram messages 2026-08-01 15:19:33 +04:00
admin.go Revert "feat: allow bridge delivery to MAX channels" 2026-07-30 22:41:21 +04:00
admin_test.go feat: expose manual moderation commands 2026-07-31 01:26:42 +04:00
billing_entitlements_addon.go fix: resolve workspace PRO entitlements 2026-07-29 21:46:47 +04:00
botchats.go v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
breaker_pause_test.go add crosspost pause controls 2026-07-19 01:23:30 +04:00
bridge.go Expose VK publisher recovery endpoint 2026-08-04 14:29:54 +04:00
bridge_direction.go v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
crosspost_access.go show live bot access in crosspost status 2026-08-03 18:20:47 +04:00
crosspost_access_test.go show live bot access in crosspost status 2026-08-03 18:20:47 +04:00
crosspost_funnel_test.go support channel crosspost accumulators 2026-07-26 14:41:05 +04:00
crosspost_status.go show live bot access in crosspost status 2026-08-03 18:20:47 +04:00
crosspost_status_test.go show live bot access in crosspost status 2026-08-03 18:20:47 +04:00
discussion_relay_test.go Relay channel posts from linked discussion groups 2026-08-02 22:35:36 +04:00
docker-compose.yml v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
Dockerfile v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
doctor.go show live bot access in crosspost status 2026-08-03 18:20:47 +04:00
doctor_test.go show live bot access in crosspost status 2026-08-03 18:20:47 +04:00
dualbot.go v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
format.go Fix TG album captions: drop double attribution, keep caption on later photo 2026-08-18 12:04:59 +04:00
format_test.go Relay channel posts from linked discussion groups 2026-08-02 22:35:36 +04:00
funnel_test.go support channel crosspost accumulators 2026-07-26 14:41:05 +04:00
go.mod update Telegram SDK for chat automation 2026-07-19 00:23:03 +04:00
go.sum update Telegram SDK for chat automation 2026-07-19 00:23:03 +04:00
help.go add paged extension help menu 2026-07-19 12:16:05 +04:00
helpmenu.go Remove legacy bridge prefixes 2026-08-01 20:45:11 +04:00
helpmenu_test.go feat: expose manual moderation commands 2026-07-31 01:26:42 +04:00
LICENSE v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
main.go chore: add safe MAX native comments probe 2026-07-30 11:26:57 +04:00
main_test.go v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
Makefile v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
markup.go Preserve nested Telegram formatting in MAX 2026-08-09 14:18:17 +04:00
markup_test.go Preserve nested Telegram formatting in MAX 2026-08-09 14:18:17 +04:00
max.go show live bot access in crosspost status 2026-08-03 18:20:47 +04:00
max_callback_test.go route MAX dialog callbacks to the clicker 2026-07-18 16:58:46 +04:00
max_caption_test.go Send long MAX media posts as Telegram rich messages 2026-07-28 14:16:33 +04:00
max_comment_probe.go chore: add safe MAX native comments probe 2026-07-30 11:26:57 +04:00
max_comment_probe_test.go chore: add safe MAX native comments probe 2026-07-30 11:26:57 +04:00
max_delete_suppress_test.go prevent bulk MAX cleanup from deleting Telegram posts 2026-07-18 11:55:43 +04:00
max_format_send_test.go Preserve nested Telegram formatting in MAX 2026-08-09 14:18:17 +04:00
max_share_test.go fix MAX share preview images 2026-07-23 13:59:16 +04:00
max_video_queue_test.go Handle MAX GIF photos without queue stalls 2026-07-27 23:25:28 +04:00
maxban.go v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
mediagroup.go Fix TG album captions: drop double attribution, keep caption on later photo 2026-08-18 12:04:59 +04:00
mediagroup_caption_test.go Fix TG album captions: drop double attribution, keep caption on later photo 2026-08-18 12:04:59 +04:00
mediagroup_document_test.go fix PDF albums and MAX repost links 2026-07-22 22:00:28 +04:00
mediagroup_manual_test.go support reliable addon media delivery tracking 2026-07-18 11:52:46 +04:00
message_origin_test.go fan out VK posts through Telegram crossposts 2026-07-27 13:52:11 +04:00
migrate.go v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
pair_rank_test.go feat: enforce post-PRO group fallback 2026-07-29 13:07:18 +04:00
postgres.go Retain mappings for pinned Telegram messages 2026-08-01 15:19:33 +04:00
queue.go feat: enforce post-PRO group fallback 2026-07-29 13:07:18 +04:00
queue_fairness_test.go Back off overloaded Telegram media delivery 2026-07-27 23:28:04 +04:00
README.md Preserve Telegram video documents as MAX files 2026-08-01 13:56:53 +04:00
replacements.go v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
replacements_entities_test.go v0.7.0 public bridge core 2026-07-18 01:41:16 +04:00
repository.go Retain mappings for pinned Telegram messages 2026-08-01 15:19:33 +04:00
sqlite.go Retain mappings for pinned Telegram messages 2026-08-01 15:19:33 +04:00
telegram.go Relay Telegram inline bot media 2026-08-10 14:31:25 +04:00
telegram_crosspost_edit_test.go Reapply crosspost replacements on edits 2026-08-10 13:12:51 +04:00
tg_document.go Preserve Telegram video documents as MAX files 2026-08-01 13:56:53 +04:00
tg_document_test.go Preserve Telegram video documents as MAX files 2026-08-01 13:56:53 +04:00
tg_media_edit.go Reapply crosspost replacements on edits 2026-08-10 13:12:51 +04:00
tgsender.go Relay Telegram inline bot media 2026-08-10 14:31:25 +04:00
tgsender_backpressure_test.go Prevent Telegram update drops under burst load 2026-07-31 18:19:53 +04:00
tgsender_impl.go Relay Telegram inline bot media 2026-08-10 14:31:25 +04:00
tgsender_impl_test.go Relay Telegram inline bot media 2026-08-10 14:31:25 +04:00
tgsender_rich.go Send long MAX media posts as Telegram rich messages 2026-07-28 14:16:33 +04:00
tgsender_welcome_ephemeral.go fix: limit Telegram whispers to welcomes 2026-07-30 18:25:44 +04:00
upload.go Preserve Telegram video documents as MAX files 2026-08-01 13:56:53 +04:00

Bridge Bot

MaxTelegramBridgeBot

Мост между Telegram и MAX мессенджером. Пересылает сообщения, медиа, файлы и редактирования между связанными чатами.

Сайт: maxtelegrambridge.ru

Боты: Telegram | MAX

❤ Поддержать проект

Возможности

  • Пересылка текстовых сообщений в обе стороны
  • Пересылка медиа: фото, видео, GIF, стикеры, документы, голосовые, аудио, кружки
  • Поддержка ответов (reply) — сохраняется контекст
  • Отслеживание редактирования сообщений. Если при редактировании добавлено медиа — отправляется как новое сообщение (MAX API не поддерживает редактирование вложений)
  • Удаление сообщений (MAX→TG). TG→MAX удаление невозможно — Telegram Bot API не отправляет событие удаления
  • Retry-очередь — при недоступности API сообщения сохраняются в БД и доставляются позже
  • Поддержка локального Telegram Bot API сервера (TG_API_URL)
  • Поддержка форумов (топиков) в TG-группах — сообщения из MAX приходят в нужный топик
  • Команда /thread — выбрать топик по умолчанию для сообщений из MAX
  • Команда /thread_bridge — связать отдельный TG-тред с отдельным MAX-чатом (форум ↔ несколько MAX-групп)
  • Reply из MAX автоматически попадает в тред исходного сообщения (а не в дефолтный)
  • Автосброс топика при отключении форума в группе
  • Настраиваемый префикс [TG] / [MAX]
  • Кросспостинг каналов с выбором направления (tg>max, max>tg, both)
  • Сохранение форматирования при кросспостинге (жирный, курсив, код, ссылки, зачёркнутый, подчёркнутый)
  • Управление кросспостингом через inline-кнопки
  • SQLite или PostgreSQL для хранения связок и маппинга сообщений

Форматирование при кросспостинге

Формат TG → MAX MAX → TG
Жирный
Курсив
Моноширинный
Зачёркнутый
Подчёркнутый
Ссылки
Цитата
Спойлер

Цитаты и спойлеры не поддерживаются MAX Bot API.

Установка

Из бинаря

Скачайте бинарь со страницы релизов и запустите:

chmod +x max-telegram-bridge-bot
./max-telegram-bridge-bot

Docker

docker run -e TG_TOKEN=your_token -e MAX_TOKEN=your_token ghcr.io/bearlogin/max-telegram-bridge-bot:latest

Docker Compose (с PostgreSQL)

cp .env.example .env
# Заполните TG_TOKEN и MAX_TOKEN в .env
docker compose up -d

PostgreSQL настраивается через .env:

POSTGRES_USER=bridge
POSTGRES_PASSWORD=bridge
POSTGRES_DB=bridge

Из исходников

git clone https://github.com/BEARlogin/max-telegram-bridge-bot.git
cd max-telegram-bridge-bot
go build -o max-telegram-bridge-bot .
./max-telegram-bridge-bot

Быстрый старт

1. Создайте ботов

  • Telegram: через @BotFather, отключите Privacy Mode (Bot Settings → Group Privacy → Turn off)
  • MAX: через business.max.ru

2. Настройте и запустите

Передайте токены через переменные окружения:

TG_TOKEN=your_token MAX_TOKEN=your_token ./max-telegram-bridge-bot

Или через export:

export TG_TOKEN=your_token
export MAX_TOKEN=your_token
./max-telegram-bridge-bot

3. Свяжите чаты

  1. Добавьте бота в Telegram-группу и MAX-группу
  2. В MAX сделайте бота админом группы
  3. В Telegram сделайте бота админом, если группа — супергруппа с темами (форум). В обычных группах админство не требуется (нужно только отключить Bot Privacy Mode через @BotFather, либо сделать бота админом)
  4. В одном из чатов отправьте /bridge
  5. Бот выдаст ключ — отправьте /bridge <ключ> в другом чате (в группе, не в ЛС бота)

4. Кросспостинг каналов

Настройка через личные сообщения с ботами (ничего не публикуется в каналах):

  1. Добавьте бота как админа в TG-канал и MAX-канал
  2. Перешлите любой пост из TG-канала в личку TG-бота → бот покажет ID канала
  3. В личке MAX-бота напишите /crosspost <TG_ID>
  4. Перешлите любой пост из MAX-канала в личку MAX-бота → кросспостинг настроен!

По умолчанию посты идут в обе стороны. Управление:

  • /crosspost (в личке любого бота) — список всех связок с кнопками
  • Перешлите пост из связанного канала в личку бота → появятся кнопки управления (направление, удаление)

Команды

Группы (bridge)

Команда Описание
/start, /help Инструкция
/bridge Создать ключ для связки
/bridge <ключ> Связать чат по ключу
/bridge prefix on/off Включить/выключить префикс [TG]/[MAX]
/unbridge Удалить связку
/thread Направить сообщения из MAX в текущий топик (форум-группы)

Форум-тред ↔ отдельная MAX-группа (thread-bridge)

В MAX нет тредов, но можно связать отдельные MAX-группы с конкретными тредами TG-форума — каждый тред получает своё зеркало.

Команда Где Описание
/thread_bridge TG, внутри треда Создать ключ для связки этого треда (нужны права админа, не работает в General)
/thread_bridge <ключ> MAX, отдельная группа Связать MAX-чат с TG-тредом по ключу
/thread_unbridge TG (в треде) или MAX Удалить связку треда

Один MAX-чат может быть зеркалом максимум одного треда и не может одновременно участвовать в /bridge. В одной форум-группе может быть несколько /thread_bridge (по одной на тред) параллельно с обычным /bridge для General.

Каналы (crosspost) — через личку бота

Команда Где Описание
/crosspost TG или MAX личка Список всех связок с кнопками управления
/crosspost <TG_ID> MAX личка Начать настройку (затем переслать пост из MAX-канала)
Переслать пост из канала TG или MAX личка Показать ID (если не связан) или кнопки управления

Кнопки управления позволяют менять направление (TG→MAX, MAX→TG, оба) и удалять связку.

5. Автозамены в кросспостинге

Автоматическая замена текста при пересылке постов. Удобно для UTM-меток, ссылок и любых строк.

  1. /crosspost → нажмите 🔄 Замены на нужной связке
  2. Выберите направление: + TG→MAX или + MAX→TG
  3. Выберите тип: Весь текст или Только ссылки
  4. Отправьте правило: from | to

Для регулярных выражений: /regex/ | replacement

Пример: utm_source=tg | utm_source=max — при пересылке из TG в MAX все вхождения utm_source=tg заменятся на utm_source=max.

Переменные окружения

Переменная Описание По умолчанию
TG_TOKEN Токен Telegram бота — (обязательно)
MAX_TOKEN Токен MAX бота — (обязательно)
DB_PATH Путь к SQLite базе bridge.db
DATABASE_URL DSN для PostgreSQL (если задана — SQLite игнорируется)
TG_BOT_URL Ссылка на TG-бота (показывается в /help) https://t.me/MaxTelegramBridgeBot
MAX_BOT_URL Ссылка на основного MAX-бота (показывается в /help) https://max.ru/id710708943262_bot
MAX_BOT_URL_RESERVE Ссылка на запасного MAX-бота (failover; пусто — скрыть подсказку) https://max.ru/id710708943262_4_bot
MAX_WEBHOOK_URL Базовый URL для webhook, например https://bridge.example.com (если не задан — long polling). Эндпоинт: /max-webhook
TG_WEBHOOK_URL Базовый URL для webhook, например https://bridge.example.com (если не задан — long polling). Эндпоинты: /tg-webhook
MAX_WEBHOOK_PORT Порт для webhook сервера MAX. Если порт совпадает с Telegram, значит будет общий сервер 8443
TG_WEBHOOK_PORT Порт для webhook сервера Telegram . Если порт совпадает с Max, значит будет общий сервер 8443
LOG_LEVEL Уровень логирования: debug, info, warn, error info
TG_API_URL URL локального Telegram Bot API сервера, например http://localhost:8081. Снимает лимиты на размер файлов
ALLOWED_USERS Белый список Telegram user ID через запятую. Если не задан — доступ открыт для всех
TG_MAX_FILE_SIZE_MB Дополнительный лимит файла из Telegram в MAX. Если не задан: документы — до 1 ГиБ, остальные медиа — до 512 МиБ
MAX_MAX_FILE_SIZE_MB Максимальный размер файла из Max в Telegram. Рекомендуется 20 МБ (если не используется локальный сервер API), если не задано - без ограничений
MAX_ALLOWED_EXTENSIONS Список расширений файлов через запятую, которые разрешены к отправке. Если не задано - без ограничений
MESSAGE_FORMAT Формат сообщений. inline (текущий Имя: текст) и newline (Имя:\nтекст) inline

Расширения (аддоны)

Бридж умеет подключать опциональные расширения — отдельные модули, которые добавляют свои команды и обработчики, не меняя ядро. В публичной сборке аддоны отсутствуют (всё работает как обычный мост); реализация подключается отдельной сборкой через build-тег.

Как это устроено

  • addon.go — интерфейс Addon, который должно реализовать расширение:

    type Addon interface {
        // Запуск фоновой работы (воркеры, регистрация вебхуков и т.п.).
        Start(ctx context.Context) error
        // Личное сообщение боту: вернуть true, если расширение его обработало.
        HandleDMCommand(ctx context.Context, userID, chatID int64, text string) (handled bool)
        // Нажатие inline-кнопки. msgID — id сообщения с кнопкой (можно удалить).
        HandleCallback(ctx context.Context, userID, chatID int64, callbackID, data string, msgID int) (handled bool)
        // Пересланный в личку пост из канала (sourceMsgID — id оригинала в канале).
        HandleDMForward(ctx context.Context, userID, dmChatID, sourceChatID int64, sourceTitle string, sourceMsgID int) (handled bool)
    }
    

    Аддон получает личные сообщения, форварды и callback'и первым: если он вернул true, ядро дальше их не обрабатывает.

  • addon_stub.go (//go:build !addon) — публичная сборка, расширения выключены:

    func loadAddon(b *Bridge) Addon { return nil }
    
  • addon_local.go (//go:build addon) — склейка с конкретным расширением. Этот файл не входит в публичный репозиторий.gitignore); его пишет тот, кто подключает своё расширение. Здесь:

    • создаётся экземпляр расширения и пробрасываются нужные операции бриджа (отправка, пересылка, удаление сообщений, резолв связок и т.п.) через узкие колбэки — ядро не знает внутренней логики расширения;
    • команды меню расширения добавляются обобщённо: b.extraCommands = append(b.extraCommands, BotCommand{...}) — ядро лишь покажет их в setMyCommands, не зная их семантики.

Сборка

# Без аддонов (публичная сборка)
go build -o bridge .

# С подключённым расширением
go build -tags addon -o bridge .

Для локальной разработки приватного расширения как отдельного Go-модуля удобно использовать go.work (тоже в .gitignore):

go work init . ../path-to-addon-module
go build -tags addon -o bridge .

Как написать своё расширение

  1. Реализуйте интерфейс Addon в своём пакете (отдельный модуль или подпапка).
  2. Создайте addon_local.go с тегом //go:build addon и функцией loadAddon(b *Bridge) Addon, которая собирает ваш аддон, прокидывая ему нужные операции бриджа.
  3. Соберите с -tags addon.

Ядро остаётся независимым: убрав тег (или собрав публично), вы получаете чистый мост без следов расширения.

Лицензия

CC BY-NC 4.0 — свободное использование и модификация, но коммерческое использование только с письменного разрешения автора.

Разработчик

bearlogin.dev — разработка ботов, сайтов, лендингов и digital-продуктов под ключ. Консультации по автоматизации и AI.