style: isort + black

This commit is contained in:
2026-02-02 00:13:33 +03:00
parent 5f66c86d99
commit 561c9074dd
86 changed files with 8459 additions and 5793 deletions

View File

@@ -22,7 +22,12 @@ from .post_repository import PostRepository
from .user_repository import UserRepository
__all__ = [
'UserRepository', 'BlacklistRepository', 'BlacklistHistoryRepository',
'MessageRepository', 'PostRepository', 'AdminRepository', 'AudioRepository',
'MigrationRepository'
"UserRepository",
"BlacklistRepository",
"BlacklistHistoryRepository",
"MessageRepository",
"PostRepository",
"AdminRepository",
"AudioRepository",
"MigrationRepository",
]

View File

@@ -7,15 +7,15 @@ 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 = '''
audio_query = """
CREATE TABLE IF NOT EXISTS audio_message_reference (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
file_name TEXT NOT NULL UNIQUE,
@@ -23,33 +23,33 @@ class AudioRepository(DatabaseConnection):
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 = '''
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 = '''
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 = """
@@ -63,13 +63,17 @@ class AudioRepository(DatabaseConnection):
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:
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)
@@ -82,30 +86,30 @@ class AudioRepository(DatabaseConnection):
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 = """
@@ -115,7 +119,7 @@ class AudioRepository(DatabaseConnection):
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 = """
@@ -125,115 +129,129 @@ class AudioRepository(DatabaseConnection):
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_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}")
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}")
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 в читаемую дату
readable_date = datetime.fromtimestamp(date_added).strftime('%d.%m.%Y %H:%M')
readable_date = datetime.fromtimestamp(date_added).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:
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}")
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]:
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}")
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]
})
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}")
self.logger.info(f"Удалена запись аудио сообщения: {file_name}")

View File

@@ -1,11 +1,13 @@
"""Репозиторий для работы с миграциями базы данных."""
import aiosqlite
from database.base import DatabaseConnection
class MigrationRepository(DatabaseConnection):
"""Репозиторий для управления миграциями базы данных."""
async def create_table(self):
"""Создает таблицу migrations, если она не существует."""
query = """
@@ -17,13 +19,15 @@ class MigrationRepository(DatabaseConnection):
"""
await self._execute_query(query)
self.logger.info("Таблица migrations создана или уже существует")
async def get_applied_migrations(self) -> list[str]:
"""Возвращает список имен примененных скриптов миграций."""
conn = None
try:
conn = await self._get_connection()
cursor = await conn.execute("SELECT script_name FROM migrations ORDER BY applied_at")
cursor = await conn.execute(
"SELECT script_name FROM migrations ORDER BY applied_at"
)
rows = await cursor.fetchall()
await cursor.close()
return [row[0] for row in rows]
@@ -33,15 +37,14 @@ class MigrationRepository(DatabaseConnection):
finally:
if conn:
await conn.close()
async def is_migration_applied(self, script_name: str) -> bool:
"""Проверяет, применена ли миграция."""
conn = None
try:
conn = await self._get_connection()
cursor = await conn.execute(
"SELECT COUNT(*) FROM migrations WHERE script_name = ?",
(script_name,)
"SELECT COUNT(*) FROM migrations WHERE script_name = ?", (script_name,)
)
row = await cursor.fetchone()
await cursor.close()
@@ -52,15 +55,14 @@ class MigrationRepository(DatabaseConnection):
finally:
if conn:
await conn.close()
async def mark_migration_applied(self, script_name: str) -> None:
"""Отмечает миграцию как примененную."""
conn = None
try:
conn = await self._get_connection()
await conn.execute(
"INSERT INTO migrations (script_name) VALUES (?)",
(script_name,)
"INSERT INTO migrations (script_name) VALUES (?)", (script_name,)
)
await conn.commit()
self.logger.info(f"Миграция {script_name} отмечена как примененная")
@@ -72,7 +74,7 @@ class MigrationRepository(DatabaseConnection):
finally:
if conn:
await conn.close()
async def create_table_from_sql(self, sql_script: str) -> None:
"""Создает таблицу из SQL скрипта. Используется в миграциях."""
await self._execute_query(sql_script)

View File

@@ -439,19 +439,19 @@ class PostRepository(DatabaseConnection):
f"Получен контент опубликованного поста: {len(post_content)} элементов для published_message_id={published_message_id}"
)
return post_content
# ============================================
# Методы для работы с ML-скорингом
# ============================================
async def update_ml_scores(self, message_id: int, ml_scores_json: str) -> bool:
"""
Обновляет ML-скоры для поста.
Args:
message_id: ID сообщения в группе модерации
ml_scores_json: JSON строка со скорами
Returns:
True если обновлено успешно
"""
@@ -461,16 +461,18 @@ class PostRepository(DatabaseConnection):
self.logger.info(f"ML-скоры обновлены для message_id={message_id}")
return True
except Exception as e:
self.logger.error(f"Ошибка обновления ML-скоров для message_id={message_id}: {e}")
self.logger.error(
f"Ошибка обновления ML-скоров для message_id={message_id}: {e}"
)
return False
async def get_ml_scores_by_message_id(self, message_id: int) -> Optional[str]:
"""
Получает ML-скоры для поста.
Args:
message_id: ID сообщения
Returns:
JSON строка со скорами или None
"""
@@ -479,14 +481,14 @@ class PostRepository(DatabaseConnection):
if rows and rows[0][0]:
return rows[0][0]
return None
async def get_post_text_by_message_id(self, message_id: int) -> Optional[str]:
"""
Получает текст поста по message_id.
Args:
message_id: ID сообщения
Returns:
Текст поста или None
"""
@@ -495,14 +497,14 @@ class PostRepository(DatabaseConnection):
if rows and rows[0][0]:
return rows[0][0]
return None
async def get_approved_posts_texts(self, limit: int = 1000) -> List[str]:
"""
Получает тексты опубликованных постов для обучения RAG.
Args:
limit: Максимальное количество постов
Returns:
Список текстов
"""
@@ -519,14 +521,14 @@ class PostRepository(DatabaseConnection):
texts = [row[0] for row in rows if row[0]]
self.logger.info(f"Получено {len(texts)} опубликованных постов для обучения")
return texts
async def get_declined_posts_texts(self, limit: int = 1000) -> List[str]:
"""
Получает тексты отклоненных постов для обучения RAG.
Args:
limit: Максимальное количество постов
Returns:
Список текстов
"""
@@ -543,4 +545,3 @@ class PostRepository(DatabaseConnection):
texts = [row[0] for row in rows if row[0]]
self.logger.info(f"Получено {len(texts)} отклоненных постов для обучения")
return texts