Files
Mover-Mouse/main.py
T
sargatxetandCopilot App 5ecdde187e Mover: utilidad para mover el ratón tras inactividad
- Mover.ps1: activación tras inactividad, parada al detectar uso, deslizamiento
  animado visible, mensajes de estado y cierre de instancias previas.
- main.py: movimiento solo tras 3 minutos de inactividad.
- Documentación: README, AGENTS, CHANGELOG y TODO.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-07 08:33:17 +02:00

83 lines
2.6 KiB
Python

"""Mueve el ratón aleatoriamente solo tras un periodo de inactividad del usuario (solo Windows)."""
import ctypes
import ctypes.wintypes
import random
import time
import pyautogui
# Segundos sin uso de teclado/ratón antes de empezar a mover el cursor
TIEMPO_INACTIVIDAD = 180
# Desplazamiento máximo (píxeles) en cada eje
DESPLAZAMIENTO_MAX = 50
# Intervalo de comprobación de actividad (segundos)
INTERVALO_COMPROBACION = 0.2
class LASTINPUTINFO(ctypes.Structure):
"""Estructura de Win32 que recibe el instante de la última entrada del usuario."""
_fields_ = [("cbSize", ctypes.wintypes.UINT), ("dwTime", ctypes.wintypes.DWORD)]
def obtener_ultima_entrada():
"""
Obtiene el instante (en ticks del sistema, ms) de la última entrada de teclado o ratón.
:return: valor dwTime devuelto por GetLastInputInfo.
"""
info = LASTINPUTINFO()
info.cbSize = ctypes.sizeof(LASTINPUTINFO)
if not ctypes.windll.user32.GetLastInputInfo(ctypes.byref(info)):
raise ctypes.WinError()
return info.dwTime
def segundos_inactivo():
"""
Calcula los segundos transcurridos desde la última entrada de teclado o ratón.
:return: segundos de inactividad.
"""
ahora = ctypes.windll.kernel32.GetTickCount() & 0xFFFFFFFF
# Máscara para tolerar el desbordamiento de GetTickCount (~49,7 días)
return ((ahora - obtener_ultima_entrada()) & 0xFFFFFFFF) / 1000.0
def esperar_inactividad():
"""Bloquea hasta que el usuario lleve TIEMPO_INACTIVIDAD segundos sin usar teclado ni ratón."""
while segundos_inactivo() < TIEMPO_INACTIVIDAD:
time.sleep(1)
def mover_mientras_inactivo():
"""
Mueve el ratón aleatoriamente hasta detectar actividad real del usuario.
Los movimientos propios también actualizan GetLastInputInfo, por lo que tras cada
movimiento se guarda el dwTime resultante; cualquier cambio posterior indica uso real.
"""
while True:
pyautogui.moveRel(random.randrange(-DESPLAZAMIENTO_MAX, DESPLAZAMIENTO_MAX),
random.randrange(-DESPLAZAMIENTO_MAX, DESPLAZAMIENTO_MAX))
ultima_propia = obtener_ultima_entrada()
fin_pausa = time.monotonic() + random.randrange(2, 5)
while time.monotonic() < fin_pausa:
time.sleep(INTERVALO_COMPROBACION)
if obtener_ultima_entrada() != ultima_propia:
return
def main():
"""Bucle principal: espera la inactividad, mueve el ratón y se detiene al detectar uso."""
while True:
try:
esperar_inactividad()
mover_mientras_inactivo()
except Exception:
time.sleep(1)
if __name__ == "__main__":
main()