167 lines
4.6 KiB
Python
167 lines
4.6 KiB
Python
import datetime
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import time
|
|
from pprint import pprint
|
|
from zoneinfo import ZoneInfo
|
|
|
|
import state
|
|
import task
|
|
from config import logger, switches
|
|
|
|
desktops = ("Plan", "Think", "Work", "Other", "Away", "Work", "Work", "Work")
|
|
unlabeled = "Away"
|
|
config_file = "config.json"
|
|
|
|
|
|
def load_config():
|
|
"""Load configuration from JSON file"""
|
|
with open(config_file, "r") as f:
|
|
return json.load(f)
|
|
|
|
|
|
def reload_config_if_changed():
|
|
"""Check if config file changed and reload to state if needed"""
|
|
current_config_mtime = state.retrieve("current").get("config_mtime")
|
|
config_mtime = os.path.getmtime(config_file)
|
|
|
|
if current_config_mtime != config_mtime:
|
|
cfg = load_config()
|
|
work_desktop_tasks = {int(k): v for k, v in cfg["work_desktop_tasks"].items()}
|
|
state.sync_desktop_tasks(work_desktop_tasks)
|
|
state.save("current", config_mtime=config_mtime)
|
|
logger.info(f"Config reloaded: {work_desktop_tasks}")
|
|
|
|
|
|
def now():
|
|
cfg = load_config()
|
|
return datetime.datetime.now(ZoneInfo(cfg["timezone"]))
|
|
|
|
|
|
def handle_task_file_changes():
|
|
"""Check if task file changed and sync definitions to DB. Does not change current task."""
|
|
current_mtime = state.retrieve("current").get("filetime")
|
|
file_mtime = task.get_file_mtime(None)
|
|
|
|
if current_mtime != file_mtime:
|
|
task.file_to_db(None)
|
|
state.save("current", filetime=file_mtime)
|
|
logger.info("Task file changed, definitions synced to DB")
|
|
return True # File changed
|
|
|
|
return False # No change
|
|
|
|
|
|
def update_workspace_state():
|
|
"""Update current workspace in state"""
|
|
current_workspace = active_workspace()
|
|
state.save("current", workspace=current_workspace)
|
|
return current_workspace
|
|
|
|
|
|
def enforce_desktop_task(current_workspace, work_desktop_tasks, current_task):
|
|
"""Enforce assigned task for work desktops. Updates MongoDB state only, never writes to file."""
|
|
if (
|
|
current_workspace in work_desktop_tasks
|
|
and work_desktop_tasks[current_workspace]
|
|
):
|
|
assigned_task = work_desktop_tasks[current_workspace]
|
|
|
|
if current_task != assigned_task:
|
|
current_task = assigned_task
|
|
state.save("current", task=current_task)
|
|
logger.debug(
|
|
f"Enforced task {assigned_task} for workspace {current_workspace}"
|
|
)
|
|
|
|
return current_task
|
|
|
|
|
|
def track_workspace_switch(current_workspace, current_task, last_switch_time):
|
|
"""Update or create switch record"""
|
|
last_doc = switches.find_one(sort=[("_id", -1)])
|
|
|
|
if (
|
|
last_doc["workspace"] == desktop(current_workspace)
|
|
and last_doc["task"] == current_task
|
|
):
|
|
delta = round((now() - last_switch_time).total_seconds())
|
|
switches.update_one(
|
|
{"_id": last_doc["_id"]}, {"$set": {"delta": delta, "task": current_task}}
|
|
)
|
|
return last_switch_time
|
|
else:
|
|
switch = {
|
|
"workspace": desktop(current_workspace),
|
|
"date": now(),
|
|
"delta": 0,
|
|
"task": current_task,
|
|
}
|
|
switches.insert_one(switch)
|
|
return now()
|
|
|
|
|
|
def active_workspace():
|
|
workspaces = (
|
|
subprocess.check_output(["wmctrl", "-d"])
|
|
.decode("utf-8")
|
|
.strip("\n")
|
|
.split("\n")
|
|
)
|
|
|
|
for workspace in workspaces:
|
|
if workspace[3] == "*":
|
|
return int(workspace[0])
|
|
|
|
|
|
def desktop(workspace_index):
|
|
try:
|
|
return desktops[workspace_index]
|
|
except IndexError:
|
|
return unlabeled
|
|
|
|
|
|
# Sync task definitions from file to DB on startup
|
|
task.file_to_db(None)
|
|
state.save("current", filetime=task.get_file_mtime(None))
|
|
|
|
current_workspace = active_workspace()
|
|
current_task = state.retrieve("current").get("task")
|
|
last_switch_time = now()
|
|
|
|
switch = {
|
|
"workspace": desktop(current_workspace),
|
|
"date": now(),
|
|
"delta": 0,
|
|
"task": current_task,
|
|
}
|
|
|
|
switches.insert_one(switch)
|
|
|
|
while True:
|
|
# Check if config changed and reload
|
|
reload_config_if_changed()
|
|
|
|
# Load work_desktop_tasks from state
|
|
work_desktop_tasks = state.retrieve_desktop_state()
|
|
|
|
# Sync task definitions if file changed (does not change current task)
|
|
handle_task_file_changes()
|
|
|
|
# Get current state
|
|
current_task = state.retrieve("current").get("task")
|
|
current_workspace = update_workspace_state()
|
|
|
|
# Enforce work desktop task assignments
|
|
current_task = enforce_desktop_task(
|
|
current_workspace, work_desktop_tasks, current_task
|
|
)
|
|
|
|
# Track workspace switches
|
|
last_switch_time = track_workspace_switch(
|
|
current_workspace, current_task, last_switch_time
|
|
)
|
|
|
|
time.sleep(2)
|