Implement user-specific question numbering and update database schema. Added triggers for automatic question numbering and adjustments upon deletion. Enhanced CRUD operations to manage user_question_number effectively.
This commit is contained in:
17
keyboards/__init__.py
Normal file
17
keyboards/__init__.py
Normal file
@@ -0,0 +1,17 @@
|
||||
"""
|
||||
Клавиатуры для бота
|
||||
"""
|
||||
|
||||
from .inline import (
|
||||
get_answer_keyboard,
|
||||
get_admin_keyboard,
|
||||
get_stats_keyboard
|
||||
)
|
||||
from .reply import get_main_keyboard
|
||||
|
||||
__all__ = [
|
||||
'get_answer_keyboard',
|
||||
'get_admin_keyboard',
|
||||
'get_stats_keyboard',
|
||||
'get_main_keyboard'
|
||||
]
|
||||
615
keyboards/inline.py
Normal file
615
keyboards/inline.py
Normal file
@@ -0,0 +1,615 @@
|
||||
"""
|
||||
Inline клавиатуры для бота
|
||||
"""
|
||||
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from models.question import Question
|
||||
from typing import List
|
||||
from services.utils import escape_html
|
||||
|
||||
|
||||
def get_answer_keyboard(question_id: int, from_user_id: int = None) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Клавиатура для ответа на вопрос
|
||||
|
||||
Args:
|
||||
question_id: ID вопроса
|
||||
from_user_id: ID отправителя вопроса (для блокировки)
|
||||
|
||||
Returns:
|
||||
Inline клавиатура
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="💬 Ответить",
|
||||
callback_data=f"answer_{question_id}"
|
||||
)
|
||||
)
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="❌ Отклонить",
|
||||
callback_data=f"reject_{question_id}"
|
||||
)
|
||||
)
|
||||
|
||||
# Добавляем кнопку блокировки, если есть ID отправителя
|
||||
if from_user_id:
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="🚫 Заблокировать",
|
||||
callback_data=f"block_{from_user_id}_{question_id}"
|
||||
)
|
||||
)
|
||||
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="🗑️ Удалить",
|
||||
callback_data=f"delete_{question_id}"
|
||||
)
|
||||
)
|
||||
|
||||
builder.adjust(1) # По одной кнопке в ряд
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
|
||||
|
||||
def get_admin_keyboard() -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Клавиатура для администраторов
|
||||
|
||||
Returns:
|
||||
Inline клавиатура
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="📊 Статистика",
|
||||
callback_data="admin_stats"
|
||||
)
|
||||
)
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="📢 Рассылка",
|
||||
callback_data="admin_broadcast"
|
||||
)
|
||||
)
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="🔍 Назначить суперпользователя",
|
||||
callback_data="admin_assign_superuser"
|
||||
)
|
||||
)
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="🚫 Забанить пользователя",
|
||||
callback_data="admin_ban_user"
|
||||
)
|
||||
)
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="🚦 Rate Limiting",
|
||||
callback_data="admin_rate_limit"
|
||||
)
|
||||
)
|
||||
|
||||
builder.adjust(2) # По две кнопки в ряд
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_superuser_assignment_keyboard(users: List, page: int = 0, per_page: int = 10) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Клавиатура для назначения суперпользователей
|
||||
|
||||
Args:
|
||||
users: Список пользователей
|
||||
page: Номер страницы
|
||||
per_page: Количество пользователей на странице
|
||||
|
||||
Returns:
|
||||
Inline клавиатура с пользователями для назначения
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
# Вычисляем диапазон пользователей для текущей страницы
|
||||
start_idx = page * per_page
|
||||
end_idx = min(start_idx + per_page, len(users))
|
||||
page_users = users[start_idx:end_idx]
|
||||
|
||||
# Добавляем кнопки для пользователей
|
||||
for user in page_users:
|
||||
# Определяем статус пользователя
|
||||
status_emoji = "🔍" if user.is_superuser else "👤"
|
||||
button_text = f"{status_emoji} {user.display_name}"
|
||||
|
||||
# Обрезаем текст если слишком длинный
|
||||
if len(button_text) > 30:
|
||||
button_text = button_text[:27] + "..."
|
||||
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text=button_text,
|
||||
callback_data=f"assign_superuser_{user.telegram_id}"
|
||||
)
|
||||
)
|
||||
|
||||
# Настраиваем расположение кнопок: 1 кнопка в ряд для лучшей читаемости
|
||||
builder.adjust(1)
|
||||
|
||||
# Добавляем управляющие кнопки
|
||||
control_buttons = []
|
||||
|
||||
# Кнопка "Предыдущая" (если есть предыдущие страницы)
|
||||
if page > 0:
|
||||
control_buttons.append(
|
||||
InlineKeyboardButton(
|
||||
text="⬅️ Предыдущая",
|
||||
callback_data=f"superuser_page_{page - 1}"
|
||||
)
|
||||
)
|
||||
|
||||
# Кнопка "Следующая" (если есть следующие страницы)
|
||||
total_pages = (len(users) + per_page - 1) // per_page
|
||||
if page < total_pages - 1:
|
||||
control_buttons.append(
|
||||
InlineKeyboardButton(
|
||||
text="Следующая ➡️",
|
||||
callback_data=f"superuser_page_{page + 1}"
|
||||
)
|
||||
)
|
||||
|
||||
# Добавляем управляющие кнопки
|
||||
if control_buttons:
|
||||
builder.row(*control_buttons)
|
||||
|
||||
# Кнопка "Назад"
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="🔙 Назад к админ панели",
|
||||
callback_data="back_to_admin"
|
||||
)
|
||||
)
|
||||
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_superuser_confirm_keyboard(user_id: int, is_superuser: bool) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Клавиатура для подтверждения назначения/снятия суперпользователя
|
||||
|
||||
Args:
|
||||
user_id: ID пользователя
|
||||
is_superuser: Текущий статус суперпользователя
|
||||
|
||||
Returns:
|
||||
Inline клавиатура с кнопками подтверждения
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
if is_superuser:
|
||||
# Если уже суперпользователь, предлагаем снять права
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="❌ Снять права суперпользователя",
|
||||
callback_data=f"remove_superuser_{user_id}"
|
||||
)
|
||||
)
|
||||
else:
|
||||
# Если не суперпользователь, предлагаем назначить
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="✅ Назначить суперпользователем",
|
||||
callback_data=f"confirm_superuser_{user_id}"
|
||||
)
|
||||
)
|
||||
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="🔙 Назад к списку",
|
||||
callback_data="admin_assign_superuser"
|
||||
)
|
||||
)
|
||||
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_ban_user_keyboard(users: List, page: int = 0, per_page: int = 10) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Клавиатура для выбора пользователя для бана
|
||||
|
||||
Args:
|
||||
users: Список пользователей
|
||||
page: Номер страницы
|
||||
per_page: Количество пользователей на странице
|
||||
|
||||
Returns:
|
||||
Inline клавиатура с пользователями для бана
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
# Вычисляем диапазон пользователей для текущей страницы
|
||||
start_idx = page * per_page
|
||||
end_idx = min(start_idx + per_page, len(users))
|
||||
page_users = users[start_idx:end_idx]
|
||||
|
||||
# Добавляем кнопки для пользователей
|
||||
for user in page_users:
|
||||
# Определяем статус пользователя
|
||||
status_emoji = "🚫" if user.is_banned else "👤"
|
||||
button_text = f"{status_emoji} {user.display_name}"
|
||||
|
||||
# Обрезаем текст если слишком длинный
|
||||
if len(button_text) > 30:
|
||||
button_text = button_text[:27] + "..."
|
||||
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text=button_text,
|
||||
callback_data=f"ban_user_select_{user.telegram_id}"
|
||||
)
|
||||
)
|
||||
|
||||
# Настраиваем расположение кнопок: 1 кнопка в ряд для лучшей читаемости
|
||||
builder.adjust(1)
|
||||
|
||||
# Добавляем управляющие кнопки
|
||||
control_buttons = []
|
||||
|
||||
# Кнопка "Предыдущая" (если есть предыдущие страницы)
|
||||
if page > 0:
|
||||
control_buttons.append(
|
||||
InlineKeyboardButton(
|
||||
text="⬅️ Предыдущая",
|
||||
callback_data=f"ban_user_page_{page - 1}"
|
||||
)
|
||||
)
|
||||
|
||||
# Кнопка "Следующая" (если есть следующие страницы)
|
||||
total_pages = (len(users) + per_page - 1) // per_page
|
||||
if page < total_pages - 1:
|
||||
control_buttons.append(
|
||||
InlineKeyboardButton(
|
||||
text="Следующая ➡️",
|
||||
callback_data=f"ban_user_page_{page + 1}"
|
||||
)
|
||||
)
|
||||
|
||||
# Добавляем управляющие кнопки
|
||||
if control_buttons:
|
||||
builder.row(*control_buttons)
|
||||
|
||||
# Кнопка "Назад"
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="🔙 Назад к админ панели",
|
||||
callback_data="back_to_admin"
|
||||
)
|
||||
)
|
||||
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_ban_duration_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Клавиатура для выбора срока бана
|
||||
|
||||
Args:
|
||||
user_id: ID пользователя для бана
|
||||
|
||||
Returns:
|
||||
Inline клавиатура с вариантами срока бана
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
# Варианты срока бана
|
||||
ban_options = [
|
||||
("1 час", "ban_1h"),
|
||||
("1 день", "ban_1d"),
|
||||
("3 дня", "ban_3d"),
|
||||
("1 неделя", "ban_1w"),
|
||||
("1 месяц", "ban_1m"),
|
||||
("Навсегда", "ban_forever")
|
||||
]
|
||||
|
||||
for text, callback_data in ban_options:
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text=text,
|
||||
callback_data=f"{callback_data}_{user_id}"
|
||||
)
|
||||
)
|
||||
|
||||
builder.adjust(2) # По две кнопки в ряд
|
||||
|
||||
# Кнопка "Назад"
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="🔙 Назад к списку",
|
||||
callback_data="admin_ban_user"
|
||||
)
|
||||
)
|
||||
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_ban_confirm_keyboard(user_id: int, duration: str, reason: str = None) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Клавиатура для подтверждения бана пользователя
|
||||
|
||||
Args:
|
||||
user_id: ID пользователя
|
||||
duration: Срок бана
|
||||
reason: Причина бана
|
||||
|
||||
Returns:
|
||||
Inline клавиатура с кнопками подтверждения
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="✅ Подтвердить бан",
|
||||
callback_data=f"confirm_ban_{user_id}_{duration}"
|
||||
)
|
||||
)
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="❌ Отменить",
|
||||
callback_data=f"ban_user_select_{user_id}"
|
||||
)
|
||||
)
|
||||
|
||||
builder.adjust(1)
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_unban_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Клавиатура для разбана пользователя
|
||||
|
||||
Args:
|
||||
user_id: ID пользователя
|
||||
|
||||
Returns:
|
||||
Inline клавиатура с кнопкой разбана
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="✅ Разбанить пользователя",
|
||||
callback_data=f"unban_user_{user_id}"
|
||||
)
|
||||
)
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="🔙 Назад к списку",
|
||||
callback_data="admin_ban_user"
|
||||
)
|
||||
)
|
||||
|
||||
builder.adjust(1)
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_stats_keyboard() -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Клавиатура для статистики
|
||||
|
||||
Returns:
|
||||
Inline клавиатура
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="📈 Общая статистика",
|
||||
callback_data="stats_general"
|
||||
)
|
||||
)
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="⬅️ Назад",
|
||||
callback_data="back_to_admin"
|
||||
)
|
||||
)
|
||||
|
||||
builder.adjust(2)
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_user_questions_keyboard(questions: list, page: int = 0, per_page: int = 9, total_questions: int = None) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Клавиатура со списком вопросов пользователя
|
||||
|
||||
Args:
|
||||
questions: Список вопросов для текущей страницы
|
||||
page: Номер страницы
|
||||
per_page: Количество вопросов на странице
|
||||
total_questions: Общее количество вопросов (для расчета пагинации)
|
||||
|
||||
Returns:
|
||||
Inline клавиатура
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
# Если не передано общее количество вопросов, используем длину списка
|
||||
if total_questions is None:
|
||||
total_questions = len(questions)
|
||||
|
||||
# Вычисляем общее количество страниц
|
||||
total_pages = (total_questions + per_page - 1) // per_page if total_questions > 0 else 1
|
||||
|
||||
# Добавляем кнопки для вопросов
|
||||
for i, question_data in enumerate(questions):
|
||||
# Проверяем, является ли элемент кортежем (question, author_user) или просто question
|
||||
if isinstance(question_data, tuple):
|
||||
question, author_user = question_data
|
||||
else:
|
||||
question = question_data
|
||||
|
||||
status_emoji = {
|
||||
'pending': '⏳',
|
||||
'answered': '✅',
|
||||
'rejected': '❌',
|
||||
'deleted': '🗑️'
|
||||
}
|
||||
|
||||
emoji = status_emoji.get(question.status.value, '❓')
|
||||
# Используем user_question_number для отображения
|
||||
display_number = question.user_question_number if question.user_question_number is not None else (page * per_page + i + 1)
|
||||
text = f"{emoji} Вопрос #{display_number}"
|
||||
|
||||
# Обрезаем текст если слишком длинный
|
||||
if len(text) > 30:
|
||||
text = text[:27] + "..."
|
||||
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text=text,
|
||||
callback_data=f"view_question_{question.id}"
|
||||
)
|
||||
)
|
||||
|
||||
# Настраиваем расположение кнопок: 3 кнопки в ряд для вопросов
|
||||
builder.adjust(3)
|
||||
|
||||
# Добавляем управляющие кнопки только если есть больше одной страницы
|
||||
if total_pages > 1:
|
||||
control_buttons = []
|
||||
|
||||
# Кнопка "Предыдущая" (только если не первая страница)
|
||||
if page > 0:
|
||||
control_buttons.append(
|
||||
InlineKeyboardButton(
|
||||
text="⬅️ Предыдущая",
|
||||
callback_data=f"questions_page_{page - 1}"
|
||||
)
|
||||
)
|
||||
|
||||
# Кнопка "В меню"
|
||||
control_buttons.append(
|
||||
InlineKeyboardButton(
|
||||
text="🏠 В меню",
|
||||
callback_data="back_to_main"
|
||||
)
|
||||
)
|
||||
|
||||
# Кнопка "Следующая" (только если не последняя страница)
|
||||
if page < total_pages - 1:
|
||||
control_buttons.append(
|
||||
InlineKeyboardButton(
|
||||
text="Следующая ➡️",
|
||||
callback_data=f"questions_page_{page + 1}"
|
||||
)
|
||||
)
|
||||
|
||||
# Добавляем управляющие кнопки в отдельный ряд
|
||||
builder.row(*control_buttons)
|
||||
else:
|
||||
# Если только одна страница, добавляем только кнопку "В меню"
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text="🏠 В меню",
|
||||
callback_data="back_to_main"
|
||||
)
|
||||
)
|
||||
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_question_view_keyboard(question: Question) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Клавиатура для просмотра конкретного вопроса
|
||||
|
||||
Args:
|
||||
question: Объект вопроса
|
||||
|
||||
Returns:
|
||||
Inline клавиатура
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
if question.status.value == 'pending':
|
||||
# Если вопрос ожидает ответа
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="💬 Ответить",
|
||||
callback_data=f"answer_{question.id}"
|
||||
)
|
||||
)
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="❌ Отклонить",
|
||||
callback_data=f"reject_{question.id}"
|
||||
)
|
||||
)
|
||||
elif question.status.value == 'answered':
|
||||
# Если вопрос уже отвечен
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="✏️ Редактировать ответ",
|
||||
callback_data=f"edit_answer_{question.id}"
|
||||
)
|
||||
)
|
||||
|
||||
# Общие действия
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="🗑️ Удалить",
|
||||
callback_data=f"delete_{question.id}"
|
||||
)
|
||||
)
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="⬅️ К списку вопросов",
|
||||
callback_data="back_to_questions"
|
||||
)
|
||||
)
|
||||
|
||||
builder.adjust(1)
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_rate_limit_keyboard() -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Клавиатура для управления rate limiting
|
||||
|
||||
Returns:
|
||||
Inline клавиатура с кнопками rate limiting
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="📊 Статистика Rate Limiting",
|
||||
callback_data="rate_limit_stats"
|
||||
)
|
||||
)
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="🔄 Сбросить статистику",
|
||||
callback_data="rate_limit_reset_stats"
|
||||
)
|
||||
)
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="⚙️ Адаптировать конфигурацию",
|
||||
callback_data="rate_limit_adapt"
|
||||
)
|
||||
)
|
||||
builder.add(
|
||||
InlineKeyboardButton(
|
||||
text="⬅️ Назад к админке",
|
||||
callback_data="back_to_admin"
|
||||
)
|
||||
)
|
||||
|
||||
builder.adjust(1)
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
118
keyboards/reply.py
Normal file
118
keyboards/reply.py
Normal file
@@ -0,0 +1,118 @@
|
||||
"""
|
||||
Reply клавиатуры для бота
|
||||
"""
|
||||
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton
|
||||
from aiogram.utils.keyboard import ReplyKeyboardBuilder
|
||||
from services.auth.auth_new import AuthService
|
||||
from dependencies import get_auth
|
||||
|
||||
|
||||
def get_main_keyboard(user_id: int = None, auth: AuthService = None) -> ReplyKeyboardMarkup:
|
||||
"""
|
||||
Основная клавиатура бота
|
||||
|
||||
Args:
|
||||
user_id: ID пользователя для проверки роли
|
||||
auth: Сервис авторизации для проверки роли
|
||||
|
||||
Returns:
|
||||
Reply клавиатура
|
||||
"""
|
||||
builder = ReplyKeyboardBuilder()
|
||||
|
||||
builder.add(
|
||||
KeyboardButton(text="📋 Мои вопросы"),
|
||||
KeyboardButton(text="🔗 Моя ссылка")
|
||||
)
|
||||
builder.add(
|
||||
KeyboardButton(text="🚫 Заблокированные"),
|
||||
KeyboardButton(text="ℹ️ Помощь")
|
||||
)
|
||||
|
||||
# Добавляем кнопку статистики только для администраторов
|
||||
if user_id and auth and auth.is_admin(user_id):
|
||||
builder.add(KeyboardButton(text="📊 Статистика"))
|
||||
builder.adjust(2, 2, 1) # 2 кнопки в первом ряду, 2 во втором, 1 в третьем
|
||||
else:
|
||||
builder.adjust(2, 2) # 2 кнопки в первом ряду, 2 во втором
|
||||
|
||||
return builder.as_markup(
|
||||
resize_keyboard=True,
|
||||
one_time_keyboard=False,
|
||||
input_field_placeholder="Выберите действие или отправьте вопрос..."
|
||||
)
|
||||
|
||||
|
||||
def get_main_keyboard_for_user(user_id: int, auth: AuthService = None) -> ReplyKeyboardMarkup:
|
||||
"""
|
||||
Основная клавиатура бота для конкретного пользователя
|
||||
|
||||
Args:
|
||||
user_id: ID пользователя для проверки роли
|
||||
auth: Сервис авторизации для проверки роли (опционально, если не передан, будет получен через DI)
|
||||
|
||||
Returns:
|
||||
Reply клавиатура
|
||||
"""
|
||||
if auth is None:
|
||||
auth = get_auth()
|
||||
return get_main_keyboard(user_id, auth)
|
||||
|
||||
|
||||
def get_admin_reply_keyboard() -> ReplyKeyboardMarkup:
|
||||
"""
|
||||
Reply клавиатура для администраторов
|
||||
|
||||
Returns:
|
||||
Reply клавиатура для админов
|
||||
"""
|
||||
builder = ReplyKeyboardBuilder()
|
||||
|
||||
builder.add(
|
||||
KeyboardButton(text="📋 Мои вопросы"),
|
||||
KeyboardButton(text="🔗 Моя ссылка")
|
||||
)
|
||||
builder.add(
|
||||
KeyboardButton(text="🚫 Заблокированные"),
|
||||
KeyboardButton(text="ℹ️ Помощь")
|
||||
)
|
||||
builder.add(
|
||||
KeyboardButton(text="📊 Статистика"),
|
||||
KeyboardButton(text="⚙️ Админ панель")
|
||||
)
|
||||
|
||||
builder.adjust(2, 2, 2) # 2 кнопки в каждом ряду
|
||||
|
||||
return builder.as_markup(
|
||||
resize_keyboard=True,
|
||||
one_time_keyboard=False,
|
||||
input_field_placeholder="Выберите действие или отправьте вопрос..."
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def get_cancel_keyboard() -> ReplyKeyboardMarkup:
|
||||
"""
|
||||
Клавиатура с кнопкой отмены
|
||||
|
||||
Returns:
|
||||
Reply клавиатура
|
||||
"""
|
||||
builder = ReplyKeyboardBuilder()
|
||||
|
||||
builder.add(
|
||||
KeyboardButton(text="❌ Отмена")
|
||||
)
|
||||
|
||||
return builder.as_markup(
|
||||
resize_keyboard=True,
|
||||
one_time_keyboard=True,
|
||||
input_field_placeholder="Отправьте текст или нажмите 'Отмена'"
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user