Очередная статья про то, как AI упрощает жизнь разработчикам, и параллельно отбирает у него куски работы, которые ещё недавно казались «только руками и с опытом». Долго можно было отмахиваться: «ну нет, это игрушка». Сейчас уже сложнее: случилось то, что отрицали. Описал задачу, получил рабочий код, осталось проверить на стенде и не накосячить в проде.
Cursor использую постоянно, но история не про «AI всё сделал за меня» (хотя в целом сделал но не с первого раза). Задачи от бизнеса не было: три мелочи в Mattermost нас задолбали, я решил допилить сам. Заодно опенсорс в копилку и немного кармы: порадовать коллег, с которыми каждый день в одних чатах. Раньше на это ушла бы неделя: docs, примеры, trial and error. Ушёл день. Вот что из этого вышло.
Кратко: self‑hosted Mattermost, обычная лицензия. Три раздражителя в ежедневной работе:
ответ на сообщение в ленте
статус «прочитал или нет» (ну такое, но тоже полезно)
быстрый голосовой созвон.
Закрыл тремя плагинами, собрал за ~день в Cursor, выложил на GitHub. Ниже: зачем, что получилось и где не ждите чуда.

Почему бы вообще не переехать
Когда в Mattermost не хватает мелочи, мысль всплывает сама: «Может, на другое?»
Переезда не было, но думали. Решений на СНГ рынке много, как стартапов так и решений из Big Tech. Каждый раз упирались в одно: у вендора, за чей продукт начнёшь платить, что‑то пойдёт не так. Падения, деньги кончатся, закроются, заблокируют. А ты уже мигрировал, уже заплатил. И снова искать, куда бежать.
Mattermost не идеальный из коробки, зато платформа с плагинами. Не хватает фичи: допилить. Не хочешь допиливать: Enterprise. Я пошёл третьим путём, своими силами, без тикета в бэклог.
Три боли, три плагина
Ответ на конкретное сообщение в ленте канала, не только в треде.
Галочки «доставлено / прочитано» на своих сообщениях.
Постоянные голосовые комнаты в сайдбаре, без отдельного сервиса.
Почему 3 отдельных а не один
Вспомним один из принципов SRP (Single Responsibility Principle). Я решил что каждый плагин должен закрывать свою проблему и есть риск одним плагином заблокировать работу других, а так можно отключить конкретный и продолжать работать с остальными.
Channel Reply: “ответь на это сообщение”
В Mattermost есть треды. Нажал Reply, ответ ушёл в боковую панель. Для длинных веток норм.
Но часто нужно другое: ответ в потоке канала с цитатой, чтобы все видели контекст, а не копировали текст руками и не писали «+1 к сообщению @ivan выше».
Что сделал:
кнопка Reply на сообщении;
превью цитаты над полем ввода;
ответ отдельным постом с кликабельной цитатой (переход к оригиналу);
встроенную кнопку MM переименовал в Thread, чтобы не путать;


Мобилка: UI плагина там не работает. Но в текст поста зашита markdown‑цитата, прочитать ответ с контекстом можно. Красивый блок с кликом только в вебе.
Message Status: “он видел или я в пустоту пишу?”
Классическая рабочая ситуация: написал коллеге, ждёшь. Тишина. Он занят? Не заходил? Прочитал и забыл ответить? В Mattermost на Team Edition ты этого не знаешь. В Enterprise read receipts есть, но мы не на Enterprise.
Зачем галочки:
✓ серая: сообщение дошло до сервера, доставлено;
✓✓ зелёные: собеседник увидел сообщение в клиенте (прокрутил в зону видимости);
при наведении: кто именно прочитал.
Плагин рисует галочки только на своих сообщениях. Обновления в реальном времени.

Хитрость, которую стоит знать: «прочитано» фиксируется, когда человек смотрит сообщение в вебе или desktop (там крутится webapp плагина). Открыл чат в нативном приложении, галочки у отправителя не зеленеют. Можно читать «тихо»:)
Галочки сами по себе тоже видны только в web/desktop, в телефоне их UI нет.
Voice Channels: “созвонимся на пять минут”
Нужен был быстрый голос без ссылки на Jitsi, который мы обычно использовали (там была отдельная авторизация, что ещё больше раздражало, но отдадим должное, работал стабильно). Комнаты в сайдбаре: зашёл, поговорил, вышел. Всё на своём сервере.
Что сделал: WebRTC + Pion на Go, аудио живёт прямо в server‑плагине, без отдельного медиа‑хоста. Комнаты под Threads, список участников, mute, плавающий виджет. Настройки STUN/TURN и NAT для прода за Docker.
Почему не LiveKit, MediaSoup и прочие SFU “на отдельной машине”: нужно было быстрое базовое решение, а не второй сервис с деплоем, мониторингом и ещё одним местом, где что‑то упадёт. Pion внутри плагина проще для нашего масштаба.

