import os import json import subprocess import time from threading import Thread from flask import Flask, request, jsonify from werkzeug.utils import secure_filename from flask_cors import CORS from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler # --- Configurações (sem alterações) --- PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) print(f"Raiz do projeto detectada em: {PROJECT_ROOT}") CONFIGS = [ { "source_dir": "src/samples", "output_file": "metadata/samples-manifest.json", "scan_type": "tree" }, { "source_dir": "mmp", "output_file": "metadata/mmp-manifest.json", "scan_type": "list", "extensions": ['.mmp', '.mmpz'] } ] UPLOAD_FOLDER = os.path.join(PROJECT_ROOT, "src", "samples", "samples") WATCH_FOLDER = os.path.join(PROJECT_ROOT, "src", "samples") # Pasta a ser vigiada ALLOWED_EXTENSIONS = {'wav', 'ogg', 'flac', 'mp3'} app = Flask(__name__) CORS(app, origins=["https://alice.ufsj.edu.br", "http://localhost:8000", "http://127.0.0.1:5500"]) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER # --- Funções do Gerador de Manifesto (sem alterações) --- def scan_directory_tree(path): tree = {} if not os.path.isdir(path): return tree for item in sorted(os.listdir(path)): full_path = os.path.join(path, item) if os.path.isdir(full_path): tree[item] = scan_directory_tree(full_path) else: if item.lower().endswith(('.wav', '.ogg', '.flac', '.mp3')): tree[item] = {"_isFile": True} return tree def scan_directory_list(path, allowed_extensions): file_list = [] if not os.path.isdir(path): return file_list for item in os.listdir(path): full_path = os.path.join(path, item) if os.path.isfile(full_path) and any(item.lower().endswith(ext) for ext in allowed_extensions): file_list.append(item) return sorted(file_list) def run_jekyll_build(): print("\nExecutando o comando de build do Jekyll...") destination_path = "/nethome/jotachina/public_html/mmpSearch/" jekyll_args = ["--destination", destination_path, "--force"] try: command = ["bundle", "exec", "jekyll", "build"] + jekyll_args result = subprocess.run(command, cwd=PROJECT_ROOT, capture_output=True, text=True, check=False) if result.returncode != 0: print("Falha com 'bundle', tentando 'jekyll build' diretamente...") command = ["jekyll", "build"] + jekyll_args result = subprocess.run(command, cwd=PROJECT_ROOT, capture_output=True, text=True, check=False) if result.returncode == 0: print("SUCESSO: Jekyll build concluído.") else: print(f"ERRO no Jekyll build: {result.stderr}") except Exception as e: print(f"ERRO inesperado durante o Jekyll build: {e}") def generate_manifests(): print("\nIniciando geração de arquivos de manifesto...") # ... (lógica interna sem alterações) ... for config in CONFIGS: source_dir_abs = os.path.join(PROJECT_ROOT, config["source_dir"]) output_file_abs = os.path.join(PROJECT_ROOT, config["output_file"]) if not os.path.isdir(source_dir_abs): continue result_data = None if config["scan_type"] == "tree": result_data = scan_directory_tree(source_dir_abs) elif config["scan_type"] == "list": result_data = scan_directory_list(source_dir_abs, config.get("extensions", [])) if result_data is not None: output_dir = os.path.dirname(output_file_abs) os.makedirs(output_dir, exist_ok=True) with open(output_file_abs, 'w', encoding='utf-8') as f: json.dump(result_data, f, indent=2, ensure_ascii=False) print(f"SUCESSO: Arquivo '{output_file_abs}' gerado!") print("\nGeração de manifestos concluída.") run_jekyll_build() # --- Lógica do Servidor Flask (sem alterações) --- def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @app.route('/upload-sample', methods=['POST']) def upload_file(): if 'sampleFile' not in request.files: return jsonify({"error": "Nenhum arquivo enviado"}), 400 file = request.files['sampleFile'] if file.filename == '': return jsonify({"error": "Nenhum arquivo selecionado"}), 400 if file and allowed_file(file.filename): filename = secure_filename(file.filename) os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) save_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) try: file.save(save_path) generate_manifests() return jsonify({"success": True, "message": f"Arquivo '{filename}' salvo e site atualizado!"}), 200 except Exception as e: return jsonify({"error": str(e)}), 500 return jsonify({"error": "Tipo de arquivo não permitido"}), 400 # --- NOVO: LÓGICA DO "VIGIA" DE ARQUIVOS (WATCHDOG) --- class ManifestEventHandler(FileSystemEventHandler): """Um manipulador de eventos que gera os manifestos quando um arquivo muda.""" def __init__(self): self.last_triggered = 0 def on_any_event(self, event): # Desconsidera eventos em diretórios if event.is_directory: return # Mecanismo simples para evitar múltiplas execuções seguidas (debounce) current_time = time.time() if current_time - self.last_triggered > 5: # Espera 5 segundos entre as atualizações print(f"\n[VIGIA] Mudança detectada: {event.src_path}") generate_manifests() self.last_triggered = current_time def start_file_watcher(): """Inicia o observador de arquivos em uma thread separada.""" print(f"\n[VIGIA] Iniciando monitoramento da pasta: {WATCH_FOLDER}") event_handler = ManifestEventHandler() observer = Observer() observer.schedule(event_handler, WATCH_FOLDER, recursive=True) observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: observer.stop() observer.join() # --- ATUALIZAÇÃO: INICIALIZAÇÃO PRINCIPAL --- if __name__ == '__main__': # Gera os manifestos uma vez ao iniciar o servidor generate_manifests() # Inicia o "vigia" de arquivos em uma thread separada (em segundo plano) watcher_thread = Thread(target=start_file_watcher, daemon=True) watcher_thread.start() # Inicia o servidor Flask (thread principal) print("\n[FLASK] Iniciando servidor de upload...") app.run(host='0.0.0.0', port=5000, debug=False) # Debug mode deve ser False para evitar que rode duas vezes