bot rafactor and bugfix
This commit is contained in:
@@ -1,31 +1,111 @@
|
||||
from __future__ import annotations
|
||||
import shlex
|
||||
from typing import Dict
|
||||
from enum import Enum
|
||||
from typing import Dict, Optional
|
||||
|
||||
|
||||
class MessageType(Enum):
|
||||
TEXT = "text"
|
||||
PHOTO = "photo"
|
||||
VIDEO = "video"
|
||||
ANIMATION = "animation"
|
||||
|
||||
|
||||
class Messages:
|
||||
# Команды
|
||||
WELCOME_MESSAGE = (
|
||||
"👋 Привет! Я редактор постов для каналов.\n\n"
|
||||
"🤖 Сначала добавьте бота через /add_bot\n"
|
||||
"📢 Затем добавьте каналы через /add_channel\n"
|
||||
"📝 Потом можно:\n"
|
||||
"- Создать пост: /newpost\n"
|
||||
"- Управлять шаблонами: /tpl_new, /tpl_list\n"
|
||||
"- Посмотреть список ботов: /bots\n"
|
||||
"- Посмотреть список каналов: /channels\n\n"
|
||||
"❓ Справка: /help"
|
||||
)
|
||||
|
||||
HELP_MESSAGE = (
|
||||
"📖 Справка по командам:\n\n"
|
||||
"Управление ботами и каналами:\n"
|
||||
"/add_bot - Добавить нового бота\n"
|
||||
"/bots - Список ваших ботов\n"
|
||||
"/add_channel - Добавить канал\n"
|
||||
"/channels - Список ваших каналов\n\n"
|
||||
"Управление постами:\n"
|
||||
"/newpost - Создать новый пост\n\n"
|
||||
"Управление шаблонами:\n"
|
||||
"/tpl_new - Создать шаблон\n"
|
||||
"/tpl_list - Список ваших шаблонов"
|
||||
)
|
||||
|
||||
START = ("👋 Привет! Я редактор постов. Доступные команды:\n"
|
||||
"/newpost — создать новый пост\n"
|
||||
"/tpl_new — создать шаблон\n"
|
||||
"/tpl_list — список шаблонов")
|
||||
|
||||
# Ошибки
|
||||
ERROR_SESSION_EXPIRED = "❌ Сессия истекла. Начните заново с /newpost"
|
||||
ERROR_INVALID_FORMAT = "❌ Неверный формат. Попробуйте еще раз"
|
||||
ERROR_NO_CHANNELS = "❌ У вас нет каналов. Добавьте канал через админку"
|
||||
ERROR_TEMPLATE_NOT_FOUND = "❌ Шаблон не найден"
|
||||
ERROR_TEMPLATE_CREATE = "❌ Ошибка при создании шаблона: {error}"
|
||||
ERROR_INVALID_KEYBOARD = "❌ Неверный формат клавиатуры"
|
||||
|
||||
# Создание поста
|
||||
SELECT_CHANNEL = "📢 Выберите канал для публикации:"
|
||||
SELECT_TYPE = "📝 Выберите тип поста:"
|
||||
SELECT_FORMAT = "🔤 Выберите формат текста:"
|
||||
ENTER_TEXT = "✏️ Введите текст сообщения\nИли используйте #имя_шаблона для применения шаблона"
|
||||
ENTER_MEDIA = "📎 Отправьте {media_type}"
|
||||
ENTER_KEYBOARD = "⌨️ Введите клавиатуру в формате:\nтекст|url\nтекст2|url2\n\nИли отправьте 'skip' для пропуска"
|
||||
|
||||
# Шаблоны
|
||||
TEMPLATE_LIST = "📜 Список шаблонов (стр. {page}/{total_pages}):"
|
||||
TEMPLATE_CREATE_NAME = "📝 Введите имя для нового шаблона:"
|
||||
TEMPLATE_CREATE_TYPE = "📌 Выберите тип шаблона:"
|
||||
TEMPLATE_CREATE_FORMAT = "🔤 Выберите формат текста:"
|
||||
TEMPLATE_CREATE_CONTENT = "✏️ Введите содержимое шаблона:"
|
||||
TEMPLATE_CREATE_KEYBOARD = "⌨️ Введите клавиатуру или отправьте 'skip':"
|
||||
TEMPLATE_CREATED = "✅ Шаблон успешно создан"
|
||||
TEMPLATE_DELETED = "🗑 Шаблон удален"
|
||||
|
||||
# Отправка
|
||||
CONFIRM_SEND = "📤 Как отправить пост?"
|
||||
ENTER_SCHEDULE = "📅 Введите дату и время для публикации в формате YYYY-MM-DD HH:MM"
|
||||
POST_SCHEDULED = "✅ Пост запланирован на {datetime}"
|
||||
POST_SENT = "✅ Пост отправлен"
|
||||
|
||||
|
||||
class MessageParsers:
|
||||
@staticmethod
|
||||
def parse_template_invocation(s: str) -> tuple[str, Dict[str, str]]:
|
||||
"""
|
||||
Пример: "#promo title='Hi' url=https://x.y"
|
||||
-> ("promo", {"title":"Hi", "url":"https://x.y"})
|
||||
Парсит вызов шаблона вида: "#promo title='Hi' url=https://x.y"
|
||||
Возвращает: ("promo", {"title":"Hi", "url":"https://x.y"})
|
||||
"""
|
||||
s = (s or "").strip()
|
||||
if not s.startswith("#"):
|
||||
raise ValueError("not a template invocation")
|
||||
parts = shlex.split(s)
|
||||
name = parts[0][1:]
|
||||
args: Dict[str, str] = {}
|
||||
for tok in parts[1:]:
|
||||
if "=" in tok:
|
||||
k, v = tok.split("=", 1)
|
||||
args[k] = v
|
||||
return name, args
|
||||
|
||||
try:
|
||||
parts = shlex.split(s)
|
||||
name = parts[0][1:] # убираем #
|
||||
args: Dict[str, str] = {}
|
||||
|
||||
for tok in parts[1:]:
|
||||
if "=" in tok:
|
||||
k, v = tok.split("=", 1)
|
||||
args[k.strip()] = v.strip().strip('"\'')
|
||||
return name, args
|
||||
|
||||
except ValueError as e:
|
||||
raise ValueError(f"Ошибка парсинга шаблона: {e}")
|
||||
|
||||
@staticmethod
|
||||
def parse_key_value_lines(text: str) -> Dict[str, str]:
|
||||
"""
|
||||
Поддерживает:
|
||||
Парсит переменные в форматах:
|
||||
- построчно:
|
||||
key=value
|
||||
key2="quoted value"
|
||||
@@ -35,17 +115,60 @@ class MessageParsers:
|
||||
text = (text or "").strip()
|
||||
if not text:
|
||||
return {}
|
||||
if "\n" in text:
|
||||
out: Dict[str, str] = {}
|
||||
|
||||
try:
|
||||
if "\n" in text:
|
||||
# Построчный формат
|
||||
out: Dict[str, str] = {}
|
||||
for line in text.splitlines():
|
||||
line = line.strip()
|
||||
if "=" in line:
|
||||
k, v = line.split("=", 1)
|
||||
out[k.strip()] = v.strip().strip('"\'')
|
||||
return out
|
||||
else:
|
||||
# Однострочный формат
|
||||
out: Dict[str, str] = {}
|
||||
for tok in shlex.split(text):
|
||||
if "=" in tok:
|
||||
k, v = tok.split("=", 1)
|
||||
out[k.strip()] = v.strip()
|
||||
return out
|
||||
|
||||
except ValueError as e:
|
||||
raise ValueError(f"Ошибка парсинга переменных: {e}")
|
||||
|
||||
@staticmethod
|
||||
def parse_keyboard(text: str) -> Optional[Dict]:
|
||||
"""
|
||||
Парсит клавиатуру в формате:
|
||||
текст1|url1
|
||||
текст2|url2
|
||||
|
||||
Возвращает:
|
||||
{
|
||||
"rows": [
|
||||
[{"text": "текст1", "url": "url1"}],
|
||||
[{"text": "текст2", "url": "url2"}]
|
||||
]
|
||||
}
|
||||
"""
|
||||
text = (text or "").strip()
|
||||
if not text or text.lower() == "skip":
|
||||
return None
|
||||
|
||||
try:
|
||||
rows = []
|
||||
for line in text.splitlines():
|
||||
if "=" in line:
|
||||
k, v = line.split("=", 1)
|
||||
out[k.strip()] = v.strip().strip('"')
|
||||
return out
|
||||
|
||||
out: Dict[str, str] = {}
|
||||
for tok in shlex.split(text):
|
||||
if "=" in tok:
|
||||
k, v = tok.split("=", 1)
|
||||
out[k] = v
|
||||
line = line.strip()
|
||||
if "|" in line:
|
||||
text, url = line.split("|", 1)
|
||||
rows.append([{
|
||||
"text": text.strip(),
|
||||
"url": url.strip()
|
||||
}])
|
||||
return {"rows": rows} if rows else None
|
||||
|
||||
except Exception as e:
|
||||
raise ValueError(f"Ошибка парсинга клавиатуры: {e}")
|
||||
return out
|
||||
|
||||
Reference in New Issue
Block a user