from autoLoader.config import FILESAPTH from autoLoader.loader.connector import ConnectorSFTP import datetime, os from autoLoader.database import Audio, get_db_session from sqlalchemy import inspect local_path = os.path.join(os.getcwd(), FILESAPTH) class Loader(): def __init__(self): self.call_types = ['in'] self.loaded_files = [] # Список загруженных файлов def filter_call(self, filename: str): if filename.split("-")[0] in self.call_types: return True return False def check_database(self): """Проверяет существование таблиц в БД""" from autoLoader.database import engine inspector = inspect(engine) existing_tables = inspector.get_table_names() if 'audio' not in existing_tables: print("❌ Таблица 'audio' не существует в базе данных!") print("💡 Запустите 'python init_db.py' для создания таблиц") return False return True def send_to_recognition(self, limit: int = None): """ Отправляет загруженные файлы на распознавание Args: limit: Максимальное количество файлов для отправки """ if not self.loaded_files: print("⏭️ Нет файлов для отправки на распознавание") return from autoLoader.loader import RecognitionChecker print(f"\n🎤 Отправка {len(self.loaded_files)} файлов на распознавание...") checker = RecognitionChecker() # Проверяем доступность API if not checker.check_api_availability(): print("❌ GigaAM API недоступен. Пропускаем распознавание.") return # Проверяем БД if not checker.check_database(): print("❌ База данных не готова. Пропускаем распознавание.") return # Фильтруем только что загруженные файлы без заключения files_to_send = [] for audio in self.loaded_files: # Проверяем, есть ли у файла заключение with get_db_session() as db: from autoLoader.database import AiConclusion existing_conclusion = db.query(AiConclusion).filter( AiConclusion.audio_id == audio.id ).first() if existing_conclusion: print(f"⏭️ Файл {audio.filename} уже имеет заключение") continue else: # Конвертируем SQLAlchemy объект в словарь files_to_send.append({ 'id': str(audio.id), 'filename': audio.filename, 'file_size': audio.file_size, 'index_date': audio.index_date.isoformat() if audio.index_date else None }) if not files_to_send: print("✅ Все файлы уже имеют заключения") return # Отправляем файлы параллельно print(f"🚀 Отправка {len(files_to_send)} файлов параллельно...") results = checker.send_to_recognition_parallel(files_to_send) print(f"✅ Отправлено {results['sent']} из {results['total']} файлов на распознавание") def load(self): # Проверяем БД перед началом работы if not self.check_database(): exit(1) date_now = datetime.datetime.now()# - datetime.timedelta(days=1) remote_path = f"/{date_now.strftime('%Y/%m/%d')}" connector = ConnectorSFTP() connector.connect(remote_path=remote_path) sftp_client = connector.sftp ssh_client = connector.ssh if sftp_client is None or ssh_client is None: print("Не удалось подключиться к SFTP. Завершение работы.") exit(1) try: listdir = sftp_client.listdir() os.makedirs(local_path, exist_ok = True) for file in listdir: if self.filter_call(filename=file): remote_file = f"{file}".lstrip('/') filepath = os.path.join(local_path, file) # Проверяем, существует ли файл локально if os.path.exists(filepath): print(f"Файл уже существует локально: {file}") continue try: # Скачиваем файл sftp_client.get(remote_file, filepath) print(f"📥 Скачан файл: {remote_file}") # Получаем размер файла file_size = os.path.getsize(filepath) # Сохраняем в БД через контекстный менеджер with get_db_session() as db: # Проверяем, есть ли уже такой файл в БД existing_audio = db.query(Audio).filter(Audio.filename == file).first() if existing_audio: print(f"⏭️ Файл {file} уже есть в БД, пропускаем") continue # Создаём новую запись audio = Audio() audio.index_date = datetime.datetime.now() audio.filename = file audio.file_size = file_size db.add(audio) db.flush() # Чтобы получить audio.id # Сохраняем в список для последующей отправки self.loaded_files.append(audio) print(f"✅ Файл {file} сохранён в БД") except Exception as e: print(f"❌ Ошибка при обработке файла {remote_file}: {e}") # Если файл скачался, но ошибка в БД - удаляем файл if os.path.exists(filepath): try: os.remove(filepath) print(f"🗑️ Файл {file} удалён из-за ошибки") except: pass finally: # Закрываем соединения sftp_client.close() ssh_client.close() # После загрузки всех файлов отправляем на распознавание print(f"\n📊 Загружено файлов: {len(self.loaded_files)}") self.send_to_recognition()