#!/usr/bin/env python3 """ Sistema de cliques automáticos baseado em reconhecimento de imagem. Clique no botão especificado por 'botaoparaclicar.png' a cada X segundos, apenas dentro do horário configurado no .env. """ import os import sys import time import random import cv2 import numpy as np import pyautogui from datetime import datetime from dotenv import load_dotenv # Carrega variáveis do .env load_dotenv() INTERVALO_MINIMO_CLIQUE = int(os.getenv("INTERVALO_MINIMO_CLIQUE", "10")) INTERVALO_MAXIMO_CLIQUE = int(os.getenv("INTERVALO_MAXIMO_CLIQUE", "30")) INTERVALO_PRIMEIRO_CLIQUE = int(os.getenv("INTERVALO_PRIMEIRO_CLIQUE", "10")) MAXIMO_CLIQUES_POR_SESSAO = int(os.getenv("MAXIMO_CLIQUES_POR_SESSAO", "20")) INTERVALO_ENTRE_SESSOES = int(os.getenv("INTERVALO_ENTRE_SESSOES", "60")) MAXIMO_FALHAS = int(os.getenv("MAXIMO_FALHAS", "5")) HORA_INICIO = os.getenv("HORA_INICIO", "09:00") HORA_FIM = os.getenv("HORA_FIM", "18:00") CONFIANCA = float(os.getenv("CONFIANCA", "0.8")) IMAGEM_BOTAO = os.path.join(os.path.dirname(os.path.abspath(__file__)), "botaoparaclicar.png") LOG_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "log.txt") pyautogui.FAILSAFE = True def gerar_intervalo_aleatorio(intervalo_min: int, intervalo_max: int) -> int: """Gera um valor aleatório entre intervalo_min e intervalo_max (inclusive).""" return random.randint(intervalo_min, intervalo_max) def log(mensagem: str) -> None: """Registra mensagem com timestamp.""" timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") linha = f"[{timestamp}] {mensagem}" print(linha) try: with open(LOG_FILE, "a", encoding="utf-8") as f: f.write(linha + "\n") except Exception: pass def dentro_horario(hora_inicio: str, hora_fim: str) -> bool: """Verifica se o horário atual está dentro do intervalo configurado.""" 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): """ Procura a imagem do botão na tela usando template matching. Retorna as coordenadas (x, y) do centro do botão ou None. """ if not os.path.isfile(imagem_path): log(f"ERRO: Imagem '{imagem_path}' não encontrada.") return None # Captura screenshot da tela screenshot = pyautogui.screenshot() screenshot_np = np.array(screenshot) screenshot_cv = cv2.cvtColor(screenshot_np, cv2.COLOR_RGB2BGR) # Carrega template do botão template = cv2.imread(imagem_path, cv2.IMREAD_UNCHANGED) if template is None: log(f"ERRO: Não foi possível carregar a imagem '{imagem_path}'.") return None # Converte template para BGR se tiver alpha channel if template.shape[2] == 4: template_bgr = cv2.cvtColor(template, cv2.COLOR_BGRA2BGR) # Cria máscara para o canal alpha alpha = template[:, :, 3] mascara = alpha.astype(np.uint8) else: template_bgr = template mascara = None # Template matching resultado = cv2.matchTemplate(screenshot_cv, template_bgr, cv2.TM_CCOEFF_NORMED, mask=mascara) _, max_val, _, max_loc = cv2.minMaxLoc(resultado) if max_val >= confianca: h, w = template_bgr.shape[:2] centro_x = max_loc[0] + w // 2 centro_y = max_loc[1] + h // 2 log(f"Botão encontrado! Confiança: {max_val:.2f} | Posição: ({centro_x}, {centro_y})") return (centro_x, centro_y) else: log(f"Botão NÃO encontrado. Melhor confiança: {max_val:.2f} (necessário >= {confianca})") return None def main() -> None: log("=" * 60) log("Sistema de Cliques Automáticos iniciado") log(f"Intervalo mínimo entre cliques: {INTERVALO_MINIMO_CLIQUE}s") log(f"Intervalo máximo entre cliques: {INTERVALO_MAXIMO_CLIQUE}s") log(f"Aguardar antes do 1º clique: {INTERVALO_PRIMEIRO_CLIQUE}s") log(f"Máximo de cliques por sessão: {MAXIMO_CLIQUES_POR_SESSAO}") log(f"Intervalo entre sessões: {INTERVALO_ENTRE_SESSOES}s") log(f"Máximo de falhas antes de encerrar: {MAXIMO_FALHAS}") log(f"Horário de funcionamento: {HORA_INICIO} às {HORA_FIM}") log(f"Confiança mínima: {CONFIANCA}") log(f"Imagem do botão: {IMAGEM_BOTAO}") log("=" * 60) log("Pressione CTRL+C para parar.") primeiro_clique = True falhas_consecutivas = 0 total_cliques = 0 cliques_na_sessao = 0 numero_sessao = 1 try: while True: agora = datetime.now() if not dentro_horario(HORA_INICIO, HORA_FIM): log(f"[Sessão {numero_sessao}] Fora do horário permitido ({agora.strftime('%H:%M:%S')}).") log(f"Pausando até {HORA_INICIO}...") falhas_consecutivas = 0 cliques_na_sessao = 0 time.sleep(30) continue if primeiro_clique: log(f"--- Sessão {numero_sessao} iniciada ---") log(f"Aguardando {INTERVALO_PRIMEIRO_CLIQUE}s antes do primeiro clique...") time.sleep(INTERVALO_PRIMEIRO_CLIQUE) primeiro_clique = False posicao = encontrar_botao(IMAGEM_BOTAO, CONFIANCA) if posicao: x, y = posicao log(f"[Sessão {numero_sessao}] Clicando em ({x}, {y})...") pyautogui.click(x, y) total_cliques += 1 cliques_na_sessao += 1 log(f"Clique executado com sucesso. Total geral: {total_cliques} | Sessão {numero_sessao}: {cliques_na_sessao}/{MAXIMO_CLIQUES_POR_SESSAO}") falhas_consecutivas = 0 else: falhas_consecutivas += 1 log(f"[Sessão {numero_sessao}] Botão não encontrado. Falhas consecutivas: {falhas_consecutivas}/{MAXIMO_FALHAS} | Total de cliques: {total_cliques}") if falhas_consecutivas >= MAXIMO_FALHAS: log(f"Máximo de falhas ({MAXIMO_FALHAS}) atingido. Encerrando sistema.") log(f"Total de cliques realizados com sucesso: {total_cliques}") sys.exit(1) # Verifica se atingiu o máximo de cliques da sessão if cliques_na_sessao >= MAXIMO_CLIQUES_POR_SESSAO: log(f"--- Sessão {numero_sessao} finalizada: {cliques_na_sessao} cliques ---") numero_sessao += 1 cliques_na_sessao = 0 log(f"Aguardando {INTERVALO_ENTRE_SESSOES}s até a próxima sessão (Sessão {numero_sessao})...") time.sleep(INTERVALO_ENTRE_SESSOES) primeiro_clique = True continue intervalo = gerar_intervalo_aleatorio(INTERVALO_MINIMO_CLIQUE, INTERVALO_MAXIMO_CLIQUE) log(f"[Sessão {numero_sessao}] Aguardando {intervalo}s até o próximo ciclo...") time.sleep(intervalo) except KeyboardInterrupt: log(f"\nSistema interrompido pelo usuário (CTRL+C). Total de cliques: {total_cliques}") if __name__ == "__main__": main()