#!/usr/bin/env python3 """ File monitoring and discovery for RTGS Inward files. Scans SFTP directories for new files across multiple banks. Filename convention handled: DDMMYYYY_HH_RTGS_INWARD.TXT Example: 06032026_14_RTGS_INWARD.TXT """ import re from typing import List, Tuple, Dict from logging_config import get_logger from config import get_config from .sftp_client import SFTPClient logger = get_logger(__name__) class FileMonitor: """Monitors SFTP for new RTGS Inward files.""" def __init__(self, sftp_client: SFTPClient = None): """ Initialize file monitor. Args: sftp_client: SFTPClient instance (optional) """ self.config = get_config() self.sftp_client = sftp_client or SFTPClient() def scan_for_new_files(self, processed_filenames: List[str]) -> List[Tuple[str, str, str]]: """ Scan all bank directories for new RTGS files. Args: processed_filenames: List of already processed filenames to skip Returns: List of (filename, bankcode, full_remote_path) tuples """ new_files: List[Tuple[str, str, str]] = [] for bank_code in self.config.bank_codes: # Adjust subfolder name here if required (e.g., 'RTGS_INWARD' or other) remote_path = f"{self.config.sftp_base_path}/{bank_code}/RTGS" # Match any RTGS inward file for any date/hour files = self.sftp_client.list_files(remote_path, pattern='*_RTGS_INWARD.TXT') for filename in files: if filename not in processed_filenames: full_path = f"{remote_path}/{filename}" new_files.append((filename, bank_code, full_path)) logger.info(f"Found new RTGS file: {filename} (bank: {bank_code})") else: logger.debug(f"Skipping already processed RTGS file: {filename}") logger.info(f"RTGS scan complete: Found {len(new_files)} new files") return new_files @staticmethod def parse_filename(filename: str) -> Dict[str, str]: """ Parse RTGS filename to extract metadata. Expected format: DDMMYYYY_HH_RTGS_INWARD.TXT Example: 06032026_14_RTGS_INWARD.TXT Args: filename: Filename to parse Returns: Dictionary with extracted metadata or empty dict if parse fails """ # Groups: DD, MM, YYYY, HH pattern = r'^(\d{2})(\d{2})(\d{4})_(\d{2})_RTGS_INWARD\.TXT$' match = re.match(pattern, filename, flags=re.IGNORECASE) if not match: logger.warning(f"Could not parse RTGS filename: {filename}") return {} day, month, year, hour = match.groups() return { 'filename': filename, 'day': day, 'month': month, 'year': year, 'hour': hour, 'timestamp': f"{day}/{month}/{year} {hour}:00:00" } def __enter__(self): """Context manager entry.""" if not self.sftp_client.sftp: self.sftp_client.connect() return self def __exit__(self, exc_type, exc_val, exc_tb): """Context manager exit.""" self.sftp_client.disconnect()