- Added `ca-certificates` installation to Dockerfile for improved network security. - Updated health check command in Dockerfile to include better timeout handling. - Refactored `run_helper.py` to implement proper signal handling and logging during shutdown. - Transitioned database operations to an asynchronous model in `async_db.py`, improving performance and responsiveness. - Updated database schema to support new foreign key relationships and optimized indexing for better query performance. - Enhanced various bot handlers to utilize async database methods, improving overall efficiency and user experience. - Removed obsolete database and fix scripts to streamline the project structure.
259 lines
12 KiB
Python
259 lines
12 KiB
Python
from datetime import datetime
|
||
from typing import Optional, List, Dict, Any
|
||
from database.base import DatabaseConnection
|
||
from database.models import User
|
||
|
||
|
||
class UserRepository(DatabaseConnection):
|
||
"""Репозиторий для работы с пользователями."""
|
||
|
||
async def create_tables(self):
|
||
"""Создание таблицы пользователей."""
|
||
query = '''
|
||
CREATE TABLE IF NOT EXISTS our_users (
|
||
user_id INTEGER NOT NULL PRIMARY KEY,
|
||
first_name TEXT,
|
||
full_name TEXT,
|
||
username TEXT,
|
||
is_bot BOOLEAN DEFAULT 0,
|
||
language_code TEXT,
|
||
has_stickers BOOLEAN DEFAULT 0 NOT NULL,
|
||
emoji TEXT,
|
||
date_added INTEGER NOT NULL,
|
||
date_changed INTEGER NOT NULL,
|
||
voice_bot_welcome_received BOOLEAN DEFAULT 0
|
||
)
|
||
'''
|
||
await self._execute_query(query)
|
||
self.logger.info("Таблица пользователей создана")
|
||
|
||
async def user_exists(self, user_id: int) -> bool:
|
||
"""Проверяет, существует ли пользователь в базе данных."""
|
||
query = "SELECT user_id FROM our_users WHERE user_id = ?"
|
||
rows = await self._execute_query_with_result(query, (user_id,))
|
||
self.logger.info(f"Проверка существования пользователя: user_id={user_id}, результат={rows}")
|
||
return bool(len(rows))
|
||
|
||
async def add_user(self, user: User) -> None:
|
||
"""Добавление нового пользователя."""
|
||
if not user.date_added:
|
||
user.date_added = int(datetime.now().timestamp())
|
||
if not user.date_changed:
|
||
user.date_changed = int(datetime.now().timestamp())
|
||
|
||
query = """
|
||
INSERT INTO our_users (user_id, first_name, full_name, username, is_bot,
|
||
language_code, emoji, has_stickers, date_added, date_changed, voice_bot_welcome_received)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||
"""
|
||
params = (user.user_id, user.first_name, user.full_name, user.username,
|
||
user.is_bot, user.language_code, user.emoji, user.has_stickers,
|
||
user.date_added, user.date_changed, user.voice_bot_welcome_received)
|
||
|
||
await self._execute_query(query, params)
|
||
self.logger.info(f"Новый пользователь добавлен: {user.user_id}")
|
||
|
||
async def get_user_info(self, user_id: int) -> Optional[User]:
|
||
"""Получение информации о пользователе."""
|
||
query = "SELECT username, full_name, has_stickers, emoji FROM our_users WHERE user_id = ?"
|
||
rows = await self._execute_query_with_result(query, (user_id,))
|
||
row = rows[0] if rows else None
|
||
|
||
if row:
|
||
return User(
|
||
user_id=user_id,
|
||
first_name="", # Не получаем из этого запроса
|
||
full_name=row[1],
|
||
username=row[0],
|
||
has_stickers=bool(row[2]) if row[2] is not None else False,
|
||
emoji=row[3]
|
||
)
|
||
return None
|
||
|
||
async def get_user_by_id(self, user_id: int) -> Optional[User]:
|
||
"""Получение пользователя по ID."""
|
||
query = "SELECT * FROM our_users WHERE user_id = ?"
|
||
rows = await self._execute_query_with_result(query, (user_id,))
|
||
row = rows[0] if rows else None
|
||
|
||
if row:
|
||
return User(
|
||
user_id=row[0],
|
||
first_name=row[1],
|
||
full_name=row[2],
|
||
username=row[3],
|
||
is_bot=bool(row[4]),
|
||
language_code=row[5],
|
||
has_stickers=bool(row[6]),
|
||
emoji=row[7],
|
||
date_added=row[8],
|
||
date_changed=row[9],
|
||
voice_bot_welcome_received=bool(row[10]) if len(row) > 10 else False
|
||
)
|
||
return None
|
||
|
||
async def get_username(self, user_id: int) -> Optional[str]:
|
||
"""Возвращает username пользователя."""
|
||
query = "SELECT username FROM our_users WHERE user_id = ?"
|
||
rows = await self._execute_query_with_result(query, (user_id,))
|
||
row = rows[0] if rows else None
|
||
|
||
if row:
|
||
username = row[0]
|
||
self.logger.info(f"Username пользователя найден: user_id={user_id}, username={username}")
|
||
return username
|
||
return None
|
||
|
||
async def get_user_id_by_username(self, username: str) -> Optional[int]:
|
||
"""Возвращает user_id пользователя по username."""
|
||
query = "SELECT user_id FROM our_users WHERE username = ?"
|
||
rows = await self._execute_query_with_result(query, (username,))
|
||
row = rows[0] if rows else None
|
||
|
||
if row:
|
||
user_id = row[0]
|
||
self.logger.info(f"User_id пользователя найден: username={username}, user_id={user_id}")
|
||
return user_id
|
||
return None
|
||
|
||
async def get_full_name_by_id(self, user_id: int) -> Optional[str]:
|
||
"""Возвращает full_name пользователя."""
|
||
query = "SELECT full_name FROM our_users WHERE user_id = ?"
|
||
rows = await self._execute_query_with_result(query, (user_id,))
|
||
row = rows[0] if rows else None
|
||
|
||
if row:
|
||
full_name = row[0]
|
||
self.logger.info(f"Full_name пользователя найден: user_id={user_id}, full_name={full_name}")
|
||
return full_name
|
||
return None
|
||
|
||
async def get_user_first_name(self, user_id: int) -> Optional[str]:
|
||
"""Возвращает first_name пользователя."""
|
||
query = "SELECT first_name FROM our_users WHERE user_id = ?"
|
||
rows = await self._execute_query_with_result(query, (user_id,))
|
||
row = rows[0] if rows else None
|
||
|
||
if row:
|
||
first_name = row[0]
|
||
self.logger.info(f"First_name пользователя найден: user_id={user_id}, first_name={first_name}")
|
||
return first_name
|
||
return None
|
||
|
||
async def get_all_user_ids(self) -> List[int]:
|
||
"""Возвращает список всех user_id."""
|
||
query = "SELECT user_id FROM our_users"
|
||
rows = await self._execute_query_with_result(query)
|
||
user_ids = [row[0] for row in rows]
|
||
self.logger.info(f"Получен список всех user_id: {user_ids}")
|
||
return user_ids
|
||
|
||
async def get_last_users(self, limit: int = 30) -> List[tuple]:
|
||
"""Получение последних пользователей."""
|
||
query = "SELECT full_name, user_id FROM our_users ORDER BY date_changed DESC LIMIT ?"
|
||
rows = await self._execute_query_with_result(query, (limit,))
|
||
return rows
|
||
|
||
async def update_user_date(self, user_id: int) -> None:
|
||
"""Обновление даты последнего изменения пользователя."""
|
||
date_changed = int(datetime.now().timestamp())
|
||
query = "UPDATE our_users SET date_changed = ? WHERE user_id = ?"
|
||
await self._execute_query(query, (date_changed, user_id))
|
||
|
||
async def update_user_info(self, user_id: int, username: str = None, full_name: str = None) -> None:
|
||
"""Обновление информации о пользователе."""
|
||
if username and full_name:
|
||
query = "UPDATE our_users SET username = ?, full_name = ? WHERE user_id = ?"
|
||
params = (username, full_name, user_id)
|
||
elif username:
|
||
query = "UPDATE our_users SET username = ? WHERE user_id = ?"
|
||
params = (username, user_id)
|
||
elif full_name:
|
||
query = "UPDATE our_users SET full_name = ? WHERE user_id = ?"
|
||
params = (full_name, user_id)
|
||
else:
|
||
return
|
||
|
||
await self._execute_query(query, params)
|
||
|
||
async def update_user_emoji(self, user_id: int, emoji: str) -> None:
|
||
"""Обновление эмодзи пользователя."""
|
||
query = "UPDATE our_users SET emoji = ? WHERE user_id = ?"
|
||
await self._execute_query(query, (emoji, user_id))
|
||
|
||
async def update_stickers_info(self, user_id: int) -> None:
|
||
"""Обновление информации о стикерах."""
|
||
query = "UPDATE our_users SET has_stickers = 1 WHERE user_id = ?"
|
||
await self._execute_query(query, (user_id,))
|
||
|
||
async def get_stickers_info(self, user_id: int) -> bool:
|
||
"""Получение информации о стикерах."""
|
||
query = "SELECT has_stickers FROM our_users WHERE user_id = ?"
|
||
rows = await self._execute_query_with_result(query, (user_id,))
|
||
row = rows[0] if rows else None
|
||
return bool(row[0]) if row and row[0] is not None else False
|
||
|
||
async def check_emoji_exists(self, emoji: str) -> bool:
|
||
"""Проверка существования эмодзи."""
|
||
query = "SELECT 1 FROM our_users WHERE emoji = ?"
|
||
rows = await self._execute_query_with_result(query, (emoji,))
|
||
row = rows[0] if rows else None
|
||
return bool(row)
|
||
|
||
async def get_user_emoji(self, user_id: int) -> str:
|
||
"""
|
||
Получает эмодзи пользователя.
|
||
|
||
Args:
|
||
user_id: ID пользователя.
|
||
|
||
Returns:
|
||
str: Эмодзи пользователя или "Смайл еще не определен" если не установлен.
|
||
"""
|
||
query = "SELECT emoji FROM our_users WHERE user_id = ?"
|
||
rows = await self._execute_query_with_result(query, (user_id,))
|
||
row = rows[0] if rows else None
|
||
|
||
if row and row[0]:
|
||
emoji = row[0]
|
||
self.logger.info(f"Эмодзи пользователя найден: user_id={user_id}, emoji={emoji}")
|
||
return str(emoji)
|
||
else:
|
||
self.logger.info(f"Эмодзи пользователя не найден: user_id={user_id}")
|
||
return "Смайл еще не определен"
|
||
|
||
async def check_emoji_for_user(self, user_id: int) -> str:
|
||
"""
|
||
Проверяет, есть ли уже у пользователя назначенный emoji.
|
||
|
||
Args:
|
||
user_id: ID пользователя.
|
||
|
||
Returns:
|
||
str: Эмодзи пользователя или "Смайл еще не определен" если не установлен.
|
||
"""
|
||
return await self.get_user_emoji(user_id)
|
||
|
||
async def check_voice_bot_welcome_received(self, user_id: int) -> bool:
|
||
"""Проверяет, получал ли пользователь приветственное сообщение от voice_bot."""
|
||
query = "SELECT voice_bot_welcome_received FROM our_users WHERE user_id = ?"
|
||
rows = await self._execute_query_with_result(query, (user_id,))
|
||
row = rows[0] if rows else None
|
||
|
||
if row:
|
||
welcome_received = bool(row[0])
|
||
self.logger.info(f"Пользователь {user_id} получал приветствие: {welcome_received}")
|
||
return welcome_received
|
||
return False
|
||
|
||
async def mark_voice_bot_welcome_received(self, user_id: int) -> bool:
|
||
"""Отмечает, что пользователь получил приветственное сообщение от voice_bot."""
|
||
try:
|
||
query = "UPDATE our_users SET voice_bot_welcome_received = 1 WHERE user_id = ?"
|
||
await self._execute_query(query, (user_id,))
|
||
self.logger.info(f"Пользователь {user_id} отмечен как получивший приветствие")
|
||
return True
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка при отметке получения приветствия: {e}")
|
||
return False
|