symkey/playback.py

97 lines
2.3 KiB
Python

import argparse
import keyboard
import logging
import mouse
import pickle
import threading
import time
LOGGER = logging.getLogger("playback")
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument(
"-d", "--delay",
default=5,
type=int,
help="Seconds to wait before replay."
)
parser.add_argument(
"-i", "--input",
default="dump.capture",
help="Name of the file to replay from."
)
parser.add_argument(
"--verbose",
action="store_true",
help="Show verbose messages."
)
args = parser.parse_args()
logging.basicConfig(
level = logging.DEBUG if args.verbose else logging.INFO
)
_do_delay(args.delay)
events = _load_events(args.input)
_play_events(events)
def _play_events(events) -> None:
LOGGER.info("Playback started.")
key_state = keyboard.stash_state()
last_time = None
for event in events:
if last_time is not None:
to_sleep = event.time - last_time
if to_sleep > 0:
time.sleep(to_sleep)
last_time = event.time
if isinstance(event, keyboard.KeyboardEvent):
_play_event_keyboard(event)
elif any([
isinstance(event, mouse.ButtonEvent),
isinstance(event, mouse.MoveEvent),
isinstance(event, mouse.WheelEvent),
]):
_play_event_mouse(event)
else:
raise ValueError(f"Not a recognized event {event}")
keyboard.restore_modifiers(key_state)
LOGGER.info("Done.")
def _play_event_keyboard(event) -> None:
LOGGER.debug("Key %s", event)
key = event.scan_code or event.name
keyboard.press(key) if event.event_type == keyboard.KEY_DOWN else keyboard.release(key)
def _play_event_mouse(event) -> None:
LOGGER.debug("Mouse %s", event)
if isinstance(event, mouse.ButtonEvent):
if event.event_type == mouse.UP:
mouse.release(event.button)
else:
mouse.press(event.button)
elif isinstance(event, mouse.MoveEvent):
mouse.move(event.x, event.y, absolute=True)
# mouse.move(event.x, event.y)
elif isinstance(event, mouse.WheelEvent):
mouse.wheel(event.delta)
def _do_delay(delay: int) -> None:
if not delay:
return
print("\n")
for i in range(delay):
print(f"\rStarting in {delay-i} seconds")
time.sleep(1)
def _load_events(filename: str):
with open(filename, "rb") as input_:
events = pickle.load(input_)
LOGGER.debug("Loaded %s", filename)
return events
if __name__ == "__main__":
main()