- Removed the metrics scheduler functionality from the bot, transitioning to real-time metrics updates via middleware. - Enhanced logging for metrics operations across various handlers to improve monitoring and debugging capabilities. - Integrated metrics tracking for user activities and database errors, providing better insights into bot performance. - Cleaned up code by removing obsolete comments and unused imports, improving overall readability and maintainability.
304 lines
14 KiB
Python
304 lines
14 KiB
Python
import html
|
||
import traceback
|
||
import time
|
||
from datetime import datetime
|
||
|
||
from aiogram import Router, F
|
||
from aiogram.types import CallbackQuery
|
||
from aiogram.fsm.context import FSMContext
|
||
from aiogram.filters import MagicData
|
||
|
||
from helper_bot.handlers.voice.constants import CALLBACK_SAVE, CALLBACK_DELETE
|
||
from helper_bot.handlers.voice.services import AudioFileService
|
||
from helper_bot.keyboards.keyboards import create_keyboard_with_pagination, get_reply_keyboard_admin, \
|
||
create_keyboard_for_ban_reason
|
||
from helper_bot.utils.helper_func import get_banned_users_list, get_banned_users_buttons
|
||
from helper_bot.utils.base_dependency_factory import get_global_instance
|
||
from .dependency_factory import get_post_publish_service, get_ban_service
|
||
from .exceptions import UserBlockedBotError, PostNotFoundError, UserNotFoundError, PublishError, BanError
|
||
from .constants import (
|
||
CALLBACK_PUBLISH, CALLBACK_DECLINE, CALLBACK_BAN, CALLBACK_UNLOCK,
|
||
CALLBACK_RETURN, CALLBACK_PAGE, MESSAGE_PUBLISHED, MESSAGE_DECLINED,
|
||
MESSAGE_USER_BANNED, MESSAGE_USER_UNLOCKED, MESSAGE_ERROR,
|
||
ERROR_BOT_BLOCKED
|
||
)
|
||
from logs.custom_logger import logger
|
||
|
||
# Local imports - metrics
|
||
from helper_bot.utils.metrics import (
|
||
metrics,
|
||
track_time,
|
||
track_errors,
|
||
db_query_time
|
||
)
|
||
|
||
callback_router = Router()
|
||
|
||
|
||
@callback_router.callback_query(F.data == CALLBACK_PUBLISH)
|
||
@track_time("post_for_group", "callback_handlers")
|
||
@track_errors("callback_handlers", "post_for_group")
|
||
async def post_for_group(
|
||
call: CallbackQuery,
|
||
settings: MagicData("settings")
|
||
):
|
||
publish_service = get_post_publish_service()
|
||
# TODO: переделать на MagicData
|
||
logger.info(
|
||
f'Получен callback-запрос с действием: {call.data} от пользователя {call.from_user.full_name} (ID сообщения: {call.message.message_id})')
|
||
|
||
try:
|
||
await publish_service.publish_post(call)
|
||
await call.answer(text=MESSAGE_PUBLISHED, cache_time=3)
|
||
except UserBlockedBotError:
|
||
await call.answer(text=MESSAGE_ERROR, show_alert=True, cache_time=3)
|
||
except (PostNotFoundError, PublishError) as e:
|
||
logger.error(f'Ошибка при публикации поста: {str(e)}')
|
||
await call.answer(text=MESSAGE_ERROR, show_alert=True, cache_time=3)
|
||
except Exception as e:
|
||
if str(e) == ERROR_BOT_BLOCKED:
|
||
await call.answer(text=MESSAGE_ERROR, show_alert=True, cache_time=3)
|
||
else:
|
||
important_logs = settings['Telegram']['important_logs']
|
||
await call.bot.send_message(
|
||
chat_id=important_logs,
|
||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}"
|
||
)
|
||
logger.error(f'Неожиданная ошибка при публикации поста: {str(e)}')
|
||
await call.answer(text=MESSAGE_ERROR, show_alert=True, cache_time=3)
|
||
|
||
|
||
@callback_router.callback_query(F.data == CALLBACK_DECLINE)
|
||
@track_time("decline_post_for_group", "callback_handlers")
|
||
@track_errors("callback_handlers", "decline_post_for_group")
|
||
async def decline_post_for_group(
|
||
call: CallbackQuery,
|
||
settings: MagicData("settings")
|
||
):
|
||
publish_service = get_post_publish_service()
|
||
# TODO: переделать на MagicData
|
||
logger.info(
|
||
f'Получен callback-запрос с данными: {call.data} от пользователя {call.from_user.full_name} (ID: {call.from_user.id})')
|
||
try:
|
||
await publish_service.decline_post(call)
|
||
await call.answer(text=MESSAGE_DECLINED, cache_time=3)
|
||
except UserBlockedBotError:
|
||
await call.answer(text=MESSAGE_ERROR, show_alert=True, cache_time=3)
|
||
except (PostNotFoundError, PublishError) as e:
|
||
logger.error(f'Ошибка при отклонении поста: {str(e)}')
|
||
await call.answer(text=MESSAGE_ERROR, show_alert=True, cache_time=3)
|
||
except Exception as e:
|
||
if str(e) == ERROR_BOT_BLOCKED:
|
||
await call.answer(text=MESSAGE_ERROR, show_alert=True, cache_time=3)
|
||
else:
|
||
important_logs = settings['Telegram']['important_logs']
|
||
await call.bot.send_message(
|
||
chat_id=important_logs,
|
||
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}"
|
||
)
|
||
logger.error(f'Неожиданная ошибка при отклонении поста: {str(e)}')
|
||
await call.answer(text=MESSAGE_ERROR, show_alert=True, cache_time=3)
|
||
|
||
|
||
@callback_router.callback_query(F.data == CALLBACK_BAN)
|
||
@track_time("ban_user_from_post", "callback_handlers")
|
||
@track_errors("callback_handlers", "ban_user_from_post")
|
||
async def ban_user_from_post(call: CallbackQuery, **kwargs):
|
||
ban_service = get_ban_service()
|
||
# TODO: переделать на MagicData
|
||
try:
|
||
await ban_service.ban_user_from_post(call)
|
||
await call.answer(text=MESSAGE_USER_BANNED, cache_time=3)
|
||
except UserBlockedBotError:
|
||
await call.answer(text=MESSAGE_ERROR, show_alert=True, cache_time=3)
|
||
except (UserNotFoundError, BanError) as e:
|
||
logger.error(f'Ошибка при блокировке пользователя: {str(e)}')
|
||
await call.answer(text=MESSAGE_ERROR, show_alert=True, cache_time=3)
|
||
except Exception as e:
|
||
if str(e) == ERROR_BOT_BLOCKED:
|
||
await call.answer(text=MESSAGE_ERROR, show_alert=True, cache_time=3)
|
||
else:
|
||
logger.error(f'Неожиданная ошибка при блокировке пользователя: {str(e)}')
|
||
await call.answer(text=MESSAGE_ERROR, show_alert=True, cache_time=3)
|
||
|
||
|
||
@callback_router.callback_query(F.data.contains(CALLBACK_BAN))
|
||
@track_time("process_ban_user", "callback_handlers")
|
||
@track_errors("callback_handlers", "process_ban_user")
|
||
async def process_ban_user(call: CallbackQuery, state: FSMContext, **kwargs):
|
||
ban_service = get_ban_service()
|
||
# TODO: переделать на MagicData
|
||
user_id = call.data[4:]
|
||
logger.info(f"Вызов функции process_ban_user. Данные callback: {call.data} пользователь: {user_id}")
|
||
|
||
# Проверяем, что user_id является валидным числом
|
||
try:
|
||
user_id_int = int(user_id)
|
||
except ValueError:
|
||
logger.error(f"Некорректный user_id в callback: {user_id}")
|
||
await call.answer(text="Ошибка: некорректный ID пользователя", show_alert=True, cache_time=3)
|
||
return
|
||
|
||
try:
|
||
user_name = await ban_service.ban_user(str(user_id_int), "")
|
||
await state.update_data(user_id=user_id_int, 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_int}\n<b>username:</b> {user_name_escaped}\nИмя:{full_name_escaped}\nВыбери причину бана из списка или напиши ее в чат",
|
||
reply_markup=markup
|
||
)
|
||
await state.set_state('BAN_2')
|
||
except UserNotFoundError:
|
||
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(CALLBACK_UNLOCK))
|
||
@track_time("process_unlock_user", "callback_handlers")
|
||
@track_errors("callback_handlers", "process_unlock_user")
|
||
async def process_unlock_user(call: CallbackQuery, **kwargs):
|
||
ban_service = get_ban_service()
|
||
# TODO: переделать на MagicData
|
||
user_id = call.data[7:]
|
||
|
||
# Проверяем, что user_id является валидным числом
|
||
try:
|
||
user_id_int = int(user_id)
|
||
except ValueError:
|
||
logger.error(f"Некорректный user_id в callback: {user_id}")
|
||
await call.answer(text="Ошибка: некорректный ID пользователя", show_alert=True, cache_time=3)
|
||
return
|
||
|
||
try:
|
||
username = await ban_service.unlock_user(str(user_id_int))
|
||
await call.answer(f'{MESSAGE_USER_UNLOCKED} {username}', show_alert=True)
|
||
except UserNotFoundError:
|
||
await call.answer(text='Пользователь не найден в базе', show_alert=True, cache_time=3)
|
||
except Exception as e:
|
||
logger.error(f'Ошибка при разблокировке пользователя: {str(e)}')
|
||
await call.answer(text=MESSAGE_ERROR, show_alert=True, cache_time=3)
|
||
|
||
|
||
@callback_router.callback_query(F.data == CALLBACK_RETURN)
|
||
@track_time("return_to_main_menu", "callback_handlers")
|
||
@track_errors("callback_handlers", "return_to_main_menu")
|
||
async def return_to_main_menu(call: CallbackQuery, **kwargs):
|
||
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(CALLBACK_PAGE))
|
||
@track_time("change_page", "callback_handlers")
|
||
@track_errors("callback_handlers", "change_page")
|
||
async def change_page(
|
||
call: CallbackQuery,
|
||
bot_db: MagicData("bot_db"),
|
||
**kwargs
|
||
):
|
||
try:
|
||
page_number = int(call.data[5:])
|
||
except ValueError:
|
||
logger.error(f"Некорректный номер страницы в callback: {call.data}")
|
||
await call.answer(text="Ошибка: некорректный номер страницы", show_alert=True, cache_time=3)
|
||
return
|
||
|
||
logger.info(f"Переход на страницу {page_number}")
|
||
|
||
if call.message.text == 'Список пользователей которые последними обращались к боту':
|
||
list_users = await bot_db.get_last_users(30)
|
||
keyboard = create_keyboard_with_pagination(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, bot_db)
|
||
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(bot_db)
|
||
keyboard = create_keyboard_with_pagination(page_number, 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
|
||
)
|
||
|
||
|
||
@callback_router.callback_query(F.data == CALLBACK_SAVE)
|
||
@track_time("save_voice_message", "callback_handlers")
|
||
@track_errors("callback_handlers", "save_voice_message")
|
||
async def save_voice_message(
|
||
call: CallbackQuery,
|
||
bot_db: MagicData("bot_db"),
|
||
settings: MagicData("settings"),
|
||
**kwargs
|
||
):
|
||
try:
|
||
# Создаем сервис для работы с аудио файлами
|
||
audio_service = AudioFileService(bot_db)
|
||
|
||
# Получаем ID пользователя из базы
|
||
user_id = await bot_db.get_user_id_by_message_id_for_voice_bot(call.message.message_id)
|
||
|
||
# Генерируем имя файла
|
||
file_name = await audio_service.generate_file_name(user_id)
|
||
|
||
# Собираем инфо о сообщении
|
||
time_UTC = int(time.time())
|
||
date_added = datetime.fromtimestamp(time_UTC)
|
||
|
||
# Получаем file_id из voice сообщения
|
||
file_id = call.message.voice.file_id if call.message.voice else ""
|
||
|
||
# Сохраняем в базу данных
|
||
await audio_service.save_audio_file(file_name, user_id, date_added, file_id)
|
||
|
||
# Скачиваем и сохраняем файл
|
||
await audio_service.download_and_save_audio(call.bot, call.message, file_name)
|
||
|
||
# Удаляем сообщение из предложки
|
||
await call.bot.delete_message(
|
||
chat_id=settings['Telegram']['group_for_posts'],
|
||
message_id=call.message.message_id
|
||
)
|
||
|
||
await call.answer(text='Сохранено!', cache_time=3)
|
||
|
||
except Exception as e:
|
||
logger.error(f"Ошибка при сохранении голосового сообщения: {e}")
|
||
await call.answer(text='Ошибка при сохранении!', cache_time=3)
|
||
|
||
|
||
@callback_router.callback_query(F.data == CALLBACK_DELETE)
|
||
@track_time("delete_voice_message", "callback_handlers")
|
||
@track_errors("callback_handlers", "delete_voice_message")
|
||
async def delete_voice_message(
|
||
call: CallbackQuery,
|
||
bot_db: MagicData("bot_db"),
|
||
settings: MagicData("settings"),
|
||
**kwargs
|
||
):
|
||
try:
|
||
# Удаляем сообщение из предложки
|
||
await call.bot.delete_message(
|
||
chat_id=settings['Telegram']['group_for_posts'],
|
||
message_id=call.message.message_id
|
||
)
|
||
|
||
await call.answer(text='Удалено!', cache_time=3)
|
||
|
||
except Exception as e:
|
||
logger.error(f"Ошибка при удалении голосового сообщения: {e}")
|
||
await call.answer(text='Ошибка при удалении!', cache_time=3)
|