You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Версия: maxapi-python 2.4.0 (в main на сегодня код src/pymax/formatting/markdown.py идентичен — баг актуален и в 2.4.1). Python 3.10.
Проблема
Client.send_message() безусловно прогоняет текст через Formatter.format_markdown(). Парсер считает маркерами одиночные _ и * и ищет для них пару в пределах строки, не проверяя, стоит ли маркер внутри слова. Из-за этого он вырезает символы из обычного текста, который никакой разметкой не был.
Больнее всего это бьёт по ссылкам: в MAX ссылка распознаётся по самому тексту, и после вырезанного подчёркивания она просто перестаёт открываться. У меня так побился закреплённый пост в канале — половина ссылок на боты и каналы стали нерабочими, причём без единой ошибки в логах.
Воспроизведение
from pymax.formatting.markdown import Formatter
for s in [
"https://max.ru/channel_iclub_new",
"https://t.me/Iclub_tradein_bot",
"https://t.me/iclubnsk_bot",
"snake_case_name",
"цена 52 = 10, скидка 33",
]:
print(repr(s), "->", repr(Formatter.format_markdown(s)[0]))
Ожидалось: текст без изменений — курсив тут никто не имел в виду.
Отдельно неприятно, что поведение выглядит случайным: строка с одним _ проходит нормально, а с двумя — молча портится. Пока не заглянешь в исходники библиотеки, кажется, что это делает сервер MAX.
Причина
src/pymax/formatting/markdown.py, format_markdown(): маркер открывается по любому совпадению text.startswith(marker, i), без проверки соседних символов. В CommonMark на это есть отдельное правило: _ не может открывать или закрывать эмфазис, если слева и справа от него стоят буквы или цифры (intraword emphasis запрещён именно ради snake_case и URL). Для * правило мягче, но 5*2 в CommonMark тоже не курсив — закрывающий маркер должен быть left-flanking.
Что предлагаю (любого пункта хватило бы)
Не открывать _ внутри слова — проверять символы вокруг маркера по правилу CommonMark. Это чинит и ссылки, и snake_case, и не ломает нормальный курсив.
Поддержать экранирование _, * — сейчас обратный слеш просто остаётся в тексте, а маркер всё равно срабатывает.
Дать возможность выключить разметку — например send_message(..., parse_mode=None) или format=False. Это же закрыло бы и запрос Добавить поддержку HTML-форматирования сообщений #91 (HTML-форматирование): выбор режима вместо жёстко зашитого markdown.
Сейчас единственный способ отправить текст как есть — обезьяний патч Formatter.format_markdown = lambda t: (t, []) до вызова send_message(), что, понятно, ломается на любом рефакторинге библиотеки.
Спасибо за библиотеку — в остальном она отлично работает.
Версия: maxapi-python 2.4.0 (в main на сегодня код src/pymax/formatting/markdown.py идентичен — баг актуален и в 2.4.1). Python 3.10.
Проблема
Client.send_message() безусловно прогоняет текст через Formatter.format_markdown(). Парсер считает маркерами одиночные _ и * и ищет для них пару в пределах строки, не проверяя, стоит ли маркер внутри слова. Из-за этого он вырезает символы из обычного текста, который никакой разметкой не был.
Больнее всего это бьёт по ссылкам: в MAX ссылка распознаётся по самому тексту, и после вырезанного подчёркивания она просто перестаёт открываться. У меня так побился закреплённый пост в канале — половина ссылок на боты и каналы стали нерабочими, причём без единой ошибки в логах.
Воспроизведение
from pymax.formatting.markdown import Formatter
for s in [
"https://max.ru/channel_iclub_new",
"https://t.me/Iclub_tradein_bot",
"https://t.me/iclubnsk_bot",
"snake_case_name",
"цена 52 = 10, скидка 33",
]:
print(repr(s), "->", repr(Formatter.format_markdown(s)[0]))
Результат:
'https://max.ru/channel_iclub_new' -> 'https://max.ru/channeliclubnew'
'https://t.me/Iclub_tradein_bot' -> 'https://t.me/Iclubtradeinbot'
'https://t.me/iclubnsk_bot' -> 'https://t.me/iclubnsk_bot' # уцелела: маркер один, пары нет
'snake_case_name' -> 'snakecasename'
'цена 52 = 10, скидка 33' -> 'цена 52 = 10, скидка 33'
Ожидалось: текст без изменений — курсив тут никто не имел в виду.
Отдельно неприятно, что поведение выглядит случайным: строка с одним _ проходит нормально, а с двумя — молча портится. Пока не заглянешь в исходники библиотеки, кажется, что это делает сервер MAX.
Причина
src/pymax/formatting/markdown.py, format_markdown(): маркер открывается по любому совпадению text.startswith(marker, i), без проверки соседних символов. В CommonMark на это есть отдельное правило: _ не может открывать или закрывать эмфазис, если слева и справа от него стоят буквы или цифры (intraword emphasis запрещён именно ради snake_case и URL). Для * правило мягче, но 5*2 в CommonMark тоже не курсив — закрывающий маркер должен быть left-flanking.
Что предлагаю (любого пункта хватило бы)
Сейчас единственный способ отправить текст как есть — обезьяний патч Formatter.format_markdown = lambda t: (t, []) до вызова send_message(), что, понятно, ломается на любом рефакторинге библиотеки.
Спасибо за библиотеку — в остальном она отлично работает.