#!/usr/bin/env python3 """stay_active_win.py — keep Microsoft Teams showing 'Available' on Windows. Teams marks you 'Away' after ~5 minutes of no keyboard/mouse input. This tool resets Windows' idle timer periodically by sending a harmless input via the Win32 SendInput API. It also optionally tells Windows not to sleep/turn off the display while running. No third-party packages required — pure ctypes against user32/kernel32. Windows only. Press Ctrl+C to stop. """ import argparse import ctypes import sys import time from ctypes import wintypes if not sys.platform.startswith("win"): sys.exit("This script is for Windows. On Linux use stay_active.py instead.") user32 = ctypes.WinDLL("user32", use_last_error=True) kernel32 = ctypes.WinDLL("kernel32", use_last_error=True) # --- SendInput structures ---------------------------------------------------- ULONG_PTR = wintypes.WPARAM INPUT_MOUSE = 0 INPUT_KEYBOARD = 1 MOUSEEVENTF_MOVE = 0x0001 KEYEVENTF_KEYUP = 0x0002 VK_F15 = 0x7E # virtual key; valid even without a physical F15 on the keyboard # SetThreadExecutionState flags (keep system/display awake) ES_CONTINUOUS = 0x80000000 ES_SYSTEM_REQUIRED = 0x00000001 ES_DISPLAY_REQUIRED = 0x00000002 class MOUSEINPUT(ctypes.Structure): _fields_ = [ ("dx", wintypes.LONG), ("dy", wintypes.LONG), ("mouseData", wintypes.DWORD), ("dwFlags", wintypes.DWORD), ("time", wintypes.DWORD), ("dwExtraInfo", ULONG_PTR), ] class KEYBDINPUT(ctypes.Structure): _fields_ = [ ("wVk", wintypes.WORD), ("wScan", wintypes.WORD), ("dwFlags", wintypes.DWORD), ("time", wintypes.DWORD), ("dwExtraInfo", ULONG_PTR), ] class _INPUTunion(ctypes.Union): _fields_ = [("mi", MOUSEINPUT), ("ki", KEYBDINPUT)] class INPUT(ctypes.Structure): _fields_ = [("type", wintypes.DWORD), ("u", _INPUTunion)] def _send(*inputs): n = len(inputs) arr = (INPUT * n)(*inputs) sent = user32.SendInput(n, arr, ctypes.sizeof(INPUT)) if sent != n: raise ctypes.WinError(ctypes.get_last_error()) def nudge_mouse(): # Relative move +1px then -1px: cursor ends where it started, effectively invisible. right = INPUT(type=INPUT_MOUSE, u=_INPUTunion(mi=MOUSEINPUT(1, 0, 0, MOUSEEVENTF_MOVE, 0, 0))) left = INPUT(type=INPUT_MOUSE, u=_INPUTunion(mi=MOUSEINPUT(-1, 0, 0, MOUSEEVENTF_MOVE, 0, 0))) _send(right, left) def tap_f15(): down = INPUT(type=INPUT_KEYBOARD, u=_INPUTunion(ki=KEYBDINPUT(VK_F15, 0, 0, 0, 0))) up = INPUT(type=INPUT_KEYBOARD, u=_INPUTunion(ki=KEYBDINPUT(VK_F15, 0, KEYEVENTF_KEYUP, 0, 0))) _send(down, up) def main(): p = argparse.ArgumentParser(description="Keep Teams presence 'Available' on Windows.") p.add_argument("-i", "--interval", type=float, default=120, help="seconds between signals (default: 120; keep under Teams' ~300s Away threshold)") p.add_argument("-m", "--method", choices=["mouse", "key"], default="key", help="how to signal activity (default: key — an invisible F15 tap)") p.add_argument("--no-sleep", action="store_true", help="also prevent the system and display from sleeping while running") p.add_argument("-q", "--quiet", action="store_true", help="don't print heartbeat messages") args = p.parse_args() action = tap_f15 if args.method == "key" else nudge_mouse label = "tapping F15" if args.method == "key" else "nudging mouse 1px" if args.no_sleep: flags = ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED kernel32.SetThreadExecutionState(flags) if not args.quiet: awake = " (sleep inhibited)" if args.no_sleep else "" print(f"stay_active: {label} every {args.interval:g}s{awake}. Press Ctrl+C to stop.") taps = 0 try: while True: action() taps += 1 if not args.quiet: print(f"\r active — {taps} signal(s) sent, last at {time.strftime('%H:%M:%S')}", end="", flush=True) time.sleep(args.interval) except KeyboardInterrupt: if not args.quiet: print("\nstay_active: stopped.") finally: if args.no_sleep: kernel32.SetThreadExecutionState(ES_CONTINUOUS) # release the keep-awake request if __name__ == "__main__": main()