Skip to content

Instantly share code, notes, and snippets.

@FredrikM97
Last active February 26, 2026 09:15
Show Gist options
  • Select an option

  • Save FredrikM97/0da2d8cd236094e9ad36d4d11e02b0f8 to your computer and use it in GitHub Desktop.

Select an option

Save FredrikM97/0da2d8cd236094e9ad36d4d11e02b0f8 to your computer and use it in GitHub Desktop.
wabbajack-download-button-clicker
import os
import sys
import time
import signal
from dataclasses import dataclass
import pyautogui
import keyboard
# -------------------- CONFIG --------------------
# To use take a snippet of the download button and insert the path into the image_path of the config.
#
@dataclass
class Config:
image_path: str = r"absolute/path/to/file"
confidence: float = 0.8
retry_attempts: int = 3
retry_delay: float = 0.5
loop_delay: float = 7.0
exit_hotkey: str = "ctrl+shift+e"
CONFIG = Config()
# -------------------- UTILITIES --------------------
def validate_image_path(path: str) -> None:
"""Ensure the image file exists."""
if not os.path.isfile(path):
print(f"[ERROR] Image file not found:\n{path}")
sys.exit(1)
def click_on_image(config: Config) -> bool:
"""
Search for an image on screen and click it if found.
Returns True if clicked, False otherwise.
"""
for attempt in range(1, config.retry_attempts + 1):
try:
location = pyautogui.locateOnScreen(
config.image_path,
confidence=config.confidence
)
if location:
center = pyautogui.center(location)
original_position = pyautogui.position()
print(f"[✓] Found button at {center} (attempt {attempt})")
pyautogui.click(center)
pyautogui.moveTo(original_position)
return True
print(f"[{attempt}/{config.retry_attempts}] Not found. Retrying...")
time.sleep(config.retry_delay)
except Exception as e:
print(f"[ERROR] Screen search failed: {e}")
time.sleep(config.retry_delay)
print("[!] Button not found after retries.")
return False
# -------------------- MAIN LOOP --------------------
running = True
def stop_program():
global running
print("\n[INFO] Exit triggered. Shutting down...")
running = False
def main():
validate_image_path(CONFIG.image_path)
print("Move this console window so it doesn't cover the button.")
input("Press Enter to start...\n")
keyboard.add_hotkey(CONFIG.exit_hotkey, stop_program)
print(f"[INFO] Press {CONFIG.exit_hotkey.upper()} to stop.\n")
while running:
click_on_image(CONFIG)
time.sleep(CONFIG.loop_delay)
# -------------------- ENTRY POINT --------------------
if __name__ == "__main__":
# Allow CTRL+C to exit cleanly
signal.signal(signal.SIGINT, lambda s, f: stop_program())
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment