Refactor admin handlers to improve access control and state management. Added checks for admin rights in ban functions and streamlined router inclusion order in main bot file. Updated keyboard layouts for better user experience and removed unused state definitions.
This commit is contained in:
@@ -41,10 +41,12 @@ async def admin_panel(message: types.Message, state: FSMContext):
|
||||
reply_markup=markup)
|
||||
else:
|
||||
await message.answer('Доступ запрещен, досвидания!')
|
||||
await state.set_state("START")
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при запуске админ панели: {e}")
|
||||
await message.bot.send_message(IMPORTANT_LOGS,
|
||||
f'Ошибка в функции admin_panel {e}. Traceback: {traceback.format_exc()}')
|
||||
await state.set_state("START")
|
||||
|
||||
|
||||
@admin_router.message(
|
||||
@@ -52,7 +54,12 @@ async def admin_panel(message: types.Message, state: FSMContext):
|
||||
StateFilter("ADMIN"),
|
||||
F.text == 'Бан (Список)'
|
||||
)
|
||||
async def get_last_users(message: types.Message):
|
||||
async def get_last_users(message: types.Message, state: FSMContext):
|
||||
# Дополнительная проверка на админские права
|
||||
if not check_access(message.from_user.id, BotDB):
|
||||
await message.answer('Доступ запрещен!')
|
||||
await state.set_state("START")
|
||||
return
|
||||
logger.info(
|
||||
f"Попытка получения списка последних пользователей. Текст сообщения: {message.text} Имя автора сообщения: {message.from_user.full_name})")
|
||||
list_users = BotDB.get_last_users_from_db()
|
||||
@@ -67,6 +74,11 @@ async def get_last_users(message: types.Message):
|
||||
F.text == 'Бан по нику'
|
||||
)
|
||||
async def ban_by_nickname(message: types.Message, state: FSMContext):
|
||||
# Дополнительная проверка на админские права
|
||||
if not check_access(message.from_user.id, BotDB):
|
||||
await message.answer('Доступ запрещен!')
|
||||
await state.set_state("START")
|
||||
return
|
||||
await message.answer('Пришли мне username блокируемого пользователя')
|
||||
await state.set_state('PRE_BAN')
|
||||
|
||||
@@ -77,25 +89,29 @@ async def ban_by_nickname(message: types.Message, state: FSMContext):
|
||||
F.text == 'Бан по ID'
|
||||
)
|
||||
async def ban_by_id(message: types.Message, state: FSMContext):
|
||||
# Дополнительная проверка на админские права
|
||||
if not check_access(message.from_user.id, BotDB):
|
||||
await message.answer('Доступ запрещен!')
|
||||
await state.set_state("START")
|
||||
return
|
||||
await message.answer('Пришли мне ID блокируемого пользователя')
|
||||
await state.set_state('PRE_BAN_ID')
|
||||
|
||||
|
||||
@admin_router.message(
|
||||
ChatTypeFilter(chat_type=["private"]),
|
||||
StateFilter("ADMIN"),
|
||||
F.text == 'Тестовый бан'
|
||||
)
|
||||
async def ban_by_forward(message: types.Message, state: FSMContext):
|
||||
await message.answer('Перешлите мне сообщение от пользователя, которого хотите заблокировать')
|
||||
await state.set_state('PRE_BAN_FORWARD')
|
||||
|
||||
|
||||
|
||||
@admin_router.message(
|
||||
ChatTypeFilter(chat_type=["private"]),
|
||||
StateFilter("PRE_BAN", "PRE_BAN_ID", "BAN_2"),
|
||||
F.text == 'Отменить'
|
||||
)
|
||||
async def decline_ban(message: types.Message, state: FSMContext):
|
||||
# Дополнительная проверка на админские права
|
||||
if not check_access(message.from_user.id, BotDB):
|
||||
await message.answer('Доступ запрещен!')
|
||||
await state.set_state("START")
|
||||
return
|
||||
current_state = await state.get_state()
|
||||
await state.set_data({})
|
||||
await state.set_state("ADMIN")
|
||||
@@ -109,6 +125,11 @@ async def decline_ban(message: types.Message, state: FSMContext):
|
||||
StateFilter("PRE_BAN")
|
||||
)
|
||||
async def ban_by_nickname_step_2(message: types.Message, state: FSMContext):
|
||||
# Дополнительная проверка на админские права
|
||||
if not check_access(message.from_user.id, BotDB):
|
||||
await message.answer('Доступ запрещен!')
|
||||
await state.set_state("START")
|
||||
return
|
||||
logger.info(
|
||||
f"Функция ban_by_nickname_2. Получен никнейм пользователя: {message.text}")
|
||||
user_name = message.text
|
||||
@@ -132,6 +153,11 @@ async def ban_by_nickname_step_2(message: types.Message, state: FSMContext):
|
||||
StateFilter("PRE_BAN_ID")
|
||||
)
|
||||
async def ban_by_id_step_2(message: types.Message, state: FSMContext):
|
||||
# Дополнительная проверка на админские права
|
||||
if not check_access(message.from_user.id, BotDB):
|
||||
await message.answer('Доступ запрещен!')
|
||||
await state.set_state("START")
|
||||
return
|
||||
try:
|
||||
user_id = int(message.text)
|
||||
logger.info(f"Функция ban_by_id_step_2. Получен ID пользователя: {user_id}")
|
||||
@@ -168,73 +194,10 @@ async def ban_by_id_step_2(message: types.Message, state: FSMContext):
|
||||
await message.answer('Вернулись в меню', reply_markup=markup)
|
||||
|
||||
|
||||
@admin_router.message(
|
||||
ChatTypeFilter(chat_type=["private"]),
|
||||
StateFilter("PRE_BAN_FORWARD"),
|
||||
F.forward_from
|
||||
)
|
||||
async def ban_by_forward_step_2(message: types.Message, state: FSMContext):
|
||||
"""Обработчик пересланных сообщений для бана пользователя"""
|
||||
try:
|
||||
# Получаем информацию о пользователе из пересланного сообщения
|
||||
forwarded_user = message.forward_from
|
||||
|
||||
if not forwarded_user:
|
||||
await message.answer("Не удалось получить информацию о пользователе из пересланного сообщения. Возможно, пользователь скрыл возможность пересылки своих сообщений.")
|
||||
await state.set_state('ADMIN')
|
||||
markup = get_reply_keyboard_admin()
|
||||
await message.answer('Вернулись в меню', reply_markup=markup)
|
||||
return
|
||||
|
||||
user_id = forwarded_user.id
|
||||
user_name = forwarded_user.username or "private_username"
|
||||
full_name = forwarded_user.full_name or "Неизвестно"
|
||||
|
||||
logger.info(f"Функция ban_by_forward_step_2. Получен пользователь из пересланного сообщения: ID={user_id}, username={user_name}, full_name={full_name}")
|
||||
|
||||
# Проверяем, существует ли пользователь в базе
|
||||
user_info = BotDB.get_user_info_by_id(user_id)
|
||||
if not user_info:
|
||||
# Если пользователя нет в базе, используем информацию из пересланного сообщения
|
||||
logger.info(f"Пользователь с ID {user_id} не найден в базе данных, используем данные из пересланного сообщения")
|
||||
user_name = user_name
|
||||
full_name = full_name
|
||||
else:
|
||||
# Если пользователь есть в базе, используем данные из базы
|
||||
user_name = user_info.get('username', user_name)
|
||||
full_name = user_info.get('full_name', full_name)
|
||||
|
||||
await state.update_data(user_id=user_id, user_name=user_name, message_for_user=None,
|
||||
date_to_unban=None)
|
||||
|
||||
markup = create_keyboard_for_ban_reason()
|
||||
# Экранируем потенциально проблемные символы
|
||||
user_name_escaped = html.escape(str(user_name))
|
||||
full_name_escaped = html.escape(str(full_name))
|
||||
await message.answer(
|
||||
text=f"<b>Выбран пользователь из пересланного сообщения:\nid:</b> {user_id}\n<b>username:</b> {user_name_escaped}\n"
|
||||
f"Имя:{full_name_escaped}\nВыбери причину бана из списка или напиши ее в чат",
|
||||
reply_markup=markup)
|
||||
await state.set_state('BAN_2')
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при обработке пересланного сообщения: {e}")
|
||||
await message.answer("Произошла ошибка при обработке пересланного сообщения.")
|
||||
await state.set_state('ADMIN')
|
||||
markup = get_reply_keyboard_admin()
|
||||
await message.answer('Вернулись в меню', reply_markup=markup)
|
||||
|
||||
|
||||
@admin_router.message(
|
||||
ChatTypeFilter(chat_type=["private"]),
|
||||
StateFilter("PRE_BAN_FORWARD")
|
||||
)
|
||||
async def ban_by_forward_invalid(message: types.Message, state: FSMContext):
|
||||
"""Обработчик для случаев, когда сообщение не является пересланным или не содержит информацию о пользователе"""
|
||||
if message.forward_from_chat:
|
||||
await message.answer("Пересланное сообщение из канала или группы не содержит информацию о конкретном пользователе. Пожалуйста, перешлите сообщение из приватного чата.")
|
||||
else:
|
||||
await message.answer("Пожалуйста, перешлите сообщение от пользователя, которого хотите заблокировать. Обычное сообщение не подходит.")
|
||||
|
||||
|
||||
|
||||
|
||||
@admin_router.message(
|
||||
|
||||
@@ -1,284 +1,322 @@
|
||||
import html
|
||||
import traceback
|
||||
|
||||
from aiogram import Router, F
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery
|
||||
|
||||
from helper_bot.keyboards.keyboards import create_keyboard_with_pagination, get_reply_keyboard_admin, \
|
||||
create_keyboard_for_ban_reason
|
||||
from helper_bot.utils.base_dependency_factory import get_global_instance
|
||||
from helper_bot.utils.helper_func import send_text_message, send_photo_message, get_banned_users_list, \
|
||||
get_banned_users_buttons, delete_user_blacklist, send_media_group_to_channel, \
|
||||
send_video_message, send_video_note_message, send_audio_message, send_voice_message
|
||||
from logs.custom_logger import logger
|
||||
|
||||
callback_router = Router()
|
||||
|
||||
bdf = get_global_instance()
|
||||
GROUP_FOR_POST = bdf.settings['Telegram']['group_for_posts']
|
||||
GROUP_FOR_MESSAGE = bdf.settings['Telegram']['group_for_message']
|
||||
MAIN_PUBLIC = bdf.settings['Telegram']['main_public']
|
||||
GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs']
|
||||
IMPORTANT_LOGS = bdf.settings['Telegram']['important_logs']
|
||||
PREVIEW_LINK = bdf.settings['Telegram']['preview_link']
|
||||
LOGS = bdf.settings['Settings']['logs']
|
||||
TEST = bdf.settings['Settings']['test']
|
||||
|
||||
BotDB = bdf.get_db()
|
||||
|
||||
|
||||
@callback_router.callback_query(
|
||||
F.data == "publish"
|
||||
)
|
||||
async def post_for_group(call: CallbackQuery, state: FSMContext):
|
||||
logger.info(
|
||||
f'Получен callback-запрос с действием: {call.data} от пользователя {call.from_user.full_name} (ID сообщения: {call.message.message_id})')
|
||||
text_post = html.escape(str(call.message.text))
|
||||
text_post_with_photo = html.escape(str(call.message.caption))
|
||||
if call.message.content_type == 'text' and call.message.text != "^":
|
||||
try:
|
||||
# Пересылаем сообщение в канал
|
||||
await send_text_message(MAIN_PUBLIC, call.message, text_post)
|
||||
|
||||
# Получаем из базы автора
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
# Очищаем предложку и удаляем оттуда пост
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
logger.info(f'Текст сообщения опубликован в канале {MAIN_PUBLIC}.')
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
|
||||
# Отвечаем пользователю
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
|
||||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при публикации текста в канал {MAIN_PUBLIC}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
elif call.message.content_type == 'photo':
|
||||
try:
|
||||
await send_photo_message(MAIN_PUBLIC, call.message, call.message.photo[-1].file_id, text_post_with_photo)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
# Удаляем пост из предложки
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
logger.info(f'Пост с фото опубликован в канале {MAIN_PUBLIC}.')
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
|
||||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при публикации фотографии в канал {MAIN_PUBLIC}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
elif call.message.content_type == 'video':
|
||||
try:
|
||||
await send_video_message(MAIN_PUBLIC, call.message, call.message.video.file_id, text_post_with_photo)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
logger.info(f'Пост с видео опубликован в канале {MAIN_PUBLIC}.')
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
|
||||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при публикации видео в канал {MAIN_PUBLIC}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
elif call.message.content_type == 'video_note':
|
||||
try:
|
||||
await send_video_note_message(MAIN_PUBLIC, call.message, call.message.video_note.file_id)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
logger.info(f'Пост с кружком опубликован в канале {MAIN_PUBLIC}.')
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
|
||||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при публикации кружка в канал {MAIN_PUBLIC}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
elif call.message.content_type == 'audio':
|
||||
try:
|
||||
await send_audio_message(MAIN_PUBLIC, call.message, call.message.audio.file_id, text_post_with_photo)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
logger.info(f'Пост с аудио опубликован в канале {MAIN_PUBLIC}.')
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
|
||||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при публикации аудио в канал {MAIN_PUBLIC}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
elif call.message.content_type == 'voice':
|
||||
try:
|
||||
await send_voice_message(MAIN_PUBLIC, call.message, call.message.voice.file_id)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
logger.info(f'Пост с войсом опубликован в канале {MAIN_PUBLIC}.')
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
|
||||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при публикации войса в канал {MAIN_PUBLIC}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
elif call.message.text == "^":
|
||||
# Получаем контент медиагруппы и текст для публикации
|
||||
post_content = BotDB.get_post_content_from_telegram_by_last_id(call.message.message_id)
|
||||
pre_text = BotDB.get_post_text_from_telegram_by_last_id(call.message.message_id)
|
||||
post_text = html.escape(str(pre_text))
|
||||
|
||||
# Готовим список для удаления
|
||||
post_ids = BotDB.get_post_ids_from_telegram_by_last_id(call.message.message_id)
|
||||
message_ids = [row[0] for row in post_ids]
|
||||
message_ids.append(call.message.message_id)
|
||||
|
||||
# Выкладываем пост в канал
|
||||
await send_media_group_to_channel(bot=call.bot, chat_id=MAIN_PUBLIC, post_content=post_content,
|
||||
post_text=post_text)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_helper_message_id(call.message.message_id)
|
||||
|
||||
# TODO: Удалить фотки с локалки после выкладки?
|
||||
await call.bot.delete_messages(chat_id=GROUP_FOR_POST, message_ids=message_ids)
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
|
||||
|
||||
@callback_router.callback_query(
|
||||
F.data == "decline"
|
||||
)
|
||||
async def decline_post_for_group(call: CallbackQuery, state: FSMContext):
|
||||
logger.info(
|
||||
f'Получен callback-запрос с данными: {call.data} от пользователя {call.from_user.full_name} (ID: {call.from_user.id})')
|
||||
try:
|
||||
if call.message.content_type == 'text' and call.message.text != "^" or call.message.content_type == 'photo' \
|
||||
or call.message.content_type == 'audio' or call.message.content_type == 'voice' \
|
||||
or call.message.content_type == 'video' or call.message.content_type == 'video_note':
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
logger.info(
|
||||
f'Сообщение отклонено админом {call.from_user.full_name} (ID: {call.from_user.id}).')
|
||||
await call.answer(text='Отклонено!', cache_time=3)
|
||||
await send_text_message(author_id, call.message, 'Твой пост был отклонен😔')
|
||||
if call.message.text == '^':
|
||||
post_ids = BotDB.get_post_ids_from_telegram_by_last_id(call.message.message_id)
|
||||
message_ids = [row[0] for row in post_ids]
|
||||
message_ids.append(call.message.message_id)
|
||||
|
||||
await call.bot.delete_messages(chat_id=GROUP_FOR_POST, message_ids=message_ids)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_helper_message_id(call.message.message_id)
|
||||
|
||||
await call.answer(text='Удалено!', cache_time=3)
|
||||
|
||||
await send_text_message(author_id, call.message, 'Твой пост был отклонен😔')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(IMPORTANT_LOGS,
|
||||
f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при удалении сообщения в группе {GROUP_FOR_POST}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
|
||||
|
||||
@callback_router.callback_query(
|
||||
F.data.contains('ban')
|
||||
)
|
||||
async def process_ban_user(call: CallbackQuery, state: FSMContext):
|
||||
user_id = call.data[4:]
|
||||
logger.info(
|
||||
f"Вызов функции process_ban_user. Данные callback: {call.data} пользователь: {user_id}")
|
||||
user_name = BotDB.get_username(user_id=user_id)
|
||||
if user_name:
|
||||
await state.update_data(user_id=user_id, user_name=user_name, message_for_user=None,
|
||||
date_to_unban=None)
|
||||
markup = create_keyboard_for_ban_reason()
|
||||
# Экранируем потенциально проблемные символы
|
||||
user_name_escaped = html.escape(str(user_name))
|
||||
full_name_escaped = html.escape(str(call.message.from_user.full_name))
|
||||
await call.message.answer(
|
||||
text=f"<b>Выбран пользователь:\nid:</b> {user_id}\n<b>username:</b> {user_name_escaped}\nИмя:{full_name_escaped}\nВыбери причину бана из списка или напиши ее в чат",
|
||||
reply_markup=markup)
|
||||
await state.set_state('BAN_2')
|
||||
else:
|
||||
markup = get_reply_keyboard_admin()
|
||||
await call.message.answer(text='Пользователь с таким ID не найден в базе', markup=markup)
|
||||
await state.set_state('ADMIN')
|
||||
|
||||
|
||||
@callback_router.callback_query(
|
||||
F.data.contains('unlock')
|
||||
)
|
||||
async def process_unlock_user(call: CallbackQuery):
|
||||
user_id = call.data[7:]
|
||||
user_name = BotDB.get_username(user_id=user_id)
|
||||
delete_user_blacklist(user_id, BotDB)
|
||||
logger.info(f"Разблокирован пользователь с ID: {user_id} username:{user_name}")
|
||||
username = BotDB.get_username(user_id)
|
||||
await call.answer(f'Пользователь разблокирован {username}', show_alert=True)
|
||||
|
||||
|
||||
@callback_router.callback_query(
|
||||
F.data == 'return'
|
||||
)
|
||||
async def return_to_main_menu(call: CallbackQuery):
|
||||
await call.message.delete()
|
||||
logger.info(f"Запуск админ панели для пользователя: {call.message.from_user.id}")
|
||||
markup = get_reply_keyboard_admin()
|
||||
await call.message.answer("Добро пожаловать в админку. Выбери что хочешь:",
|
||||
reply_markup=markup)
|
||||
|
||||
|
||||
@callback_router.callback_query(
|
||||
F.data.contains('page')
|
||||
)
|
||||
async def change_page(call: CallbackQuery):
|
||||
page_number = int(call.data[5:])
|
||||
logger.info(f"Переход на страницу {page_number}")
|
||||
if call.message.text == 'Список пользователей которые последними обращались к боту':
|
||||
list_users = BotDB.get_last_users_from_db()
|
||||
# TODO: Здесь где-то надо добавить обработку ошибки IndexError: list index out of range
|
||||
keyboard = create_keyboard_with_pagination(int(page_number), len(list_users), list_users,
|
||||
'ban')
|
||||
|
||||
await call.bot.edit_message_reply_markup(chat_id=call.message.chat.id, message_id=call.message.message_id,
|
||||
reply_markup=keyboard)
|
||||
else:
|
||||
# Готовим сообщения
|
||||
message_user = get_banned_users_list(int(page_number) * 7 - 7, BotDB)
|
||||
await call.bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
|
||||
text=message_user)
|
||||
|
||||
# Готовим клавиатуру
|
||||
buttons = get_banned_users_buttons(BotDB)
|
||||
keyboard = create_keyboard_with_pagination(int(call.data[5:]), len(buttons), buttons, 'unlock')
|
||||
await call.bot.edit_message_reply_markup(chat_id=call.message.chat.id, message_id=call.message.message_id,
|
||||
reply_markup=keyboard)
|
||||
import html
|
||||
import traceback
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from aiogram import Router, F
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery
|
||||
|
||||
from helper_bot.keyboards.keyboards import create_keyboard_with_pagination, get_reply_keyboard_admin, \
|
||||
create_keyboard_for_ban_reason
|
||||
from helper_bot.utils.base_dependency_factory import get_global_instance
|
||||
from helper_bot.utils.helper_func import send_text_message, send_photo_message, get_banned_users_list, \
|
||||
get_banned_users_buttons, delete_user_blacklist, send_media_group_to_channel, \
|
||||
send_video_message, send_video_note_message, send_audio_message, send_voice_message
|
||||
from logs.custom_logger import logger
|
||||
|
||||
callback_router = Router()
|
||||
|
||||
bdf = get_global_instance()
|
||||
GROUP_FOR_POST = bdf.settings['Telegram']['group_for_posts']
|
||||
GROUP_FOR_MESSAGE = bdf.settings['Telegram']['group_for_message']
|
||||
MAIN_PUBLIC = bdf.settings['Telegram']['main_public']
|
||||
GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs']
|
||||
IMPORTANT_LOGS = bdf.settings['Telegram']['important_logs']
|
||||
PREVIEW_LINK = bdf.settings['Telegram']['preview_link']
|
||||
LOGS = bdf.settings['Settings']['logs']
|
||||
TEST = bdf.settings['Settings']['test']
|
||||
|
||||
BotDB = bdf.get_db()
|
||||
|
||||
|
||||
@callback_router.callback_query(
|
||||
F.data == "publish"
|
||||
)
|
||||
async def post_for_group(call: CallbackQuery, state: FSMContext):
|
||||
logger.info(
|
||||
f'Получен callback-запрос с действием: {call.data} от пользователя {call.from_user.full_name} (ID сообщения: {call.message.message_id})')
|
||||
text_post = html.escape(str(call.message.text))
|
||||
text_post_with_photo = html.escape(str(call.message.caption))
|
||||
if call.message.content_type == 'text' and call.message.text != "^":
|
||||
try:
|
||||
# Пересылаем сообщение в канал
|
||||
await send_text_message(MAIN_PUBLIC, call.message, text_post)
|
||||
|
||||
# Получаем из базы автора
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
# Очищаем предложку и удаляем оттуда пост
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
logger.info(f'Текст сообщения опубликован в канале {MAIN_PUBLIC}.')
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
|
||||
# Отвечаем пользователю
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
|
||||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при публикации текста в канал {MAIN_PUBLIC}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
elif call.message.content_type == 'photo':
|
||||
try:
|
||||
await send_photo_message(MAIN_PUBLIC, call.message, call.message.photo[-1].file_id, text_post_with_photo)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
# Удаляем пост из предложки
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
logger.info(f'Пост с фото опубликован в канале {MAIN_PUBLIC}.')
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
|
||||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при публикации фотографии в канал {MAIN_PUBLIC}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
elif call.message.content_type == 'video':
|
||||
try:
|
||||
await send_video_message(MAIN_PUBLIC, call.message, call.message.video.file_id, text_post_with_photo)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
logger.info(f'Пост с видео опубликован в канале {MAIN_PUBLIC}.')
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
|
||||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при публикации видео в канал {MAIN_PUBLIC}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
elif call.message.content_type == 'video_note':
|
||||
try:
|
||||
await send_video_note_message(MAIN_PUBLIC, call.message, call.message.video_note.file_id)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
logger.info(f'Пост с кружком опубликован в канале {MAIN_PUBLIC}.')
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
|
||||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при публикации кружка в канал {MAIN_PUBLIC}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
elif call.message.content_type == 'audio':
|
||||
try:
|
||||
await send_audio_message(MAIN_PUBLIC, call.message, call.message.audio.file_id, text_post_with_photo)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
logger.info(f'Пост с аудио опубликован в канале {MAIN_PUBLIC}.')
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
|
||||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при публикации аудио в канал {MAIN_PUBLIC}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
elif call.message.content_type == 'voice':
|
||||
try:
|
||||
await send_voice_message(MAIN_PUBLIC, call.message, call.message.voice.file_id)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
logger.info(f'Пост с войсом опубликован в канале {MAIN_PUBLIC}.')
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
|
||||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при публикации войса в канал {MAIN_PUBLIC}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
elif call.message.text == "^":
|
||||
# Получаем контент медиагруппы и текст для публикации
|
||||
post_content = BotDB.get_post_content_from_telegram_by_last_id(call.message.message_id)
|
||||
pre_text = BotDB.get_post_text_from_telegram_by_last_id(call.message.message_id)
|
||||
post_text = html.escape(str(pre_text))
|
||||
|
||||
# Готовим список для удаления
|
||||
post_ids = BotDB.get_post_ids_from_telegram_by_last_id(call.message.message_id)
|
||||
message_ids = [row[0] for row in post_ids]
|
||||
message_ids.append(call.message.message_id)
|
||||
|
||||
# Выкладываем пост в канал
|
||||
await send_media_group_to_channel(bot=call.bot, chat_id=MAIN_PUBLIC, post_content=post_content,
|
||||
post_text=post_text)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_helper_message_id(call.message.message_id)
|
||||
|
||||
# TODO: Удалить фотки с локалки после выкладки?
|
||||
await call.bot.delete_messages(chat_id=GROUP_FOR_POST, message_ids=message_ids)
|
||||
await call.answer(text='Выложено!', cache_time=3)
|
||||
|
||||
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
|
||||
|
||||
|
||||
@callback_router.callback_query(
|
||||
F.data == "decline"
|
||||
)
|
||||
async def decline_post_for_group(call: CallbackQuery, state: FSMContext):
|
||||
logger.info(
|
||||
f'Получен callback-запрос с данными: {call.data} от пользователя {call.from_user.full_name} (ID: {call.from_user.id})')
|
||||
try:
|
||||
if call.message.content_type == 'text' and call.message.text != "^" or call.message.content_type == 'photo' \
|
||||
or call.message.content_type == 'audio' or call.message.content_type == 'voice' \
|
||||
or call.message.content_type == 'video' or call.message.content_type == 'video_note':
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
logger.info(
|
||||
f'Сообщение отклонено админом {call.from_user.full_name} (ID: {call.from_user.id}).')
|
||||
await call.answer(text='Отклонено!', cache_time=3)
|
||||
await send_text_message(author_id, call.message, 'Твой пост был отклонен😔')
|
||||
if call.message.text == '^':
|
||||
post_ids = BotDB.get_post_ids_from_telegram_by_last_id(call.message.message_id)
|
||||
message_ids = [row[0] for row in post_ids]
|
||||
message_ids.append(call.message.message_id)
|
||||
|
||||
await call.bot.delete_messages(chat_id=GROUP_FOR_POST, message_ids=message_ids)
|
||||
|
||||
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
|
||||
author_id = BotDB.get_author_id_by_helper_message_id(call.message.message_id)
|
||||
|
||||
await call.answer(text='Удалено!', cache_time=3)
|
||||
|
||||
await send_text_message(author_id, call.message, 'Твой пост был отклонен😔')
|
||||
except Exception as e:
|
||||
if e.message != 'Forbidden: bot was blocked by the user':
|
||||
await call.bot.send_message(IMPORTANT_LOGS,
|
||||
f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
|
||||
logger.error(f'Ошибка при удалении сообщения в группе {GROUP_FOR_POST}: {str(e)}')
|
||||
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
|
||||
|
||||
|
||||
@callback_router.callback_query(
|
||||
F.data == "ban"
|
||||
)
|
||||
async def ban_user_from_post(call: CallbackQuery):
|
||||
try:
|
||||
# Получаем информацию о пользователе из сообщения
|
||||
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
|
||||
user_name = BotDB.get_username(user_id=author_id)
|
||||
full_name = call.message.from_user.full_name if call.message.from_user else "Неизвестно"
|
||||
|
||||
# Устанавливаем причину бана и дату разблокировки (+7 дней)
|
||||
current_date = datetime.now()
|
||||
date_to_unban = current_date + timedelta(days=7)
|
||||
|
||||
# Записываем в базу данных
|
||||
BotDB.set_user_blacklist(
|
||||
user_id=author_id,
|
||||
user_name=user_name,
|
||||
message_for_user="Спам",
|
||||
date_to_unban=date_to_unban
|
||||
)
|
||||
|
||||
# Удаляем пост из предложки
|
||||
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
|
||||
|
||||
# Отправляем сообщение пользователю о блокировке
|
||||
date_str = date_to_unban.strftime("%d.%m.%Y %H:%M")
|
||||
await send_text_message(author_id, call.message, f"Ты заблокирован за спам. Дата разблокировки: {date_str}")
|
||||
|
||||
logger.info(f"Пользователь {author_id} заблокирован за спам до {date_str}")
|
||||
await call.answer(text='Пользователь заблокирован!', cache_time=3)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f'Ошибка при блокировке пользователя: {str(e)}')
|
||||
await call.answer(text='Ошибка при блокировке!', show_alert=True, cache_time=3)
|
||||
|
||||
|
||||
@callback_router.callback_query(
|
||||
F.data.contains('ban')
|
||||
)
|
||||
async def process_ban_user(call: CallbackQuery, state: FSMContext):
|
||||
user_id = call.data[4:]
|
||||
logger.info(
|
||||
f"Вызов функции process_ban_user. Данные callback: {call.data} пользователь: {user_id}")
|
||||
user_name = BotDB.get_username(user_id=user_id)
|
||||
if user_name:
|
||||
await state.update_data(user_id=user_id, user_name=user_name, message_for_user=None,
|
||||
date_to_unban=None)
|
||||
markup = create_keyboard_for_ban_reason()
|
||||
# Экранируем потенциально проблемные символы
|
||||
user_name_escaped = html.escape(str(user_name))
|
||||
full_name_escaped = html.escape(str(call.message.from_user.full_name))
|
||||
await call.message.answer(
|
||||
text=f"<b>Выбран пользователь:\nid:</b> {user_id}\n<b>username:</b> {user_name_escaped}\nИмя:{full_name_escaped}\nВыбери причину бана из списка или напиши ее в чат",
|
||||
reply_markup=markup)
|
||||
await state.set_state('BAN_2')
|
||||
else:
|
||||
markup = get_reply_keyboard_admin()
|
||||
await call.message.answer(text='Пользователь с таким ID не найден в базе', reply_markup=markup)
|
||||
await state.set_state('ADMIN')
|
||||
|
||||
|
||||
@callback_router.callback_query(
|
||||
F.data.contains('unlock')
|
||||
)
|
||||
async def process_unlock_user(call: CallbackQuery):
|
||||
user_id = call.data[7:]
|
||||
user_name = BotDB.get_username(user_id=user_id)
|
||||
delete_user_blacklist(user_id, BotDB)
|
||||
logger.info(f"Разблокирован пользователь с ID: {user_id} username:{user_name}")
|
||||
username = BotDB.get_username(user_id)
|
||||
await call.answer(f'Пользователь разблокирован {username}', show_alert=True)
|
||||
|
||||
|
||||
@callback_router.callback_query(
|
||||
F.data == 'return'
|
||||
)
|
||||
async def return_to_main_menu(call: CallbackQuery):
|
||||
await call.message.delete()
|
||||
logger.info(f"Запуск админ панели для пользователя: {call.message.from_user.id}")
|
||||
markup = get_reply_keyboard_admin()
|
||||
await call.message.answer("Добро пожаловать в админку. Выбери что хочешь:",
|
||||
reply_markup=markup)
|
||||
|
||||
|
||||
@callback_router.callback_query(
|
||||
F.data.contains('page')
|
||||
)
|
||||
async def change_page(call: CallbackQuery):
|
||||
page_number = int(call.data[5:])
|
||||
logger.info(f"Переход на страницу {page_number}")
|
||||
if call.message.text == 'Список пользователей которые последними обращались к боту':
|
||||
list_users = BotDB.get_last_users_from_db()
|
||||
# TODO: Здесь где-то надо добавить обработку ошибки IndexError: list index out of range
|
||||
keyboard = create_keyboard_with_pagination(int(page_number), len(list_users), list_users,
|
||||
'ban')
|
||||
|
||||
await call.bot.edit_message_reply_markup(chat_id=call.message.chat.id, message_id=call.message.message_id,
|
||||
reply_markup=keyboard)
|
||||
else:
|
||||
# Готовим сообщения
|
||||
message_user = get_banned_users_list(int(page_number) * 7 - 7, BotDB)
|
||||
await call.bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
|
||||
text=message_user)
|
||||
|
||||
# Готовим клавиатуру
|
||||
buttons = get_banned_users_buttons(BotDB)
|
||||
keyboard = create_keyboard_with_pagination(int(call.data[5:]), len(buttons), buttons, 'unlock')
|
||||
await call.bot.edit_message_reply_markup(chat_id=call.message.chat.id, message_id=call.message.message_id,
|
||||
reply_markup=keyboard)
|
||||
|
||||
@@ -5,10 +5,12 @@ from aiogram.utils.keyboard import ReplyKeyboardBuilder, InlineKeyboardBuilder
|
||||
def get_reply_keyboard_for_post():
|
||||
builder = InlineKeyboardBuilder()
|
||||
builder.row(types.InlineKeyboardButton(
|
||||
text="Опубликовать", callback_data="publish")
|
||||
text="Опубликовать", callback_data="publish"),
|
||||
types.InlineKeyboardButton(
|
||||
text="Отклонить", callback_data="decline")
|
||||
)
|
||||
builder.row(types.InlineKeyboardButton(
|
||||
text="Отклонить", callback_data="decline")
|
||||
text="👮♂️ Забанить", callback_data="ban")
|
||||
)
|
||||
markup = builder.as_markup(resize_keyboard=True, one_time_keyboard=True)
|
||||
return markup
|
||||
@@ -37,7 +39,7 @@ def get_reply_keyboard_admin():
|
||||
builder.add(types.KeyboardButton(text="Бан (Список)"))
|
||||
builder.add(types.KeyboardButton(text="Бан по нику"))
|
||||
builder.add(types.KeyboardButton(text="Бан по ID"))
|
||||
builder.add(types.KeyboardButton(text="Тестовый бан"))
|
||||
builder.row()
|
||||
builder.add(types.KeyboardButton(text="Разбан (список)"))
|
||||
builder.add(types.KeyboardButton(text="Вернуться в бота"))
|
||||
markup = builder.as_markup(resize_keyboard=True, one_time_keyboard=True)
|
||||
@@ -49,7 +51,7 @@ def create_keyboard_with_pagination(page: int, total_items: int, array_items: li
|
||||
Создает клавиатуру с пагинацией для заданного набора элементов и устанавливает необходимый callback
|
||||
|
||||
Args:
|
||||
page: Номер текущей страницы.
|
||||
page: Номер текущей страницы (начинается с 1).
|
||||
total_items: Общее количество элементов.
|
||||
array_items: Лист кортежей. Содержит в себе user_name: user_id
|
||||
callback: Действие в коллбеке. Вернет callback вида ({callback}_{user_id})
|
||||
@@ -57,34 +59,75 @@ def create_keyboard_with_pagination(page: int, total_items: int, array_items: li
|
||||
Returns:
|
||||
InlineKeyboardMarkup: Клавиатура с кнопками пагинации.
|
||||
"""
|
||||
|
||||
# Проверяем валидность входных данных
|
||||
if page < 1:
|
||||
page = 1
|
||||
if not array_items:
|
||||
# Если нет элементов, возвращаем только кнопку "Назад"
|
||||
keyboard = InlineKeyboardBuilder()
|
||||
home_button = types.InlineKeyboardButton(text="🏠 Назад", callback_data="return")
|
||||
keyboard.row(home_button)
|
||||
return keyboard.as_markup()
|
||||
|
||||
# Определяем общее количество страниц
|
||||
total_pages = (total_items + 9 - 1) // 9
|
||||
items_per_page = 9
|
||||
total_pages = (total_items + items_per_page - 1) // items_per_page
|
||||
|
||||
# Ограничиваем страницу максимальным значением
|
||||
if page > total_pages:
|
||||
page = total_pages
|
||||
|
||||
# Создаем билдер для клавиатуры
|
||||
keyboard = InlineKeyboardBuilder()
|
||||
|
||||
# Вычисляем стартовый номер для текущей страницы
|
||||
start_index = (page - 1) * 9
|
||||
|
||||
# Кнопки с номерами страниц
|
||||
for i in range(start_index, min(start_index + 9, len(array_items))):
|
||||
keyboard.add(types.InlineKeyboardButton(
|
||||
start_index = (page - 1) * items_per_page
|
||||
|
||||
# Кнопки с элементами текущей страницы
|
||||
end_index = min(start_index + items_per_page, len(array_items))
|
||||
current_row = []
|
||||
|
||||
for i in range(start_index, end_index):
|
||||
current_row.append(types.InlineKeyboardButton(
|
||||
text=f"{array_items[i][0]}", callback_data=f"{callback}_{array_items[i][1]}"
|
||||
))
|
||||
keyboard.adjust(3)
|
||||
|
||||
next_button = types.InlineKeyboardButton(
|
||||
text="➡️ Следующая", callback_data=f"page_{page + 1}"
|
||||
)
|
||||
prev_button = types.InlineKeyboardButton(
|
||||
text="⬅️ Предыдущая", callback_data=f"page_{page - 1}"
|
||||
)
|
||||
keyboard.row(prev_button, next_button)
|
||||
home_button = types.InlineKeyboardButton(
|
||||
text="🏠 Назад", callback_data="return")
|
||||
|
||||
# Когда набирается 3 кнопки, добавляем ряд
|
||||
if len(current_row) == 3:
|
||||
keyboard.row(*current_row)
|
||||
current_row = []
|
||||
|
||||
# Добавляем оставшиеся кнопки, если они есть
|
||||
if current_row:
|
||||
keyboard.row(*current_row)
|
||||
|
||||
# Создаем кнопки навигации только если нужно
|
||||
navigation_buttons = []
|
||||
|
||||
# Кнопка "Предыдущая" - показываем только если не первая страница
|
||||
if page > 1:
|
||||
prev_button = types.InlineKeyboardButton(
|
||||
text="⬅️ Предыдущая", callback_data=f"page_{page - 1}"
|
||||
)
|
||||
navigation_buttons.append(prev_button)
|
||||
|
||||
# Кнопка "Следующая" - показываем только если не последняя страница
|
||||
if page < total_pages:
|
||||
next_button = types.InlineKeyboardButton(
|
||||
text="➡️ Следующая", callback_data=f"page_{page + 1}"
|
||||
)
|
||||
navigation_buttons.append(next_button)
|
||||
|
||||
# Добавляем кнопки навигации, если они есть
|
||||
if navigation_buttons:
|
||||
keyboard.row(*navigation_buttons)
|
||||
|
||||
# Кнопка "Назад"
|
||||
home_button = types.InlineKeyboardButton(text="🏠 Назад", callback_data="return")
|
||||
keyboard.row(home_button)
|
||||
k = keyboard.as_markup()
|
||||
return k
|
||||
|
||||
return keyboard.as_markup()
|
||||
|
||||
|
||||
def create_keyboard_for_ban_reason():
|
||||
|
||||
@@ -16,6 +16,6 @@ async def start_bot(bdf):
|
||||
link_preview_is_disabled=bdf.settings['Telegram']['preview_link']
|
||||
), timeout=30.0) # Добавляем таймаут для предотвращения зависаний
|
||||
dp = Dispatcher(storage=MemoryStorage(), fsm_strategy=FSMStrategy.GLOBAL_USER)
|
||||
dp.include_routers(private_router, callback_router, group_router, admin_router)
|
||||
dp.include_routers(admin_router, private_router, callback_router, group_router)
|
||||
await bot.delete_webhook(drop_pending_updates=True)
|
||||
await dp.start_polling(bot, skip_updates=True)
|
||||
|
||||
@@ -9,7 +9,6 @@ class StateUser(StatesGroup):
|
||||
PRE_CHAT = State()
|
||||
PRE_BAN = State()
|
||||
PRE_BAN_ID = State()
|
||||
PRE_BAN_FORWARD = State()
|
||||
BAN_2 = State()
|
||||
BAN_3 = State()
|
||||
BAN_4 = State()
|
||||
|
||||
Reference in New Issue
Block a user