Log windows and intention (aka whiteblocks if active)
This commit is contained in:
@@ -18,6 +18,7 @@ class Block(BaseModel):
|
|||||||
class Config(BaseModel):
|
class Config(BaseModel):
|
||||||
blackblocks: List[Block]
|
blackblocks: List[Block]
|
||||||
whiteblocks: List[Block]
|
whiteblocks: List[Block]
|
||||||
|
window_log_file: Path = Path("/home/felixm/tmp/antidrift/history.log")
|
||||||
daemon_log_file: Path = Path()
|
daemon_log_file: Path = Path()
|
||||||
client_log_file: Path = Path()
|
client_log_file: Path = Path()
|
||||||
config_file: Path = Path()
|
config_file: Path = Path()
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
|
import dbus
|
||||||
|
import dbus.service
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import pwd
|
import pwd
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import antidrift.xwindow as xwindow
|
import time
|
||||||
import dbus
|
|
||||||
import dbus.service
|
|
||||||
|
|
||||||
|
from antidrift.xwindow import XWindow
|
||||||
from antidrift.config import Config, State, Block
|
from antidrift.config import Config, State, Block
|
||||||
from gi.repository import GLib, Gio
|
from gi.repository import GLib, Gio
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
@@ -142,11 +143,26 @@ class AntiDriftDaemon(dbus.service.Object):
|
|||||||
m = f"Blackblock [sky_blue3]{blackblock.name}[/sky_blue3] is now allowed."
|
m = f"Blackblock [sky_blue3]{blackblock.name}[/sky_blue3] is now allowed."
|
||||||
logging.info(m)
|
logging.info(m)
|
||||||
|
|
||||||
|
def get_intention(self) -> str:
|
||||||
|
s = " ".join(map(lambda b: b.name, self.state.active_whiteblocks))
|
||||||
|
return f"intention is {s} work" if s else "no intention"
|
||||||
|
|
||||||
def run(self, debug: bool = False):
|
def run(self, debug: bool = False):
|
||||||
def _enforce():
|
def _enforce():
|
||||||
self.enforce()
|
self.enforce()
|
||||||
GLib.timeout_add(self.config.polling_cycle_ms, _enforce)
|
GLib.timeout_add(self.config.polling_cycle_ms, _enforce)
|
||||||
|
|
||||||
|
def _log():
|
||||||
|
self.config.window_log_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
window = XWindow()
|
||||||
|
ts = int(time.time())
|
||||||
|
intention = self.get_intention()
|
||||||
|
log_line = f"{ts}, {window.name}, {window.cls}, {intention}\n"
|
||||||
|
with self.config.window_log_file.open('a') as f:
|
||||||
|
f.write(log_line)
|
||||||
|
ONE_MINUTE_IN_MS = 60 * 1000
|
||||||
|
GLib.timeout_add(ONE_MINUTE_IN_MS, _log)
|
||||||
|
|
||||||
# autorestart on file change for development
|
# autorestart on file change for development
|
||||||
monitors = []
|
monitors = []
|
||||||
files = [
|
files = [
|
||||||
@@ -156,20 +172,22 @@ class AntiDriftDaemon(dbus.service.Object):
|
|||||||
"antidrift/config.py",
|
"antidrift/config.py",
|
||||||
]
|
]
|
||||||
if debug:
|
if debug:
|
||||||
|
logging.warning("[red]Running in debug mode.[/red]")
|
||||||
for filename in files:
|
for filename in files:
|
||||||
gio_file = Gio.File.new_for_path(filename)
|
gio_file = Gio.File.new_for_path(filename)
|
||||||
monitor = gio_file.monitor_file(Gio.FileMonitorFlags.NONE, None)
|
monitor = gio_file.monitor_file(Gio.FileMonitorFlags.NONE, None)
|
||||||
monitor.connect("changed", reload_callback)
|
monitor.connect("changed", reload_callback)
|
||||||
monitors.append(monitor)
|
monitors.append(monitor)
|
||||||
|
|
||||||
logging.info("[rosy_brown]Start.[/rosy_brown]")
|
|
||||||
_enforce()
|
_enforce()
|
||||||
|
_log()
|
||||||
mainloop = GLib.MainLoop()
|
mainloop = GLib.MainLoop()
|
||||||
mainloop.run()
|
mainloop.run()
|
||||||
|
xwindow.notify(f"AntiDrift running.")
|
||||||
|
|
||||||
def enforce(self):
|
def enforce(self):
|
||||||
if self.enforce_count >= self.enforce_value:
|
if self.enforce_count >= self.enforce_value:
|
||||||
window = xwindow.XWindow()
|
window = XWindow()
|
||||||
xwindow.notify(f"Minimize {window.name[:30]}.")
|
xwindow.notify(f"Minimize {window.name[:30]}.")
|
||||||
window.minimize()
|
window.minimize()
|
||||||
self.enforce_count = 0
|
self.enforce_count = 0
|
||||||
@@ -188,11 +206,11 @@ def window_is_blocked(state: State, silent: bool = False) -> bool:
|
|||||||
blackblocks = state.active_blackblocks
|
blackblocks = state.active_blackblocks
|
||||||
whiteblocks = state.active_whiteblocks
|
whiteblocks = state.active_whiteblocks
|
||||||
|
|
||||||
window = xwindow.XWindow()
|
window = XWindow()
|
||||||
if not window.keywords:
|
if not window.keywords:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def keyword_matches_window(keyword: str, window: xwindow.XWindow):
|
def keyword_matches_window(keyword: str, window: XWindow):
|
||||||
if keyword.startswith("/") and keyword.endswith("/"):
|
if keyword.startswith("/") and keyword.endswith("/"):
|
||||||
try:
|
try:
|
||||||
r = re.compile(keyword[1:-1], re.IGNORECASE)
|
r = re.compile(keyword[1:-1], re.IGNORECASE)
|
||||||
@@ -240,9 +258,3 @@ def window_is_blocked(state: State, silent: bool = False) -> bool:
|
|||||||
if not silent:
|
if not silent:
|
||||||
xwindow.notify(f"'{window.name[:30]}…' not on any whiteblock.")
|
xwindow.notify(f"'{window.name[:30]}…' not on any whiteblock.")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def run(config: Config):
|
|
||||||
add = AntiDriftDaemon(config)
|
|
||||||
xwindow.notify(f"AntiDrift.run()")
|
|
||||||
add.run()
|
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ class XWindow:
|
|||||||
self.pid = self._run(["getwindowpid", self.window])
|
self.pid = self._run(["getwindowpid", self.window])
|
||||||
self.keywords = list(re.findall(r"\w+", self.name.lower()))
|
self.keywords = list(re.findall(r"\w+", self.name.lower()))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<XWindow '{self.name[:20]}' '{self.cls[:20]}'>"
|
||||||
|
|
||||||
def _run(self, cmd) -> str:
|
def _run(self, cmd) -> str:
|
||||||
cmd = ["xdotool"] + cmd
|
cmd = ["xdotool"] + cmd
|
||||||
p = subprocess.run(cmd, capture_output=True)
|
p = subprocess.run(cmd, capture_output=True)
|
||||||
|
|||||||
7
main.py
7
main.py
@@ -10,7 +10,7 @@ from rich.logging import RichHandler
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import antidrift.client
|
import antidrift.client
|
||||||
import antidrift.daemon
|
from antidrift.daemon import AntiDriftDaemon
|
||||||
from antidrift.config import Config
|
from antidrift.config import Config
|
||||||
|
|
||||||
from dbus.mainloop.glib import DBusGMainLoop
|
from dbus.mainloop.glib import DBusGMainLoop
|
||||||
@@ -81,15 +81,14 @@ def main_daemon(config):
|
|||||||
newpid = os.fork()
|
newpid = os.fork()
|
||||||
if newpid == 0:
|
if newpid == 0:
|
||||||
init_logging(config.daemon_log_file)
|
init_logging(config.daemon_log_file)
|
||||||
antidrift.daemon.run(config)
|
AntiDriftDaemon(config).run()
|
||||||
else:
|
else:
|
||||||
if sys.argv[0] == "antidrift":
|
if sys.argv[0] == "antidrift":
|
||||||
cmd = ["sudo", "antidrift", "--daemon"]
|
cmd = ["sudo", "antidrift", "--daemon"]
|
||||||
subprocess.Popen(cmd)
|
subprocess.Popen(cmd)
|
||||||
else:
|
else:
|
||||||
init_logging(config.daemon_log_file, dev_mode=True)
|
init_logging(config.daemon_log_file, dev_mode=True)
|
||||||
logging.warning("[red]Running in development mode.[/red]")
|
AntiDriftDaemon(config).run(debug=True)
|
||||||
antidrift.daemon.run(config)
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user