- Introduced a new `PrivateHandlers` class to encapsulate private message handling logic, improving organization and maintainability. - Added new dependencies in `requirements.txt` for database support with `aiosqlite`. - Updated the private handlers to utilize modular components for better separation of concerns and easier testing. - Implemented error handling and logging for improved robustness in message processing.
996 lines
42 KiB
Python
996 lines
42 KiB
Python
import os
|
||
import aiosqlite
|
||
from datetime import datetime
|
||
from typing import Optional, List, Dict, Any, Tuple
|
||
from logs.custom_logger import logger
|
||
|
||
|
||
class AsyncBotDB:
|
||
"""Асинхронный класс для работы с базой данных."""
|
||
|
||
def __init__(self, db_path: str):
|
||
self.db_path = os.path.abspath(db_path)
|
||
self.logger = logger
|
||
self.logger.info(f'Инициация асинхронной базы данных: {self.db_path}')
|
||
|
||
async def _get_connection(self):
|
||
"""Получение асинхронного соединения с базой данных."""
|
||
try:
|
||
# Используем connect вместо connect с контекстным менеджером
|
||
conn = await aiosqlite.connect(self.db_path)
|
||
# Включаем поддержку внешних ключей
|
||
await conn.execute("PRAGMA foreign_keys = ON")
|
||
# Включаем WAL режим для лучшей производительности
|
||
await conn.execute("PRAGMA journal_mode = WAL")
|
||
await conn.execute("PRAGMA synchronous = NORMAL")
|
||
await conn.execute("PRAGMA cache_size = 10000")
|
||
await conn.execute("PRAGMA temp_store = MEMORY")
|
||
return conn
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении асинхронного соединения: {e}")
|
||
raise
|
||
|
||
async def create_tables(self):
|
||
"""Создание таблиц в базе данных."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
|
||
# Таблица пользователей
|
||
await conn.execute('''
|
||
CREATE TABLE IF NOT EXISTS our_users (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
user_id INTEGER UNIQUE NOT NULL,
|
||
first_name TEXT NOT NULL,
|
||
full_name TEXT NOT NULL,
|
||
username TEXT,
|
||
is_bot BOOLEAN DEFAULT FALSE,
|
||
language_code TEXT DEFAULT 'ru',
|
||
emoji TEXT DEFAULT '😊',
|
||
has_stickers BOOLEAN DEFAULT FALSE,
|
||
date_added TEXT NOT NULL,
|
||
date_changed TEXT NOT NULL
|
||
)
|
||
''')
|
||
|
||
# Таблица черного списка
|
||
await conn.execute('''
|
||
CREATE TABLE IF NOT EXISTS blacklist (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
user_id INTEGER UNIQUE NOT NULL,
|
||
user_name TEXT,
|
||
message_for_user TEXT,
|
||
date_to_unban TEXT,
|
||
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
||
)
|
||
''')
|
||
|
||
# Таблица сообщений пользователей
|
||
await conn.execute('''
|
||
CREATE TABLE IF NOT EXISTS user_messages (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
message_text TEXT NOT NULL,
|
||
user_id INTEGER NOT NULL,
|
||
message_id INTEGER UNIQUE NOT NULL,
|
||
date TEXT NOT NULL,
|
||
FOREIGN KEY (user_id) REFERENCES our_users (user_id)
|
||
)
|
||
''')
|
||
|
||
# Таблица постов из Telegram
|
||
await conn.execute('''
|
||
CREATE TABLE IF NOT EXISTS post_from_telegram_suggest (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
message_id INTEGER UNIQUE NOT NULL,
|
||
text TEXT NOT NULL,
|
||
author_id INTEGER NOT NULL,
|
||
helper_text_message_id INTEGER,
|
||
created_at TEXT NOT NULL,
|
||
FOREIGN KEY (author_id) REFERENCES our_users (user_id)
|
||
)
|
||
''')
|
||
|
||
# Таблица контента постов (создаем ПЕРЕД таблицей связей)
|
||
await conn.execute('''
|
||
CREATE TABLE IF NOT EXISTS content_post_from_telegram (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
message_id INTEGER UNIQUE NOT NULL,
|
||
content_name TEXT NOT NULL,
|
||
content_type TEXT NOT NULL
|
||
)
|
||
''')
|
||
|
||
# Таблица связи сообщений с контентом
|
||
await conn.execute('''
|
||
CREATE TABLE IF NOT EXISTS message_link_to_content (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
post_id INTEGER NOT NULL,
|
||
message_id INTEGER NOT NULL,
|
||
FOREIGN KEY (post_id) REFERENCES post_from_telegram_suggest (message_id),
|
||
FOREIGN KEY (message_id) REFERENCES content_post_from_telegram (message_id)
|
||
)
|
||
''')
|
||
|
||
# Таблица администраторов
|
||
await conn.execute('''
|
||
CREATE TABLE IF NOT EXISTS admins (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
user_id INTEGER UNIQUE NOT NULL,
|
||
role TEXT NOT NULL DEFAULT 'admin',
|
||
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
||
FOREIGN KEY (user_id) REFERENCES our_users (user_id)
|
||
)
|
||
''')
|
||
|
||
# Таблица миграций
|
||
await conn.execute('''
|
||
CREATE TABLE IF NOT EXISTS migrations (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
version INTEGER UNIQUE NOT NULL,
|
||
script_name TEXT NOT NULL,
|
||
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
||
)
|
||
''')
|
||
|
||
# Таблица аудио сообщений
|
||
await conn.execute('''
|
||
CREATE TABLE IF NOT EXISTS audio_message_reference (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
file_name TEXT NOT NULL,
|
||
author_id INTEGER NOT NULL,
|
||
date_added TEXT NOT NULL,
|
||
listen_count INTEGER DEFAULT 0,
|
||
file_id TEXT NOT NULL,
|
||
FOREIGN KEY (author_id) REFERENCES our_users (user_id)
|
||
)
|
||
''')
|
||
|
||
# Таблица прослушивания аудио
|
||
await conn.execute('''
|
||
CREATE TABLE IF NOT EXISTS listen_audio_users (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
file_name TEXT NOT NULL,
|
||
user_id INTEGER NOT NULL,
|
||
is_listen BOOLEAN DEFAULT FALSE,
|
||
FOREIGN KEY (user_id) REFERENCES our_users (user_id)
|
||
)
|
||
''')
|
||
|
||
# Таблица для voice bot
|
||
await conn.execute('''
|
||
CREATE TABLE IF NOT EXISTS audio_moderate (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
message_id INTEGER UNIQUE NOT NULL,
|
||
user_id INTEGER NOT NULL,
|
||
FOREIGN KEY (user_id) REFERENCES our_users (user_id)
|
||
)
|
||
''')
|
||
|
||
await conn.commit()
|
||
self.logger.info("Таблицы успешно созданы")
|
||
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при создании таблиц: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def user_exists(self, user_id: int) -> bool:
|
||
"""Проверка существования пользователя."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute("SELECT 1 FROM our_users WHERE user_id = ?", (user_id,)) as cursor:
|
||
result = await cursor.fetchone()
|
||
return bool(result)
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при проверке существования пользователя: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def add_new_user(self, user_id: int, first_name: str, full_name: str, username: str = None,
|
||
is_bot: bool = False, language_code: str = "ru", emoji: str = "😊"):
|
||
"""Добавление нового пользователя."""
|
||
conn = None
|
||
try:
|
||
date_added = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
|
||
date_changed = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
|
||
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"INSERT INTO our_users (user_id, first_name, full_name, username, is_bot, "
|
||
"language_code, emoji, date_added, date_changed) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||
(user_id, first_name, full_name, username, is_bot, language_code, emoji, date_added, date_changed)
|
||
)
|
||
await conn.commit()
|
||
self.logger.info(f"Новый пользователь добавлен: {user_id}")
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при добавлении пользователя: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_user_info(self, user_id: int) -> Optional[Dict[str, Any]]:
|
||
"""Получение информации о пользователе."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT username, full_name, has_stickers, emoji FROM our_users WHERE user_id = ?",
|
||
(user_id,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
if result:
|
||
return {
|
||
'username': result[0],
|
||
'full_name': result[1],
|
||
'has_stickers': bool(result[2]) if result[2] is not None else False,
|
||
'emoji': result[3]
|
||
}
|
||
return None
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении информации о пользователе: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def update_user_date(self, user_id: int):
|
||
"""Обновление даты последнего изменения пользователя."""
|
||
conn = None
|
||
try:
|
||
date_changed = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"UPDATE our_users SET date_changed = ? WHERE user_id = ?",
|
||
(date_changed, user_id)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при обновлении даты пользователя: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def update_user_info(self, user_id: int, username: str = None, full_name: str = None):
|
||
"""Обновление информации о пользователе."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
if username and full_name:
|
||
await conn.execute(
|
||
"UPDATE our_users SET username = ?, full_name = ? WHERE user_id = ?",
|
||
(username, full_name, user_id)
|
||
)
|
||
elif username:
|
||
await conn.execute(
|
||
"UPDATE our_users SET username = ? WHERE user_id = ?",
|
||
(username, user_id)
|
||
)
|
||
elif full_name:
|
||
await conn.execute(
|
||
"UPDATE our_users SET full_name = ? WHERE user_id = ?",
|
||
(full_name, user_id)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при обновлении информации о пользователе: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def update_user_emoji(self, user_id: int, emoji: str):
|
||
"""Обновление эмодзи пользователя."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"UPDATE our_users SET emoji = ? WHERE user_id = ?",
|
||
(emoji, user_id)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при обновлении эмодзи: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_user_emoji(self, user_id: int) -> Optional[str]:
|
||
"""Получение эмодзи пользователя."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT emoji FROM our_users WHERE user_id = ?", (user_id,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return result[0] if result else None
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении эмодзи: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def check_emoji_exists(self, emoji: str) -> bool:
|
||
"""Проверка существования эмодзи."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT 1 FROM our_users WHERE emoji = ?", (emoji,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return bool(result)
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при проверке эмодзи: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def update_stickers_info(self, user_id: int):
|
||
"""Обновление информации о стикерах."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"UPDATE our_users SET has_stickers = 1 WHERE user_id = ?",
|
||
(user_id,)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при обновлении информации о стикерах: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_stickers_info(self, user_id: int) -> bool:
|
||
"""Получение информации о стикерах."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT has_stickers FROM our_users WHERE user_id = ?", (user_id,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return bool(result[0]) if result and result[0] is not None else False
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении информации о стикерах: {e}")
|
||
return False
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def add_message(self, message_text: str, user_id: int, message_id: int):
|
||
"""Добавление сообщения пользователя."""
|
||
conn = None
|
||
try:
|
||
date = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"INSERT INTO user_messages (message_text, user_id, message_id, date) VALUES (?, ?, ?, ?)",
|
||
(message_text, user_id, message_id, date)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при добавлении сообщения: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def add_post(self, message_id: int, text: str, author_id: int):
|
||
"""Добавление поста."""
|
||
conn = None
|
||
try:
|
||
created_at = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"INSERT INTO post_from_telegram_suggest (message_id, text, author_id, created_at) VALUES (?, ?, ?, ?)",
|
||
(message_id, text, author_id, created_at)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при добавлении поста: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def update_helper_message(self, message_id: int, helper_message_id: int):
|
||
"""Обновление helper сообщения."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"UPDATE post_from_telegram_suggest SET helper_text_message_id = ? WHERE message_id = ?",
|
||
(helper_message_id, message_id)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при обновлении helper сообщения: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def add_post_content(self, post_id: int, message_id: int, content_name: str, content_type: str):
|
||
"""Добавление контента поста."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
# Сначала добавляем связь
|
||
await conn.execute(
|
||
"INSERT INTO message_link_to_content (post_id, message_id) VALUES (?, ?)",
|
||
(post_id, message_id)
|
||
)
|
||
# Затем добавляем контент
|
||
await conn.execute(
|
||
"INSERT INTO content_post_from_telegram (message_id, content_name, content_type) VALUES (?, ?, ?)",
|
||
(message_id, content_name, content_type)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при добавлении контента поста: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_post_content(self, last_post_id: int) -> List[Tuple[str, str]]:
|
||
"""Получение контента поста."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute("""
|
||
SELECT cpft.content_name, cpft.content_type
|
||
FROM post_from_telegram_suggest pft
|
||
JOIN message_link_to_content mltc ON pft.message_id = mltc.post_id
|
||
JOIN content_post_from_telegram cpft ON cpft.message_id = mltc.message_id
|
||
WHERE pft.helper_text_message_id = ?
|
||
""", (last_post_id,)) as cursor:
|
||
return await cursor.fetchall()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении контента поста: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_post_text(self, last_post_id: int) -> Optional[str]:
|
||
"""Получение текста поста."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT text FROM post_from_telegram_suggest WHERE helper_text_message_id = ?",
|
||
(last_post_id,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return result[0] if result else None
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении текста поста: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_post_ids(self, last_post_id: int) -> List[int]:
|
||
"""Получение ID постов."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute("""
|
||
SELECT mltc.message_id
|
||
FROM post_from_telegram_suggest pft
|
||
JOIN message_link_to_content mltc ON pft.message_id = mltc.post_id
|
||
WHERE pft.helper_text_message_id = ?
|
||
""", (last_post_id,)) as cursor:
|
||
result = await cursor.fetchall()
|
||
return [row[0] for row in result]
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении ID постов: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_author_id_by_message(self, message_id: int) -> Optional[int]:
|
||
"""Получение ID автора по message_id."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT author_id FROM post_from_telegram_suggest WHERE message_id = ?",
|
||
(message_id,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return result[0] if result else None
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении ID автора: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_author_id_by_helper_message(self, helper_message_id: int) -> Optional[int]:
|
||
"""Получение ID автора по helper_message_id."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT author_id FROM post_from_telegram_suggest WHERE helper_text_message_id = ?",
|
||
(helper_message_id,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return result[0] if result else None
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении ID автора по helper сообщению: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_last_users(self, limit: int = 30) -> List[Tuple[str, int]]:
|
||
"""Получение последних пользователей."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT full_name, user_id FROM our_users ORDER BY date_changed DESC LIMIT ?",
|
||
(limit,)
|
||
) as cursor:
|
||
return await cursor.fetchall()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении последних пользователей: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_user_by_message_id(self, message_id: int) -> Optional[int]:
|
||
"""Получение пользователя по message_id."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT user_id FROM user_messages WHERE message_id = ?",
|
||
(message_id,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return result[0] if result else None
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении пользователя по message_id: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
# Методы для работы с черным списком
|
||
async def add_to_blacklist(self, user_id: int, user_name: str = None,
|
||
message_for_user: str = None, date_to_unban: str = None):
|
||
"""Добавление пользователя в черный список."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"INSERT INTO blacklist (user_id, user_name, message_for_user, date_to_unban) VALUES (?, ?, ?, ?)",
|
||
(user_id, user_name, message_for_user, date_to_unban)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при добавлении в черный список: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def remove_from_blacklist(self, user_id: int) -> bool:
|
||
"""Удаление пользователя из черного списка."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
await conn.execute("DELETE FROM blacklist WHERE user_id = ?", (user_id,))
|
||
await conn.commit()
|
||
return True
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при удалении из черного списка: {e}")
|
||
return False
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def check_blacklist(self, user_id: int) -> bool:
|
||
"""Проверка пользователя в черном списке."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT 1 FROM blacklist WHERE user_id = ?", (user_id,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return bool(result)
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при проверке черного списка: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_blacklist_users(self, offset: int = 0, limit: int = 10) -> List[Tuple[str, int, str, str]]:
|
||
"""Получение пользователей из черного списка."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT user_name, user_id, message_for_user, date_to_unban FROM blacklist LIMIT ?, ?",
|
||
(offset, limit)
|
||
) as cursor:
|
||
return await cursor.fetchall()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении пользователей из черного списка: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_blacklist_count(self) -> int:
|
||
"""Получение количества пользователей в черном списке."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute("SELECT COUNT(*) FROM blacklist") as cursor:
|
||
result = await cursor.fetchone()
|
||
return result[0] if result else 0
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении количества пользователей в черном списке: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_users_for_unban_today(self, date_to_unban: str) -> List[Tuple[int, str]]:
|
||
"""Получение пользователей для разблокировки сегодня."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT user_id, user_name FROM blacklist WHERE date_to_unban = ?",
|
||
(date_to_unban,)
|
||
) as cursor:
|
||
return await cursor.fetchall()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении пользователей для разблокировки: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
# Методы для работы с администраторами
|
||
async def add_admin(self, user_id: int, role: str = "admin"):
|
||
"""Добавление администратора."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"INSERT INTO admins (user_id, role) VALUES (?, ?)",
|
||
(user_id, role)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при добавлении администратора: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def remove_admin(self, user_id: int):
|
||
"""Удаление администратора."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
await conn.execute("DELETE FROM admins WHERE user_id = ?", (user_id,))
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при удалении администратора: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def is_admin(self, user_id: int) -> bool:
|
||
"""Проверка, является ли пользователь администратором."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT 1 FROM admins WHERE user_id = ?", (user_id,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return bool(result)
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при проверке прав администратора: {e}")
|
||
return False
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
# Методы для работы с аудио
|
||
async def add_audio_record(self, file_name: str, author_id: int, file_id: str):
|
||
"""Добавление аудио записи."""
|
||
conn = None
|
||
try:
|
||
date_added = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"INSERT INTO audio_message_reference (file_name, author_id, date_added, file_id) VALUES (?, ?, ?, ?)",
|
||
(file_name, author_id, date_added, file_id)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при добавлении аудио записи: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_last_audio_date(self) -> Optional[str]:
|
||
"""Получение даты последнего аудио."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT date_added FROM audio_message_reference ORDER BY date_added DESC LIMIT 1"
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return result[0] if result else None
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении даты последнего аудио: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_user_audio_records(self, user_id: int) -> bool:
|
||
"""Проверка наличия аудио записей у пользователя."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT 1 FROM audio_message_reference WHERE author_id = ? LIMIT 1",
|
||
(user_id,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return bool(result)
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при проверке аудио записей пользователя: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_audio_file_id(self, user_id: int) -> Optional[str]:
|
||
"""Получение file_id последнего аудио пользователя."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT file_id FROM audio_message_reference WHERE author_id = ? ORDER BY date_added DESC LIMIT 1",
|
||
(user_id,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return result[0] if result else None
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении file_id аудио: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_audio_file_name(self, user_id: int) -> Optional[str]:
|
||
"""Получение имени файла последнего аудио пользователя."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT file_name FROM audio_message_reference WHERE author_id = ? ORDER BY date_added DESC LIMIT 1",
|
||
(user_id,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return result[0] if result else None
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении имени файла аудио: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def check_audio_listened(self, user_id: int) -> List[str]:
|
||
"""Проверка прослушанных аудио пользователем."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
# Получаем все аудио файлы
|
||
async with conn.execute(
|
||
"SELECT file_name FROM audio_message_reference WHERE author_id != ?",
|
||
(user_id,)
|
||
) as cursor:
|
||
all_audio = await cursor.fetchall()
|
||
|
||
# Получаем прослушанные пользователем
|
||
async with conn.execute("""
|
||
SELECT l.file_name
|
||
FROM audio_message_reference a
|
||
LEFT JOIN listen_audio_users l ON l.file_name = a.file_name
|
||
WHERE l.user_id = ? AND l.file_name IS NOT NULL
|
||
""", (user_id,)) as cursor:
|
||
listened_audio = await cursor.fetchall()
|
||
|
||
# Находим непрослушанные
|
||
all_audio_names = {row[0] for row in all_audio}
|
||
listened_names = {row[0] for row in listened_audio}
|
||
return list(all_audio_names - listened_names)
|
||
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при проверке прослушанных аудио: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def mark_audio_listened(self, file_name: str, user_id: int):
|
||
"""Отметка аудио как прослушанного."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"INSERT INTO listen_audio_users (file_name, user_id, is_listen) VALUES (?, ?, ?)",
|
||
(file_name, user_id, 1)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при отметке аудио как прослушанного: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def clear_user_audio_listen(self, user_id: int):
|
||
"""Очистка данных о прослушивании аудио пользователем."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"DELETE FROM listen_audio_users WHERE user_id = ?",
|
||
(user_id,)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при очистке данных о прослушивании: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_user_by_audio_file(self, file_name: str) -> Optional[int]:
|
||
"""Получение пользователя по имени аудио файла."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT author_id FROM audio_message_reference WHERE file_name = ?",
|
||
(file_name,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return result[0] if result else None
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении пользователя по имени файла: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_audio_date(self, file_name: str) -> Optional[str]:
|
||
"""Получение даты аудио файла."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT date_added FROM audio_message_reference WHERE file_name = ?",
|
||
(file_name,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return result[0] if result else None
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении даты аудио файла: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
# Методы для voice bot
|
||
async def set_voice_bot_message(self, message_id: int, user_id: int):
|
||
"""Установка связи message_id и user_id для voice bot."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"INSERT INTO audio_moderate (message_id, user_id) VALUES (?, ?)",
|
||
(message_id, user_id)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при установке связи для voice bot: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def get_voice_bot_user(self, message_id: int) -> Optional[int]:
|
||
"""Получение пользователя voice bot по message_id."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT user_id FROM audio_moderate WHERE message_id = ?",
|
||
(message_id,)
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return result[0] if result else None
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении пользователя voice bot: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
# Методы для миграций
|
||
async def get_migration_version(self) -> int:
|
||
"""Получение текущей версии миграции."""
|
||
conn = None
|
||
try:
|
||
conn = await self._get_connection()
|
||
async with conn.execute(
|
||
"SELECT version FROM migrations ORDER BY version DESC LIMIT 1"
|
||
) as cursor:
|
||
result = await cursor.fetchone()
|
||
return result[0] if result else 0
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при получении версии миграции: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def update_migration_version(self, version: int, script_name: str):
|
||
"""Обновление версии миграции."""
|
||
conn = None
|
||
try:
|
||
created_at = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
|
||
conn = await self._get_connection()
|
||
await conn.execute(
|
||
"INSERT INTO migrations (version, script_name, created_at) VALUES (?, ?, ?)",
|
||
(version, script_name, created_at)
|
||
)
|
||
await conn.commit()
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при обновлении версии миграции: {e}")
|
||
raise
|
||
finally:
|
||
if conn:
|
||
await conn.close()
|
||
|
||
async def close(self):
|
||
"""Закрытие соединений."""
|
||
# Соединения закрываются в каждом методе
|
||
pass
|