#!/usr/bin/env python3 """ File monitoring and discovery for UPI files. Scans SFTP directories for new files across multiple banks. Filename convention handled: _DDMMYYYY__UPI.txt.gz Example: TUMLUK_31052026_8C_UPI.txt.gz """ 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 UPI files.""" def __init__(self, sftp_client: SFTPClient = None): 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 UPI files. Returns: List of (filename, bankcode, full_remote_path) """ new_files: List[Tuple[str, str, str]] = [] for bank_code in self.config.bank_codes: remote_path = f"{self.config.sftp_base_path}/{bank_code}/UPI" # Pattern for UPI files files = self.sftp_client.list_files( remote_path, pattern='*_UPI.txt.gz' ) 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 UPI file: {filename} (bank: {bank_code})") else: logger.debug(f"Skipping already processed UPI file: {filename}") logger.info(f"UPI scan complete: Found {len(new_files)} new files") return new_files @staticmethod def parse_filename(filename: str) -> Dict[str, str]: """ Parse UPI filename. Expected format: _DDMMYYYY__UPI.txt.gz Example: TUMLUK_31052026_8C_UPI.txt.gz """ pattern = r'^([A-Z]+)_(\d{2})(\d{2})(\d{4})_([A-Z0-9]+)_UPI\.txt\.gz$' match = re.match(pattern, filename, flags=re.IGNORECASE) if not match: logger.warning(f"Could not parse UPI filename: {filename}") return {} location, day, month, year, code = match.groups() return { 'filename': filename, 'location': location, 'day': day, 'month': month, 'year': year, 'code': code, 'timestamp': f"{day}/{month}/{year}" } def __enter__(self): if not self.sftp_client.sftp: self.sftp_client.connect() return self def __exit__(self, exc_type, exc_val, exc_tb): self.sftp_client.disconnect()