惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
Blog — PlanetScale
Blog — PlanetScale
L
LangChain Blog
aimingoo的专栏
aimingoo的专栏
Martin Fowler
Martin Fowler
D
Docker
酷 壳 – CoolShell
酷 壳 – CoolShell
A
About on SuperTechFans
WordPress大学
WordPress大学
The Register - Security
The Register - Security
MongoDB | Blog
MongoDB | Blog
O
OpenAI News
Cyberwarzone
Cyberwarzone
P
Proofpoint News Feed
A
Arctic Wolf
B
Blog RSS Feed
I
InfoQ
C
Cisco Blogs
F
Fortinet All Blogs
T
Threatpost
N
Netflix TechBlog - Medium
AWS News Blog
AWS News Blog
S
SegmentFault 最新的问题
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cloudbric
Cloudbric
Webroot Blog
Webroot Blog
Recent Announcements
Recent Announcements
T
Troy Hunt's Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
小众软件
小众软件
L
LINUX DO - 最新话题
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
The Blog of Author Tim Ferriss
IT之家
IT之家
Latest news
Latest news
L
Lohrmann on Cybersecurity
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Attack and Defense Labs
Attack and Defense Labs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
云风的 BLOG
云风的 BLOG
Recent Commits to openclaw:main
Recent Commits to openclaw:main
G
Google Developers Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
E
Exploit-DB.com RSS Feed
T
Tenable Blog
S
Secure Thoughts
PCI Perspectives
PCI Perspectives
Forbes - Security
Forbes - Security
S
Schneier on Security

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Кто решает судьбу вашего проекта? Разбираем заинтересованные стороны. BABOK #1 Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Практическое махоботоводство в 2026 году. Часть 1
lubezniy · 2026-06-14 · via Все публикации подряд на Хабре

Сразу оговорюсь: здешнее отношение к маху мне известно. У меня оно сугубо прагматичное: если в каких-то условиях деструктивное нытьё не работает, то и решать проблему хочешь или нет, надо конструктивно — то есть, делом. Поставили задачу бота сделать — выполняем.

В этой, первой, публикации опишу текущий способ и условия регистрации ботов в MAX, расскажу про отличия Bot API у Telegram и MAX и приведу проверенный Hello, world на чистом PHP.

Disclaimer: материал данной части собирался и описывался в течение начала-середины 2026 года. И публикация содержит информацию, актуальную на момент сбора. Не быстро, но всё же меняются и API, и методики. Возможно, на момент прочтения информация здесь может быть не очень актуальной или содержать ошибки; для серьёзной работы рекомендуется предварительно проверить всё самостоятельно.

Порядок регистрации ботов в MAX

Начнём с условий и порядка создания ботов. Для регистрации бота на момент написания материала нужен аккаунт в MAX и верифицированный бизнес-аккаунт хозяйствующего субъекта на бизнес-портале MAX business.max.ru с тем же номером телефона. Такой аккаунт могут завести российское юридическое лицо или индивидуальный предприниматель. Верификация хозяйствующего субъекта доступна через портал госуслуг и несколько крупных банков. Обладание таким аккаунтом даёт возможность создать один публичный канал и до пяти ботов. При этом их публичные имена будут прямо указывать на владельца, т. к. содержат его ИНН. Но некоторые боты имеют нормальные публичные имена. Как они это сделали, не знаю, предполагать не буду; у меня задач по переименованию не было.

Сама регистрация бота осуществляется на бизнес-портале после верификации и привязки аккаунта в MAX. Порядок несколько месяцев назад был такой: заполняется форма с данными (а просят там в том числе сайт и телефон компании, и попробуй не введи, но никто не мешает давать ссылки на другие площадки в качестве сайта), которые после ввода уходят на модерацию. Модерация, если я правильно помню написанное (дело было уже не один месяц назад), длится до нескольких часов, в моём случае управились минут за 20. Может, потому, что делал в рабочее время по московскому, не знаю.

Уведомление о прохождении модерации приходит в MAX. Дальше на том же портале делается токен доступа к боту, который используется в API.

Подытоживаем: порядок весьма своеобразный, но в принципе работающий невзирая на ограничения. Пару ботов под отладку своей либы и отдельно ботов под проекты я завёл; разработчики, работающие на российские компании, с помощью своих работодателей тоже могут завести ботов под свои задачи. Но: практически всё делающееся через бот делается под токеном, принадлежащим бизнесу, действия логируются, а штрафы за какие-то пусть неосознанные, но незаконные действия для бизнеса, как правило, выше, чем для обычных граждан. Поэтому и с отладкой стоит быть аккуратнее, и боевые задачи, если речь идёт, например, о чувствительных данных вроде персональных, не мешает обсудить с юристом, которому дополнительно можно дать почитать громадное количество правил, требований и инструкций от MAX. Публичных каких-то средств для тестирования и отладки от MAX я не видел. Так что осваиваемся, что называется, в учебно-боевых условиях.

