|
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 |