|
@@ -1,13 +1,13 @@
|
|
|
|
|
|
from sys import argv as _argv
|
|
from sys import argv as _argv
|
|
|
|
|
|
-from os import name as _OS_NAME
|
|
|
|
-from os import listdir as _listdir
|
|
|
|
|
|
+from os import name as _OS_NAME, environ as _env
|
|
|
|
+from os import listdir as _listdir, mkdir as _mkdir, chown as _chown
|
|
from os.path import exists as _exists, join as _join, isdir as _isdir
|
|
from os.path import exists as _exists, join as _join, isdir as _isdir
|
|
|
|
|
|
from time import sleep as _sleep
|
|
from time import sleep as _sleep
|
|
|
|
|
|
-from typing import Dict as _Dict, Tuple as _Tuple
|
|
|
|
|
|
+from typing import Dict as _Dict, Tuple as _Tuple, List as _List
|
|
|
|
|
|
try:
|
|
try:
|
|
from click import echo as _echo, style as _style
|
|
from click import echo as _echo, style as _style
|
|
@@ -25,16 +25,16 @@ from toml import load as _toml_load
|
|
from asyncio import run as _run, sleep as _asleep
|
|
from asyncio import run as _run, sleep as _asleep
|
|
from asyncio.tasks import gather as _task_group
|
|
from asyncio.tasks import gather as _task_group
|
|
|
|
|
|
-def print_err(msg: str):
|
|
|
|
|
|
+def _print_err(msg: str):
|
|
_echo(_style("ERROR", fg="bright_red") + " " + msg)
|
|
_echo(_style("ERROR", fg="bright_red") + " " + msg)
|
|
|
|
|
|
-def print_warn(msg: str):
|
|
|
|
|
|
+def _print_warn(msg: str):
|
|
_echo(_style("WARN ", fg="bright_yellow") + " " + msg)
|
|
_echo(_style("WARN ", fg="bright_yellow") + " " + msg)
|
|
|
|
|
|
-def print_ok(msg: str):
|
|
|
|
|
|
+def _print_ok(msg: str):
|
|
_echo(_style(" OK ", fg="bright_green") + " " + msg)
|
|
_echo(_style(" OK ", fg="bright_green") + " " + msg)
|
|
|
|
|
|
-def print_info(msg: str):
|
|
|
|
|
|
+def _print_info(msg: str):
|
|
print(" " + msg)
|
|
print(" " + msg)
|
|
|
|
|
|
def _keyboard_output(msg: str, delay: int=50, hold: int=20):
|
|
def _keyboard_output(msg: str, delay: int=50, hold: int=20):
|
|
@@ -57,538 +57,238 @@ elif "windows" in os_name or "nt" in os_name:
|
|
elif "darwin" in os_name:
|
|
elif "darwin" in os_name:
|
|
platform = "MACOS"
|
|
platform = "MACOS"
|
|
else:
|
|
else:
|
|
- print_err("Platform 'Linux', 'Windows' or 'MacOS' expected")
|
|
|
|
- print_info(f"Platform: {_OS_NAME}")
|
|
|
|
|
|
+ _print_err("Platform 'Linux', 'Windows' or 'MacOS' expected")
|
|
|
|
+ _print_info(f"Platform: {_OS_NAME}")
|
|
exit()
|
|
exit()
|
|
|
|
|
|
-class ActionKind(int):
|
|
|
|
- """
|
|
|
|
- Actions can be defined to do different things
|
|
|
|
-
|
|
|
|
- Because of this complexity, Actions are separated into
|
|
|
|
-
|
|
|
|
- Mouse Actions:
|
|
|
|
- - Click (Press mouse button down, then release mouse button up)
|
|
|
|
- - Click Down (Press mouse button down, never releasing up)
|
|
|
|
-
|
|
|
|
- Keyboard Actions:
|
|
|
|
- - Key (Press key down, then release key up)
|
|
|
|
- - Key Down (Press key down, never releasing up)
|
|
|
|
-
|
|
|
|
- Mirror Actions will typically be one of the above (mouse or keyboard actions, typically Click or Key)
|
|
|
|
-
|
|
|
|
- They Mirror a key's state, if it's down: pressing or clicking down, if it's up: releasing up
|
|
|
|
- """
|
|
|
|
- NONE = 0
|
|
|
|
- """ Invalid Action state """
|
|
|
|
- CLICK = 1
|
|
|
|
- """ Mouse Action, Click (Press mouse button down, then release mouse button up) """
|
|
|
|
- CLICK_DOWN = 2
|
|
|
|
- """ Mouse Action, Click Down (Press mouse button down, never releasing up) """
|
|
|
|
- KEY = 3
|
|
|
|
- """ Keyboard Action, Key (Press key down, then release key up) """
|
|
|
|
- KEY_DOWN = 4
|
|
|
|
- """ Keyboard Action, Key Down (Press key down, never releasing up) """
|
|
|
|
- MIRROR = 5
|
|
|
|
- """ Mirror Actions will typically be one of the above (mouse or keyboard actions, typically Click or Key)
|
|
|
|
-
|
|
|
|
- They Mirror a key's state, if it's down: pressing or clicking down, if it's up: releasing up
|
|
|
|
- """
|
|
|
|
- def __init__(self, kind: str | int):
|
|
|
|
- # Unlike most __init__ methods, this converts a string into a ActionKind (returning the ActionKind)
|
|
|
|
- if type(kind) is str:
|
|
|
|
- k = kind.lower().strip()
|
|
|
|
- if k == "click":
|
|
|
|
- return ActionKind.CLICK
|
|
|
|
- elif k == "click down":
|
|
|
|
- return ActionKind.CLICK_DOWN
|
|
|
|
- elif k == "key":
|
|
|
|
- return ActionKind.KEY
|
|
|
|
- elif k == "key down":
|
|
|
|
- return ActionKind.KEY_DOWN
|
|
|
|
- elif k == "mirror":
|
|
|
|
- return ActionKind.MIRROR
|
|
|
|
- else:
|
|
|
|
- return ActionKind.NONE
|
|
|
|
- elif type(kind) is int:
|
|
|
|
- if kind == 1:
|
|
|
|
- return ActionKind.CLICK
|
|
|
|
- elif kind == 2:
|
|
|
|
- return ActionKind.CLICK_DOWN
|
|
|
|
- elif kind == 3:
|
|
|
|
- return ActionKind.KEY
|
|
|
|
- elif kind == 4:
|
|
|
|
- return ActionKind.KEY_DOWN
|
|
|
|
- elif kind == 5:
|
|
|
|
- return ActionKind.MIRROR
|
|
|
|
- else:
|
|
|
|
- return ActionKind.NONE
|
|
|
|
-
|
|
|
|
- def __str__(self) -> str:
|
|
|
|
- # Converts the ActionKind into a string, mostly for debugging
|
|
|
|
- if self == ActionKind.CLICK:
|
|
|
|
- return "click"
|
|
|
|
- elif self == ActionKind.CLICK_DOWN:
|
|
|
|
- return "click down"
|
|
|
|
- elif self == ActionKind.KEY:
|
|
|
|
- return "key"
|
|
|
|
- elif self == ActionKind.KEY_DOWN:
|
|
|
|
- return "key down"
|
|
|
|
- elif self == ActionKind.MIRROR:
|
|
|
|
- return "mirror"
|
|
|
|
- else:
|
|
|
|
- return f"<ActionKind {int(self)}>"
|
|
|
|
-
|
|
|
|
- def is_mouse(self) -> bool:
|
|
|
|
- """ Is this Action a Mouse Action
|
|
|
|
-
|
|
|
|
- Mouse Actions:
|
|
|
|
- - Click (Press mouse button down, then release mouse button up)
|
|
|
|
- - Click Down (Press mouse button down, never releasing up)
|
|
|
|
- """
|
|
|
|
- return self == ActionKind.CLICK or self == ActionKind.CLICK_DOWN
|
|
|
|
-
|
|
|
|
- def is_keyboard(self) -> bool:
|
|
|
|
- """ Is this Action a Keyboard Action
|
|
|
|
-
|
|
|
|
- Keyboard Actions:
|
|
|
|
- - Key (Press key down, then release key up)
|
|
|
|
- - Key Down (Press key down, never releasing up)
|
|
|
|
- """
|
|
|
|
- return self == ActionKind.KEY or self == ActionKind.KEY_DOWN
|
|
|
|
-
|
|
|
|
-class Action:
|
|
|
|
- name: str
|
|
|
|
- """ Action's can be named to describe and clarify what the Action should do
|
|
|
|
-
|
|
|
|
- i.e. 'auto click' for some Auto Clicker, 'shop' for something that opens a shop (such as '/shop')
|
|
|
|
- """
|
|
|
|
- kind: ActionKind
|
|
|
|
- """ The Kind of Action to do
|
|
|
|
-
|
|
|
|
- See tyrell.ActionKind
|
|
|
|
- """
|
|
|
|
- extra: _Dict
|
|
|
|
- enabled: bool
|
|
|
|
- delay: int
|
|
|
|
- max_delay: int
|
|
|
|
- def __init__(self, name: str, kind: str, extra: _Dict, on: bool=False, delay: int=0):
|
|
|
|
- self.name = name
|
|
|
|
- self.kind = ActionKind(kind)
|
|
|
|
- self.enabled = on
|
|
|
|
- self.delay = delay
|
|
|
|
- self.max_delay = delay
|
|
|
|
-
|
|
|
|
- def toggle(self) -> bool:
|
|
|
|
- self.enabled = not self.enabled
|
|
|
|
- return self.enabled
|
|
|
|
-
|
|
|
|
- def enable(self):
|
|
|
|
- self.enabled = True
|
|
|
|
-
|
|
|
|
- def disable(self):
|
|
|
|
- self.enabled = False
|
|
|
|
-
|
|
|
|
- def is_ticker(self) -> bool:
|
|
|
|
- """ Actions can be time based or not
|
|
|
|
-
|
|
|
|
- Tickers are: Actions time based will fire after a number of ticks (at a set delay, tick speed)
|
|
|
|
-
|
|
|
|
- All Actions not time based fire only when the selected "keybind" is pressed (where tickers use the "keybind" to toggle them on and off)
|
|
|
|
- """
|
|
|
|
- return self.max_delay != 0
|
|
|
|
-
|
|
|
|
- def is_mirror(self, key: str) -> bool:
|
|
|
|
- if self.kind != ActionKind.MIRROR:
|
|
|
|
- return False
|
|
|
|
- return key == self.extra["mirror"]
|
|
|
|
-
|
|
|
|
- def tick(self) -> bool:
|
|
|
|
- if not self.is_ticker():
|
|
|
|
- return False
|
|
|
|
- if not self.enabled:
|
|
|
|
- if self.delay != self.max_delay:
|
|
|
|
- self.delay = self.max_delay
|
|
|
|
- return False
|
|
|
|
- self.delay -= 1
|
|
|
|
- if self.delay <= 0:
|
|
|
|
- self.delay = self.max_delay
|
|
|
|
- return True
|
|
|
|
- return False
|
|
|
|
-
|
|
|
|
- def do(self, key: _Tuple[str, int], delay: int=50, hold: int=20):
|
|
|
|
- if not self.enabled:
|
|
|
|
- return
|
|
|
|
- d = delay
|
|
|
|
- h = hold
|
|
|
|
- if "delay" in self.extra:
|
|
|
|
- d = self.extra["delay"]
|
|
|
|
- if "hold" in self.extra:
|
|
|
|
- h = self.extra["hold"]
|
|
|
|
- if self.kind == ActionKind.CLICK:
|
|
|
|
- _mouse_output(self.extra["button"], d, h)
|
|
|
|
- elif self.kind == ActionKind.CLICK_DOWN:
|
|
|
|
- _mouse_down(button=self.extra["button"])
|
|
|
|
- elif self.kind == ActionKind.KEY:
|
|
|
|
- _keyboard_output(self.extra["write"], d, h)
|
|
|
|
- elif self.kind == ActionKind.KEY_DOWN:
|
|
|
|
- _key_down(self.extra["write"])
|
|
|
|
- elif self.kind == ActionKind.MIRROR:
|
|
|
|
- if key[1] == 0: # Up
|
|
|
|
- if "write" in self.extra: # Key Mirror
|
|
|
|
- _key_up(self.extra["write"])
|
|
|
|
- elif "button" in self.extra: # Mouse Mirror
|
|
|
|
- _mouse_up(button=self.extra["button"])
|
|
|
|
- elif key[1] == 1: # Down
|
|
|
|
- if "write" in self.extra: # Key Mirror
|
|
|
|
- _key_down(self.extra["write"])
|
|
|
|
- elif "button" in self.extra: # Mouse Mirror
|
|
|
|
- _mouse_down(button=self.extra["button"])
|
|
|
|
-
|
|
|
|
- def do_tick(self, delay: int=50, hold: int=20):
|
|
|
|
- if self.tick():
|
|
|
|
- self.do(delay, hold)
|
|
|
|
-
|
|
|
|
-class Tyrell:
|
|
|
|
- pass
|
|
|
|
-
|
|
|
|
-class OldAction():
|
|
|
|
|
|
+def _profile_pre_check(profile_name: str):
|
|
|
|
+ if profile_name.endswith(".toml"):
|
|
|
|
+ profile_name = profile_name.removesuffix(".toml")
|
|
|
|
+ if not _exists(profile_name):
|
|
|
|
+ _mkdir(profile_name)
|
|
|
|
+ if "SUDO_USER" in _env:
|
|
|
|
+ _chown(profile_name, int(_env['SUDO_UID']), int(_env['SUDO_GID']))
|
|
|
|
+ if not _exists(_join(profile_name, "keys")):
|
|
|
|
+ _mkdir(_join(profile_name, "keys"))
|
|
|
|
+ if "SUDO_USER" in _env:
|
|
|
|
+ _chown(_join(profile_name, "keys"), int(_env['SUDO_UID']), int(_env['SUDO_GID']))
|
|
|
|
+
|
|
|
|
+def _write_profile(profile_name: str):
|
|
|
|
+ if profile_name.endswith(".toml"):
|
|
|
|
+ profile_name = profile_name.removesuffix(".toml")
|
|
|
|
+ _profile_pre_check(profile_name)
|
|
|
|
+ with open(_join(profile_name, profile_name+".toml"), "w") as f:
|
|
|
|
+ f.writelines("\n".join([
|
|
|
|
+ '# Tyrell :: v0.1-dev :: More human than human',
|
|
|
|
+ '',
|
|
|
|
+ '# Placeholders',
|
|
|
|
+ '',
|
|
|
|
+ "# Enable '{name}', emitting profile name",
|
|
|
|
+ "placeholder_name = 'true'",
|
|
|
|
+ '',
|
|
|
|
+ '# Tick speed',
|
|
|
|
+ '# Value in milliseconds',
|
|
|
|
+ "# Defaults to 20 ticks per second",
|
|
|
|
+ "# Can't be overridden",
|
|
|
|
+ 'tick = 50',
|
|
|
|
+ '',
|
|
|
|
+ '# What is the key to activate/deactivate Tyrell',
|
|
|
|
+ "# This hotkey must be in the format, 'ctrl+shift+a' (user holds ctrl, shift and 'a' at once)",
|
|
|
|
+ "# Can't be overridden",
|
|
|
|
+ "activator = '`'",
|
|
|
|
+ '',
|
|
|
|
+ '# What is the key to display help',
|
|
|
|
+ "# This hotkey must be in the format, 'ctrl+shift+a' (user holds ctrl, shift and 'a' at once)",
|
|
|
|
+ "# Defaults to '?'",
|
|
|
|
+ "# Can't be overridden",
|
|
|
|
+ "helper = 'shift+/'",
|
|
|
|
+ '',
|
|
|
|
+ '# These can be overridden per key-bind',
|
|
|
|
+ '',
|
|
|
|
+ '# Delay between each keys',
|
|
|
|
+ '# Value in milliseconds',
|
|
|
|
+ 'delay = 50',
|
|
|
|
+ '',
|
|
|
|
+ '# Hold delay for each key',
|
|
|
|
+ '# Keys are sent like below:',
|
|
|
|
+ '# 1. key down',
|
|
|
|
+ '# 2. hold delay',
|
|
|
|
+ '# 3. key up',
|
|
|
|
+ '# 4. hold delay',
|
|
|
|
+ '# 5. delay (see above)',
|
|
|
|
+ '# 6. Repeat for keys',
|
|
|
|
+ '# Value in milliseconds',
|
|
|
|
+ 'hold = 20',
|
|
|
|
+ ]))
|
|
|
|
+ if "SUDO_USER" in _env:
|
|
|
|
+ _chown(_join(profile_name, profile_name+".toml"), int(_env['SUDO_UID']), int(_env['SUDO_GID']))
|
|
|
|
+
|
|
|
|
+def _write_example(profile_name: str):
|
|
|
|
+ if profile_name.endswith(".toml"):
|
|
|
|
+ profile_name = profile_name.removesuffix(".toml")
|
|
|
|
+ _profile_pre_check(profile_name)
|
|
|
|
+ with open(_join(profile_name, "keys", "example.toml"), "w") as f:
|
|
|
|
+ f.writelines("\n".join([
|
|
|
|
+ '# Example Key-bind',
|
|
|
|
+ '',
|
|
|
|
+ "# When 'h' is pressed, write 'Hello World!'",
|
|
|
|
+ '',
|
|
|
|
+ '# Key to trigger on',
|
|
|
|
+ "# This hotkey must be in the format, 'ctrl+shift+a' (user holds ctrl, shift and 'a' at once)",
|
|
|
|
+ "key = 'h'",
|
|
|
|
+ '',
|
|
|
|
+ '# Kind of action to perform',
|
|
|
|
+ '# click -> Click a mouse button',
|
|
|
|
+ '# click down -> Click a mouse button down, but never release up',
|
|
|
|
+ '# key -> Type the following keys, pressing each key',
|
|
|
|
+ '# key down -> Press the following keys down, never releasing them',
|
|
|
|
+ '# mirror -> When the mirror key is pressed down so is key or button, on release so are key or button',
|
|
|
|
+ '# See also example_mirror.toml',
|
|
|
|
+ "kind = 'key'",
|
|
|
|
+ '',
|
|
|
|
+ '# Type this',
|
|
|
|
+ "# This is required for 'key' and 'key down' kinds (Optional for 'mirror')",
|
|
|
|
+ "# This hotkey must be in the format, 'ctrl+shift+a' (user holds ctrl, shift and 'a' at once)",
|
|
|
|
+ "# This example will write 'Hello World!'",
|
|
|
|
+ "write = 'shift+h, e, l, l, o, space, shift+w, o, r, l, d, shift+1'",
|
|
|
|
+ '',
|
|
|
|
+ '# If this should repeat X number of ticks',
|
|
|
|
+ "# This is a simple example, it won't use this",
|
|
|
|
+ '# Assuming tick speed is 20ms, this would occur every second',
|
|
|
|
+ '#duration = 50',
|
|
|
|
+ '',
|
|
|
|
+ '# Use this mouse button',
|
|
|
|
+ "# This is a simple example, it won't use this",
|
|
|
|
+ "# This is required for 'click' and 'click down' kinds (Optional for 'mirror')",
|
|
|
|
+ "# There currently is 'left' or 'right'",
|
|
|
|
+ "#button = 'left'",
|
|
|
|
+ '',
|
|
|
|
+ '# Mirror key',
|
|
|
|
+ "# This is a simple example, it won't use this",
|
|
|
|
+ '# This is the key whose state will be mirrored',
|
|
|
|
+ '# See also example_mirror.toml',
|
|
|
|
+ '#',
|
|
|
|
+ "# This hotkey must be in the format, 'ctrl+shift+a' (user holds ctrl, shift and 'a' at once)",
|
|
|
|
+ "# This example will press 'g' when 'h' is down, and release 'g' when 'h' is up",
|
|
|
|
+ "#mirror = 'g'",
|
|
|
|
+ '',
|
|
|
|
+ '# Optional Overrides',
|
|
|
|
+ '',
|
|
|
|
+ '# Override delay between each keys',
|
|
|
|
+ '# Value in milliseconds',
|
|
|
|
+ 'delay = 50',
|
|
|
|
+ '',
|
|
|
|
+ '# Override hold delay for each key',
|
|
|
|
+ '# Keys are sent like below:',
|
|
|
|
+ '# 1. key down',
|
|
|
|
+ '# 2. hold delay',
|
|
|
|
+ '# 3. key up',
|
|
|
|
+ '# 4. hold delay',
|
|
|
|
+ '# 5. delay (see above)',
|
|
|
|
+ '# 6. Repeat for keys',
|
|
|
|
+ '# Value in milliseconds',
|
|
|
|
+ 'hold = 20',
|
|
|
|
+ ]))
|
|
|
|
+ if "SUDO_USER" in _env:
|
|
|
|
+ _chown(_join(profile_name, "keys", "example.toml"), int(_env['SUDO_UID']), int(_env['SUDO_GID']))
|
|
|
|
+
|
|
|
|
+def _write_example_mirror(profile_name: str):
|
|
|
|
+ if profile_name.endswith(".toml"):
|
|
|
|
+ profile_name = profile_name.removesuffix(".toml")
|
|
|
|
+ _profile_pre_check(profile_name)
|
|
|
|
+ with open(_join(profile_name, "keys", "example_mirror.toml"), "w") as f:
|
|
|
|
+ f.writelines("\n".join([
|
|
|
|
+ '# Example Mirror Key-bind',
|
|
|
|
+ '',
|
|
|
|
+ "# Press alt when 'w' is down, and release when 'w' is up",
|
|
|
|
+ "# Use 'z' to toggle on/off",
|
|
|
|
+ '',
|
|
|
|
+ '# Key to toggle',
|
|
|
|
+ "key = 'z'",
|
|
|
|
+ '',
|
|
|
|
+ '# Kind of event',
|
|
|
|
+ "kind = 'mirror'",
|
|
|
|
+ '',
|
|
|
|
+ '# Mirror what key',
|
|
|
|
+ "mirror = 'w'",
|
|
|
|
+ '',
|
|
|
|
+ '# When mirror is down, so will this',
|
|
|
|
+ '# When mirror is up, so will this',
|
|
|
|
+ "write = 'alt'",
|
|
|
|
+ '',
|
|
|
|
+ '# Or a mouse button could be configured',
|
|
|
|
+ "# But this example doesn't",
|
|
|
|
+ "#button = 'right'",
|
|
|
|
+ '',
|
|
|
|
+ '# You could override delay and hold',
|
|
|
|
+ '# Tyrell will turn them off for Mirror kinds automatically',
|
|
|
|
+ ]))
|
|
|
|
+ if "SUDO_USER" in _env:
|
|
|
|
+ _chown(_join(profile_name, "keys", "example_mirror.toml"), int(_env['SUDO_UID']), int(_env['SUDO_GID']))
|
|
|
|
+
|
|
|
|
+class Profile:
|
|
name: str
|
|
name: str
|
|
- kind: str
|
|
|
|
- extra: _Dict
|
|
|
|
- toggled: bool
|
|
|
|
- delay: int
|
|
|
|
- max_delay: int
|
|
|
|
- def __init__(self, name, kind, extra=None, toggled=False, delay=0):
|
|
|
|
- self.name = name
|
|
|
|
- self.kind = kind
|
|
|
|
- if extra is not None:
|
|
|
|
- self.extra = extra
|
|
|
|
- else:
|
|
|
|
- self.extra = {}
|
|
|
|
- self.toggled = toggled
|
|
|
|
- self.delay = delay
|
|
|
|
- self.max_delay = delay
|
|
|
|
-
|
|
|
|
- def toggle(self) -> bool:
|
|
|
|
- self.toggled = not self.toggled
|
|
|
|
- return self.toggled
|
|
|
|
-
|
|
|
|
- def tick(self) -> bool:
|
|
|
|
- if not self.toggled:
|
|
|
|
- if self.delay != self.max_delay:
|
|
|
|
- self.delay = self.max_delay
|
|
|
|
- return False
|
|
|
|
- if self.max_delay != 0:
|
|
|
|
- self.delay -= 1
|
|
|
|
- if self.delay <= 0:
|
|
|
|
- self.delay = self.max_delay
|
|
|
|
- return True
|
|
|
|
- return False
|
|
|
|
-
|
|
|
|
- def do(self, delay: int=50, hold: int=20):
|
|
|
|
- if not self.toggled:
|
|
|
|
- return
|
|
|
|
- d = delay
|
|
|
|
- h = hold
|
|
|
|
- if self.extra is not None:
|
|
|
|
- if "delay" in self.extra:
|
|
|
|
- d = self.extra["delay"]
|
|
|
|
- if "hold" in self.extra:
|
|
|
|
- h = self.extra["hold"]
|
|
|
|
- if self.kind == "click":
|
|
|
|
- _mouse_output(self.extra["button"], d, h)
|
|
|
|
- elif self.kind == "click down":
|
|
|
|
- _mouse_down(self.extra["button"])
|
|
|
|
- elif self.kind == "key":
|
|
|
|
- _keyboard_output(self.extra["write"], d, h)
|
|
|
|
- elif self.kind == "key down":
|
|
|
|
- _key_down(self.extra["write"])
|
|
|
|
-
|
|
|
|
-class OldTyrell():
|
|
|
|
- keybinds: _Dict[str, OldAction]
|
|
|
|
- mirrors: _Dict[str, str] # mirror key -> key in keybinds
|
|
|
|
- toggled: bool
|
|
|
|
|
|
+ placeholders: _Dict[str, bool]
|
|
|
|
+ tick: int
|
|
delay: int
|
|
delay: int
|
|
hold: int
|
|
hold: int
|
|
- def __init__(self, profile_name: str):
|
|
|
|
- self.profile = {
|
|
|
|
- "activator": "`",
|
|
|
|
- "helper": "?",
|
|
|
|
- "delay": 50,
|
|
|
|
- "hold": 20,
|
|
|
|
- "tick": 50,
|
|
|
|
- "placeholder_name": False,
|
|
|
|
- }
|
|
|
|
- self.name = profile_name
|
|
|
|
- if profile_name.endswith(".toml"):
|
|
|
|
- self.name = profile_name.removesuffix(".toml")
|
|
|
|
- if not _exists(self.name) or not _isdir(self.name):
|
|
|
|
- print_err(f"Invalid profile '{self.name}'")
|
|
|
|
- print_info(f"This should be a directory")
|
|
|
|
- exit()
|
|
|
|
- profile_config = _join(self.name, self.name+".toml")
|
|
|
|
- if _exists(profile_config):
|
|
|
|
- with open(profile_config, "r") as f:
|
|
|
|
- try:
|
|
|
|
- t = _toml_load(f)
|
|
|
|
- except Exception as err:
|
|
|
|
- print_err(f"Invalid profile '{self.name}'")
|
|
|
|
- print_info(f"Invalid '{self.name+'.toml'}' config")
|
|
|
|
- print(err)
|
|
|
|
- exit()
|
|
|
|
- self.profile = t
|
|
|
|
- if "activator" not in self.profile:
|
|
|
|
- self.profile["activator"] = "`"
|
|
|
|
- if "helper" not in self.profile:
|
|
|
|
- self.profile["helper"] = "?"
|
|
|
|
- if "hold" not in self.profile:
|
|
|
|
- self.profile["hold"] = 20
|
|
|
|
- if "delay" not in self.profile:
|
|
|
|
- self.profile["delay"] = 50
|
|
|
|
- if "tick" not in self.profile:
|
|
|
|
- self.profile["tick"] = 50
|
|
|
|
- if "placeholder_name" not in self.profile:
|
|
|
|
- self.profile["placeholder_name"] = False
|
|
|
|
|
|
+ activator: str
|
|
|
|
+ helper: str
|
|
|
|
+ def __init__(self, name: str):
|
|
|
|
+ # Unify name without extension
|
|
|
|
+ if name.endswith(".toml"):
|
|
|
|
+ self.name = name.removesuffix(".toml")
|
|
else:
|
|
else:
|
|
- print_err(f"Invalid profile '{self.name}'")
|
|
|
|
- print_info(f"Missing '{self.name+'.toml'}' config")
|
|
|
|
- exit()
|
|
|
|
- self.delay = self.profile["delay"]
|
|
|
|
- self.hold = self.profile["hold"]
|
|
|
|
- self.keybinds = {}
|
|
|
|
- self.mirrors = {}
|
|
|
|
- self.toggled = False
|
|
|
|
- if not _exists(_join(self.name, 'keys')):
|
|
|
|
- print_err(f"Invalid profile '{self.name}'")
|
|
|
|
- print_info("Missing 'keys' directory (for keybinds)")
|
|
|
|
- exit()
|
|
|
|
|
|
+ self.name = name
|
|
|
|
+ # Pre-Check
|
|
|
|
+ if not _exists(self.name):
|
|
|
|
+ # Does not exist, new everything
|
|
|
|
+ _write_profile(self.name)
|
|
|
|
+ _write_example(self.name)
|
|
|
|
+ _write_example_mirror(self.name)
|
|
else:
|
|
else:
|
|
- for ent in _listdir(_join(self.name, "keys")):
|
|
|
|
- if ent.startswith(".") or _isdir(ent) or not ent.endswith(".toml"):
|
|
|
|
- continue
|
|
|
|
- with open(_join(self.name, "keys", ent), "r") as f:
|
|
|
|
- t = _toml_load(f)
|
|
|
|
- if t["keybind"] == "?" or t["keybind"] == "`":
|
|
|
|
- continue
|
|
|
|
- if "duration" in t:
|
|
|
|
- self.add_action(t["keybind"], OldAction(ent.removesuffix(".toml"), t["kind"], extra=t, delay=t["duration"]))
|
|
|
|
|
|
+ # Profile config?
|
|
|
|
+ if not _exists(_join(self.name, self.name+".toml")):
|
|
|
|
+ _write_profile(self.name)
|
|
|
|
+ # Do we have keys?
|
|
|
|
+ if not _exists(_join(self.name, "keys")):
|
|
|
|
+ _write_example(self.name)
|
|
|
|
+ _write_example_mirror(self.name)
|
|
|
|
+ # Initial load
|
|
|
|
+ self.reload()
|
|
|
|
+
|
|
|
|
+ def reload(self):
|
|
|
|
+ # Load toml config
|
|
|
|
+ with open(_join(self.name, self.name+".toml"), "r") as f:
|
|
|
|
+ dat = _toml_load(f)
|
|
|
|
+ self.placeholders = {
|
|
|
|
+ "name": False,
|
|
|
|
+ }
|
|
|
|
+ self.tick = 50
|
|
|
|
+ self.activator = "`"
|
|
|
|
+ self.helper = "shift+/"
|
|
|
|
+ self.delay = 50
|
|
|
|
+ self.hold = 20
|
|
|
|
+ for key in dat:
|
|
|
|
+ val = dat[key]
|
|
|
|
+ if key.startswith("placeholder_"):
|
|
|
|
+ if str(val) in ('true', 'TRUE', 'True', 'T', 't', 'yes', 'YES', 'Yes', 'Y', 'y', '1'):
|
|
|
|
+ self.placeholders[key.removeprefix("placeholder_")] = True
|
|
else:
|
|
else:
|
|
- self.add_action(t["keybind"], OldAction(ent.removesuffix(".toml"), t["kind"], extra=t))
|
|
|
|
-
|
|
|
|
- def toggle(self, all: bool=False, all_tickers: bool=False, all_notickers: bool=False) -> bool:
|
|
|
|
- self.toggled = not self.toggled
|
|
|
|
- if all:
|
|
|
|
- for key in self.keybinds:
|
|
|
|
- act = self.keybinds[key]
|
|
|
|
- act.toggle()
|
|
|
|
- elif all_tickers:
|
|
|
|
- for key in self.keybinds:
|
|
|
|
- act = self.keybinds[key]
|
|
|
|
- if act.max_delay != 0:
|
|
|
|
- act.toggle()
|
|
|
|
- elif all_notickers:
|
|
|
|
- for key in self.keybinds:
|
|
|
|
- act = self.keybinds[key]
|
|
|
|
- if act.max_delay == 0:
|
|
|
|
- act.toggle()
|
|
|
|
- return self.toggled
|
|
|
|
-
|
|
|
|
- def disable(self, all: bool=False, all_tickers: bool=False, all_notickers: bool=False):
|
|
|
|
- self.toggled = False
|
|
|
|
- if all:
|
|
|
|
- for key in self.keybinds:
|
|
|
|
- act = self.keybinds[key]
|
|
|
|
- act.toggled = False
|
|
|
|
- elif all_tickers:
|
|
|
|
- for key in self.keybinds:
|
|
|
|
- act = self.keybinds[key]
|
|
|
|
- if act.max_delay != 0:
|
|
|
|
- act.toggled = False
|
|
|
|
- elif all_notickers:
|
|
|
|
- for key in self.keybinds:
|
|
|
|
- act = self.keybinds[key]
|
|
|
|
- if act.max_delay == 0:
|
|
|
|
- act.toggled = False
|
|
|
|
-
|
|
|
|
- def enable(self, all: bool=False, all_tickers: bool=False, all_notickers: bool=False):
|
|
|
|
- self.toggled = True
|
|
|
|
- if all:
|
|
|
|
- for key in self.keybinds:
|
|
|
|
- act = self.keybinds[key]
|
|
|
|
- act.toggled = True
|
|
|
|
- elif all_tickers:
|
|
|
|
- for key in self.keybinds:
|
|
|
|
- act = self.keybinds[key]
|
|
|
|
- if act.max_delay != 0:
|
|
|
|
- act.toggled = True
|
|
|
|
- elif all_notickers:
|
|
|
|
- for key in self.keybinds:
|
|
|
|
- act = self.keybinds[key]
|
|
|
|
- if act.max_delay == 0:
|
|
|
|
- act.toggled = True
|
|
|
|
-
|
|
|
|
- def add_action(self, bind: str, act: OldAction):
|
|
|
|
- act.toggled = False
|
|
|
|
- if "placeholder_name" in self.profile:
|
|
|
|
- if self.profile["placeholder_name"] and "write" in act.extra:
|
|
|
|
- act.extra["write"] = act.extra["write"].replace("{name}", self.name)
|
|
|
|
- if act.kind == "mirror" and "mirror" in act.extra:
|
|
|
|
- self.mirrors[act.extra["mirror"]] = bind
|
|
|
|
- self.keybinds[bind] = act
|
|
|
|
-
|
|
|
|
- def remove_action(self, bind: str):
|
|
|
|
- self.keybinds[bind] = None
|
|
|
|
-
|
|
|
|
- def is_action(self, bind: str) -> bool:
|
|
|
|
- return self.keybinds[bind] is not None
|
|
|
|
-
|
|
|
|
- def print_help(self):
|
|
|
|
- print_ok(f"{int(1000 / self.profile['tick'])} ticks per second ({self.profile['tick']} ms per tick)")
|
|
|
|
- print_ok(f"Name placeholder: {self.profile['placeholder_name']}")
|
|
|
|
- print_warn(f"{self.profile['activator']} -> Activate/Deactivate")
|
|
|
|
- print_warn(f"{self.profile['helper']} -> Displays Help")
|
|
|
|
- for key in self.keybinds:
|
|
|
|
- act = self.keybinds[key]
|
|
|
|
- if act.max_delay == 0 and act.toggled:
|
|
|
|
- print_info(f"{key} -> {act.name}")
|
|
|
|
- else:
|
|
|
|
- print_info(f"{key} -> {act.name} = {act.toggled} ({act.max_delay} ticks)")
|
|
|
|
- print_ok("Please use " + _style("CTRL+C", fg="bright_yellow") + " to stop")
|
|
|
|
-
|
|
|
|
- def tick(self):
|
|
|
|
- for key in self.keybinds:
|
|
|
|
- act = self.keybinds[key]
|
|
|
|
- if act.tick():
|
|
|
|
- act.do(self.delay, self.hold)
|
|
|
|
-
|
|
|
|
- # def callback(self, event: KeyboardEvent):
|
|
|
|
- # key_name = event.name
|
|
|
|
- # #if key_name in self.mirrors:
|
|
|
|
- # # # key mirrors currently lag
|
|
|
|
- # # act = self.keybinds[self.mirrors[key_name]]
|
|
|
|
- # # if act.toggled:
|
|
|
|
- # # if "write" in act.extra:
|
|
|
|
- # # if event.event_type == "down":
|
|
|
|
- # # key_down(act.extra["write"])
|
|
|
|
- # # else:
|
|
|
|
- # # key_up(act.extra["write"])
|
|
|
|
- # # elif "button" in act.extra:
|
|
|
|
- # # if event.event_type == "down":
|
|
|
|
- # # mouse_down(button=act.extra["button"])
|
|
|
|
- # # else:
|
|
|
|
- # # mouse_up(button=act.extra["button"])
|
|
|
|
- # #if event.event_type == "up":
|
|
|
|
- # if key_name == self.profile["activator"]:
|
|
|
|
- # if self.toggle():
|
|
|
|
- # print_ok("ON")
|
|
|
|
- # else:
|
|
|
|
- # print_ok("OFF")
|
|
|
|
- # elif self.toggled:
|
|
|
|
- # #print(f"Name: {event.name}")
|
|
|
|
- # #print(f"Code: {event.scan_code}")
|
|
|
|
- # #print(f"Modifiers: {event.modifiers}")
|
|
|
|
- # if self.profile["helper"] == "?" and "shift" in event.modifiers and event.name == "/" or key_name == self.profile["helper"]:
|
|
|
|
- # self.print_help()
|
|
|
|
- # elif key_name in self.keybinds:
|
|
|
|
- # act = self.keybinds[key_name]
|
|
|
|
- # if act.max_delay == 0 and act.toggled:
|
|
|
|
- # print_info(f"{key_name} -> {act.kind}")
|
|
|
|
- # act.do(self.delay, self.hold)
|
|
|
|
- # else:
|
|
|
|
- # print_info(f"{key_name} -> {act.kind} = {act.toggle()}")
|
|
|
|
- # self.toggle()
|
|
|
|
- # print_ok("OFF")
|
|
|
|
-
|
|
|
|
- def callback(self, bind, state=None, mirror_host=None):
|
|
|
|
- if bind == "__toggle__":
|
|
|
|
- if self.toggle():
|
|
|
|
- print_info(_style("ON", fg="bright_green"))
|
|
|
|
- else:
|
|
|
|
- print_info(_style("OFF", fg="bright_red"))
|
|
|
|
- return
|
|
|
|
- if state == "up" or state == "down":
|
|
|
|
- act = self.keybinds[mirror_host]
|
|
|
|
- if act.toggled:
|
|
|
|
- if act.extra["write"] != None or len(act.extra["write"]) != 0:
|
|
|
|
- if state == "up":
|
|
|
|
- print(f"'{bind}' -> {act.name} UP")
|
|
|
|
- _key_up(act.extra["write"])
|
|
|
|
- elif state == "down":
|
|
|
|
- print(f"'{bind}' -> {act.name} DOWN")
|
|
|
|
- _key_down(act.extra["write"])
|
|
|
|
- elif act.extra["button"] != None or len(act.extra["button"]) != 0:
|
|
|
|
- if state == "up":
|
|
|
|
- print(f"'{bind}' -> {act.name} UP")
|
|
|
|
- _mouse_up(button=act.extra["button"])
|
|
|
|
- elif state == "down":
|
|
|
|
- print(f"'{bind}' -> {act.name} DOWN")
|
|
|
|
- _mouse_down(button=act.extra["button"])
|
|
|
|
- return
|
|
|
|
- if not self.toggled:
|
|
|
|
- return
|
|
|
|
- if bind == "__help__":
|
|
|
|
- self.print_help()
|
|
|
|
- self.disable()
|
|
|
|
- print_info(_style("OFF", fg="bright_red"))
|
|
|
|
- return
|
|
|
|
- act = self.keybinds[bind]
|
|
|
|
- if act.toggled:
|
|
|
|
- print(f"'{bind}' -> {act.name}")
|
|
|
|
- act.do(self.delay, self.hold)
|
|
|
|
- elif act.max_delay != 0 or act.kind == "mirror":
|
|
|
|
- if act.toggle():
|
|
|
|
- print(f"'{bind}' -> {act.name} " + _style("ON", fg="bright_green"))
|
|
|
|
- else:
|
|
|
|
- print(f"'{bind}' -> {act.name} " + _style("OFF", fg="bright_red"))
|
|
|
|
- self.disable()
|
|
|
|
- print_info(_style("OFF", fg="bright_red"))
|
|
|
|
-
|
|
|
|
- async def background(self):
|
|
|
|
- while True:
|
|
|
|
- self.tick()
|
|
|
|
- await _asleep(self.profile["tick"] / 1000) # 50 ms (20 per second, same as Minecraft)
|
|
|
|
-
|
|
|
|
- async def mainloop(self):
|
|
|
|
- #keyboard_hook(self.callback)
|
|
|
|
- _add_hotkey(41, self.callback, args=["__toggle__"])
|
|
|
|
- _add_hotkey("shift+?", self.callback, args=["__help__"])
|
|
|
|
- for bind in self.keybinds:
|
|
|
|
- act = self.keybinds[bind]
|
|
|
|
- if act.kind == "key" or act.kind == "key down":
|
|
|
|
- print(f"hotkey -=> {bind}")
|
|
|
|
- _add_hotkey(bind, self.callback, args=[bind])
|
|
|
|
- elif act.kind == "mirror":
|
|
|
|
- print(f"hotkey -=> {bind} (mirror {act.extra['mirror']})")
|
|
|
|
- _add_hotkey(bind, self.callback, args=[bind])
|
|
|
|
- _add_hotkey(bind, self.callback, args=[act.extra["mirror"], "down", bind])
|
|
|
|
- _add_hotkey(bind, self.callback, args=[act.extra["mirror"], "up", bind], trigger_on_release=True)
|
|
|
|
- await _task_group(
|
|
|
|
- self.background()
|
|
|
|
- )
|
|
|
|
|
|
+ self.placeholders[key.removeprefix("placeholder_")] = False
|
|
|
|
+ elif key == "tick":
|
|
|
|
+ self.tick = int(val)
|
|
|
|
+ elif key == "delay":
|
|
|
|
+ self.delay = int(val)
|
|
|
|
+ elif key == "hold":
|
|
|
|
+ self.hold = int(val)
|
|
|
|
+ elif key == "activator":
|
|
|
|
+ self.activator = str(val)
|
|
|
|
+ elif key == "helper":
|
|
|
|
+ self.helper = str(val)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if __name__ == "__main__":
|
|
- if len(_argv) == 1:
|
|
|
|
- print_err("Missing profile filename")
|
|
|
|
- print_info("Example: 'tyrell.py Apollo' would look for 'Apollo.toml'")
|
|
|
|
- print()
|
|
|
|
- print_info("Profiles allow you to add placeholders,")
|
|
|
|
- print_info("And defines in a \"global\" sense key delay and hold delay.")
|
|
|
|
- print()
|
|
|
|
- exit()
|
|
|
|
- ty = OldTyrell(",".join(_argv[1:]))
|
|
|
|
- if len(ty.keybinds) == 0:
|
|
|
|
- print_err("Missing keybinds")
|
|
|
|
- print_info("(Might want some keybinds, place them in a 'keys' directory)")
|
|
|
|
- print_info(f"( Need an example? Look at '{_join('_example', 'keys', 'example.toml')}')")
|
|
|
|
- exit()
|
|
|
|
- ty.enable(all_notickers=True)
|
|
|
|
- ty.disable()
|
|
|
|
- ty.print_help()
|
|
|
|
- if ty.name == "_example":
|
|
|
|
- print_warn("This is the " + _style("example", fg="bright_yellow") + ", please define you're own profile")
|
|
|
|
- print_info("Please DO NOT EDIT this example profile")
|
|
|
|
- try:
|
|
|
|
- _run(ty.mainloop())
|
|
|
|
- except KeyboardInterrupt:
|
|
|
|
|
|
+ if not _exists("_example"):
|
|
|
|
+ p = Profile("_example")
|
|
exit()
|
|
exit()
|
|
|
|
+ _print_ok("All okay")
|