Разница в Bot API у MAX и Telegram

Перейдём к API. Он описан на портале для разработчиков dev.max.ru; в нём сейчас около 30 методов (а всего в библиотеке описаний запросов, ответов и объектов у меня получилось на данный момент 82, и это я ещё некоторые структуры объединил). Разработчики MAX опубликовали на github и поддерживают две официальных библиотеки — под TypeScript и Golang. В последнее время я занимаюсь работой на PHP с фреймворком yii2, и переписывать большие проекты на что-то предложенное нет ни времени, ни желания. Так что взялся за разработку библиотеки и пока в несколько недоделанном варианте использую её в нескольких проектах. Но про неё напишу в следующих частях.

Так получилось, что мне приходилось и до сих пор приходится активно заниматься разработкой и сопровождением чатботов для Telegram. И не особо сомневаюсь, что backend-коллеги, которым нужно работать по чатботам MAX, уже во многом имеют аналогичный опыт работы с Telegram-ботами. Поэтому считаю, что будет полезно описать основные глобальные и не очень отличия для понимания, как организовать разработку для своих языков программирования, сред разработки и исполнения. Всю документацию, конечно, пересказывать не буду; просто опишу то, что выловилось в процессе разработки либы.

Первое — способы отправки запросов к Bot API

В Telegram токен бота передаётся в URI запроса, а HTTP-метод запроса имеет относительно небольшое значение. Поэтому с ним для простой отправки сообщения в том же PHP можно слепить URL из всех необходимых параметров, дёрнуть его командой file_get_contents, и дело в шляпе.

С MAX так не получится: токен передаётся через заголовок запроса, параметры в зависимости от метода API приходится подставлять и в URI, и в query string, и в тело запроса JSON-ом, ну и HTTP-методы используются разные. Т. е., не обойтись без полноценного HTTP-клиента вроде curl и работы с JSON, а для экспериментов можно использовать Postman, RESTer и другие подобные продукты или небольшие скрипты. Ну хоть ответ всегда возвращается в JSON (ну кроме скачиваемого файла). Ниже, в разделе «Hello, world», будет пример кода отправки сообщения на чистом PHP; если заведёте бота, можете поэкспериментировать.

Второе — получение апдейтов

Как и в Telegram, в MAX для получения ботом информации о новых событиях (апдейтов) реализованы два механизма: long polling (запрос бота на сервер мессенджера) и вебхуки (мессенджер сам отправляет запросы на заданный URL бота).

Отличие: MAX настоятельно не рекомендует, если вообще не запрещает (в разных местах документации написано по-разному, и понять не очень просто), использовать long polling в продакшне.

Дополнение №1: при опросе MAX-бота в бесконечном цикле с какими-то другими действиями важно не забывать устанавливать в запросе параметр timeout, иначе ожидание ответа может длиться с полминуты, если апдейтов нет.

Дополнение №2: при опросе необходимо считывать из ответа и далее подставлять снова в запрос параметр marker. В противном случае апдейты в выдачах могут дублироваться.

Отдельно предостерегу от попыток использования long polling на боте, подписанном на вебхуки. Телеграм в этом случае с ходу посылает запрашивающего клиента лесом, а Макс почему-то нет. Какие апдейты он отдаст, а какие нет — непредсказуемо. Так что сначала делаем GET /subscriptions (метод получения списка подписок в MAX Bot API), затем по каждой подписке делаем DELETE /subscriptions (URL удаляемой подписки идёт в запрос), а после этого уже можно поллить.

По вебхукам у меня нормально заработал вариант с сервером в России и SSL-сертификатом от Let’s Encrypt. Работает только https на дефолтном порту TCP/443, нестандартные порты и самоподписанные сертификаты не поддерживаются. Отправку Максом вебхук-запросов за бугор (как и приём оттуда запросов) не проверял.

В вебхуках при отправке запроса на подписку очень важно задавать параметр secret и сверять его значение со значением HTTP-заголовка X-Max-Bot-Api-Secret каждого входящего запроса. По сути это единственная имеющаяся на данный момент в MAX защита от подделки входящих запросов.

