@@ -46,6 +46,7 @@ def get_pixel_rgb(x, y):
4646controller = KeyboardController ()
4747current_chars = 0
4848current_percent = 0
49+ controller_typing = False # Flag to ignore synthetic keypresses
4950
5051def interruptible_sleep (duration ):
5152 global copypastaing
@@ -106,6 +107,20 @@ def split_sentences(filepath, max_length=60, disable_space_breaking=False, disab
106107pause_event = threading .Event ()
107108pause_event .set () # Start as running
108109
110+ def safe_type (text ):
111+ """Type text while flagging to ignore synthetic keypresses"""
112+ global controller_typing
113+ controller_typing = True
114+ controller .type (text )
115+ controller_typing = False
116+
117+ def safe_tap (key ):
118+ """Tap key while flagging to ignore synthetic keypresses"""
119+ global controller_typing
120+ controller_typing = True
121+ controller .tap (key )
122+ controller_typing = False
123+
109124def replace_emojis (text ):
110125 # Emoji unicode ranges
111126 emoji_pattern = re .compile (
@@ -128,7 +143,7 @@ def replace_emojis(text):
128143
129144def copypasta (id , prepare = False , disable_space_breaking = False , disable_finish_text = False , disable_line_breaks = False ):
130145 time .sleep (2 )
131- global ids , copypastaing , filepaths , controller , pause_event , current_chars , current_percent
146+ global ids , copypastaing , filepaths , controller , pause_event , current_chars , current_percent , controller_typing
132147 if id in ids :
133148 index = ids .index (id )
134149 filepath = filepaths [index ]
@@ -147,33 +162,33 @@ def copypasta(id, prepare=False, disable_space_breaking=False, disable_finish_te
147162 # Extract just the copypastas/filename.txt part for display
148163 path_obj = Path (filepath )
149164 relative_path = f"copypastas/{ path_obj .name } "
150- controller . tap (Key .enter )
165+ safe_tap (Key .enter )
151166 interruptible_sleep (0.1 )
152- controller . type (f"Arras Copypasta Utility [ACU] > v02.04.11-beta.4 < loading" )
167+ safe_type (f"Arras Copypasta Utility [ACU] > v02.04.11-beta.4 < loading" )
153168 interruptible_sleep (0.1 )
154169 for _ in range (2 ):
155- controller . tap (Key .enter )
170+ safe_tap (Key .enter )
156171 interruptible_sleep (0.1 )
157- controller . type (f"Filepath: > [.../{ relative_path } ] < | Loaded > { leng } chars <" )
172+ safe_type (f"Filepath: > [.../{ relative_path } ] < | Loaded > { leng } chars <" )
158173 interruptible_sleep (0.1 )
159174 for _ in range (2 ):
160- controller . tap (Key .enter )
175+ safe_tap (Key .enter )
161176 interruptible_sleep (0.1 )
162- controller . type (f"Size: > [{ file_size_kb :.2f} KB] < | Time taken > [{ round ((end - start )* 1000 , 3 )} ms] <" )
177+ safe_type (f"Size: > [{ file_size_kb :.2f} KB] < | Time taken > [{ round ((end - start )* 1000 , 3 )} ms] <" )
163178 interruptible_sleep (0.1 )
164- controller . tap (Key .enter )
179+ safe_tap (Key .enter )
165180 interruptible_sleep (10 )
166181 endf = False
167182 for sentence in sentences :
168183 if not copypastaing :
169184 break
170185 pause_event .wait () # Wait here if paused
171- controller . tap (Key .enter )
186+ safe_tap (Key .enter )
172187 interruptible_sleep (0.1 )
173188 sentence_no_emoji = replace_emojis (sentence )
174- controller . type (sentence_no_emoji )
189+ safe_type (sentence_no_emoji )
175190 interruptible_sleep (0.1 )
176- controller . tap (Key .enter )
191+ safe_tap (Key .enter )
177192 pos += len (sentence_no_emoji )
178193 current_chars = pos
179194 current_percent = (current_chars / leng ) * 100 if leng > 0 else 0
@@ -184,58 +199,62 @@ def copypasta(id, prepare=False, disable_space_breaking=False, disable_finish_te
184199 percent_typed = (chars_typed / leng ) * 100 if leng > 0 else 0
185200 if not endf : # Force stop by Escape
186201 print (f"Forced stop at > [{ chars_typed } ] characters [{ percent_typed :.2f} %]" )
187- controller . tap (Key .enter )
202+ safe_tap (Key .enter )
188203 interruptible_sleep (0.1 )
189- controller . type (f"Forced stop at > [{ chars_typed } ] characters [{ percent_typed :.2f} %]" )
204+ safe_type (f"Forced stop at > [{ chars_typed } ] characters [{ percent_typed :.2f} %]" )
190205 interruptible_sleep (0.1 )
191206 else :
192207 if not disable_finish_text :
193208 print (f"Copypasta of > [{ leng } ] characters < finished" )
194- controller . tap (Key .enter )
209+ safe_tap (Key .enter )
195210 interruptible_sleep (0.1 )
196- controller . type (f"Copypasta of > [{ leng } ] characters < finished" )
211+ safe_type (f"Copypasta of > [{ leng } ] characters < finished" )
197212 interruptible_sleep (0.1 )
198213 else :
199214 print (f"Copypasta of > [{ leng } ] characters < finished (without finish text)" )
200215 if not disable_finish_text :
201- controller . tap (Key .enter )
216+ safe_tap (Key .enter )
202217 interruptible_sleep (0.1 )
203218 time .sleep (3.5 )
204- controller . tap (Key .enter )
219+ safe_tap (Key .enter )
205220 interruptible_sleep (0.1 )
206221 print (f"Time taken: > [{ round (1000 * (time .time ()- start ), 3 )} ms] <" )
207- controller . type (f"Time taken: > [{ round (1000 * (time .time ()- start ), 3 )} ms] <" )
222+ safe_type (f"Time taken: > [{ round (1000 * (time .time ()- start ), 3 )} ms] <" )
208223 interruptible_sleep (0.1 )
209- controller . tap (Key .enter )
224+ safe_tap (Key .enter )
210225 interruptible_sleep (0.1 )
211226 # Do not exit here; let the thread finish
212227 copypastaing = False
213228
214229def on_press (key ):
215- global copypastaing , pause_event , current_chars , current_percent , controller
230+ global copypastaing , pause_event , current_chars , current_percent , controller , controller_typing
216231 try :
232+ # Ignore synthetic keypresses from the controller
233+ if controller_typing :
234+ return
235+
217236 if key == keyboard .Key .esc :
218237 copypastaing = False
219238 elif hasattr (key , 'char' ) and key .char == 'p' and copypastaing :
220239 if pause_event .is_set ():
221240 pause_event .clear ()
222241 time .sleep (3.3 )
223242 print (f"Paused at > [{ current_chars } ] < chars | > [{ current_percent :.2f} %] <" )
224- controller . tap (Key .enter )
243+ safe_tap (Key .enter )
225244 interruptible_sleep (0.1 )
226- controller . type (f"Paused at > [{ current_chars } ] < chars | > [{ current_percent :.2f} %] <" )
245+ safe_type (f"Paused at > [{ current_chars } ] < chars | > [{ current_percent :.2f} %] <" )
227246 interruptible_sleep (0.1 )
228- controller . tap (Key .enter )
247+ safe_tap (Key .enter )
229248 interruptible_sleep (0.1 )
230249 else :
231250 pause_event .set ()
232251 time .sleep (3.3 )
233252 print (f"Resumed at > [{ current_chars } ] < chars | > [{ current_percent :.2f} %] <" )
234- controller . tap (Key .enter )
253+ safe_tap (Key .enter )
235254 interruptible_sleep (0.1 )
236- controller . type (f"Resumed at > [{ current_chars } ] < chars | > [{ current_percent :.2f} %] <" )
255+ safe_type (f"Resumed at > [{ current_chars } ] < chars | > [{ current_percent :.2f} %] <" )
237256 interruptible_sleep (0.1 )
238- controller . tap (Key .enter )
257+ safe_tap (Key .enter )
239258 interruptible_sleep (0.1 )
240259 except UnicodeDecodeError :
241260 print ("UnicodeDecodeError: Non-standard key (emoji?) pressed. Ignored." )
0 commit comments