1+ import keyboard
2+ import mouse
3+ import json
4+ import time
5+ from pynput .mouse import Controller as MouseController
6+ from pynput .keyboard import Controller as KeyboardController
7+ from datetime import datetime
8+ import os
9+
10+ class MacroRecorder :
11+ def __init__ (self ):
12+ self .recording = False
13+ self .events = []
14+ self .mouse = MouseController ()
15+ self .keyboard = KeyboardController ()
16+ self .start_time = None
17+ self .macro_dir = "macros"
18+
19+ # Create macros directory if it doesn't exist
20+ if not os .path .exists (self .macro_dir ):
21+ os .makedirs (self .macro_dir )
22+
23+ def start_recording (self ):
24+ print ("Recording started... Press 'Esc' to stop recording." )
25+ self .recording = True
26+ self .events = []
27+ self .start_time = time .time ()
28+
29+ # Start listening to events
30+ keyboard .hook (self .on_keyboard_event )
31+ mouse .hook (self .on_mouse_event )
32+
33+ def stop_recording (self ):
34+ self .recording = False
35+ keyboard .unhook_all ()
36+ mouse .unhook_all ()
37+ print ("Recording stopped." )
38+ return self .events
39+
40+ def on_keyboard_event (self , event ):
41+ if event .event_type == 'down' :
42+ if event .name == 'esc' and self .recording :
43+ self .stop_recording ()
44+ return
45+
46+ current_time = time .time () - self .start_time
47+ self .events .append ({
48+ 'type' : 'keyboard' ,
49+ 'event' : 'press' ,
50+ 'key' : event .name ,
51+ 'time' : current_time
52+ })
53+
54+ def on_mouse_event (self , event ):
55+ if not self .recording :
56+ return
57+
58+ current_time = time .time () - self .start_time
59+ if hasattr (event , 'button' ):
60+ self .events .append ({
61+ 'type' : 'mouse' ,
62+ 'event' : event .event_type ,
63+ 'button' : event .button ,
64+ 'position' : (event .x , event .y ),
65+ 'time' : current_time
66+ })
67+ elif hasattr (event , 'x' ):
68+ self .events .append ({
69+ 'type' : 'mouse' ,
70+ 'event' : 'move' ,
71+ 'position' : (event .x , event .y ),
72+ 'time' : current_time
73+ })
74+
75+ def save_macro (self , name = None ):
76+ if not name :
77+ name = datetime .now ().strftime ("%Y%m%d_%H%M%S" )
78+
79+ filename = os .path .join (self .macro_dir , f"{ name } .json" )
80+ with open (filename , 'w' ) as f :
81+ json .dump (self .events , f )
82+ print (f"Macro saved as: { filename } " )
83+ return filename
84+
85+ def load_macro (self , filename ):
86+ with open (filename , 'r' ) as f :
87+ self .events = json .load (f )
88+ return self .events
89+
90+ def play_macro (self , events = None ):
91+ if events is None :
92+ events = self .events
93+
94+ if not events :
95+ print ("No events to play!" )
96+ return
97+
98+ print ("Playing macro in 3 seconds..." )
99+ time .sleep (3 )
100+
101+ last_time = 0
102+ for event in events :
103+ # Wait for the appropriate time
104+ time_to_wait = event ['time' ] - last_time
105+ if time_to_wait > 0 :
106+ time .sleep (time_to_wait )
107+
108+ if event ['type' ] == 'keyboard' :
109+ if event ['event' ] == 'press' :
110+ keyboard .press (event ['key' ])
111+ keyboard .release (event ['key' ])
112+
113+ elif event ['type' ] == 'mouse' :
114+ if event ['event' ] == 'move' :
115+ self .mouse .position = event ['position' ]
116+ elif event ['event' ] == 'click' :
117+ mouse .move (event ['position' ][0 ], event ['position' ][1 ])
118+ mouse .click (event ['button' ])
119+ elif event ['event' ] == 'double click' :
120+ mouse .move (event ['position' ][0 ], event ['position' ][1 ])
121+ mouse .double_click (event ['button' ])
122+
123+ last_time = event ['time' ]
124+
125+ def main ():
126+ recorder = MacroRecorder ()
127+ print ("Macro Recorder" )
128+ print ("Press 'F7' to start recording" )
129+ print ("Press 'F8' to play last recorded macro" )
130+ print ("Press 'F9' to save last recorded macro" )
131+ print ("Press 'Ctrl+Q' to quit" )
132+
133+ def on_f7 ():
134+ recorder .start_recording ()
135+
136+ def on_f8 ():
137+ if recorder .events :
138+ recorder .play_macro ()
139+ else :
140+ print ("No macro recorded yet!" )
141+
142+ def on_f9 ():
143+ if recorder .events :
144+ recorder .save_macro ()
145+ else :
146+ print ("No macro recorded yet!" )
147+
148+ keyboard .add_hotkey ('f7' , on_f7 )
149+ keyboard .add_hotkey ('f8' , on_f8 )
150+ keyboard .add_hotkey ('f9' , on_f9 )
151+
152+ keyboard .wait ('ctrl+q' )
153+ print ("Program terminated." )
154+
155+ if __name__ == "__main__" :
156+ main ()
0 commit comments