Третье — начало и конец общения пользователя с ботом

В Telegram, как мы знаем, «личную» переписку с чатботом всегда начинает пользователь. При этом боту в апдейте приходит сообщение с текстом /start. А в MAX первое, что нужно сделать пользователю чатбота для начала работы с ним, это в чате или профиле бота нажать кнопку «Начать» (по сути — подписаться на бота и позволить ему отправлять пользователю сообщение). При этом боту приходит не сообщение, а апдейт с типом bot_started; при его обработке часто есть смысл зафиксировать id и контакт пользователя и отправить ему какое-нибудь приветственное сообщение. После «начала» кнопка «Начать» исчезнет, а в выпадающем меню окна профиля бота появятся варианты «Остановить» и «Удалить и остановить». При выборе любого из этих вариантов произойдёт отписка от бота, и боту отправится апдейт с типом bot_stopped. После «остановки» бота отправить пользователю сообщение не получится, пока пользователь вновь не нажмёт «Начать»; боту есть резон зафиксировать у себя, что подписка приостановлена, и до возобновления подписки не пытаться что-то этому пользователю отправлять.

Четвёртое — форматы id

У Telegram, как известно, все id числовые, а id сообщения представляет собой его порядковый номер в конкретном чате. В MAX многие id также числовые, но не id сообщения. Последний имеет строковой тип; там что-то больше похожее на длинный уникальный идентификатор, глобальный минимум в пределах всего мессенджера. И, например, при удалении сообщения соответствующему методу нужно передавать в запросе только id сообщения; id чата не нужен.

Про основные функциональные отличия

Скачивание файлов ботом

Максимальный размер загружаемого файла у обоих мессенджеров составляет 4 гигабайта. Но, если у Telegram бот может скачать файл-вложение максимум в 20 мегабайт, то у MAX такое ограничение (пока?) отсутствует. При этом, насколько я понял, ссылки на скачивание файлов MAX отдаёт не временные, а постоянные. Это очень упрощает скачивание, но насколько это безопасно — вопрос.

Получение сообщений из чата

Если бот подписан на какой-то чат или канал, то Telegram, если я правильно помню, шлёт апдейты о новом сообщении или посте в канал, и на этом всё: после обработки (или необработки) апдейта сообщение через Bot API более не доступно.

В MAX есть пока мной не проверенный, но метод GET /messages, ему можно подсунуть id сообщений или chat_id, и получай JSON с данными. На мой взгляд, это плюс, если адекватен механизм контроля доступа. Для бэкапов очень даже норм (надеюсь, никто не возражает, что резервное копирование переписки в мессенджере у себя иногда бывает очень полезным).

Кнопки под сообщениями из бота

В Telegram Bot API реализованы весьма богатые возможности для подстановки кнопок под сообщения, сформированные ботом. Но с ними не всегда с ходу получается разобраться, и порой случаются вещи, требующие долгой возни.

В MAX для этого к сообщению прикладывается относительно простой аттач с типом inline_keyboard и описанием кнопок. Но есть особенности.

Особенность 1: в MAX клавиатуру нельзя с помощью её настроек сделать исчезающей после нажатия кнопки. Пока не проверял, но, по идее, редактированием сообщения через соответствующий метод бота после обработки нажатия кнопки можно аттач убрать, и тогда клавиатура исчезнет.

Особенность 2: для MAX придётся учиться писать названия кнопок коротко. Текст названия кнопки, не помещающийся в её размер, не переносится даже по словам, а просто остаётся за границами видимой области. При этом на десктопной и мобильной версиях размеры этой видимой области получаются разные. В документации в описании к соответствующему методу MAX даны рекомендации по максимальному количеству символов, которые рекомендуется использовать.

Меню команд

В MAX Bot API есть метод задания меню команд, но вот работа созданного им меню на клиентах… я пока так до конца и не понял, как с ней обстоит дело. На мобильных под Android это меню есть, но нет отдельной кнопки для его вызова; надо догадаться нажать / на клавиатуре. На десктопной версии под Windows этого меню нет вообще (или не сработало у меня?). Веб-версию и огрызки лично не проверял (а с последними событиями появились сомнения в смысле проверки на огрызках). При этом есть распознавание текста команды в тексте сообщения с автоматической подстановкой ссылки. Но работает почему-то не у всех пользователей бота; что когда, пока так и не понял. В общем, провожу пока исследование и приглашаю коллег в помощь — вдруг кто-то уже понял принципы.

Текстовый контент сообщений