Важно: нужно пробросить UDP‑порты (20000–20010) и указать публичный IP. Без этого плагин самый капризный из трёх. Зато завёлся, удобно.
Еще момент, что вариант с медиасервером а не P2P выбран для дальнейшего внедрения записей встреч и отправкой ссылки на неё ботом в канал, но это как руки дойдут.
Как уложился в ~день с Cursor
Я не Mattermost‑разработчик, зато работаю с медиа (WebRTC, стриминг, аудио/видео). С Mattermost plugin API до этого особо не пересекался: CRT, registerPostActionComponent, всё новое.
AI не в вакууме. Для Cursor заранее заложил правила: что использовать, как собирать, как отлаживать, особенно для плагина со звонками. Явно прописал: медиа через Pion в Go‑плагине, без разворачивания LiveKit/MediaSoup на отдельном хосте. Без этого Cursor любезно предложил бы «поднимите SFU‑кластер», красиво, но не за день.
Но в целом можно сделать так, чтобы медиасервер не лежал прямо внутри а был отдельно развернут указав адрес где он живет, полезно чтобы не уронить звонками весь мессенджер, но нас не очень много в компании, поэтому должно справиться.
Работало так:
Описал боль и ограничения: «reply как в Slack», “галочки на своих сообщениях”, «голосовые комнаты, Pion, один бинарник плагина.»
AI набросал каркас:
plugin.json, Makefile, webapp, server hooks.Итерации по скриншотам и логам: «кнопка не там», «renegotiation ломается», «NAT без 1:1 IP», правка,
make dist, стенд.Документацию MM читал точечно; по WebRTC/Pion опирался на свой бэкграунд и подсказывал AI, где он уходит не туда.
~один рабочий день до рабочих прототипов. Поставил на стенд, коллеги начали пользоваться, без презентаций и «официального релиза». Для меня это и был успех: перестало бесить, плюс три репозитория на GitHub.
AI хорош для каркаса и незнакомого API, если ты задаёшь рамки. Без опыта в медиа и без правил для Cursor он бы утонул в over‑engineering. Staging, NAT, mobile, всё равно на вас.
Главный подводный камень: плагины = web + desktop
Запомнить одно:
Web, Desktop | ✅ всё работает
приложения iOS, Android | ❌ UI плагинов нет
Нативные приложения не грузят ваш main.js. Server‑side (Go) работает везде. Кнопки, галочки, комнаты только там, где webapp.
На практике:
Reply: создавать с телефона нельзя, читать (как цитату) можно.
Галочки: видны и обновляются в web/desktop; в приложении, «тихое чтение».
Голос: только web/desktop. (но вполне можно вытащить в отдельный веб чтобы и с телефона заходить на крайний случай)
Как поставить
Можно собрать самому.
make dist
Либо из релиза взять готовую сборку и загрузить её.
→ .tar.gz в System Console → Plugins → Upload. Mattermost 9.0+, после установки Ctrl+F5.
Риски: major‑апдейт MM может потребовать правок; support на вас; перед продом, staging.
Итог
Mattermost на обычной лицензии не тупик, если готовы допилить узкие боли плагинами. Три штуки за день с AI: личная инициатива, не проект от бизнеса. Trade‑off один: мобилка урезана, у нас большинство с ПК и ноутбука, терпимо.
Ссылки:
Channel Reply — https://github.com/Azario16/mattermost‑plugin‑channel‑reply
Message Status‑ https://github.com/Azario16/mattermost‑plugin‑message‑status
Voice Channels — https://github.com/Azario16/mattermost‑plugin‑voice‑channel
MIT. Берите, форкайте, критикуйте. Я сначала починил своё, потом выложил наружу.
ИИ‑ииии помните:)
Пишите почаще руками.
Всем удачи!
