From 44cadc29ba014c1c441a76a6ef138da51024193c Mon Sep 17 00:00:00 2001 From: Zakhar Izmaylov Date: Tue, 21 Jan 2025 12:03:56 +0300 Subject: [PATCH] Refactor file handling to use aiofiles for asynchronous operations - Replaced synchronous file reading with asynchronous file handling using aiofiles in multiple handlers and the backup module. - Improved performance and responsiveness when sending images and backups by utilizing async file operations. - Ensured consistent use of BufferedInputFile across all relevant functions for better code maintainability. --- backup.py | 7 ++++--- handlers/instructions/instructions.py | 7 ++++--- handlers/keys/keys.py | 12 +++++++----- handlers/profile.py | 18 +++++++++++------- handlers/start.py | 7 ++++--- 5 files changed, 30 insertions(+), 21 deletions(-) diff --git a/backup.py b/backup.py index c97c4364..a36e4d31 100644 --- a/backup.py +++ b/backup.py @@ -1,7 +1,7 @@ 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 @@ -58,8 +58,9 @@ def _create_database_backup(): async def _send_backup_to_admin(bot, backup_file_path): try: - with open(backup_file_path, "rb") as backup_file: - backup_input_file = BufferedInputFile(backup_file.read(), filename=os.path.basename(backup_file_path)) + 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: diff --git a/handlers/instructions/instructions.py b/handlers/instructions/instructions.py index 3b278264..2686c24d 100644 --- a/handlers/instructions/instructions.py +++ b/handlers/instructions/instructions.py @@ -1,6 +1,6 @@ import os from typing import Any - +import aiofiles import asyncpg from aiogram import F, Router, types from aiogram.types import BufferedInputFile, InlineKeyboardButton @@ -45,9 +45,10 @@ async def send_instructions( else: send_photo = callback_query_or_message.answer_photo - with open(image_path, "rb") as image_from_buffer: + async with aiofiles.open(image_path, "rb") as image_from_buffer: + image_data = await image_from_buffer.read() await send_photo( - BufferedInputFile(image_from_buffer.read(), filename="instructions.jpg"), + BufferedInputFile(image_data, filename="instructions.jpg"), caption=instructions_message, reply_markup=builder.as_markup(), ) diff --git a/handlers/keys/keys.py b/handlers/keys/keys.py index 5fdc6f16..191e1efa 100644 --- a/handlers/keys/keys.py +++ b/handlers/keys/keys.py @@ -3,7 +3,7 @@ import locale import os from datetime import datetime, timedelta from typing import Any - +import aiofiles from aiogram import F, Router, types from aiogram.types import BufferedInputFile, InlineKeyboardButton from aiogram.utils.keyboard import InlineKeyboardBuilder @@ -123,9 +123,10 @@ async def send_with_optional_image(send_message, send_photo, image_path, text, k Отправляет сообщение с изображением, если файл существует. В противном случае отправляет только текст. """ if os.path.isfile(image_path): - with open(image_path, "rb") as image_file: + async with aiofiles.open(image_path, "rb") as image_file: + image_data = await image_file.read() await send_photo( - photo=BufferedInputFile(image_file.read(), filename=os.path.basename(image_path)), + photo=BufferedInputFile(image_data, filename=os.path.basename(image_path)), caption=text, reply_markup=keyboard, ) @@ -219,9 +220,10 @@ async def process_callback_view_key(callback_query: types.CallbackQuery, session await callback_query.message.answer("Файл изображения не найден.") return - with open(image_path, "rb") as image_file: + async with aiofiles.open(image_path, "rb") as image_file: + image_data = await image_file.read() await callback_query.message.answer_photo( - photo=BufferedInputFile(image_file.read(), filename="pic_view.jpg"), + photo=BufferedInputFile(image_data, filename="pic_view.jpg"), caption=response_message, reply_markup=keyboard, ) diff --git a/handlers/profile.py b/handlers/profile.py index 185eb793..6e7a3126 100644 --- a/handlers/profile.py +++ b/handlers/profile.py @@ -3,6 +3,7 @@ from typing import Any import asyncpg from aiogram import F, Router, types +import aiofiles from aiogram.fsm.context import FSMContext from aiogram.types import BufferedInputFile, InlineKeyboardButton from aiogram.utils.keyboard import InlineKeyboardBuilder @@ -83,16 +84,17 @@ async def process_callback_view_profile( builder.row(InlineKeyboardButton(text=MAIN_MENU, callback_data="start")) if os.path.isfile(image_path): - with open(image_path, "rb") as image_file: + async with aiofiles.open(image_path, "rb") as image_file: + image_data = await image_file.read() if is_callback: await callback_query_or_message.message.answer_photo( - photo=BufferedInputFile(image_file.read(), filename="pic.jpg"), + photo=BufferedInputFile(image_data, filename="pic.jpg"), caption=profile_message, reply_markup=builder.as_markup(), ) else: await callback_query_or_message.answer_photo( - photo=BufferedInputFile(image_file.read(), filename="pic.jpg"), + photo=BufferedInputFile(image_data, filename="pic.jpg"), caption=profile_message, reply_markup=builder.as_markup(), ) @@ -173,9 +175,10 @@ async def view_tariffs_handler(callback_query: types.CallbackQuery): ) if os.path.isfile(image_path): - with open(image_path, "rb") as image_file: + async with aiofiles.open(image_path, "rb") as image_file: + image_data = await image_file.read() await callback_query.message.answer_photo( - photo=BufferedInputFile(image_file.read(), filename="tariffs.jpg"), + photo=BufferedInputFile(image_data, filename="tariffs.jpg"), caption=tariffs_message, reply_markup=builder.as_markup(), ) @@ -200,9 +203,10 @@ async def invite_handler(callback_query: types.CallbackQuery): builder = InlineKeyboardBuilder() builder.row(InlineKeyboardButton(text="👤 Личный кабинет", callback_data="profile")) if os.path.isfile(image_path): - with open(image_path, "rb") as image_file: + async with aiofiles.open(image_path, "rb") as image_file: + image_data = await image_file.read() await callback_query.message.answer_photo( - photo=BufferedInputFile(image_file.read(), filename="pic_invite.jpg"), + photo=BufferedInputFile(image_data, filename="pic_invite.jpg"), caption=invite_message, reply_markup=builder.as_markup(), ) diff --git a/handlers/start.py b/handlers/start.py index d7560ac3..f834ffda 100644 --- a/handlers/start.py +++ b/handlers/start.py @@ -1,6 +1,6 @@ import os from typing import Any - +import aiofiles from aiogram import F, Router from aiogram.filters import Command from aiogram.fsm.context import FSMContext @@ -190,9 +190,10 @@ async def show_start_menu(message: Message, admin: bool, session: Any): builder.row(InlineKeyboardButton(text="🌐 О VPN", callback_data="about_vpn")) if os.path.isfile(image_path): - with open(image_path, "rb") as image_from_buffer: + async with aiofiles.open(image_path, "rb") as image_from_buffer: + image_data = await image_from_buffer.read() await message.answer_photo( - photo=BufferedInputFile(image_from_buffer.read(), filename="pic.jpg"), + photo=BufferedInputFile(image_data, filename="pic.jpg"), caption=WELCOME_TEXT, reply_markup=builder.as_markup(), )