Skip to content

Instantly share code, notes, and snippets.

@zr0n
Created July 7, 2026 11:13
Show Gist options
  • Select an option

  • Save zr0n/01366b4ac002d104854d71d52f54067c to your computer and use it in GitHub Desktop.

Select an option

Save zr0n/01366b4ac002d104854d71d52f54067c to your computer and use it in GitHub Desktop.
import pyautogui
import time
import sys
import pygetwindow as gw
import random
import threading
import keyboard
# Evento global disparado pela hotkey de parada (Ctrl+Alt+X)
stop_event = threading.Event()
# Hotkey que encerra o script de qualquer janela
STOP_HOTKEY = 'ctrl+alt+x'
# Intervalo padrão entre ciclos principais (segundos)
DEFAULT_INTERVAL = 20
# Apps que devem ser IGNORADOS ao escolher a janela alvo.
# A ideia e interagir em qualquer janela que NAO seja essas.
EXCLUDED_APPS = ('slack', 'discord')
NOTEPAD_BLOCKS = [
(
"reuniao de alinhamento amanha as 9h - precisamos definir as prioridades do sprint\n"
"confirmar presenca de todos do time antes de fechar a pauta\n"
"pedir para o pedro preparar os slides com os numeros do ultimo mes\n"
"nao esquecer de incluir o ponto sobre a migracao do banco de dados"
),
(
"itens pendentes para revisao antes do deploy de sexta:\n"
"- testes de integracao passando em todos os ambientes\n"
"- checklist de rollback atualizado\n"
"- comunicado enviado para os stakeholders\n"
"- janela de manutencao confirmada com a infra"
),
(
"anotacoes da call com o cliente:\n"
"ele quer o relatorio semanal toda segunda antes das 10h\n"
"principal reclamacao: tempo de resposta do suporte esta alto\n"
"sugestao: criar canal dedicado no slack para o cliente tier 1\n"
"proxima reuniao marcada para dia 15, presencial no escritorio deles"
),
(
"ideias para refatorar o modulo de autenticacao:\n"
"separar a logica de token em um servico proprio\n"
"adicionar cache para as permissoes do usuario\n"
"rever o timeout da sessao, atualmente esta em 30min o que gera reclamacao\n"
"avaliar se vale migrar para oauth2 nessa sprint ou deixar para o proximo quarter"
),
(
"feedback da retrospectiva de hoje:\n"
"o que foi bem: comunicacao melhorou bastante, entregas no prazo\n"
"o que pode melhorar: code review esta demorando mais de 2 dias em media\n"
"acao: definir SLA interno de 24h para reviews\n"
"responsavel: todo o time, acompanhar na daily"
),
(
"checklist budget Q3:\n"
"licencas de software - aguardando aprovacao do financeiro\n"
"contratacao de dois devs pleno - headcount aprovado, vaga aberta no linkedin\n"
"upgrade de infra AWS - proposta enviada, retorno esperado para semana que vem\n"
"treinamentos: reservar verba para cursos de certificacao da equipe"
),
(
"pontos para discutir no 1on1 de amanha:\n"
"progresso no plano de desenvolvimento individual\n"
"como esta o volume de trabalho, se esta sobrecarregado\n"
"interesse em liderar o projeto de dados no proximo trimestre\n"
"feedback sobre a apresentacao que fez para a diretoria na semana passada"
),
(
"documentacao que precisa ser atualizada:\n"
"readme do repositorio principal - instructions de setup estao desatualizadas\n"
"wiki da api: 3 endpoints novos sem documentacao\n"
"runbook de incidente: adicionar os passos para o novo servico de pagamento\n"
"onboarding guide: incluir acesso ao ambiente de staging"
),
]
def micro_activity():
"""Pequeno movimento de mouse para manter sinal de atividade contínua."""
dx = random.randint(-12, 12)
dy = random.randint(-12, 12)
pyautogui.moveRel(dx, dy, duration=random.uniform(0.04, 0.10))
time.sleep(0.04)
pyautogui.moveRel(-dx // 2, -dy // 2, duration=0.04)
def active_sleep(seconds):
"""Dorme pelo tempo dado, fazendo micro-atividade de mouse a cada 8-10s.
Interrompe imediatamente se a hotkey de parada for acionada.
"""
elapsed = 0.0
while elapsed < seconds:
if stop_event.is_set():
return
chunk = min(random.uniform(8, 10), seconds - elapsed)
# Dorme em pequenos passos para responder rapido a hotkey de parada
slept = 0.0
while slept < chunk:
if stop_event.is_set():
return
step = min(0.25, chunk - slept)
time.sleep(step)
slept += step
elapsed += chunk
if elapsed < seconds and not stop_event.is_set():
micro_activity()
def random_movement_within_window(window, clicks=1, movements=5):
if not window:
return False
margin_x = min(50, window.width // 4)
margin_y = min(50, window.height // 4)
x_min = window.left + margin_x
x_max = window.left + window.width - margin_x
y_min = window.top + margin_y
y_max = window.top + window.height - margin_y
x1 = random.randint(x_min, x_max)
y1 = random.randint(y_min, y_max)
pyautogui.moveTo(x1, y1, duration=random.uniform(0.05, 0.15))
if clicks > 0:
pyautogui.click()
time.sleep(random.uniform(0.05, 0.12))
for _ in range(movements - 1):
x = random.randint(x_min, x_max)
y = random.randint(y_min, y_max)
pyautogui.moveTo(x, y, duration=random.uniform(0.05, 0.18))
time.sleep(random.uniform(0.05, 0.10))
return True
def find_target_window():
"""Encontra a primeira janela visível que NAO seja de um app excluído.
Ignora Slack/Discord, janelas sem titulo e a propria janela do console.
"""
for win in gw.getAllWindows():
title = (win.title or '').strip()
if not title:
continue
if not getattr(win, 'visible', True):
continue
# Janela minimizada nao serve como alvo
if getattr(win, 'isMinimized', False):
continue
lowered = title.lower()
if any(app in lowered for app in EXCLUDED_APPS):
continue
# Ignora janelas de sistema / do proprio script
if lowered in ('program manager', 'windows input experience'):
continue
if 'antiafk' in lowered or 'python' in lowered:
continue
return win
return None
def type_text(text):
"""Digita texto caractere por caractere com delay variável (rápido)."""
for char in text:
if char == '\n':
pyautogui.press('enter')
time.sleep(random.uniform(0.03, 0.08))
else:
pyautogui.typewrite(char, interval=0)
time.sleep(random.uniform(0.002, 0.008))
def open_notepad_and_type():
block = random.choice(NOTEPAD_BLOCKS)
pyautogui.hotkey('win', 'r')
time.sleep(0.8)
pyautogui.typewrite('notepad', interval=0.02)
pyautogui.press('enter')
time.sleep(2.0)
notepad_window = None
for win in gw.getAllWindows():
title = win.title or ''
if 'Notepad' in title or 'Bloco de Notas' in title:
notepad_window = win
break
if not notepad_window:
print(" Bloco de Notas nao encontrado, pulando.")
return False
# Clica no centro da janela para garantir foco
cx = notepad_window.left + notepad_window.width // 2
cy = notepad_window.top + notepad_window.height // 2
pyautogui.click(cx, cy)
time.sleep(0.4)
type_text(block)
# Adiciona um segundo bloco aleatório às vezes
if random.random() < 0.5:
pyautogui.press('enter')
time.sleep(0.3)
type_text(random.choice(NOTEPAD_BLOCKS))
time.sleep(random.uniform(0.4, 0.9))
# Re-encontra a janela para garantir referencia fresca
notepad_window = None
for win in gw.getAllWindows():
title = win.title or ''
if 'Notepad' in title or 'Bloco de Notas' in title:
notepad_window = win
break
if notepad_window:
notepad_window.activate()
time.sleep(0.6)
pyautogui.hotkey('alt', 'f4')
time.sleep(1.0)
pyautogui.press('tab')
time.sleep(0.2)
pyautogui.press('enter')
time.sleep(0.6)
# Fallback: se ainda estiver aberto, mata o processo
still_open = any(
('Notepad' in (w.title or '') or 'Bloco de Notas' in (w.title or ''))
for w in gw.getAllWindows()
)
if still_open:
import subprocess
subprocess.run('taskkill /f /im notepad.exe', shell=True, capture_output=True)
print(" Bloco de Notas fechado via taskkill.")
else:
print(" Bloco de Notas: aberto, digitado e fechado sem salvar.")
return True
def main():
intervalo = DEFAULT_INTERVAL
if len(sys.argv) > 1:
try:
intervalo = int(sys.argv[1])
print(f"Intervalo definido para {intervalo} segundos.")
except ValueError:
print(f"Argumento invalido. Usando intervalo padrao de {DEFAULT_INTERVAL} segundos.")
print("Anti-AFK iniciado. Micro-atividade a cada 8-10s + ciclo principal a cada "
f"{intervalo}s.")
print(f"Pressione Ctrl+C ou a hotkey global {STOP_HOTKEY.upper()} para parar.")
# Registra a hotkey global de parada (funciona de qualquer janela)
try:
keyboard.add_hotkey(STOP_HOTKEY, lambda: stop_event.set())
except Exception as e:
print(f"[AVISO] Nao foi possivel registrar a hotkey {STOP_HOTKEY}: {e}")
print(" Use Ctrl+C para parar.")
ciclo = 0
proximo_notepad = random.randint(2, 3)
try:
while not stop_event.is_set():
active_sleep(intervalo)
if stop_event.is_set():
break
ciclo += 1
try:
target_window = find_target_window()
if target_window:
print(f"[OK] Alvo: '{target_window.title}' [{time.strftime('%H:%M:%S')}] ciclo {ciclo} - movimentos + Alt+Tab")
try:
target_window.activate()
time.sleep(0.2)
except Exception:
pass
random_movement_within_window(target_window, clicks=1, movements=5)
pyautogui.hotkey('alt', 'tab')
time.sleep(0.25)
pyautogui.hotkey('alt', 'tab')
else:
print(f"[--] Nenhuma janela alvo encontrada [{time.strftime('%H:%M:%S')}] - micro-movimento")
micro_activity()
if ciclo >= proximo_notepad:
print(f"[KB] Bloco de Notas (ciclo {ciclo})...")
open_notepad_and_type()
ciclo = 0
proximo_notepad = random.randint(2, 3)
if target_window:
try:
target_window.activate()
except Exception:
pass
except Exception as e:
print(f"[ERR] Erro no ciclo {ciclo} (continuando): {e}")
except KeyboardInterrupt:
pass
finally:
try:
keyboard.remove_all_hotkeys()
except Exception:
pass
if stop_event.is_set():
print(f"\nAnti-AFK encerrado pela hotkey {STOP_HOTKEY.upper()}.")
else:
print("\nAnti-AFK encerrado.")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment