import streamlit as st import os import re import shutil import pandas as pd import time # Define a raiz absoluta ROOT_DIR = "/downloads" def get_all_subfolders(root_path): folder_list = [root_path] try: for root, dirs, files in os.walk(root_path): for d in dirs: folder_list.append(os.path.join(root, d)) except: pass return sorted(folder_list) def extract_season_episode(filename): """ Testa uma lista de padrões regex para extrair Temporada e Episódio. Retorna (season, episode) ou (None, None). """ # LISTA DE PADRÕES (Do mais específico para o mais genérico) patterns = [ # 1. Padrão Scene/Universal: S01E01, S01.E01, S01_E01, S01 - E01 r'(?i)S(\d{1,4})[\s._-]*E(\d{1,4})', # 2. Padrão Anime/P2P (Seu caso): S01EP01, S01.EP01 r'(?i)S(\d{1,4})[\s._-]*EP(\d{1,4})', # 3. Padrão Antigo: 1x01, 01x01 r'(?i)(\d{1,4})x(\d{1,4})', # 4. Padrão Extenso: Season 1 Episode 1 r'(?i)Season[\s._-]*(\d{1,4})[\s._-]*Episode[\s._-]*(\d{1,4})', # 5. Padrão Hífen (Anime): "Nome S01 - 05.mkv" r'(?i)S(\d{1,4})[\s._-]*-\s*(\d{1,4})', # 6. Padrão Colchetes: [1x01] r'(?i)\[(\d{1,4})x(\d{1,4})\]', ] for pattern in patterns: match = re.search(pattern, filename) if match: # Retorna Temporada, Episódio return match.group(1), match.group(2) return None, None def render(): st.header("🏷️ Renomeador de Séries") st.info("Suporta: S01E01, S01EP01, 1x01, S01 - 01, Season 1 Episode 1...") # --- SELEÇÃO DE PASTA --- all_folders = get_all_subfolders(ROOT_DIR) idx = 0 if 'rn_last_folder' in st.session_state and st.session_state.rn_last_folder in all_folders: idx = all_folders.index(st.session_state.rn_last_folder) root_path = st.selectbox( "Selecione a pasta para analisar:", options=all_folders, index=idx, format_func=lambda x: x.replace(ROOT_DIR, "") if x != ROOT_DIR else "Raiz (/downloads)" ) st.session_state.rn_last_folder = root_path if st.button("🔍 Analisar Arquivos", type="primary"): if not os.path.exists(root_path): st.error("Pasta não encontrada.") return preview_data = [] ignored_files = [] # Varre a pasta for root, dirs, files in os.walk(root_path): # Ignora pastas do sistema if "finalizados" in root or "temp" in root: continue for file in files: if file.lower().endswith(('.mkv', '.mp4', '.avi')): # Chama a função inteligente de detecção season, episode = extract_season_episode(file) if season and episode: try: s_fmt = f"{int(season):02d}" e_fmt = f"{int(episode):02d}" ext = os.path.splitext(file)[1] season_folder = f"Temporada {s_fmt}" new_name = f"Episódio {e_fmt}{ext}" original_full = os.path.join(root, file) dest_full = os.path.join(root_path, season_folder, new_name) preview_data.append({ "Arquivo Original": file, "Nova Estrutura": f"{season_folder}/{new_name}", "src": original_full, "dst": dest_full }) except: ignored_files.append(file) else: ignored_files.append(file) st.session_state['renamer_preview'] = preview_data st.session_state['renamer_ignored'] = ignored_files # --- RESULTADOS --- if 'renamer_preview' in st.session_state and st.session_state['renamer_preview']: st.divider() st.subheader(f"✅ Identificados ({len(st.session_state['renamer_preview'])})") df = pd.DataFrame(st.session_state['renamer_preview']) st.dataframe( df[["Arquivo Original", "Nova Estrutura"]], use_container_width=True, hide_index=True ) col1, col2 = st.columns([1, 4]) with col1: if st.button("🚀 Confirmar", type="primary", use_container_width=True): count = 0 for item in st.session_state['renamer_preview']: dst_folder = os.path.dirname(item["dst"]) try: if not os.path.exists(dst_folder): os.makedirs(dst_folder, exist_ok=True) if not os.path.exists(item["dst"]): shutil.move(item["src"], item["dst"]) count += 1 except Exception as e: st.error(f"Erro ao mover {item['src']}: {e}") st.success(f"{count} arquivos organizados com sucesso!") time.sleep(2) del st.session_state['renamer_preview'] del st.session_state['renamer_ignored'] st.rerun() # Exibe ignorados se houver, para debug do usuário if 'renamer_ignored' in st.session_state and st.session_state['renamer_ignored']: with st.expander("⚠️ Arquivos ignorados (Padrão desconhecido)", expanded=False): st.write(st.session_state['renamer_ignored']) elif 'renamer_preview' in st.session_state and not st.session_state['renamer_preview']: st.warning("Nenhum arquivo de vídeo encontrado.")