From fa2be1a13c776ad7ba84ee4895f72496faf4494c Mon Sep 17 00:00:00 2001 From: marco Date: Wed, 9 Sep 2026 13:28:20 -0300 Subject: [PATCH] feat(config): add support for multiple session periods Replace single time range configuration with support for up to 10 configurable session periods. Rename INTERVALO_CLIQUE_ESPERA to INTERVALO_CLIQUE_GLOBAL for clarity. Update dentro_horario function to accept list of period tuples instead of individual start/end times. BREAKING CHANGE: HORA_INICIO and HORA_FIM environment variables are replaced by PERIODO_{n}_INICIO and PERIODO_{n}_FIM variables (n=1-10). INTERVALO_CLIQUE_ESPERA is renamed to INTERVALO_CLIQUE_GLOBAL. --- .env | 25 ++++++++++-- __pycache__/main.cpython-311.pyc | Bin 17735 -> 19448 bytes main.py | 63 +++++++++++++++++++++++-------- 3 files changed, 69 insertions(+), 19 deletions(-) mode change 100755 => 100644 __pycache__/main.cpython-311.pyc diff --git a/.env b/.env index 1d0265f..6707af6 100755 --- a/.env +++ b/.env @@ -4,8 +4,27 @@ INTERVALO_MAXIMO_CLIQUE=20 INTERVALO_PRIMEIRO_CLIQUE=10 MAXIMO_CLIQUES_POR_SESSAO=20 INTERVALO_ENTRE_SESSOES=3300 -INTERVALO_CLIQUE_ESPERA=900 +INTERVALO_CLIQUE_GLOBAL=900 MAXIMO_FALHAS=10 -HORA_INICIO=09:00 -HORA_FIM=18:00 +# Períodos de sessão (até 10). Deixe vazio para desativar um período. +PERIODO_1_INICIO=09:00 +PERIODO_1_FIM=12:00 +PERIODO_2_INICIO=14:00 +PERIODO_2_FIM=18:00 +PERIODO_3_INICIO= +PERIODO_3_FIM= +PERIODO_4_INICIO= +PERIODO_4_FIM= +PERIODO_5_INICIO= +PERIODO_5_FIM= +PERIODO_6_INICIO= +PERIODO_6_FIM= +PERIODO_7_INICIO= +PERIODO_7_FIM= +PERIODO_8_INICIO= +PERIODO_8_FIM= +PERIODO_9_INICIO= +PERIODO_9_FIM= +PERIODO_10_INICIO= +PERIODO_10_FIM= CONFIANCA=0.9 diff --git a/__pycache__/main.cpython-311.pyc b/__pycache__/main.cpython-311.pyc old mode 100755 new mode 100644 index 64aac6aac979ee511604bb6cdde51ff8cfcfa284..aa20bc73f02d1ee2fbebc7c70c189604f8552aef GIT binary patch delta 5891 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 WygdvJrcZrUb5e)-o(dgN`+os=es(DU delta 4663 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 bool: + agora = datetime.now().time() + for ini, fim in periodos: + hi = datetime.strptime(ini, "%H:%M").time() + hf = datetime.strptime(fim, "%H:%M").time() + if hi <= agora <= hf: + return True + return False pyautogui.FAILSAFE = True @@ -88,9 +107,8 @@ def painel_config() -> None: (C_CYAN, "Espera antes do 1º clique", f"{INTERVALO_PRIMEIRO_CLIQUE}s"), (C_YELLOW, "Máximo de cliques por sessão", str(MAXIMO_CLIQUES_POR_SESSAO)), (C_YELLOW, "Intervalo entre sessões", f"{INTERVALO_ENTRE_SESSOES}s"), - (C_CYAN, "Clique de espera entre sessões", f"{INTERVALO_CLIQUE_ESPERA}s"), + (C_CYAN, "Clique global de espera", f"{INTERVALO_CLIQUE_GLOBAL}s"), (C_MAG, "Máximo de falhas", str(MAXIMO_FALHAS)), - (C_WHITE, "Horário de funcionamento", f"{HORA_INICIO} às {HORA_FIM}"), (C_GRAY, "Confiança mínima", str(CONFIANCA)), ] @@ -116,6 +134,15 @@ def painel_config() -> None: ) print() + if PERIODOS_SESSAO: + print(C_WHITE + BOLD + center(" 📅 Períodos de sessão", C_TITLE) + RST) + print() + for idx, (ini, fim) in enumerate(PERIODOS_SESSAO, 1): + print(C_WHITE + f" {idx}. " + C_CYAN + f"{ini} → {fim}" + RST) + else: + print(C_RED + center(" ⚠ Nenhum período configurado!", C_RED) + RST) + print() + def cabecalho_sessao(num: int) -> None: print() print(C_MAG + BOLD + f" 🔄 SESSÃO {num} 🔄" + RST) @@ -149,12 +176,6 @@ def log(mensagem: str, cor: str = C_WHITE) -> None: except Exception: pass -def dentro_horario(hora_inicio: str, hora_fim: str) -> bool: - agora = datetime.now().time() - hi = datetime.strptime(hora_inicio, "%H:%M").time() - hf = datetime.strptime(hora_fim, "%H:%M").time() - return hi <= agora <= hf - def encontrar_botao(imagem_path: str, confianca: float = 0.8): if not os.path.isfile(imagem_path): log(f"ERRO: Imagem '{imagem_path}' não encontrada.", C_RED) @@ -219,15 +240,25 @@ def main() -> None: while True: agora = datetime.now() - if not dentro_horario(HORA_INICIO, HORA_FIM): + if not dentro_horario(PERIODOS_SESSAO): log( - f"[Sessão {numero_sessao}] Fora do horário permitido ({agora.strftime('%H:%M:%S')}).", + f"[Sessão {numero_sessao}] Fora de todos os períodos configurados ({agora.strftime('%H:%M:%S')}).", C_YELLOW, ) - log(f"Pausando até {HORA_INICIO}...", C_GRAY) + log(f"[Espera] Dormindo {INTERVALO_CLIQUE_GLOBAL}s até o próximo clique global...", C_GRAY) + time.sleep(INTERVALO_CLIQUE_GLOBAL) + pos_global = encontrar_botao(IMAGEM_BOTAO, CONFIANCA) + if pos_global: + gx, gy = pos_global + log( + f"[Espera] Clicando globalmente em ({gx}, {gy})...", + C_GREEN, + ) + pyautogui.click(gx, gy) + else: + log("[Espera] Botão não encontrado no clique global.", C_RED) falhas_consecutivas = 0 cliques_na_sessao = 0 - time.sleep(30) continue if primeiro_clique: @@ -283,7 +314,7 @@ def main() -> None: ) tempo_restante = INTERVALO_ENTRE_SESSOES while tempo_restante > 0: - tempo_ate_clique = min(tempo_restante, INTERVALO_CLIQUE_ESPERA) + tempo_ate_clique = min(tempo_restante, INTERVALO_CLIQUE_GLOBAL) log( f"[Espera] Dormindo {tempo_ate_clique}s (restam {tempo_restante}s)...", C_GRAY,