from pathlib import Path from typing import Iterable, List from app.core.config import ENCODING_UTF8, NEWLINE from app.core.crypto import DataCipher, load_encryption_key class FileManager: _cipher_instance: DataCipher | None = None def __init__(self, file_path: Path) -> None: self.file_path = file_path self.file_path.parent.mkdir(parents=True, exist_ok=True) self.file_path.touch(exist_ok=True) self._cipher = self._get_cipher() @classmethod def _get_cipher(cls) -> DataCipher: if cls._cipher_instance is None: cls._cipher_instance = DataCipher(load_encryption_key()) return cls._cipher_instance def _decode_line(self, raw: str) -> str: try: return self._cipher.decrypt(raw) except Exception: return raw def _encode_line(self, plain: str) -> str: return self._cipher.encrypt(plain) def read_lines(self) -> List[str]: with self.file_path.open("r", encoding=ENCODING_UTF8) as file: decoded: List[str] = [] for line in file: if not line.strip(): continue decoded.append(self._decode_line(line.rstrip(NEWLINE))) return decoded def write_lines(self, lines: Iterable[str]) -> None: with self.file_path.open("w", encoding=ENCODING_UTF8) as file: for line in lines: file.write(f"{self._encode_line(line)}{NEWLINE}") def append_line(self, line: str) -> None: with self.file_path.open("a", encoding=ENCODING_UTF8) as file: file.write(f"{self._encode_line(line)}{NEWLINE}")