import os import subprocess from datetime import datetime import aiofiles from aiogram.types import BufferedInputFile from config import ADMIN_ID, BACK_DIR, DB_NAME, DB_PASSWORD, DB_USER, PG_HOST, PG_PORT from logger import logger async def backup_database(): from bot import bot try: if backup_file_path := _create_database_backup(): await _send_backup_to_admin(bot, backup_file_path) _cleanup_old_backups() except Exception as e: logger.error(f"Ошибка при создании или отправке бэкапа: {e}") def _create_database_backup(): USER = DB_USER HOST = PG_HOST PORT = PG_PORT BACKUP_DIR = BACK_DIR DATE = datetime.now().strftime("%Y-%m-%d-%H%M%S") if not os.path.exists(BACKUP_DIR): os.makedirs(BACKUP_DIR) BACKUP_FILE = f"{BACKUP_DIR}/{DB_NAME}-backup-{DATE}.sql" os.environ["PGPASSWORD"] = DB_PASSWORD try: subprocess.run( [ "pg_dump", "-U", USER, "-h", HOST, "-p", PORT, "-F", "c", "-f", BACKUP_FILE, DB_NAME, ], check=True, ) logger.info(f"Бэкап базы данных создан: {BACKUP_FILE}") return BACKUP_FILE except subprocess.CalledProcessError as e: logger.error(f"Ошибка при создании бэкапа базы данных: {e}") return None finally: del os.environ["PGPASSWORD"] async def _send_backup_to_admin(bot, backup_file_path): try: async with aiofiles.open(backup_file_path, "rb") as backup_file: backup_file_data = await backup_file.read() backup_input_file = BufferedInputFile(backup_file_data, filename=os.path.basename(backup_file_path)) admin_ids: int | list[int] = ADMIN_ID if isinstance(admin_ids, list): for id in admin_ids: await bot.send_document(id, backup_input_file) logger.info(f"Бэкап базы данных отправлен админу: {id}") except Exception as e: logger.error(f"Ошибка при отправке бэкапа в Telegram: {e}") def _cleanup_old_backups(): try: subprocess.run( [ "find", BACK_DIR, "-type", "f", "-name", "*.sql", "-mtime", "+3", "-exec", "rm", "{}", ";", ], check=True, ) logger.info("Старые бэкапы удалены.") except subprocess.CalledProcessError as e: logger.error(f"Ошибка при удалении старых бэкапов: {e}") except Exception as e: logger.error(f"Ошибка при удалении старых бэкапов: {e}") async def create_backup_and_send_to_admins(xui): await xui.login() await xui.database.export()