Files
LawBot/bot/utils/text_tools.py
T
2026-05-25 01:12:43 +03:00

121 lines
3.7 KiB
Python

import html
import re
def to_html(obj):
return html.escape(str(obj))
def format_llm_answer_html(text: str | None) -> str:
if text is None:
return ""
escaped = html.escape(str(text).replace("\r\n", "\n").strip())
normalized_lines = []
for line in escaped.split("\n"):
normalized_line = re.sub(r"^\s*[-*]\s+", "", line.rstrip())
normalized_lines.append(normalized_line)
formatted = "\n".join(normalized_lines)
formatted = re.sub(r"\*\*(.+?)\*\*", r"<b>\1</b>", formatted)
return formatted
def split_plain_text_chunks(text: str | None, limit: int = 3500) -> list[str]:
if text is None:
return [""]
normalized = str(text).replace("\r\n", "\n").strip()
if not normalized:
return [""]
paragraphs = normalized.split("\n\n")
chunks: list[str] = []
current = ""
for paragraph in paragraphs:
paragraph = paragraph.strip()
if not paragraph:
continue
candidate = paragraph if not current else f"{current}\n\n{paragraph}"
if len(candidate) <= limit:
current = candidate
continue
if current:
chunks.append(current)
current = ""
if len(paragraph) <= limit:
current = paragraph
continue
lines = paragraph.split("\n")
line_buffer = ""
for line in lines:
line = line.rstrip()
line_candidate = line if not line_buffer else f"{line_buffer}\n{line}"
if len(line_candidate) <= limit:
line_buffer = line_candidate
continue
if line_buffer:
chunks.append(line_buffer)
line_buffer = ""
while len(line) > limit:
chunks.append(line[:limit].rstrip())
line = line[limit:].lstrip()
line_buffer = line
if line_buffer:
current = line_buffer
if current:
chunks.append(current)
return chunks or [normalized[:limit]]
def parse_links_to_inline_markup(message: str) -> list:
"""
Парсит сообщение с форматированными ссылками и возвращает список рядов кнопок.
Формат входного сообщения:
- [Текст кнопки + Ссылка] для одной кнопки.
- [Кнопка1 + Ссылка1][Кнопка2 + Ссылка2] для нескольких кнопок в одном ряду.
- Каждая строка представляет отдельный ряд кнопок.
Пример:
[Кнопка1 + https://example.com]
[Кнопка2 + https://example.org][Кнопка3 + https://example.net]
:param message: Строка с отформатированными ссылками.
:return: Список рядов кнопок, где каждый ряд — это список кортежей (Текст, Ссылка).
"""
# Исправленное регулярное выражение для поиска [Текст + Ссылка]
pattern = re.compile(r"\[([^\[\]+]+)\s*\+\s*(https?://[^\[\]]+)\]")
# Инициализируем список рядов кнопок
keyboard_rows = []
# Разбиваем сообщение на строки
lines = message.strip().split("\n")
for line in lines:
# Находим все совпадения в строке
matches = pattern.findall(line)
if matches:
row = []
for text, url in matches:
button = (text.strip(), url.strip())
row.append(button)
keyboard_rows.append(row)
return keyboard_rows