В отправляемом сообщении у Telegram Bot API можно задать один из трёх режимов парсинга текста: plain text, markdown и HTML. У MAX нет plain text. Также нет возможности сделать и задать скрытый текст. Ну и не разбирался со сколь-нибудь сложным форматированием текста; мои задачи пока этого не требовали. Под документирование этого дела есть отдельная страница на портале разработчиков MAX – https://dev.max.ru/docs-api#Форматирование текста в сообщениях

Ещё. Не проверял, как в Telegram, но в MAX не поддерживаются гиперссылки, у которых в URL указаны протоколы вроде tg, max и т. п. Такая ссылка в клиентском приложении не будет подсвечиваться как ссылка. Аналогично, если написать символ @ и публичное имя и попытаться добавить гиперссылку, например, на t.me с Telegram-профилем: у меня это не сработало (проверял с месяц назад).

Бан-разбан

Как известно, в Telegram Bot API есть запросы banChatMember и unbanChatMember. У MAX есть метод удаления пользователя из канала или чата DELETE /chat/{id}/{members}. И у этого метода есть применимый к чатам параметр block — забанить пользователя помимо удаления. Вроде бы и норм, но нигде не нашёл, как разбанить обратно. Поэтому этим параметром пользуемся с максимальной осторожностью. И тест на бан я делать точно не собираюсь. Так или иначе, пока чаты в MAX закрыты, практического смысла использовать эти методы там в принципе не очень много, да и сами принципы отображения добавления и удаления пользователей в чате имеют немало недостатков. Поэтому считаю, что лучше дождаться доработок.

Редактирование данных бота — undocumented в MAX

В документации по API MAX отсутствует информация о возможности редактировать данные бота через API; при этом соответствующий метод есть в штатной библиотеке для TypeScript, и он работает (в том числе в моей либе, но в production я его не применял). Отредактировать так публичное имя бота не получится; изменения, внесённые через API, применяются сразу, без модерации.

Опросы

В обоих мессенджерах есть возможность создавать опросы; у Telegram возможностей побольше, у MAX поменьше. Но в Telegram Bot API есть возможность отправить опрос ботом (метод sendPoll), а в MAX – почему-то нет.

Лайки

В Telegram, как известно, боты могут принимать апдейты вида MessageReactionUpdated – когда пользователь ставит лайк на сообщение. Ну и бот тоже может сам ставить лайк на какое-то сообщение, отправив запрос setMessageReaction. Это бывает удобно в рабочих чатах, когда бот является полноценным «участником» чата. В MAX, к сожалению, ничего такого (пока?) нет.

Прочее

Ещё про функциональное отличие, но уже не мессенджера. Документация по Telegram Bot API сделана в одном HTML-файле, и её легко скачать одним запросом. А для мониторинга изменений в ботовом API MAX приходится смотреть десятки ссылок.

Отдельно вкратце опишу загрузку файлов ботом MAX. Делается она в два приёма. Сначала POST-запросом передаётся тип файла, в ответ возвращаются URL для загрузки собственно файла и токен для последующей подстановки файла в отправляемые сообщения (можно не в одно). Загружаем файл POST-запросом на URL (описание API предлагает два способа), иногда ждём подготовку, и можно отправлять сообщение. Сам пока только отрабатываю эту тему на практике, отлаживая библиотеку на разрабатываемых примерах. Описано всё в документации здесь — https://dev.max.ru/docs-api/methods/POST/uploads

Также MAX имеет возможность создавать мини-приложения на базе ботов, и они уже в общем неплохо работают в качестве суррогатных заменителей комментариев к каналам. Но в этой теме, да и вообще во frontend-разработке, я не настолько силён, чтобы что-то писать. Подробности расписаны на портале разработки MAX. А мы продолжим бэк и наконец перейдём к Hello, world.

Hello, world

На чистом PHP 8-й версии с расширениями curl и json функция отправки ботом «в личку» пользователю сообщения с текстом выглядит примерно так:

/**
 * @param string $botToken токен бота
 * @param integer $userId id пользователя-получателя
 * @param string $text текст (HTML-код) сообщения
 * @return mixed Ответ от сервера
 */
function sendTextMessage(string $botToken, int $userId, string $text): mixed
{
    /** @var string $url URL запроса */
    $url = 'https://platform-api.max.ru/messages?user_id=' . $userId;
    /** @var CurlHandle $ch handle объекта cURL */
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_VERBOSE, false);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Host: ' . parse_url($url, PHP_URL_HOST),
        'Accept: application/json',
        'Content-Type: application/json',
        'Authorization: ' . $botToken,
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        'text' => $text,
        'format' => 'html',
    ], JSON_UNESCAPED_UNICODE));
    return curl_exec($ch);
}

