Skip to content

Rewrite loop to be non-blocking and non-destructive #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 26, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 60 additions & 61 deletions adafruit_ducky.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
from adafruit_hid.keycode import Keycode

try:
from typing import Optional
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_base import KeyboardLayoutBase
except ImportError:
Expand Down Expand Up @@ -128,76 +127,76 @@ def __init__(
self.layout = layout
self.lines = []
self.default_delay = 0
self.last = 0
self.prev_line = None
self.next_index = 0
self.wait_until = 0
self.repeat = 0

with open(filename, "r") as duckyscript:
for line in duckyscript:
self.lines.append(line[:-1].rstrip("\r"))
line = line.lstrip(" ").rstrip("\n\r")
if len(line) > 0:
self.lines.append(line)

def loop( # pylint: disable=too-many-return-statements
self, line: Optional[str] = None
self,
) -> bool: # pylint: disable=too-many-branches
"""Function that sends a line of the DuckyScript file over hid every time it is called"""
if line is None:
try:
line = self.lines[0]
except IndexError:
print("Done!")
return False
if len(line) != 0:
words = line.split(" ", 1)
start = words[0]
if start == "REM":
print(words[1])
time.sleep(self.default_delay)
self.lines.pop(0)
return True

if start in ("DEFAULT_DELAY", "DEFAULTDELAY"):
self.default_delay = int(words[1]) / 1000
time.sleep(self.default_delay)
self.last = self.lines[0]
self.lines.pop(0)
return True

if start == "DELAY":
time.sleep(int(words[1]) / 1000)
time.sleep(self.default_delay)
self.last = self.lines[0]
self.lines.pop(0)
return True

if start == "STRING":
self.layout.write(words[1])
time.sleep(self.default_delay)
self.last = self.lines[0]
self.lines.pop(0)
return True

if start == "REPEAT":
print(int(words[1]))
for _ in range(int(words[1])):
self.lines.insert(0, self.last)
self.loop()
self.last = self.lines[0]
self.lines.pop(0)
return True

self.write_key(start)
if len(words) == 1:
self.keyboard.release_all()
time.sleep(self.default_delay)
self.last = self.lines[0]
self.lines.pop(0)
return True
if len(words[1]):
self.loop(line=words[1])

now = time.monotonic_ns()
if now < self.wait_until:
return True

try:
if self.repeat > 0:
self.repeat -= 1
line = self.prev_line
else:
self.keyboard.release_all()
return True
line = self.lines[self.next_index]
self.next_index += 1
except IndexError:
print(" DONE!")
self.prev_line = None
self.next_index = 0
return False

words = line.split(" ", 1)
start = words[0]

if start == "REPEAT":
self.repeat = int(words[1])
return True

self.prev_line = line

# print(f" {line}")

if start == "REM":
# print(words[1])
return True

self.wait_until = now + self.default_delay

if start in ("DEFAULT_DELAY", "DEFAULTDELAY"):
self.wait_until -= self.default_delay
self.default_delay = int(words[1]) * 1000000
self.wait_until += self.default_delay
return True

if start == "DELAY":
self.wait_until += int(words[1]) * 1000000
return True

if start == "STRING":
self.layout.write(words[1])
return True

self.write_key(start)
if len(words) > 1:
for key in filter(None, words[1].split(" ")):
self.write_key(key)

self.keyboard.release_all()
time.sleep(self.default_delay)
return True

def write_key(self, start: str) -> None:
Expand Down