telegram-cli-bot/bot/utils/cleaners.py

82 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""Утилиты для очистки текста (ANSI-коды, нормализация)."""
import re
def clean_ansi_codes(text: str) -> str:
"""
Очистка ANSI-кодов и мусора из вывода терминала.
Обрабатывает:
- ANSI escape-последовательности \x1b[...m
- «Битые» ANSI-коды без escape-символа (например [33m, [0m)
- Символы замены Unicode ()
- Кириллические имитации ANSI-кодов (например [0м)
"""
# Удаляем ANSI escape-последовательности
text = re.sub(r'\x1b\[[0-9;?]*[a-zA-Z]', '', text)
# Удаляем «битые» ANSI-коды: [33m, [0m, [1m и т.д. (латиница и кириллица)
text = re.sub(r'\[\d+[мm]', '', text)
# Удаляем символы замены Unicode
text = text.replace('\ufffd', '')
return text
def normalize_output(text: str) -> str:
"""
Нормализовать вывод: обработать \r и убрать пустые строки.
\r используется для перезаписи строки (прогресс-баров).
"""
# Заменяем \r\n на \n
text = text.replace('\r\n', '\n')
# Обрабатываем \r (возврат каретки) — строки с \r перезаписывают друг друга
lines = []
for line in text.split('\n'):
if '\r' in line:
# Разбиваем по \r и берём последнюю часть (финальное состояние)
parts = line.split('\r')
line = parts[-1]
lines.append(line)
text = '\n'.join(lines)
# Разбиваем на строки, убираем пустые и trailing пробелы
lines = text.split('\n')
lines = [line.rstrip() for line in lines if line.strip()]
# Очищаем прогресс-бары вида "Текст… 0%Текст… 50%Текст… 100%"
# И дублирующийся текст
cleaned_lines = []
for line in lines:
# Ищем повторяющийся паттерн "текст… цифры%"
progress_pattern = re.compile(r'((?:.+?\.{3})\d+%)+')
match = progress_pattern.search(line)
if match:
# Берём последнее вхождение
items = re.findall(r'(.+?\.{3})(\d+)%', match.group(0))
if items:
last_text, last_percent = items[-1]
line = line[:match.start()] + f'{last_text}{last_percent}%' + line[match.end():]
# СНАЧАЛА удаляем остатки ANSI-кодов из строки
line = re.sub(r'.', '', line) # + любой символ
# Удаляем дублирующийся текст вида "0% [текст] 0% [текст]"
dup_pattern = re.compile(r'(\d+%\s*\[.+?\])(?:\s*\d+%\s*\[.+?\])+')
match = dup_pattern.search(line)
if match:
# Оставляем только первое вхождение
line = line[:match.start()] + match.group(1) + line[match.end():]
# Удаляем ведущие пробелы (артефакты терминала)
line = line.lstrip()
if line:
cleaned_lines.append(line)
return '\n'.join(cleaned_lines)