-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
198 lines (160 loc) · 8.1 KB
/
main.py
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import os
import threading
import wx
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.action_chains import ActionChains
import time
import random
import re
from bs4 import BeautifulSoup
class Bot:
def __init__(self):
self.driver = None
self.typing_event = threading.Event()
self.wpm = 0
self.error_rate = 0
self.website = "https://monkeytype.com"
def open_game_window(self):
chrome_options = webdriver.ChromeOptions()
chromedriver_path = ChromeDriverManager().install()
service = ChromeService(executable_path=chromedriver_path)
self.driver = webdriver.Chrome(service=service, options=chrome_options)
self.driver.get(self.website)
def html(self):
try:
if "monkeytype" in self.website:
result = self.driver.page_source.partition("""class="word active""")[2].partition("""class="keymap hidden""")[0]
result = re.sub("""class="word""", '> <', result)
x = re.findall(r"\>([a-zA-Z0-9,\. ])\<", result)
elif "typeracer" in self.website:
input_panel = self.driver.find_element(By.CLASS_NAME, "inputPanel")
spans = input_panel.find_elements(By.TAG_NAME, "span")
x = [span.text for span in spans if span.text.strip()]
x.append(' ')
else:
return []
return x
except Exception as e:
print("Error getting HTML:", e)
return []
def introduce_error(self, char):
character_set = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789, .'
if char == ' ':
return char
if random.random() < self.error_rate / 100:
return random.choice([c for c in character_set if c != char])
return char
def type_text(self):
while not self.typing_event.is_set():
try:
words = self.html()
if "monkeytype" in self.website:
while not self.typing_event.is_set():
try:
words = self.html()
for word in words:
for char in word:
if self.typing_event.is_set():
return
char = self.introduce_error(char)
start_time = time.time()
webdriver.ActionChains(self.driver).send_keys(char).perform()
end_time = time.time()
character_time = end_time - start_time
time.sleep(max(0, ((60 / (self.wpm * 5)) - character_time)))
except Exception as e:
print("Error typing text:", e)
break
elif "typeracer" in self.website:
input_box = self.driver.find_element(By.CSS_SELECTOR, "input.txtInput")
input_box.click()
table = self.driver.find_element(By.CSS_SELECTOR, "table.inputPanel")
inner_html = self.driver.execute_script("return arguments[0].innerHTML;", table)
soup = BeautifulSoup(inner_html, 'html.parser')
combined_text = ''
spans = soup.find_all('span')
for span in spans:
combined_text += span.get_text()
print(f"Combined text: '{combined_text}'")
for char in combined_text:
if self.typing_event.is_set():
return
char = self.introduce_error(char)
ActionChains(self.driver).send_keys(char).perform()
time.sleep(60 / (self.wpm * 5))
except Exception as e:
print("Error typing text:", e)
break
def start_typing(self):
self.typing_event.clear()
threading.Thread(target=self.type_text).start()
def stop_typing(self):
self.typing_event.set()
class MyFrame(wx.Frame):
def __init__(self, parent, title):
super(MyFrame, self).__init__(parent, title=title, size=(400, 500))
panel = wx.Panel(self)
panel.SetBackgroundColour(wx.Colour(26, 35, 43))
vbox = wx.BoxSizer(wx.VERTICAL)
self.bot = Bot()
open_game_btn = wx.Button(panel, label='Open Game', size=(150, 40))
open_game_btn.SetBackgroundColour(wx.Colour(26, 35, 43))
open_game_btn.SetForegroundColour(wx.Colour(255, 255, 255))
open_game_btn.Bind(wx.EVT_BUTTON, self.on_open_game)
open_game_btn.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
vbox.Add(open_game_btn, 0, wx.CENTER | wx.TOP | wx.BOTTOM, 20)
self.website_choice = wx.Choice(panel, choices=["Monkeytype", "TypeRacer"], size=(150, -1))
self.website_choice.SetSelection(0)
vbox.Add(self.website_choice, 0, wx.EXPAND | wx.ALL, 5)
wpm_label = wx.StaticText(panel, label="Words per Minute (WPM):")
wpm_label.SetForegroundColour(wx.Colour(255, 255, 255))
wpm_label.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
vbox.Add(wpm_label, 0, wx.EXPAND | wx.ALL, 5)
self.wpm_text = wx.TextCtrl(panel, size=(150, -1))
self.wpm_text.SetBackgroundColour(wx.Colour(26, 35, 43))
self.wpm_text.SetForegroundColour(wx.Colour(255, 255, 255))
vbox.Add(self.wpm_text, 0, wx.EXPAND | wx.ALL, 5)
error_label = wx.StaticText(panel, label="Human Error (%):")
error_label.SetForegroundColour(wx.Colour(255, 255, 255))
error_label.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
vbox.Add(error_label, 0, wx.EXPAND | wx.ALL, 5)
self.error_text = wx.TextCtrl(panel, size=(150, -1))
self.error_text.SetBackgroundColour(wx.Colour(26, 35, 43))
self.error_text.SetForegroundColour(wx.Colour(255, 255, 255))
vbox.Add(self.error_text, 0, wx.EXPAND | wx.ALL, 5)
start_btn = wx.Button(panel, label='Start Typing', size=(150, 40))
start_btn.SetBackgroundColour(wx.Colour(26, 35, 43))
start_btn.SetForegroundColour(wx.Colour(255, 255, 255))
start_btn.Bind(wx.EVT_BUTTON, self.on_start_typing)
start_btn.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
vbox.Add(start_btn, 0, wx.CENTER | wx.TOP | wx.BOTTOM, 20)
stop_btn = wx.Button(panel, label='Stop Typing', size=(150, 40))
stop_btn.SetBackgroundColour(wx.Colour(26, 35, 43))
stop_btn.SetForegroundColour(wx.Colour(255, 255, 255))
stop_btn.Bind(wx.EVT_BUTTON, self.on_stop_typing)
stop_btn.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
vbox.Add(stop_btn, 0, wx.CENTER | wx.TOP | wx.BOTTOM, 20)
panel.SetSizer(vbox)
def on_open_game(self, event):
if self.website_choice.GetStringSelection() == "Monkeytype":
self.bot.website = "https://monkeytype.com"
elif self.website_choice.GetStringSelection() == "Typeracer":
self.bot.website = "https://play.typeracer.com"
self.bot.open_game_window()
def on_start_typing(self, event):
wpm = int(self.wpm_text.GetValue())
error_rate = int(self.error_text.GetValue())
self.bot.wpm = wpm
self.bot.error_rate = error_rate
self.bot.start_typing()
def on_stop_typing(self, event):
self.bot.stop_typing()
app = wx.App(False)
frame = MyFrame(None, 'Typing Bot')
frame.SetForegroundColour(wx.Colour(29, 206, 38))
frame.Show(True)
app.MainLoop()