I am here. Definitively NOT sleeping or sunbathing – A configurable anti-AFK Python script with pyautogui
Yeah I know it’s kinda pointless. I was thinking the same thing when I doomscrolled youtube shorts watching a so called programmer “Herr Programmierer” showing a simple script moving the mouse in a fixed interval to coordinates in a fixed square. I was bored, I like Python and sure I could create a better pointless script 😀
Here it is. It will move your mouse pointer to random coordinates on your primary monitor if you haven’t moved your mouse since the last interval.
You can use it with a default config which moves your mouse every 5 to 10 mins. There are some commented examples on how to use it on the bottom of the script.
The interval is defined by a typle with min and max values inbetween moves. The duration of moving the pointer to the new coordinates can also be defined by a tuple with min and max values. The default movement pattern is linear, but you could use the module pytweening to get some nicer ones. Just exchange the commented lines and you are fine.
The min and max are validated and if invalid, default values are used.
import random as rnd
import typing
import pyautogui as pag
import time
# import pytweening as pt
MIN_INTERVAL = 3
MIN_DURATION = 0
class AntiAfk:
def __init__(self, interval: typing.Tuple = None, duration: typing.Tuple = None, movement: typing.Callable = None):
self.timeout = self.rnd(interval) if self.interval_ok(interval) else lambda: rnd.randint(300, 600)
self.duration = self.rnd(duration) if self.duration_ok(duration) else lambda: rnd.randint(2, 20) / 10
self.movement = movement if movement is not None else pag.linear
self.size = pag.size()
self.old_pos = pag.position()
def run(self):
while True:
time.sleep(self.timeout())
if pag.position() == self.old_pos:
coords = self.new_coords(self.old_pos)
if self.duration != (0, 0):
pag.moveTo(*coords, duration=self.duration(), tween=self.movement)
else:
pag.moveTo(*coords)
self.old_pos = pag.position()
def new_coords(self, old: (int, int)) -> (int, int):
new = rnd.randint(0, self.size.width), rnd.randint(0, self.size.height)
return new if new is not old else self.new_coords(old)
@staticmethod
def interval_ok(interval: typing.Tuple) -> bool:
ok = AntiAfk.check(interval, (int,), MIN_INTERVAL)
if not ok:
print(f'Interval not ok: {interval} - using default')
return ok
@staticmethod
def duration_ok(duration: typing.Tuple) -> bool:
ok = AntiAfk.check(duration, (int, float), MIN_DURATION)
if not ok:
print(f'Duration not ok: {duration} - using default')
return ok
@staticmethod
def check(t: (), types: typing.Tuple, minimum: float) -> bool:
return t is not None and all(type(x) in types for x in t) and minimum <= t[0] <= t[1]
@staticmethod
def rnd(v: typing.Tuple) -> typing.Callable:
if all(type(x) is int for x in v):
return lambda: (rnd.randint(*v))
if all(type(x) in (float, int) for x in v):
return lambda: (rnd.randint(round(v[0] * 10), round(v[1] * 10)) / 10)
else:
raise TypeError(f'Type combination ({[type(x) for x in v]}) not supported')
if __name__ == '__main__':
# default values: 5 to 10 min interval, move duration 0.2 to 2s
# AntiAfk().run()
# Good values to test the scipt: 3-5s interval, movement duration 0.5-1s
AntiAfk(interval=(3, 5), duration=(0.5, 1)).run()
# Good values to test the scipt: 3-5s interval, instant movement
# AntiAfk(interval=(3, 5), duration=(0, 0)).run()
# 3-5s interval, movement duration 0.5-1s, movement pattern fom pytweening
# AntiAfk(interval=(3, 5), duration=(0.5, 1), movement=pt.easeOutQuad).run()
Have fun! And please don’t be so dumb and use this for work.