id своего пользовательского аккаунта в MAX для получения сообщений от бота можно получить, подписавшись на бот (кнопка «Начать» в профиле бота или чате) и приняв апдейты от бота. Дальше в материале я покажу это на практике. Если вебхуки на бот не прописаны, то для этого можно любым http-клиентом сделать такой запрос (пример — опять же функция на чистом PHP):

/**
* @param string $botToken токен бота
* @param string|null $types Типы апдейтов через запятую и пробел
* @param integer $timeout Сколько секунд висеть запросу в ожидании апдейтов
* @param integer|null $marker Маркер от предыдущего запроса
* @return mixed Ответ от сервера
*/
function getUpdates(string $botToken, ?string $types = 'bot_started, bot_stopped', ?int $timeout = 1, ?int $marker = null): mixed
{
  /** @var array $getParams параметры GET-запроса */
  $getParams = [];
  if (isset($types)) {
      $getParams['types'] = $types;
  }
  if (isset($timeout)) {
    $getParams['timeout'] = $timeout;
  }
  if (isset($marker)) {
    $getParams['marker'] = $marker;
  }
  /** @var string $url URL запроса */
  $url = 'https://platform-api.max.ru/updates';
  if (!empty($getParams)) {
    $url .= '?' . http_build_query($getParams);
  }
  /** @var CurlHandle $ch handle объекта cURL */
  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_VERBOSE, false);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'Host: ' . parse_url($url, PHP_URL_HOST),
      'Accept: application/json',
      'Authorization: ' . $botToken,
  ]);
  return curl_exec($ch);
}

В этом коде сначала в зависимости от значения параметров собирается key-value массив. Дальше из него формируется query string для запроса, в отдельном key-value массиве собираются заголовки запроса, всё это отдаётся в CURL, запрос отправляется, и функция возвращает контент того, что сервер отдал в ответ (в кодировке JSON).

Лирическое отступление про получение других id

С получением id чата будет посложнее. Бот добавляется в чат через интерфейс мессенджера сначала с правами рядового пользователя, а затем может быть назначен администратором. Но: апдейт с типом bot_added и id чата (собственно приём этого апдейта и есть способ получения id) придёт при добавлении бота как пользователя, а апдейты message_created (уведомления о сообщениях) будут приходить только после того, как участник с соответствующими правами в чате назначит бота админом; об этом назначении бот никакими апдейтами не уведомляется. Что можно делать боту-пользователю, не знаю, не исследовал вопрос. Пока могу только предположить, что он может просто постить какие-то сообщения, но это ещё требует проверки.

По каналам (проверял на частном) несмотря на наличие кнопки «Добавить администратора» туда добавить бота не получилось. Получилось так же, как с чатом: добавил бота подписчиком — пришёл апдейт bot_added, где в chat_id был id канала; потом назначил его администратором и таким образом получил возможность постить в канал.

На всякий случай: в MAX Bot API (во всяком случае пока) получить id и другую информацию по публичной ссылке можно только для публичного канала методом GET /chats/{ссылка}; и то это я пока не проверял. Других методов не видел.

Заканчиваем Hello, world

Для здешнего Hello, world нужно иметь машинку с PHP8, библиотекой и расширением curl и зарегистрированного MAX-бота с публичным именем и секретным токеном.

Первым делом создаём скрипт, куда копируем вышеприведённые функции и пишем их вызовы с обязательным выводом результата на экран, в файл или другое доступное место. В вызовы подставляем текст сообщения (Hello, world) и токен бота.

Теперь получаем id пользователя бота. Для этого в мессенджере по публичному имени находим бота, в нём нажимаем «Начать». После этого скриптом вызываем функцию getUpdates и в её результате находим id пользователя. Результат, конечно, записываем.

Осталось дописать в вызов функции sendTextMessage полученный id своего пользователя и выполнить этот вызов в скрипте. Если всё нормально, то пользователю от бота придёт сообщение, которое можно будет в мессенджере прочитать.

Итог

В первом материале мы разобрали особенности работы с MAX Bot API без привязки к конкретному языку с примерами на PHP. В следующем рассчитываю рассказать про yii2-библиотеку и на примерах её использования описать отправку запросов посложнее (например, сообщения с кнопками, загрузка файлов — посмотрим). Если есть какая-то актуальная тема для рассмотрения в общем плане, пишите в комментах — может, что-то уже делал, и есть что рассказать.