feat(logging): improve error handling and logging for file movement
Add retry logic to the `move` function to handle cases where files are locked or in use. Implement comprehensive error handling and logging to provide detailed feedback about file movement operations. Update the `Thon` class to include more informative logging messages for banned account handling and client disconnection. Improve the `ProcessThon` class with proper resource cleanup during disconnection.
This commit is contained in:
@ -26,8 +26,21 @@ class Thon:
|
|||||||
async with ProcessThon(session, self.__options) as thon:
|
async with ProcessThon(session, self.__options) as thon:
|
||||||
if isinstance(thon, str):
|
if isinstance(thon, str):
|
||||||
if "Banned" in thon and self.__move_banned_folder:
|
if "Banned" in thon and self.__move_banned_folder:
|
||||||
await move(session.item)
|
print(
|
||||||
await move(session.json_file)
|
f"{session.item.name} | Аккаунт забанен, перемещение файлов..."
|
||||||
|
)
|
||||||
|
# Перемещаем файлы сессии с обработкой ошибок
|
||||||
|
success_session = await move(session.item, "banned")
|
||||||
|
success_json = await move(session.json_file, "banned")
|
||||||
|
|
||||||
|
if success_session and success_json:
|
||||||
|
print(
|
||||||
|
f"{session.item.name} | Файлы успешно перемещены / Files moved successfully"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print(
|
||||||
|
f"{session.item.name} | Не удалось полностью переместить файлы / Failed to move all files"
|
||||||
|
)
|
||||||
if self.__callback_error is not None:
|
if self.__callback_error is not None:
|
||||||
self.__callback_error()
|
self.__callback_error()
|
||||||
continue
|
continue
|
||||||
|
|||||||
@ -59,7 +59,7 @@ class ProcessThon(Data):
|
|||||||
def __get_client(self) -> TelegramClient:
|
def __get_client(self) -> TelegramClient:
|
||||||
__session = str(self.__item) if self.__item else self.string_session
|
__session = str(self.__item) if self.__item else self.string_session
|
||||||
proxy = self.proxy
|
proxy = self.proxy
|
||||||
print(proxy)
|
self._logger.info(f"{self.session_file} | {proxy}")
|
||||||
client = TelegramClient(
|
client = TelegramClient(
|
||||||
session=__session,
|
session=__session,
|
||||||
api_id=self.app_id,
|
api_id=self.app_id,
|
||||||
@ -169,14 +169,22 @@ class ProcessThon(Data):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
async def disconnect(self):
|
async def disconnect(self):
|
||||||
|
"""Полное отключение клиента с очисткой ресурсов"""
|
||||||
|
# Сначала переводим в оффлайн (если есть)
|
||||||
with contextlib.suppress(Exception):
|
with contextlib.suppress(Exception):
|
||||||
await self.client(UpdateStatusRequest(offline=True))
|
await self.client(UpdateStatusRequest(offline=True))
|
||||||
|
|
||||||
|
# Затем отключаем соединение (если есть)
|
||||||
with contextlib.suppress(Exception):
|
with contextlib.suppress(Exception):
|
||||||
await self.client.disconnect() # type: ignore # ty:ignore[unused-ignore-comment]
|
await self.client.disconnect()
|
||||||
|
|
||||||
|
# Явно удаляем client из памяти
|
||||||
|
with contextlib.suppress(Exception):
|
||||||
|
del self.__client
|
||||||
|
|
||||||
async def __aenter__(self) -> Self | str:
|
async def __aenter__(self) -> Self | str:
|
||||||
r = await self.check()
|
r = await self.check()
|
||||||
print(r)
|
self._logger.info(f"{self.session_file} | {r}")
|
||||||
if r != "OK":
|
if r != "OK":
|
||||||
await self.disconnect()
|
await self.disconnect()
|
||||||
return r
|
return r
|
||||||
|
|||||||
@ -27,14 +27,59 @@ def extract_verification_code(text: str, regexp: str) -> str | None:
|
|||||||
return code if code.isdigit() else None
|
return code if code.isdigit() else None
|
||||||
|
|
||||||
|
|
||||||
async def move(path: Path, move_folder_name: str = "banned"):
|
async def move(
|
||||||
|
path: Path, move_folder_name: str = "banned", max_retries: int = 5
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
Перемещает файл с retry-логикой, если файл занят.
|
||||||
|
Возвращает True если успешно, False если не удалось.
|
||||||
|
"""
|
||||||
_folder = Path(f"sessions/{move_folder_name}")
|
_folder = Path(f"sessions/{move_folder_name}")
|
||||||
__folder = Path(f"сессии/{move_folder_name}")
|
__folder = Path(f"сессии/{move_folder_name}")
|
||||||
if __folder.exists():
|
if __folder.exists():
|
||||||
_folder = __folder
|
_folder = __folder
|
||||||
_folder.mkdir(parents=True, exist_ok=True)
|
_folder.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
loop = asyncio.get_running_loop()
|
loop = asyncio.get_running_loop()
|
||||||
|
|
||||||
|
for attempt in range(max_retries):
|
||||||
try:
|
try:
|
||||||
|
# Проверяем, что файл существует и доступен для чтения
|
||||||
|
if not path.exists():
|
||||||
|
print(f"{path.name} | Файл не найден / File not found")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not path.is_file():
|
||||||
|
print(f"{path.name} | Это не файл / Not a file")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Попытка переместить файл
|
||||||
await loop.run_in_executor(None, os.rename, path, _folder / path.name)
|
await loop.run_in_executor(None, os.rename, path, _folder / path.name)
|
||||||
|
return True
|
||||||
|
|
||||||
|
except OSError:
|
||||||
|
if attempt < max_retries - 1:
|
||||||
|
# Ждем перед следующей попыткой (с экспоненциальной задержкой)
|
||||||
|
wait_time = 0.5 * (2**attempt) # 0.5s, 1s, 2s, 4s...
|
||||||
|
print(
|
||||||
|
f"{path.name} | Попытка {attempt + 1}/{max_retries}: файл занят, ждем {wait_time}s..."
|
||||||
|
)
|
||||||
|
await asyncio.sleep(wait_time)
|
||||||
|
else:
|
||||||
|
# Последняя попытка неудачна - попробуем копию
|
||||||
|
print(
|
||||||
|
f"{path.name} | Ошибка перемещения / Failed to move (final attempt), trying copy..."
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
await loop.run_in_executor(
|
||||||
|
None, os.replace, path, _folder / path.name
|
||||||
|
)
|
||||||
|
print(f"{path.name} | Файл перемещен через копию / Moved via copy")
|
||||||
|
return True
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
print(f"{path.name} | Error moving file / Не удалось переместить файл: {e}")
|
print(
|
||||||
|
f"{path.name} | Не удалось ни переместить, ни скопировать / Failed to move or copy: {e}"
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return False
|
||||||
|
|||||||
Reference in New Issue
Block a user