Skip to content

Repository files navigation

MAX Client (Flask-версия)

Скачать APK (последний релиз)

Кастомные боты

Клиент умеет подключать сторонних ботов, никак не связанных с протоколом MAX — им нужен только собственный веб-сервер (адрес + порт), отвечающий на два простых HTTP-эндпоинта. Переписка с таким ботом ведётся полностью локально (переписка хранится в localStorage браузера) и не проходит через основной MAX-аккаунт.

Управление ботами: Настройки → 🤖 Кастомные боты.

Видимость в поиске

Добавленные кастомные боты видны в общем поиске по чатам (поле поиска над списком чатов), наравне с чатами и контактами MAX. Также поиск понимает @username и ссылки вида https://max.ru/... — такой запрос показывает пункт «Найти в MAX: …», который резолвит профиль/чат/бота напрямую через сервер.

Порядок выдачи в поиске (сверху — выше приоритет):

  1. существующие чаты MAX (уже открытые диалоги/каналы);
  2. контакты MAX, с которыми ещё нет диалога;
  3. кастомные боты — сначала добавленные вручную, затем недавно «запускавшиеся» (открытые/использованные), затем остальные из реестра;
  4. локальные контакты телефона;
  5. подсказка «Найти в MAX: …» для @username / ссылок max.ru — резолвится на сервере, поэтому показывается последней.

1. Реестр ботов (GitHub)

Реестр — это обычный JSON-файл, который лежит в любом GitHub-репозитории и отдаётся через raw.githubusercontent.com (никакого отдельного бэкенда не нужно — хранилищем служит сам GitHub).

Формат bots.json:

[
{
"name": "EchoBot",
"url": "http://1.2.3.4:8080",
"description": "Отвечает эхом на любое сообщение"
},
{
"name": "WeatherBot",
"url": "http://myhost.example.com:9090",
"description": "Прогноз погоды по городу"
}
]

Поля:

ПолеОбязательноОписание
nameдаОтображаемое имя бота
urlдаБазовый адрес сервера бота, с портом (http://host:port, без завершающего /)
descriptionнетКороткое описание, показывается в списке реестра

Как подключить свой реестр в клиенте:

  1. Настройки → «Кастомные боты».
  2. В поле «Raw-ссылка на bots.json» вставить ссылку вида https://raw.githubusercontent.com/<пользователь>/<репозиторий>/<ветка>/bots.json.
  3. Нажать «⟳ Загрузить реестр» — появится список ботов с кнопкой «➕ Добавить».

Бота также можно добавить вручную (без реестра), указав только имя и http://host:port в форме «Добавить бота вручную».

2. API-контракт сервера бота

Сервер бота — это любой HTTP-сервер (Python/Node/Go/что угодно), который реализует два эндпоинта.

GET {url}/api/info

Необязательный, но рекомендуемый эндпоинт для отображения информации о боте.

Ответ 200 OK:

{
"name": "MyBot",
"description": "Что умеет бот",
"avatar_url": "https://example.com/avatar.png",
"version": "1.0"
}

POST {url}/api/message

Основной эндпоинт — клиент вызывает его при каждом сообщении пользователя.

Тело запроса (Content-Type: application/json):

{
"chat_id": "bot_a1b2c3d4",
"user": { "id": 123456, "name": "Пользователь" },
"text": "Привет!",
"history": [
{ "role": "user", "text": "предыдущее сообщение", "ts": 1690000000000 },
{ "role": "bot", "text": "предыдущий ответ бота", "ts": 1690000001000 }
]
}
  • chat_id — локальный идентификатор чата с этим ботом в клиенте (стабилен для одной установки клиента).
  • user — данные текущего пользователя клиента.
  • text — текст только что отправленного сообщения.
  • history — последние до 20 сообщений переписки (для контекста; можно игнорировать, если боту не нужна память).

Ответ (200 OK, Content-Type: application/json):

{
"text": "Привет! Чем могу помочь?\n\n```bash\necho hello\n```",
"buttons": [
[ { "text": "Кнопка 1", "value": "payload_1" } ]
]
}
  • text — обязателен, текст ответа бота. Поддерживает блоки кода в формате ```язык ... ``` — они будут красиво отрисованы клиентом с кнопкой копирования.
  • buttons — необязательно, зарезервировано под будущую поддержку инлайн-кнопок (сейчас клиент их не рендерит, но принимает без ошибок).

Любая ошибка сети или ответ не 200 отображается пользователю прямо в чате как системное сообщение вида «⚠️ Бот недоступен: …» — сам клиент не падает и не блокируется.

CORS (обязательно для локального теста в браузере)

Клиент — веб-страница, поэтому запросы к {url}/api/message идут прямо из браузера. Если сервер бота не пришлёт заголовки CORS, браузер заблокирует ответ с ошибкой вида:

Access to fetch at 'http://127.0.0.1:1904/api/message' from origin 'http://localhost:8080'
has been blocked by CORS policy: ...

Это правится только на стороне сервера бота — добавь CORS-заголовки:

# Flask + flask-cors (pip install flask-cors)fromflask_corsimportCORSCORS(app) # для локального теста достаточно разрешить все origin'ы

Без библиотеки — вручную:

@app.after_requestdefadd_cors_headers(resp):
resp.headers["Access-Control-Allow-Origin"] ="*"resp.headers["Access-Control-Allow-Methods"] ="GET, POST, OPTIONS"resp.headers["Access-Control-Allow-Headers"] ="Content-Type"returnresp

Node/Express — app.use(require('cors')()); FastAPI — CORSMiddleware с allow_origins=["*"]. Для продакшена вместо "*" лучше указать конкретный адрес клиента.

Минимальный пример сервера бота (Python/Flask)

fromflaskimportFlask, request, jsonifyfromflask_corsimportCORSapp=Flask(__name__)
CORS(app) # разрешает запросы из браузера (клиент открыт на другом origin)@app.route("/api/info")definfo():
returnjsonify({
"name": "EchoBot",
"description": "Отвечает эхом на любое сообщение",
"version": "1.0",
})
@app.route("/api/message", methods=["POST"])defmessage():
data=request.get_json(force=True)
text=data.get("text", "")
iftext=='/about':
user_info=data.get('user', {})
ifisinstance(user_info, dict):
user_name=user_info.get('name', 'Unknown')
user_id=user_info.get('id', 'Unknown')
output_text=f"Имя: {user_name}, ID: {user_id}"else:
output_text=f"{user_info}"returnjsonify({"text": output_text})
else:
returnjsonify({
"text": f"Эхо: {text}"
})
if__name__=="__main__":
app.run(host="0.0.0.0", port=1904)

После запуска добавь бота в реестр (bots.json) или вручную в клиенте, указав http://<твой-адрес>:8080.

About

оптимизированный клиент Max на flask(python) и html.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages