Skip to content

Instantly share code, notes, and snippets.

@cprima
Last active June 8, 2024 05:49
Show Gist options
  • Save cprima/d1d8b011bd1857a957533d6b101f8aa3 to your computer and use it in GitHub Desktop.
Save cprima/d1d8b011bd1857a957533d6b101f8aa3 to your computer and use it in GitHub Desktop.
autotype_from_clipboard.py

AutoType from Clipboard

This script automatically types text from the clipboard into a text area, simulating human-like typing behavior.

Usage

  1. Install Dependencies:

    pip install -r requirements.txt
  2. Copy Text to Clipboard: Copy the text you want to type into the clipboard.

  3. Focus Text Entry Field: Click on or otherwise focus the text entry field where you want the text to be typed.

  4. Run Script: Run the script by executing:

    python autotype_from_clipboard.py

    Note: The script will automatically switch to the previous window using Alt+Tab.

Author

Sourcecode

gist.github.com/cprima

License

This project is licensed under the CC BY 4.0 license. See the LICENSE file for details.

import pyautogui
import pyperclip
import time
import random
import threading
import keyboard
# Define a flag to control the interruption
interrupt_flag = False
typing_finished = False
def listen_for_interrupt():
global interrupt_flag
global typing_finished
try:
while not typing_finished:
if keyboard.is_pressed('esc'):
print("ESC key detected. Exiting...")
interrupt_flag = True
break
time.sleep(0.1) # Check every 100 ms
except:
pass
# Define a mapping of common typos
typo_map = {
'a': ['s', 'q', 'z'],
's': ['a', 'd', 'w', 'x'],
'd': ['s', 'f', 'e', 'c'],
'f': ['d', 'g', 'r', 'v'],
'g': ['f', 'h', 't', 'b'],
'h': ['g', 'j', 'y', 'n'],
'j': ['h', 'k', 'u', 'm'],
'k': ['j', 'l', 'i', ','],
'l': ['k', 'o', '.'],
'q': ['a', 'w'],
'w': ['q', 'e', 's'],
'e': ['w', 'r', 'd'],
'r': ['e', 't', 'f'],
't': ['r', 'y', 'g'],
'y': ['t', 'u', 'h'],
'u': ['y', 'i', 'j'],
'i': ['u', 'o', 'k'],
'o': ['i', 'p', 'l'],
'p': ['o'],
'z': ['a', 'x'],
'x': ['z', 'c', 's'],
'c': ['x', 'v', 'd'],
'v': ['c', 'b', 'f'],
'b': ['v', 'n', 'g'],
'n': ['b', 'm', 'h'],
'm': ['n', 'j', 'k']
}
# Function to introduce typos with a given probability
def introduce_typo(char, typo_probability):
if char.lower() in typo_map and random.random() < typo_probability:
return random.choice(typo_map[char.lower()])
return char
# Function to write text with optional pauses after specific patterns and typos
def human_typing(text, base_interval, variability, pause_multiplier, typo_probability):
global interrupt_flag
i = 0
while i < len(text):
if interrupt_flag:
print("Typing interrupted.")
return
char = text[i]
# Type the character, ensuring backticks are handled properly
if char == '`':
pyautogui.write('` ')
else:
char_with_typo = introduce_typo(char, typo_probability)
pyautogui.write(char_with_typo)
# If a typo occurred, correct it with backspace and write the correct character
if char_with_typo != char:
time.sleep(base_interval + random.uniform(-variability, variability))
pyautogui.press('backspace')
pyautogui.write(char)
# Check for "dot followed by space" or "comma followed by space"
if (char == '.' or char == ',') and i + 1 < len(text) and text[i + 1] == ' ':
time.sleep(pause_multiplier * pyautogui.PAUSE)
i += 1
# Function to slightly vary pyautogui.PAUSE with a lower floor
def vary_pause(base_pause, variability, lower_floor):
return max(lower_floor, base_pause + random.uniform(-variability, variability))
# Function to introduce random pauses
def random_pause(chance, min_duration, max_duration):
if random.random() < chance:
time.sleep(random.uniform(min_duration, max_duration))
# Step 1: Get text from the clipboard
clipboard_text = pyperclip.paste()
# Step 2: Remove multiple newlines at the end, if existing
clipboard_text = clipboard_text.rstrip('\n')
# Step 3: Split the text into lines
lines = clipboard_text.split('\n')
# Step 4: Type the modified text
pyautogui.hotkey('alt', 'tab', interval=0.1)
# Give some time to focus on the textarea
time.sleep(1)
base_pause = 0.06 # Base pause between actions
pause_variability = 0.05 # Variability for the pause
pause_multiplier = 3
typo_probability = 0.03 # 3% chance of a typo
lower_floor = 0.05 # Minimum pause duration
# Start the interrupt listener thread
interrupt_thread = threading.Thread(target=listen_for_interrupt)
interrupt_thread.start()
start_time = time.time()
for i, line in enumerate(lines):
line_start_time = time.time()
pyautogui.PAUSE = vary_pause(base_pause, pause_variability, lower_floor)
human_typing(line, pyautogui.PAUSE, 0.001, pause_multiplier, typo_probability)
if interrupt_flag:
break
print(f"Typing line {i} time: {time.time() - line_start_time:.6f} seconds")
# Introduce random pauses to simulate thinking
random_pause(0.1, 0.2, 0.5) # 10% chance of a pause between 0.2 and 0.5 seconds
if i < len(lines) - 1:
pyautogui.hotkey('shift', 'enter')
time.sleep(pause_multiplier * pyautogui.PAUSE)
# Add a noticeable pause before pressing Enter
time.sleep(1) # 1 second pause before pressing Enter
if not interrupt_flag:
print(f"Total typing time: {time.time() - start_time:.6f} seconds")
pyautogui.press('enter')
else:
print("Script interrupted by user.")
# Set typing_finished to True to stop the interrupt listener
typing_finished = True
interrupt_thread.join() # Ensure the listener thread has finished
pyautogui==0.9.53
pyperclip==1.8.2
keyboard==0.13.5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment