feat(ui): add terminal formatting and colored output

- Implement ANSI color codes and formatted display functions
- Add banner and configuration panel for startup
- Introduce terminal width configuration option
- Update default timing intervals and confidence threshold
- Add screenshot reference file
This commit is contained in:
marco
2026-09-07 12:33:42 -03:00
parent 995adb4757
commit 77a735743a
5 changed files with 422 additions and 75 deletions
+5 -4
View File
@@ -1,9 +1,10 @@
INTERVALO_MINIMO_CLIQUE=10 LARGURA_TERMINAL=50
INTERVALO_MAXIMO_CLIQUE=30 INTERVALO_MINIMO_CLIQUE=5
INTERVALO_MAXIMO_CLIQUE=10
INTERVALO_PRIMEIRO_CLIQUE=10 INTERVALO_PRIMEIRO_CLIQUE=10
MAXIMO_CLIQUES_POR_SESSAO=20 MAXIMO_CLIQUES_POR_SESSAO=10
INTERVALO_ENTRE_SESSOES=120 INTERVALO_ENTRE_SESSOES=120
MAXIMO_FALHAS=3 MAXIMO_FALHAS=3
HORA_INICIO=09:00 HORA_INICIO=09:00
HORA_FIM=18:00 HORA_FIM=18:00
CONFIANCA=0.8 CONFIANCA=0.9
Binary file not shown.
+223
View File
@@ -187,3 +187,226 @@ Sistema interrompido pelo usuário (CTRL+C).
[2026-09-07 12:00:41] Aguardando 13s até o próximo ciclo... [2026-09-07 12:00:41] Aguardando 13s até o próximo ciclo...
[2026-09-07 12:00:50] [2026-09-07 12:00:50]
Sistema interrompido pelo usuário (CTRL+C). Sistema interrompido pelo usuário (CTRL+C).
[2026-09-07 12:09:04] Pressione CTRL+C para parar.
[2026-09-07 12:09:04] [Sessão 1] Botão encontrado! Confiança: 0.91 | Pos: (450, 320)
[2026-09-07 12:09:04] Clique #1/20 | Total geral: 1
[2026-09-07 12:09:04] [Sessão 1] Aguardando 17s até o próximo ciclo...
[2026-09-07 12:09:04] [Sessão 2] Aguardando 10s antes do primeiro clique...
[2026-09-07 12:09:04] [Sessão 2] Clicando em (450, 320)...
[2026-09-07 12:09:04] Clique #5/20 | Total geral: 5
[2026-09-07 12:09:04] Total de cliques realizados: 5
[2026-09-07 12:11:04] Pressione CTRL+C para parar.
[2026-09-07 12:11:04] Aguardando 10s antes do primeiro clique...
[2026-09-07 12:11:14] Botão encontrado! Confiança: 1.00 | Pos: (1086, 752)
[2026-09-07 12:11:14] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:11:14] Clique #1/20 | Total geral: 1
[2026-09-07 12:11:14] [Sessão 1] Aguardando 27s até o próximo ciclo...
[2026-09-07 12:11:21] Total de cliques realizados: 1
[2026-09-07 12:14:43] Pressione CTRL+C para parar.
[2026-09-07 12:14:43] Aguardando 10s antes do primeiro clique...
[2026-09-07 12:14:51] Total de cliques realizados: 0
[2026-09-07 12:15:08] Pressione CTRL+C para parar.
[2026-09-07 12:15:08] Aguardando 10s antes do primeiro clique...
[2026-09-07 12:15:16] Total de cliques realizados: 0
[2026-09-07 12:15:28] Pressione CTRL+C para parar.
[2026-09-07 12:15:28] Aguardando 10s antes do primeiro clique...
[2026-09-07 12:15:38] Botão encontrado! Confiança: 1.00 | Pos: (1086, 752)
[2026-09-07 12:15:38] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:15:38] Clique #1/20 | Total geral: 1
[2026-09-07 12:15:38] [Sessão 1] Aguardando 16s até o próximo ciclo...
[2026-09-07 12:15:45] Total de cliques realizados: 1
[2026-09-07 12:15:57] Pressione CTRL+C para parar.
[2026-09-07 12:15:57] Aguardando 10s antes do primeiro clique...
[2026-09-07 12:16:08] Botão encontrado! Confiança: 0.82 | Pos: (1086, 752)
[2026-09-07 12:16:08] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:16:08] Clique #1/20 | Total geral: 1
[2026-09-07 12:16:08] [Sessão 1] Aguardando 23s até o próximo ciclo...
[2026-09-07 12:16:31] Botão NÃO encontrado. Confiança: 0.27 (mín: 0.8)
[2026-09-07 12:16:31] [Sessão 1] Botão não encontrado. Falhas: 1/3 | Total: 1
[2026-09-07 12:16:31] [Sessão 1] Aguardando 16s até o próximo ciclo...
[2026-09-07 12:16:47] Botão NÃO encontrado. Confiança: 0.28 (mín: 0.8)
[2026-09-07 12:16:47] [Sessão 1] Botão não encontrado. Falhas: 2/3 | Total: 1
[2026-09-07 12:16:47] [Sessão 1] Aguardando 16s até o próximo ciclo...
[2026-09-07 12:17:03] Botão encontrado! Confiança: 1.00 | Pos: (1086, 752)
[2026-09-07 12:17:03] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:17:03] Clique #2/20 | Total geral: 2
[2026-09-07 12:17:03] [Sessão 1] Aguardando 19s até o próximo ciclo...
[2026-09-07 12:17:22] Botão encontrado! Confiança: 1.00 | Pos: (1086, 752)
[2026-09-07 12:17:22] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:17:23] Clique #3/20 | Total geral: 3
[2026-09-07 12:17:23] [Sessão 1] Aguardando 10s até o próximo ciclo...
[2026-09-07 12:17:33] Botão NÃO encontrado. Confiança: 0.28 (mín: 0.8)
[2026-09-07 12:17:33] [Sessão 1] Botão não encontrado. Falhas: 1/3 | Total: 3
[2026-09-07 12:17:33] [Sessão 1] Aguardando 28s até o próximo ciclo...
[2026-09-07 12:18:01] Botão NÃO encontrado. Confiança: 0.28 (mín: 0.8)
[2026-09-07 12:18:01] [Sessão 1] Botão não encontrado. Falhas: 2/3 | Total: 3
[2026-09-07 12:18:01] [Sessão 1] Aguardando 24s até o próximo ciclo...
[2026-09-07 12:18:25] Botão NÃO encontrado. Confiança: 0.28 (mín: 0.8)
[2026-09-07 12:18:25] [Sessão 1] Botão não encontrado. Falhas: 3/3 | Total: 3
[2026-09-07 12:18:25] ⚠ Máximo de falhas (3) atingido. Encerrando.
[2026-09-07 12:18:25] Total de cliques realizados: 3
[2026-09-07 12:19:58] Pressione CTRL+C para parar.
[2026-09-07 12:19:58] [Sessao 1] Botao encontrado! Confianca: 0.91 | Pos: (450, 320)
[2026-09-07 12:19:58] Clique #1/20 | Total geral: 1
[2026-09-07 12:19:58] [Sessao 1] Aguardando 17s ate o proximo ciclo...
[2026-09-07 12:19:58] [Sessao 2] Aguardando 10s antes do primeiro clique...
[2026-09-07 12:19:58] [Sessao 2] Clicando em (450, 320)...
[2026-09-07 12:19:58] Clique #5/20 | Total geral: 5
[2026-09-07 12:19:58] Total de cliques realizados: 5
[2026-09-07 12:20:23] Pressione CTRL+C para parar.
[2026-09-07 12:20:23] Aguardando 10s antes do primeiro clique...
[2026-09-07 12:20:34] Botão encontrado! Confiança: 1.00 | Pos: (1086, 752)
[2026-09-07 12:20:34] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:20:34] Clique #1/20 | Total geral: 1
[2026-09-07 12:20:34] [Sessão 1] Aguardando 29s até o próximo ciclo...
[2026-09-07 12:21:03] Botão NÃO encontrado. Confiança: 0.27 (mín: 0.8)
[2026-09-07 12:21:03] [Sessão 1] Botão não encontrado. Falhas: 1/3 | Total: 1
[2026-09-07 12:21:03] [Sessão 1] Aguardando 29s até o próximo ciclo...
[2026-09-07 12:21:32] Botão NÃO encontrado. Confiança: 0.27 (mín: 0.8)
[2026-09-07 12:21:32] [Sessão 1] Botão não encontrado. Falhas: 2/3 | Total: 1
[2026-09-07 12:21:32] [Sessão 1] Aguardando 25s até o próximo ciclo...
[2026-09-07 12:21:57] Botão encontrado! Confiança: 1.00 | Pos: (1086, 752)
[2026-09-07 12:21:57] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:21:57] Clique #2/20 | Total geral: 2
[2026-09-07 12:21:57] [Sessão 1] Aguardando 26s até o próximo ciclo...
[2026-09-07 12:22:04] Total de cliques realizados: 2
[2026-09-07 12:22:07] Pressione CTRL+C para parar.
[2026-09-07 12:22:07] Aguardando 10s antes do primeiro clique...
[2026-09-07 12:22:18] Botão encontrado! Confiança: 1.00 | Pos: (1086, 752)
[2026-09-07 12:22:18] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:22:18] Clique #1/20 | Total geral: 1
[2026-09-07 12:22:18] [Sessão 1] Aguardando 19s até o próximo ciclo...
[2026-09-07 12:22:19] Pressione CTRL+C para parar.
[2026-09-07 12:22:19] [Sessao 1] Botao encontrado!
[2026-09-07 12:22:19] Clique #1/20 | Total geral: 1
[2026-09-07 12:22:19] [Sessao 1] Aguardando 17s...
[2026-09-07 12:22:19] [Sessao 2] Aguardando 10s...
[2026-09-07 12:22:19] [Sessao 2] Clicando...
[2026-09-07 12:22:19] Clique #5/20 | Total geral: 5
[2026-09-07 12:22:19] Total de cliques realizados: 5
[2026-09-07 12:22:37] Botão NÃO encontrado. Confiança: 0.28 (mín: 0.8)
[2026-09-07 12:22:37] [Sessão 1] Botão não encontrado. Falhas: 1/3 | Total: 1
[2026-09-07 12:22:37] [Sessão 1] Aguardando 27s até o próximo ciclo...
[2026-09-07 12:23:04] Botão NÃO encontrado. Confiança: 0.28 (mín: 0.8)
[2026-09-07 12:23:04] [Sessão 1] Botão não encontrado. Falhas: 2/3 | Total: 1
[2026-09-07 12:23:04] [Sessão 1] Aguardando 12s até o próximo ciclo...
[2026-09-07 12:23:16] Botão NÃO encontrado. Confiança: 0.28 (mín: 0.8)
[2026-09-07 12:23:16] [Sessão 1] Botão não encontrado. Falhas: 3/3 | Total: 1
[2026-09-07 12:23:16] ⚠ Máximo de falhas (3) atingido. Encerrando.
[2026-09-07 12:23:16] Total de cliques realizados: 1
[2026-09-07 12:24:08] Pressione CTRL+C para parar.
[2026-09-07 12:24:08] [Sessao 1] Botao encontrado!
[2026-09-07 12:24:08] Clique #1/20 | Total geral: 1
[2026-09-07 12:24:08] [Sessao 1] Aguardando 17s...
[2026-09-07 12:24:08] [Sessao 2] Aguardando 10s...
[2026-09-07 12:24:08] [Sessao 2] Clicando...
[2026-09-07 12:24:08] Clique #5/20 | Total geral: 5
[2026-09-07 12:24:08] Total de cliques realizados: 5
[2026-09-07 12:24:34] Pressione CTRL+C para parar.
[2026-09-07 12:24:34] Aguardando 10s antes do primeiro clique...
[2026-09-07 12:24:44] Botão encontrado! Confiança: 1.00 | Pos: (1086, 752)
[2026-09-07 12:24:44] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:24:44] Clique #1/20 | Total geral: 1
[2026-09-07 12:24:44] [Sessão 1] Aguardando 26s até o próximo ciclo...
[2026-09-07 12:25:10] Botão encontrado! Confiança: 0.95 | Pos: (1086, 752)
[2026-09-07 12:25:10] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:25:11] Clique #2/20 | Total geral: 2
[2026-09-07 12:25:11] [Sessão 1] Aguardando 25s até o próximo ciclo...
[2026-09-07 12:25:36] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:25:36] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:25:36] Clique #3/20 | Total geral: 3
[2026-09-07 12:25:36] [Sessão 1] Aguardando 15s até o próximo ciclo...
[2026-09-07 12:25:51] Botão encontrado! Confiança: 0.91 | Pos: (1086, 752)
[2026-09-07 12:25:51] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:25:51] Clique #4/20 | Total geral: 4
[2026-09-07 12:25:51] [Sessão 1] Aguardando 22s até o próximo ciclo...
[2026-09-07 12:26:13] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:26:13] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:26:13] Clique #5/20 | Total geral: 5
[2026-09-07 12:26:13] [Sessão 1] Aguardando 22s até o próximo ciclo...
[2026-09-07 12:26:35] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:26:35] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:26:36] Clique #6/20 | Total geral: 6
[2026-09-07 12:26:36] [Sessão 1] Aguardando 28s até o próximo ciclo...
[2026-09-07 12:27:04] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:27:04] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:27:04] Clique #7/20 | Total geral: 7
[2026-09-07 12:27:04] [Sessão 1] Aguardando 12s até o próximo ciclo...
[2026-09-07 12:27:16] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:27:16] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:27:16] Clique #8/20 | Total geral: 8
[2026-09-07 12:27:16] [Sessão 1] Aguardando 26s até o próximo ciclo...
[2026-09-07 12:27:42] Botão encontrado! Confiança: 0.95 | Pos: (1086, 752)
[2026-09-07 12:27:42] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:27:42] Clique #9/20 | Total geral: 9
[2026-09-07 12:27:42] [Sessão 1] Aguardando 29s até o próximo ciclo...
[2026-09-07 12:28:12] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:28:12] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:28:12] Clique #10/20 | Total geral: 10
[2026-09-07 12:28:12] [Sessão 1] Aguardando 29s até o próximo ciclo...
[2026-09-07 12:28:35] Total de cliques realizados: 10
[2026-09-07 12:29:24] Pressione CTRL+C para parar.
[2026-09-07 12:29:24] Aguardando 10s antes do primeiro clique...
[2026-09-07 12:29:34] Botão encontrado! Confiança: 1.00 | Pos: (1086, 752)
[2026-09-07 12:29:34] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:29:34] Clique #1/10 | Total geral: 1
[2026-09-07 12:29:34] [Sessão 1] Aguardando 7s até o próximo ciclo...
[2026-09-07 12:29:41] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:29:41] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:29:41] Clique #2/10 | Total geral: 2
[2026-09-07 12:29:41] [Sessão 1] Aguardando 9s até o próximo ciclo...
[2026-09-07 12:29:50] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:29:50] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:29:50] Clique #3/10 | Total geral: 3
[2026-09-07 12:29:50] [Sessão 1] Aguardando 5s até o próximo ciclo...
[2026-09-07 12:29:56] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:29:56] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:29:56] Clique #4/10 | Total geral: 4
[2026-09-07 12:29:56] [Sessão 1] Aguardando 8s até o próximo ciclo...
[2026-09-07 12:30:04] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:30:04] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:30:04] Clique #5/10 | Total geral: 5
[2026-09-07 12:30:04] [Sessão 1] Aguardando 7s até o próximo ciclo...
[2026-09-07 12:30:11] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:30:11] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:30:11] Clique #6/10 | Total geral: 6
[2026-09-07 12:30:11] [Sessão 1] Aguardando 9s até o próximo ciclo...
[2026-09-07 12:30:20] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:30:20] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:30:20] Clique #7/10 | Total geral: 7
[2026-09-07 12:30:20] [Sessão 1] Aguardando 8s até o próximo ciclo...
[2026-09-07 12:30:29] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:30:29] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:30:29] Clique #8/10 | Total geral: 8
[2026-09-07 12:30:29] [Sessão 1] Aguardando 7s até o próximo ciclo...
[2026-09-07 12:30:36] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:30:36] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:30:36] Clique #9/10 | Total geral: 9
[2026-09-07 12:30:36] [Sessão 1] Aguardando 8s até o próximo ciclo...
[2026-09-07 12:30:44] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:30:44] [Sessão 1] Clicando em (1086, 752)...
[2026-09-07 12:30:44] Clique #10/10 | Total geral: 10
[2026-09-07 12:30:44] --- Sessão 1 finalizada: 10 cliques ---
[2026-09-07 12:30:44] Aguardando 120s até a Sessão 2...
[2026-09-07 12:32:44] Aguardando 10s antes do primeiro clique...
[2026-09-07 12:32:54] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:32:54] [Sessão 2] Clicando em (1086, 752)...
[2026-09-07 12:32:55] Clique #1/10 | Total geral: 11
[2026-09-07 12:32:55] [Sessão 2] Aguardando 10s até o próximo ciclo...
[2026-09-07 12:33:05] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:33:05] [Sessão 2] Clicando em (1086, 752)...
[2026-09-07 12:33:05] Clique #2/10 | Total geral: 12
[2026-09-07 12:33:05] [Sessão 2] Aguardando 10s até o próximo ciclo...
[2026-09-07 12:33:15] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:33:15] [Sessão 2] Clicando em (1086, 752)...
[2026-09-07 12:33:15] Clique #3/10 | Total geral: 13
[2026-09-07 12:33:15] [Sessão 2] Aguardando 5s até o próximo ciclo...
[2026-09-07 12:33:20] Botão encontrado! Confiança: 0.97 | Pos: (1086, 752)
[2026-09-07 12:33:20] [Sessão 2] Clicando em (1086, 752)...
[2026-09-07 12:33:20] Clique #4/10 | Total geral: 14
[2026-09-07 12:33:20] [Sessão 2] Aguardando 7s até o próximo ciclo...
[2026-09-07 12:33:27] Botão encontrado! Confiança: 1.00 | Pos: (1086, 752)
[2026-09-07 12:33:27] [Sessão 2] Clicando em (1086, 752)...
[2026-09-07 12:33:28] Clique #5/10 | Total geral: 15
[2026-09-07 12:33:28] [Sessão 2] Aguardando 6s até o próximo ciclo...
[2026-09-07 12:33:28] Total de cliques realizados: 15
+179 -56
View File
@@ -9,15 +9,16 @@ import os
import sys import sys
import time import time
import random import random
import re
import cv2 import cv2
import numpy as np import numpy as np
import pyautogui import pyautogui
from datetime import datetime from datetime import datetime
from dotenv import load_dotenv from dotenv import load_dotenv
# Carrega variáveis do .env
load_dotenv() load_dotenv()
LARGURA_TERMINAL = int(os.getenv("LARGURA_TERMINAL", "60"))
INTERVALO_MINIMO_CLIQUE = int(os.getenv("INTERVALO_MINIMO_CLIQUE", "10")) INTERVALO_MINIMO_CLIQUE = int(os.getenv("INTERVALO_MINIMO_CLIQUE", "10"))
INTERVALO_MAXIMO_CLIQUE = int(os.getenv("INTERVALO_MAXIMO_CLIQUE", "30")) INTERVALO_MAXIMO_CLIQUE = int(os.getenv("INTERVALO_MAXIMO_CLIQUE", "30"))
INTERVALO_PRIMEIRO_CLIQUE = int(os.getenv("INTERVALO_PRIMEIRO_CLIQUE", "10")) INTERVALO_PRIMEIRO_CLIQUE = int(os.getenv("INTERVALO_PRIMEIRO_CLIQUE", "10"))
@@ -32,91 +33,179 @@ LOG_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "log.txt")
pyautogui.FAILSAFE = True pyautogui.FAILSAFE = True
RST = "\033[0m"
BOLD = "\033[1m"
def gerar_intervalo_aleatorio(intervalo_min: int, intervalo_max: int) -> int: C_TITLE = "\033[96m"
"""Gera um valor aleatório entre intervalo_min e intervalo_max (inclusive).""" C_GREEN = "\033[92m"
return random.randint(intervalo_min, intervalo_max) C_YELLOW = "\033[93m"
C_RED = "\033[91m"
C_MAG = "\033[95m"
C_WHITE = "\033[97m"
C_GRAY = "\033[90m"
C_CYAN = "\033[36m"
_RE_ANSI = re.compile(r"\x1b\[[0-9;]*m")
def vis_largura(texto: str) -> int:
sem_ansi = _RE_ANSI.sub("", texto)
emojis = re.findall(
r"[\U0001F300-\U0001FAFF"
r"\U00002702-\U000027B0"
r"\U0000FE0F"
r"\U0001F1E0-\U0001F1FF"
r"\U00002600-\U000026FF"
r"\U00002700-\U000027BF"
r"]+",
sem_ansi,
flags=re.UNICODE,
)
ajuste_emoji = sum((2 - len(e)) for e in emojis)
return len(sem_ansi) + ajuste_emoji
def terminal_width() -> int:
return LARGURA_TERMINAL
def largura() -> int:
return terminal_width()
def center(text: str, pre: str = "", pos: str = "") -> str:
w = largura() - vis_largura(pre) - vis_largura(pos)
return pre + text.center(w) + pos
def banner() -> None:
print()
print(center(" 🤖 AUTO-CLICADOR 🤖 ", C_TITLE + BOLD))
print(center("Sistema de Cliques Automáticos", C_TITLE))
print()
def painel_config() -> None:
itens = [
(C_GRAY, "Largura do terminal", f"{LARGURA_TERMINAL} colunas"),
(C_GREEN, "Intervalo mínimo entre cliques", f"{INTERVALO_MINIMO_CLIQUE}s"),
(C_GREEN, "Intervalo máximo entre cliques", f"{INTERVALO_MAXIMO_CLIQUE}s"),
(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_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)),
]
print(center(" ⚙ CONFIGURAÇÃO", C_TITLE + BOLD))
print()
labels_sem_cor = [_RE_ANSI.sub("", f" {label}") for _, label, _ in itens]
max_label_vis = max(vis_largura(l) for l in labels_sem_cor)
largura_label = max(max_label_vis, 1)
for cor, label, valor in itens:
label_raw = f" {label}"
label_vis = vis_largura(label_raw)
padding_label = max(1, largura_label - label_vis + 2)
print(
cor
+ label_raw
+ RST
+ " " * padding_label
+ C_WHITE
+ str(valor)
+ RST
)
print()
def cabecalho_sessao(num: int) -> None:
print()
print(C_MAG + BOLD + f" 🔄 SESSÃO {num} 🔄" + RST)
print()
def rodape_clique() -> None:
w = largura()
inner_w = w - 4
barra_preenchida = max(1, int(inner_w * 0.4))
barra_vazia = inner_w - barra_preenchida
barra = C_GREEN + "█" * barra_preenchida + C_GRAY + "░" * barra_vazia + RST
print(" " + barra)
def log(mensagem: str, cor: str = C_WHITE) -> None:
agora = datetime.now()
ts = agora.strftime("%H:%M:%S")
ts_raw = f"[{ts}] "
ts_color = C_GRAY
linha_terminal = (
" "
+ ts_color + ts_raw + RST
+ cor + mensagem + RST
)
print(linha_terminal)
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: try:
with open(LOG_FILE, "a", encoding="utf-8") as f: with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write(linha + "\n") ts_full = agora.strftime("%Y-%m-%d %H:%M:%S")
f.write(f"[{ts_full}] {_RE_ANSI.sub('', mensagem)}\n")
except Exception: except Exception:
pass pass
def dentro_horario(hora_inicio: str, hora_fim: str) -> bool: 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() agora = datetime.now().time()
hi = datetime.strptime(hora_inicio, "%H:%M").time() hi = datetime.strptime(hora_inicio, "%H:%M").time()
hf = datetime.strptime(hora_fim, "%H:%M").time() hf = datetime.strptime(hora_fim, "%H:%M").time()
return hi <= agora <= hf return hi <= agora <= hf
def encontrar_botao(imagem_path: str, confianca: float = 0.8): 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): if not os.path.isfile(imagem_path):
log(f"ERRO: Imagem '{imagem_path}' não encontrada.") log(f"ERRO: Imagem '{imagem_path}' não encontrada.", C_RED)
return None return None
# Captura screenshot da tela
screenshot = pyautogui.screenshot() screenshot = pyautogui.screenshot()
screenshot_np = np.array(screenshot) screenshot_np = np.array(screenshot)
screenshot_cv = cv2.cvtColor(screenshot_np, cv2.COLOR_RGB2BGR) screenshot_cv = cv2.cvtColor(screenshot_np, cv2.COLOR_RGB2BGR)
# Carrega template do botão
template = cv2.imread(imagem_path, cv2.IMREAD_UNCHANGED) template = cv2.imread(imagem_path, cv2.IMREAD_UNCHANGED)
if template is None: if template is None:
log(f"ERRO: Não foi possível carregar a imagem '{imagem_path}'.") log(f"ERRO: Não foi possível carregar '{imagem_path}'.", C_RED)
return None return None
# Converte template para BGR se tiver alpha channel
if template.shape[2] == 4: if template.shape[2] == 4:
template_bgr = cv2.cvtColor(template, cv2.COLOR_BGRA2BGR) template_bgr = cv2.cvtColor(template, cv2.COLOR_BGRA2BGR)
# Cria máscara para o canal alpha
alpha = template[:, :, 3] alpha = template[:, :, 3]
mascara = alpha.astype(np.uint8) mascara = alpha.astype(np.uint8)
else: else:
template_bgr = template template_bgr = template
mascara = None mascara = None
# Template matching
resultado = cv2.matchTemplate(screenshot_cv, template_bgr, cv2.TM_CCOEFF_NORMED, mask=mascara) resultado = cv2.matchTemplate(screenshot_cv, template_bgr, cv2.TM_CCOEFF_NORMED, mask=mascara)
_, max_val, _, max_loc = cv2.minMaxLoc(resultado) _, max_val, _, max_loc = cv2.minMaxLoc(resultado)
if max_val >= confianca: if max_val >= confianca:
h, w = template_bgr.shape[:2] h, w2 = template_bgr.shape[:2]
centro_x = max_loc[0] + w // 2 centro_x = max_loc[0] + w2 // 2
centro_y = max_loc[1] + h // 2 centro_y = max_loc[1] + h // 2
log(f"Botão encontrado! Confiança: {max_val:.2f} | Posição: ({centro_x}, {centro_y})") log(
f"Botão encontrado! Confiança: {max_val:.2f} | Pos: ({centro_x}, {centro_y})",
C_GREEN,
)
return (centro_x, centro_y) return (centro_x, centro_y)
else: else:
log(f"Botão NÃO encontrado. Melhor confiança: {max_val:.2f} (necessário >= {confianca})") log(
f"Botão NÃO encontrado. Confiança: {max_val:.2f} (mín: {confianca})",
C_RED,
)
return None return None
def gerar_intervalo_aleatorio(intervalo_min: int, intervalo_max: int) -> int:
return random.randint(intervalo_min, intervalo_max)
def main() -> None: def main() -> None:
log("=" * 60) banner()
log("Sistema de Cliques Automáticos iniciado") painel_config()
log(f"Intervalo mínimo entre cliques: {INTERVALO_MINIMO_CLIQUE}s")
log(f"Intervalo máximo entre cliques: {INTERVALO_MAXIMO_CLIQUE}s") print(center(" 🚀 Iniciando sistema... ", C_TITLE + BOLD))
log(f"Aguardar antes do 1º clique: {INTERVALO_PRIMEIRO_CLIQUE}s") print()
log(f"Máximo de cliques por sessão: {MAXIMO_CLIQUES_POR_SESSAO}")
log(f"Intervalo entre sessões: {INTERVALO_ENTRE_SESSOES}s") log("Pressione CTRL+C para parar.", C_YELLOW)
log(f"Máximo de falhas antes de encerrar: {MAXIMO_FALHAS}") print()
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 primeiro_clique = True
falhas_consecutivas = 0 falhas_consecutivas = 0
@@ -129,16 +218,22 @@ def main() -> None:
agora = datetime.now() agora = datetime.now()
if not dentro_horario(HORA_INICIO, HORA_FIM): 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(
log(f"Pausando até {HORA_INICIO}...") f"[Sessão {numero_sessao}] Fora do horário permitido ({agora.strftime('%H:%M:%S')}).",
C_YELLOW,
)
log(f"Pausando até {HORA_INICIO}...", C_GRAY)
falhas_consecutivas = 0 falhas_consecutivas = 0
cliques_na_sessao = 0 cliques_na_sessao = 0
time.sleep(30) time.sleep(30)
continue continue
if primeiro_clique: if primeiro_clique:
log(f"--- Sessão {numero_sessao} iniciada ---") cabecalho_sessao(numero_sessao)
log(f"Aguardando {INTERVALO_PRIMEIRO_CLIQUE}s antes do primeiro clique...") log(
f"Aguardando {INTERVALO_PRIMEIRO_CLIQUE}s antes do primeiro clique...",
C_CYAN,
)
time.sleep(INTERVALO_PRIMEIRO_CLIQUE) time.sleep(INTERVALO_PRIMEIRO_CLIQUE)
primeiro_clique = False primeiro_clique = False
@@ -146,36 +241,64 @@ def main() -> None:
if posicao: if posicao:
x, y = posicao x, y = posicao
log(f"[Sessão {numero_sessao}] Clicando em ({x}, {y})...") log(
f"[Sessão {numero_sessao}] Clicando em ({x}, {y})...",
C_GREEN,
)
pyautogui.click(x, y) pyautogui.click(x, y)
total_cliques += 1 total_cliques += 1
cliques_na_sessao += 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}") log(
f"Clique #{cliques_na_sessao}/{MAXIMO_CLIQUES_POR_SESSAO} | Total geral: {total_cliques}",
C_GREEN + BOLD,
)
falhas_consecutivas = 0 falhas_consecutivas = 0
rodape_clique()
else: else:
falhas_consecutivas += 1 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}") log(
f"[Sessão {numero_sessao}] Botão não encontrado. "
f"Falhas: {falhas_consecutivas}/{MAXIMO_FALHAS} | Total: {total_cliques}",
C_RED,
)
if falhas_consecutivas >= MAXIMO_FALHAS: if falhas_consecutivas >= MAXIMO_FALHAS:
log(f"Máximo de falhas ({MAXIMO_FALHAS}) atingido. Encerrando sistema.") print()
log(f"Total de cliques realizados com sucesso: {total_cliques}") log(
f"⚠ Máximo de falhas ({MAXIMO_FALHAS}) atingido. Encerrando.",
C_RED + BOLD,
)
log(f"Total de cliques realizados: {total_cliques}", C_YELLOW)
sys.exit(1) sys.exit(1)
# Verifica se atingiu o máximo de cliques da sessão
if cliques_na_sessao >= MAXIMO_CLIQUES_POR_SESSAO: if cliques_na_sessao >= MAXIMO_CLIQUES_POR_SESSAO:
log(f"--- Sessão {numero_sessao} finalizada: {cliques_na_sessao} cliques ---") log(
f"--- Sessão {numero_sessao} finalizada: {cliques_na_sessao} cliques ---",
C_MAG + BOLD,
)
numero_sessao += 1 numero_sessao += 1
cliques_na_sessao = 0 cliques_na_sessao = 0
log(f"Aguardando {INTERVALO_ENTRE_SESSOES}s até a próxima sessão (Sessão {numero_sessao})...") log(
f"Aguardando {INTERVALO_ENTRE_SESSOES}s até a Sessão {numero_sessao}...",
C_YELLOW,
)
time.sleep(INTERVALO_ENTRE_SESSOES) time.sleep(INTERVALO_ENTRE_SESSOES)
primeiro_clique = True primeiro_clique = True
continue continue
intervalo = gerar_intervalo_aleatorio(INTERVALO_MINIMO_CLIQUE, INTERVALO_MAXIMO_CLIQUE) intervalo = gerar_intervalo_aleatorio(
log(f"[Sessão {numero_sessao}] Aguardando {intervalo}s até o próximo ciclo...") INTERVALO_MINIMO_CLIQUE, INTERVALO_MAXIMO_CLIQUE
)
log(
f"[Sessão {numero_sessao}] Aguardando {intervalo}s até o próximo ciclo...",
C_CYAN,
)
time.sleep(intervalo) time.sleep(intervalo)
except KeyboardInterrupt: except KeyboardInterrupt:
log(f"\nSistema interrompido pelo usuário (CTRL+C). Total de cliques: {total_cliques}") print()
print(C_RED + BOLD + center(" 🛑 INTERROMPIDO PELO USUÁRIO 🛑 ") + RST)
print()
log(f"Total de cliques realizados: {total_cliques}", C_YELLOW)
if __name__ == "__main__": if __name__ == "__main__":
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB