Skip to content

Instantly share code, notes, and snippets.

@rlaphoenix
Last active August 25, 2023 20:35
Show Gist options
  • Save rlaphoenix/1bee0cddbef1651bd75e018aa7580237 to your computer and use it in GitHub Desktop.
Save rlaphoenix/1bee0cddbef1651bd75e018aa7580237 to your computer and use it in GitHub Desktop.
Python script that runs 24/7 hosting a "is user AFK" WebSocket server

Is AFK WebSocket Server

Run the Python script and just like that a Websocket Server on port 8765 will be running.
From here forward/open the port 8765, or reverse proxy it with Caddy or NGINX (I recommend Caddy).

The WebSocket server responds 0x00 byte if the user is currently active. It responds 0x01 byte if the user is currently AFK. You should also check if it fails to connect and mark yourself as Offline.

The xml file is a Windows Task Scheduler export. You need to change the Logon User to your own.
You should also update the path of the actions, i.e. where the script is, or the folder it's in.

from ctypes import Structure, windll, c_uint, sizeof, byref
import asyncio
import websockets
AFK_TIMEOUT = 60 * 5 * 1000 # 5 minutes
class LASTINPUTINFO(Structure):
_fields_ = [
("cbSize", c_uint),
("dwTime", c_uint),
]
def get_idle_duration() -> int:
"""Get duration of User being Idle in Milliseconds."""
lastInputInfo = LASTINPUTINFO()
lastInputInfo.cbSize = sizeof(lastInputInfo)
windll.user32.GetLastInputInfo(byref(lastInputInfo))
millis = windll.kernel32.GetTickCount() - lastInputInfo.dwTime
return millis
def main():
async def echo(websocket, path):
while True:
idle_duration = get_idle_duration()
await websocket.send(bytes([int(idle_duration >= AFK_TIMEOUT)]))
await asyncio.sleep(1)
start_server = websockets.serve(echo, "localhost", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
if __name__ == "__main__":
main()
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2023-08-25T21:15:04.5465853</Date>
<Author>HOME\rlaphoenix</Author>
<Description>Python script that runs 24/7 hosting a "is user AFK" WebSocket server.</Description>
<URI>\rlaphoenix\AFK WebSocket Server</URI>
</RegistrationInfo>
<Triggers>
<LogonTrigger>
<Enabled>true</Enabled>
<UserId>HOME\rlaphoenix</UserId>
</LogonTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>S-1-5-21-337567976-632876213-2291690736-1001</UserId>
<LogonType>InteractiveToken</LogonType>
<RunLevel>LeastPrivilege</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>Queue</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>true</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
<UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
<Priority>7</Priority>
<RestartOnFailure>
<Interval>PT5M</Interval>
<Count>10</Count>
</RestartOnFailure>
</Settings>
<Actions Context="Author">
<Exec>
<Command>pythonw</Command>
<Arguments>is_afk.py</Arguments>
<WorkingDirectory>C:\Caddy</WorkingDirectory>
</Exec>
</Actions>
</Task>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment