-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtypebot.py
More file actions
113 lines (98 loc) · 4 KB
/
typebot.py
File metadata and controls
113 lines (98 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
from selenium import webdriver
from datetime import datetime
import time
# A TypeBot for play.typeracer.com
# To customize configurations: modify config in main.py
class TypeBot:
def __init__(self, config):
self.config = config
self.driver = self.setup_driver(config)
self.url = 'http://play.typeracer.com/'
# Set up the web driver and return it
def setup_driver(self, config):
d = config['webdriver']
run_headless = config['run_headless']
if d == 'firefox':
options = webdriver.firefox.options.Options()
if run_headless:
options.add_argument('--headless')
return webdriver.Firefox(options=options)
else:
# Chrome as webdriver
options = webdriver.chrome.options.Options()
if run_headless:
options.add_argument('--headless')
return webdriver.Chrome(options=options)
# Run the bot
def run(self):
self.driver.get(self.url)
self.load_timeout()
if self.config['should_login']:
self.login(self.config['login_credentials'])
print("Logged in as " + self.config['login_credentials']['username'])
self.enter_race()
self.load_timeout()
text = self.get_text()
print("Text to type: " + text)
self.wait_for_start()
print("Race starting.")
time.sleep(self.config['start_delay'])
self.type(text)
print("Race ended.")
self.load_timeout()
if self.config['save_screenshot']:
self.save_ss()
self.driver.quit()
# Sleep for the webpage to load
def load_timeout(self):
time.sleep(self.config['load_timeout'])
# Save a screenshot at downloads
def save_ss(self):
path = datetime.now().strftime('downloads/SS%Y%m%d:%H%M%S.png')
self.driver.save_screenshot(path)
print("Screenshot saved at " + path)
# Type a string, character by character, in text input
def type(self, text):
text_input = self.driver.find_element_by_class_name('txtInput')
char_delay = self.char_delay(self.config['wpm'])
for char in text:
text_input.send_keys(char)
time.sleep(char_delay)
# Calculate the delay necessary for between each character given WPM
def char_delay(self, wpm):
# Accounts for the delay causedby key, sleep, etc
adj_wpm = wpm + (0.09*wpm)**1.4
return 60 / (adj_wpm * 5)
# Wait until the race starts (when text input is not disabled)
def wait_for_start(self):
text_input = self.driver.find_element_by_class_name('txtInput')
started = False
while not started:
time.sleep(0.1)
if not text_input.get_attribute('disabled'):
started = True
# Enter the race
def enter_race(self):
self.driver.find_element_by_partial_link_text('Enter a typing race').click()
# Fetch and parse the text elements into the text to be typed
def get_text(self):
elems = self.driver.find_elements_by_css_selector('span[unselectable="on"]')
# parse text
if len(elems) == 1:
return elems[0].text
# default method when not matching any special cases
text = ''
for i in range(len(elems)):
if i == len(elems)-1:
text += ' ' # before the last elem, there is a space in between
text += elems[i].text
return text.replace(' ,', ',')
# Login, if given the credentials
def login(self, credentials):
if credentials:
self.driver.find_element_by_link_text('Sign In').click()
self.driver.find_element_by_name('username').send_keys(credentials['username'])
self.driver.find_element_by_name('password').send_keys(credentials['password'])
self.driver.find_element_by_css_selector('button[class="gwt-Button"]').click()
else:
print("Login credentials not provided - using guest account.")