Created
November 16, 2025 15:51
-
-
Save eip/af158db2f1584aa377ddf6fdab42d778 to your computer and use it in GitHub Desktop.
Keep your Mac awake by jiggling the mouse
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env osascript -l JavaScript | |
| ObjC.import("Cocoa"); | |
| ObjC.import("CoreGraphics"); | |
| function screenSize() { | |
| const w = $.NSScreen.mainScreen.frame.size.width; | |
| const h = $.NSScreen.mainScreen.frame.size.height; | |
| return { w, h }; | |
| } | |
| function mousePos() { | |
| const event = $.CGEventCreate(null); | |
| const pos = $.CGEventGetLocation(event); | |
| return { x: parseInt(pos.x), y: parseInt(pos.y) }; | |
| } | |
| function mouseMove(pos) { | |
| const event = $.CGEventCreateMouseEvent(null, $.kCGEventMouseMoved, $.CGPointMake(pos.x, pos.y), null); | |
| $.CGEventPost($.kCGHIDEventTap, event); | |
| } | |
| function newPos(val, distance, max) { | |
| const jitter = Math.round(Math.random() * distance); | |
| let result = Math.random() < 0.5 ? val - jitter : val + jitter; | |
| if (val - jitter < 0) result = val + jitter; | |
| else if (val + jitter >= max) result = val - jitter; | |
| return result; | |
| } | |
| function print(str) { | |
| $.NSFileHandle.fileHandleWithStandardOutput.writeData($.NSString.alloc.initWithUTF8String(str).dataUsingEncoding($.NSUTF8StringEncoding)); | |
| } | |
| function timeFmt(date) { | |
| const hh = date.getHours(); | |
| const mm = date.getMinutes(); | |
| return `${hh}:${mm.toString().padStart(2, "0")}`; | |
| } | |
| function run(argv) { | |
| let distance, interval, hours, minutes; | |
| if (argv.length === 3) { | |
| distance = Number(argv[0]); | |
| interval = Number(argv[1]); | |
| [hours, minutes] = argv[2].split(":").map(Number); | |
| } | |
| if (isNaN(distance) || isNaN(interval) || isNaN(hours) || isNaN(minutes)) { | |
| print("Usage: engaging.js <distance pixels> <interval seconds> <until HH:MM>\n"); | |
| return; | |
| } | |
| if (interval < 1 || interval > 300) { | |
| print("Interval must be between 1 and 300 seconds.\n"); | |
| return; | |
| } | |
| if (distance < 1 || distance > 200) { | |
| print("Distance must be between 1 and 200 pixels.\n"); | |
| return; | |
| } | |
| if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) { | |
| print("Time must be in HH:MM format (24-hour clock).\n"); | |
| return; | |
| } | |
| const until = new Date(); | |
| until.setHours(hours, minutes, 0, 0); | |
| const now = new Date(); | |
| if (now > until && now - until > 12 * 60 * 60 * 1000) { | |
| until.setDate(until.getDate() + 1); | |
| } | |
| if (new Date() >= until) { | |
| print(`The specified time ${timeFmt(until)} has already passed today.\n`); | |
| return; | |
| } | |
| print(`Jiggling mouse by ${distance} pixels every ${interval} sec until ${timeFmt(until)}...\n`); | |
| let prev_pos = { x: -1, y: -1 }; | |
| const ss = screenSize(); | |
| while (new Date() < until) { | |
| const pos = mousePos(); | |
| if (pos.x != prev_pos.x || pos.y != prev_pos.y) { | |
| prev_pos = pos; | |
| delay(interval); | |
| continue; | |
| } | |
| mouseMove({ x: newPos(pos.x, distance, ss.w), y: newPos(pos.y, distance, ss.h) }); | |
| print("."); | |
| delay(0.5); | |
| mouseMove(pos); | |
| delay(interval - 0.5); | |
| } | |
| print("\nFinished.\n"); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment