Манифест plugin.json
Манифест — это «паспорт» плагина. По нему Loop узнаёт, как плагин называется, какой он версии, где лежат его серверная и клиентская части и какие настройки показать администратору. Файл лежит в корне проекта и попадает в архив плагина.
Пример
{
"id": "ru.mycompany.hello",
"name": "Hello",
"description": "Учебный плагин: slash-команда /hello, бот и счётчик приветствий",
"version": "0.1.0",
"min_server_version": "9.11.0",
"homepage_url": "https://git.mycompany.ru/team/hello",
"support_url": "https://git.mycompany.ru/team/hello/issues",
"icon_path": "assets/icon.svg",
"server": {
"executables": {
"darwin-amd64": "server/dist/plugin-darwin-amd64",
"darwin-arm64": "server/dist/plugin-darwin-arm64",
"linux-amd64": "server/dist/plugin-linux-amd64",
"linux-arm64": "server/dist/plugin-linux-arm64",
"windows-amd64": "server/dist/plugin-windows-amd64.exe"
}
},
"webapp": {
"bundle_path": "webapp/dist/main.js"
},
"settings_schema": {
"header": "Текст над настройками",
"footer": "Текст под настройками",
"settings": []
}
}
Поля
| Поле | Обязательное | Описание |
|---|---|---|
id | Да | Уникальный идентификатор: от 3 до 190 символов, латиница, цифры, ., -, _. Удобная схема — домен компании задом наперёд плюс название: ru.mycompany.hello. Не меняйте после первой установки: по ID Loop хранит настройки и данные плагина, и плагин с новым ID для него будет совсем другим |
name | Да | Название, которое видит администратор |
version | Да | Версия плагина. Используйте формат major.minor.patch (семантическое версионирование): 0.1.0, 1.2.3. Loop показывает её в списке плагинов |
description | Нет | Краткое описание |
min_server_version | Нет | Минимальная версия сервера. Если сервер старше, плагин не установится. См. ниже |
homepage_url | Нет | Ссылка на страницу плагина |
support_url | Нет | Куда сообщать об ошибках |
release_notes_url | Нет | Ссылка на список изменений |
icon_path | Нет | Путь к иконке в формате SVG внутри архива, например assets/icon.svg. Картинки PNG и JPG не поддерживаются |
server | Нет | Где лежат программы серверной части. Шаблон заполняет это поле сам — оставьте как есть. Если серверной части нет, удалите поле целиком |
webapp | Нет | Где лежит собранная клиентская часть. Если клиентской части нет, удалите поле целиком |
settings_schema | Нет | Настройки для Системной консоли. См. ниже |
props | Нет | Произвольные данные, которые могут прочитать другие плагины |
Чтобы файл попал в архив, положите его в папку assets/ в корне проекта — при сборке make dist она копируется в архив целиком. Прочитать такие файлы из серверной части можно по пути p.bundlePath + "/assets/...", а в браузере они доступны по адресу /plugins/<ID плагина>/assets/<имя файла> (маршрут для этого уже есть в server/plugin/api.go).
min_server_version
Сервер Loop сообщает собственную версию (например, 10.6.0), и она не совпадает с версией Mattermost, с которой совместимы плагины Loop (9.11.7). Именно с версией Loop сравнивается min_server_version.
Оставьте значение из шаблона — 9.11.0. Этого достаточно: все поддерживаемые версии Loop его проходят. Не пытайтесь с помощью этого поля «требовать» возможности новых версий Mattermost — в Loop их всё равно нет (см. Совместимость с Mattermost).
Настройки (settings_schema)
Если в манифесте описаны настройки, в Системной консоли появляется страница Системная консоль > Плагины > «Название плагина» с полями для каждой настройки. Администратор меняет значения, нажимает Сохранить, и плагин сразу получает новые значения — перезапускать ничего не нужно.
"settings_schema": {
"header": "Инструкция по настройке: [документация](https://example.ru/docs).",
"footer": "Вопросы — в канал ~plugin-support.",
"settings": [
{ "key": "...", "display_name": "...", "type": "...", ... }
]
}
header и footer — текст над и под настройками, поддерживается Markdown.
Поля настройки
| Поле | Описание |
|---|---|
key | Имя настройки. По нему серверная часть найдёт значение. Используйте латиницу без пробелов, например ApiUrl |
display_name | Подпись поля в Системной консоли |
type | Тип поля — см. таблицу ниже |
help_text | Подсказка под полем, поддерживается Markdown |
placeholder | Серый текст в пустом поле. Только для text, longtext, number, username, generated, custom |
default | Значение по умолчанию. Действует, пока администратор не сохранит своё |
options | Варианты выбора для dropdown и radio: список объектов {"display_name": "Подпись", "value": "значение"}. Оба поля обязательны |
regenerate_help_text | Подсказка у кнопки Сгенерировать для типа generated |
hosting | on-prem или cloud — показывать поле только в указанном типе развёртывания. Обычно не нужно |
Типы настроек
type | Как выглядит | Что получит плагин |
|---|---|---|
text | Однострочное поле | string |
longtext | Многострочное поле | string |
number | Поле для числа | int |
bool | Переключатель «да / нет» | bool |
dropdown | Выпадающий список из options | string — value выбранного варианта |
radio | Переключатели из options — для 2–4 вариантов | string — value выбранного варианта |
generated | Случайная строка и кнопка Сгенерировать — для секретов и ключей | string |
username | Поле с подсказками имён пользователей | string |
custom | Ваш собственный React-компонент, см. Клиентская часть | Что сохранит компонент |
Пример со всеми типами
"settings": [
{
"key": "ServiceURL",
"display_name": "Адрес сервиса",
"type": "text",
"placeholder": "https://service.example.ru",
"help_text": "Куда плагин будет отправлять запросы."
},
{
"key": "Template",
"display_name": "Шаблон сообщения",
"type": "longtext",
"default": "Новая задача: **{title}**"
},
{
"key": "MaxItems",
"display_name": "Сколько записей показывать",
"type": "number",
"default": 10
},
{
"key": "EnableNotifications",
"display_name": "Отправлять уведомления",
"type": "bool",
"default": true
},
{
"key": "Mode",
"display_name": "Режим работы",
"type": "dropdown",
"default": "all",
"options": [
{ "display_name": "Все каналы", "value": "all" },
{ "display_name": "Только публичные", "value": "public" }
]
},
{
"key": "Language",
"display_name": "Язык сообщений бота",
"type": "radio",
"default": "ru",
"options": [
{ "display_name": "Русский", "value": "ru" },
{ "display_name": "English", "value": "en" }
]
},
{
"key": "WebhookSecret",
"display_name": "Секрет вебхука",
"type": "generated",
"help_text": "Укажите этот секрет во внешнем сервисе.",
"regenerate_help_text": "Сгенерировать новый секрет. Старый перестанет работать."
},
{
"key": "ResponsibleUser",
"display_name": "Ответственный",
"type": "username"
}
]
Структура для этих настроек в server/plugin/configuration.go:
type Configuration struct {
ServiceURL string
Template string
MaxItems int
EnableNotifications bool
Mode string
Language string
WebhookSecret string
ResponsibleUser string
}
Имена полей совпадают с key (регистр не важен), типы — по таблице выше.
Значения настроек лежат в конфигурации сервера Loop: PluginSettings.Plugins.<ID плагина> в config.json (или в базе данных, если конфигурация хранится там). Имена ключей там записаны строчными буквами.
sectionsВ новых версиях Mattermost настройки можно разбивать на секции (settings_schema.sections). В Loop этого нет: секции будут проигнорированы, и настройки из них не появятся в Системной консоли. Сборка шаблона такую ошибку не поймает — используйте плоский список settings.