toggl-zei-py/TogglDelegate.py

110 lines
3.7 KiB
Python
Raw Normal View History

2020-08-12 18:44:23 +02:00
import struct
from toggl.TogglPy import Toggl
from zei.ZeiDelegate import ZeiDelegate
from datetime import datetime, timezone
from Mapping import Mapping
from plyer import notification
from os.path import dirname, realpath, join
2020-08-12 18:44:23 +02:00
import dateutil.parser
import logging
_log = logging.getLogger(__name__)
_log.addHandler(logging.StreamHandler())
_log.setLevel(logging.INFO)
2020-08-16 00:00:08 +02:00
class TogglDelegate(ZeiDelegate):
2020-08-12 18:44:23 +02:00
def __init__(self, periph, config):
self.config = config
self.toggl = Toggl()
2020-08-16 00:00:08 +02:00
self.toggl.setAPIKey(self.config["toggl"]["settings"]["token"])
2020-08-12 18:44:23 +02:00
self._populateProjects()
2020-08-16 00:00:08 +02:00
self._populateMappings(self.config["mappings"])
2020-08-12 18:44:23 +02:00
super().__init__(periph)
def handleNotification(self, cHandle, data):
2020-08-16 00:00:08 +02:00
if cHandle == 38: # Side Change Notification
side = struct.unpack("B", data)[0]
self._trackProjectByMapping(
self.mappings[side] if side in self.mappings else self.mappings[0]
)
2020-08-12 18:44:23 +02:00
else:
_log.info("Notification from hndl: %s - %r", cHandle, data)
def _trackProjectByMapping(self, mapping: Mapping):
2020-08-16 00:00:08 +02:00
self._trackProject(
description=mapping.description, pid=mapping.id, tags=mapping.tags
)
2020-08-12 18:44:23 +02:00
def _trackProject(self, description: str, pid: int, tags: list):
2020-08-16 00:00:08 +02:00
current = self.toggl.currentRunningTimeEntry()["data"]
2020-08-12 18:44:23 +02:00
if current is not None:
2020-08-16 00:00:08 +02:00
if (
datetime.now(timezone.utc) - dateutil.parser.isoparse(current["start"])
).total_seconds() < 20:
2020-08-12 18:44:23 +02:00
# Delete entry if not older than 20s
_log.info("Abort currently running entry")
2020-08-16 00:00:08 +02:00
self.toggl.deleteTimeEntry(current["id"])
2020-08-12 18:44:23 +02:00
else:
_log.info("Stopping currently running entry")
2020-08-16 00:00:08 +02:00
self.toggl.stopTimeEntry(current["id"])
2020-08-12 18:44:23 +02:00
if pid not in self.projects:
_log.info("Project not found, aborting")
return
2020-08-16 00:00:08 +02:00
_log.info(
"Now tracking project %s: %s (%s)",
self.projects[pid]["name"],
description,
", ".join(tags if tags else []),
)
notification.notify(
title="Toggl",
message=f"Now tracking project {self.projects[pid]['name']} {description} ({', '.join(tags) if tags else ''})",
app_name="Toggl",
app_icon=join(dirname(realpath(__file__)), "icons/toggl.png"),
timeout=5,
)
2020-08-12 18:44:23 +02:00
if pid == 0:
return
2020-08-16 00:00:08 +02:00
2020-08-12 18:44:23 +02:00
self.toggl.startTimeEntry(description, pid=pid, tags=tags)
2020-08-16 00:00:08 +02:00
2020-08-12 18:44:23 +02:00
def _populateMappings(self, mappings: dict):
2020-08-16 00:00:08 +02:00
self.mappings = {0: Mapping(0, 0)}
2020-08-12 18:44:23 +02:00
for i in mappings:
self.mappings[int(i)] = Mapping(int(i), int(mappings[i]["id"]))
if "description" in mappings[i]:
self.mappings[int(i)].description = mappings[i]["description"]
if "tags" in mappings[i]:
self.mappings[int(i)].tags = mappings[i]["tags"]
def _populateProjects(self):
self.projects = {}
2020-08-16 00:00:08 +02:00
proj = self.toggl.getWorkspaceProjects(
self.config["toggl"]["settings"]["workspace_id"]
)
NoneProj = {
"id": 0,
"wid": int(self.config["toggl"]["settings"]["workspace_id"]),
"name": "None",
"billable": False,
"is_private": True,
"active": True,
"template": False,
"at": "2020-06-09T04:02:38+00:00",
"created_at": "2019-12-09T16:36:28+00:00",
"color": "9",
"auto_estimates": False,
"actual_hours": 0,
"hex_color": "#990099",
}
2020-08-12 18:44:23 +02:00
self.projects[0] = NoneProj
for i in proj:
2020-08-16 00:00:08 +02:00
self.projects[i["id"]] = i