Files
telegram-helper-bot/voice_bot/handlers/voice_handler.py
Andrey d128e54694 Refactor project structure and remove obsolete files
- Deleted the Makefile, `README_TESTING.md`, and several deployment scripts to streamline the project.
- Updated `.dockerignore` to exclude unnecessary development files.
- Adjusted database schema comments for clarity.
- Refactored metrics handling in middleware for improved command extraction and logging.
- Enhanced command mappings for buttons and callbacks in constants for better maintainability.
- Start refactor voice bot
2025-09-01 00:54:10 +03:00

216 lines
8.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.
import asyncio
from datetime import datetime
from pathlib import Path
from aiogram import Router, types, F
from aiogram.filters import Command, StateFilter
from aiogram.fsm.context import FSMContext
from aiogram.types import FSInputFile
from helper_bot.filters.main import ChatTypeFilter
from helper_bot.middlewares.blacklist_middleware import BlacklistMiddleware
from helper_bot.utils.helper_func import update_user_info, check_user_emoji, send_voice_message
from logs.custom_logger import logger
from voice_bot.handlers.constants import *
from voice_bot.handlers.dependencies import VoiceBotMiddleware, BotDB, Settings
from voice_bot.handlers.services import VoiceBotService
from voice_bot.handlers.utils import get_last_message_text, validate_voice_message, get_user_emoji_safe
from voice_bot.keyboards.keyboards import get_main_keyboard, get_reply_keyboard_for_voice
voice_router = Router()
# Middleware
voice_router.message.middleware(VoiceBotMiddleware())
voice_router.message.middleware(BlacklistMiddleware())
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
Command(CMD_RESTART)
)
async def restart_function(message: types.Message, state: FSMContext, bot_db: BotDB):
await message.forward(chat_id=bot_db.settings['Telegram']['group_for_logs'])
await update_user_info(VOICE_BOT_NAME, message)
check_user_emoji(message)
markup = get_main_keyboard()
await message.answer(text='Я перезапущен!', reply_markup=markup)
await state.set_state(STATE_START)
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
Command(CMD_EMOJI)
)
async def handle_emoji_message(message: types.Message, state: FSMContext, bot_db: BotDB):
await message.forward(chat_id=bot_db.settings['Telegram']['group_for_logs'])
user_emoji = check_user_emoji(message)
await state.set_state(STATE_START)
if user_emoji is not None:
await message.answer(f'Твоя эмодзя - {user_emoji}', parse_mode='HTML')
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
Command(CMD_HELP)
)
async def help_function(message: types.Message, state: FSMContext, bot_db: BotDB):
await message.forward(chat_id=bot_db.settings['Telegram']['group_for_logs'])
await update_user_info(VOICE_BOT_NAME, message)
await message.answer(
text=HELP_MESSAGE,
disable_web_page_preview=not bot_db.settings['Telegram']['preview_link']
)
await state.set_state(STATE_START)
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
Command(CMD_START)
)
async def start(message: types.Message, state: FSMContext, bot_db: BotDB, settings: Settings):
await state.set_state(STATE_START)
await message.forward(chat_id=settings['Telegram']['group_for_logs'])
await update_user_info(VOICE_BOT_NAME, message)
user_emoji = get_user_emoji_safe(bot_db, message.from_user.id)
# Создаем сервис и отправляем приветственные сообщения
voice_service = VoiceBotService(bot_db, settings)
await voice_service.send_welcome_messages(message, user_emoji)
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
Command(CMD_REFRESH)
)
async def refresh_listen_function(message: types.Message, state: FSMContext, bot_db: BotDB):
await message.forward(chat_id=bot_db.settings['Telegram']['group_for_logs'])
await update_user_info(VOICE_BOT_NAME, message)
markup = get_main_keyboard()
# Очищаем прослушивания через сервис
voice_service = VoiceBotService(bot_db, bot_db.settings)
voice_service.clear_user_listenings(message.from_user.id)
await message.answer(
text=LISTENINGS_CLEARED_MESSAGE,
disable_web_page_preview=not bot_db.settings['Telegram']['preview_link'],
reply_markup=markup
)
await state.set_state(STATE_START)
@voice_router.message(
StateFilter(STATE_START),
ChatTypeFilter(chat_type=["private"]),
F.text == BTN_SPEAK
)
async def standup_write(message: types.Message, state: FSMContext, bot_db: BotDB):
await message.forward(chat_id=bot_db.settings['Telegram']['group_for_logs'])
markup = types.ReplyKeyboardRemove()
await message.answer(text=RECORD_VOICE_MESSAGE, reply_markup=markup)
try:
message_with_date = get_last_message_text(bot_db)
if message_with_date:
await message.answer(text=message_with_date, parse_mode="html")
except Exception as e:
logger.error(f'Не удалось получить дату последнего сообщения - {e}')
await state.set_state(STATE_STANDUP_WRITE)
@voice_router.message(
StateFilter(STATE_STANDUP_WRITE),
ChatTypeFilter(chat_type=["private"]),
)
async def suggest_voice(message: types.Message, state: FSMContext, bot_db: BotDB):
logger.info(
f"Вызов функции suggest_voice. Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}"
)
await message.forward(chat_id=bot_db.settings['Telegram']['group_for_logs'])
markup = get_main_keyboard()
if validate_voice_message(message):
markup_for_voice = get_reply_keyboard_for_voice()
# Отправляем аудио в приватный канал
sent_message = await send_voice_message(
bot_db.settings['Telegram']['group_for_posts'],
message,
message.voice.file_id,
markup_for_voice
)
# Сохраняем в базу инфо о посте
bot_db.set_user_id_and_message_id_for_voice_bot(sent_message.message_id, message.from_user.id)
# Отправляем юзеру ответ и возвращаем его в меню
await message.answer(text=VOICE_SAVED_MESSAGE, reply_markup=markup)
await state.set_state(STATE_START)
else:
await message.forward(chat_id=bot_db.settings['Telegram']['group_for_logs'])
await message.answer(text=UNKNOWN_CONTENT_MESSAGE, reply_markup=markup)
await state.set_state(STATE_STANDUP_WRITE)
@voice_router.message(
StateFilter(STATE_START),
ChatTypeFilter(chat_type=["private"]),
F.text == BTN_LISTEN
)
async def standup_listen_audio(message: types.Message, bot_db: BotDB):
markup = get_main_keyboard()
# Создаем сервис для работы с аудио
voice_service = VoiceBotService(bot_db, bot_db.settings)
try:
# Получаем случайное аудио
audio_data = voice_service.get_random_audio(message.from_user.id)
if not audio_data:
await message.answer(text=NO_AUDIO_MESSAGE, reply_markup=markup)
try:
message_with_date = get_last_message_text(bot_db)
if message_with_date:
await message.answer(text=message_with_date, parse_mode="html")
except Exception as e:
logger.error(f'Не удалось получить последнюю дату {e}')
return
audio_for_user, date_added, user_emoji = audio_data
# Получаем путь к файлу
path = Path(f'{VOICE_USERS_DIR}/{audio_for_user}.ogg')
voice = FSInputFile(path)
# Маркируем сообщение как прослушанное
voice_service.mark_audio_as_listened(audio_for_user, message.from_user.id)
# Формируем подпись
if user_emoji:
caption = f'{user_emoji}\nДата записи: {date_added}'
else:
caption = f'Дата записи: {date_added}'
await message.bot.send_voice(
chat_id=message.chat.id,
voice=voice,
caption=caption,
reply_markup=markup
)
# Получаем количество оставшихся аудио
remaining_count = voice_service.get_remaining_audio_count(message.from_user.id) - 1
await message.answer(
text=f'Осталось непрослушанных: <b>{remaining_count}</b>',
reply_markup=markup
)
except Exception as e:
logger.error(f"Ошибка при прослушивании аудио: {e}")
await message.answer(
text="Произошла ошибка при получении аудио. Попробуйте позже.",
reply_markup=markup
)