from datetime import datetime, timezone from typing import Any, Dict, List, Optional from database.base import DatabaseConnection from database.models import AudioListenRecord, AudioMessage, AudioModerate class AudioRepository(DatabaseConnection): """Репозиторий для работы с аудио сообщениями.""" async def enable_foreign_keys(self): """Включает поддержку внешних ключей.""" await self._execute_query("PRAGMA foreign_keys = ON;") async def create_tables(self): """Создание таблиц для аудио.""" # Таблица аудио сообщений audio_query = """ CREATE TABLE IF NOT EXISTS audio_message_reference ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, file_name TEXT NOT NULL UNIQUE, author_id INTEGER NOT NULL, date_added INTEGER NOT NULL, FOREIGN KEY (author_id) REFERENCES our_users (user_id) ON DELETE CASCADE ) """ await self._execute_query(audio_query) # Таблица прослушивания аудио listen_query = """ CREATE TABLE IF NOT EXISTS user_audio_listens ( file_name TEXT NOT NULL, user_id INTEGER NOT NULL, PRIMARY KEY (file_name, user_id), FOREIGN KEY (user_id) REFERENCES our_users (user_id) ON DELETE CASCADE ) """ await self._execute_query(listen_query) # Таблица для voice bot voice_query = """ CREATE TABLE IF NOT EXISTS audio_moderate ( user_id INTEGER NOT NULL, message_id INTEGER, PRIMARY KEY (user_id, message_id), FOREIGN KEY (user_id) REFERENCES our_users (user_id) ON DELETE CASCADE ) """ await self._execute_query(voice_query) self.logger.info("Таблицы для аудио созданы") async def add_audio_record(self, audio: AudioMessage) -> None: """Добавляет информацию о войсе пользователя.""" query = """ INSERT INTO audio_message_reference (file_name, author_id, date_added) VALUES (?, ?, ?) """ # Преобразуем datetime в UNIX timestamp если нужно if isinstance(audio.date_added, str): date_timestamp = int(datetime.fromisoformat(audio.date_added).timestamp()) elif isinstance(audio.date_added, datetime): date_timestamp = int(audio.date_added.timestamp()) else: date_timestamp = audio.date_added params = (audio.file_name, audio.author_id, date_timestamp) await self._execute_query(query, params) self.logger.info( f"Аудио добавлено: file_name={audio.file_name}, author_id={audio.author_id}" ) async def add_audio_record_simple( self, file_name: str, user_id: int, date_added ) -> None: """Добавляет информацию о войсе пользователя (упрощенная версия).""" query = """ INSERT INTO audio_message_reference (file_name, author_id, date_added) VALUES (?, ?, ?) """ # Преобразуем datetime в UNIX timestamp если нужно if isinstance(date_added, str): date_timestamp = int(datetime.fromisoformat(date_added).timestamp()) elif isinstance(date_added, datetime): date_timestamp = int(date_added.timestamp()) else: date_timestamp = date_added params = (file_name, user_id, date_timestamp) await self._execute_query(query, params) self.logger.info(f"Аудио добавлено: file_name={file_name}, user_id={user_id}") async def get_last_date_audio(self) -> Optional[int]: """Получает дату последнего войса.""" query = "SELECT date_added FROM audio_message_reference ORDER BY date_added DESC LIMIT 1" rows = await self._execute_query_with_result(query) row = rows[0] if rows else None if row: self.logger.info(f"Последняя дата аудио: {row[0]}") return row[0] return None async def get_user_audio_records_count(self, user_id: int) -> int: """Получает количество записей пользователя.""" query = "SELECT COUNT(*) FROM audio_message_reference WHERE author_id = ?" rows = await self._execute_query_with_result(query, (user_id,)) row = rows[0] if rows else None return row[0] if row else 0 async def get_path_for_audio_record(self, user_id: int) -> Optional[str]: """Получает название последнего файла пользователя.""" query = """ SELECT file_name FROM audio_message_reference WHERE author_id = ? ORDER BY date_added DESC LIMIT 1 """ rows = await self._execute_query_with_result(query, (user_id,)) row = rows[0] if rows else None return row[0] if row else None async def check_listen_audio(self, user_id: int) -> List[str]: """Проверяет непрослушанные аудио для пользователя.""" query = """ SELECT l.file_name FROM audio_message_reference a LEFT JOIN user_audio_listens l ON l.file_name = a.file_name WHERE l.user_id = ? AND l.file_name IS NOT NULL """ listened_files = await self._execute_query_with_result(query, (user_id,)) # Получаем все аудио, кроме созданных пользователем all_audio_query = ( "SELECT file_name FROM audio_message_reference WHERE author_id <> ?" ) all_files = await self._execute_query_with_result(all_audio_query, (user_id,)) # Находим непрослушанные listened_set = {row[0] for row in listened_files} all_set = {row[0] for row in all_files} new_files = list(all_set - listened_set) self.logger.info( f"Найдено {len(new_files)} непрослушанных аудио для пользователя {user_id}" ) return new_files async def mark_listened_audio(self, file_name: str, user_id: int) -> None: """Отмечает аудио прослушанным для пользователя.""" query = "INSERT OR IGNORE INTO user_audio_listens (file_name, user_id) VALUES (?, ?)" params = (file_name, user_id) await self._execute_query(query, params) self.logger.info( f"Аудио {file_name} отмечено как прослушанное для пользователя {user_id}" ) async def get_user_id_by_file_name(self, file_name: str) -> Optional[int]: """Получает user_id пользователя по имени файла.""" query = "SELECT author_id FROM audio_message_reference WHERE file_name = ?" rows = await self._execute_query_with_result(query, (file_name,)) row = rows[0] if rows else None if row: user_id = row[0] self.logger.info(f"Получен user_id {user_id} для файла {file_name}") return user_id return None async def get_date_by_file_name(self, file_name: str) -> Optional[str]: """Получает дату добавления файла.""" query = "SELECT date_added FROM audio_message_reference WHERE file_name = ?" rows = await self._execute_query_with_result(query, (file_name,)) row = rows[0] if rows else None if row: date_added = row[0] # Преобразуем UNIX timestamp в читаемую дату (UTC для одинакового результата везде) readable_date = datetime.fromtimestamp( date_added, tz=timezone.utc ).strftime("%d.%m.%Y %H:%M") self.logger.info(f"Получена дата {readable_date} для файла {file_name}") return readable_date return None async def refresh_listen_audio(self, user_id: int) -> None: """Очищает всю информацию о прослушанных аудио пользователем.""" query = "DELETE FROM user_audio_listens WHERE user_id = ?" await self._execute_query(query, (user_id,)) self.logger.info(f"Очищены записи прослушивания для пользователя {user_id}") async def delete_listen_count_for_user(self, user_id: int) -> None: """Удаляет данные о прослушанных пользователем аудио.""" query = "DELETE FROM user_audio_listens WHERE user_id = ?" await self._execute_query(query, (user_id,)) self.logger.info(f"Удалены записи прослушивания для пользователя {user_id}") # Методы для voice bot async def set_user_id_and_message_id_for_voice_bot( self, message_id: int, user_id: int ) -> bool: """Устанавливает связь между message_id и user_id для voice bot.""" try: query = "INSERT OR IGNORE INTO audio_moderate (user_id, message_id) VALUES (?, ?)" params = (user_id, message_id) await self._execute_query(query, params) self.logger.info( f"Связь установлена: message_id={message_id}, user_id={user_id}" ) return True except Exception as e: self.logger.error(f"Ошибка установки связи: {e}") return False async def get_user_id_by_message_id_for_voice_bot( self, message_id: int ) -> Optional[int]: """Получает user_id пользователя по message_id для voice bot.""" query = "SELECT user_id FROM audio_moderate WHERE message_id = ?" rows = await self._execute_query_with_result(query, (message_id,)) row = rows[0] if rows else None if row: user_id = row[0] self.logger.info(f"Получен user_id {user_id} для message_id {message_id}") return user_id return None async def delete_audio_moderate_record(self, message_id: int) -> None: """Удаляет запись из таблицы audio_moderate по message_id.""" query = "DELETE FROM audio_moderate WHERE message_id = ?" await self._execute_query(query, (message_id,)) self.logger.info( f"Удалена запись из audio_moderate для message_id {message_id}" ) async def get_all_audio_records(self) -> List[Dict[str, Any]]: """Получить все записи аудио сообщений.""" query = "SELECT file_name, author_id, date_added FROM audio_message_reference" rows = await self._execute_query_with_result(query) records = [] for row in rows: records.append( {"file_name": row[0], "author_id": row[1], "date_added": row[2]} ) self.logger.info(f"Получено {len(records)} записей аудио сообщений") return records async def delete_audio_record_by_file_name(self, file_name: str) -> None: """Удалить запись аудио сообщения по имени файла.""" query = "DELETE FROM audio_message_reference WHERE file_name = ?" await self._execute_query(query, (file_name,)) self.logger.info(f"Удалена запись аудио сообщения: {file_name}")