Files
dotfiles/system-modules/calendar-dicos.nix
Lennart J. Kurzweg (Nx2) 61a788961d calendar
lr + dicos description + cleanup
2025-03-31 01:26:42 +02:00

138 lines
3.7 KiB
Nix

{ pkgs, ... }:
{
systemd.timers."nx_cal_dicos" = {
enable = true;
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = "40m";
OnUnitActiveSec = "24h";
Unit = "nx_cal_dicos.service";
};
};
systemd.services."nx_cal_dicos" = {
script = let
nx_cal_dicos = (pkgs.writers.writePython3Bin "nx_cal_dicos" {
libraries = with pkgs.python3Packages; [
ics
];
flakeIgnore = [ "E302" "E305" "E226" "E501" ];
} /* python */ ''
import os
from glob import glob
from ics import Calendar
from ics.event import datetime
NETTO_STUNDE = 18.46
WEEKLY = 12
week_dict = {}
latest_week = 0
latest_goal = WEEKLY
deficit = 0
def fraction_to_unicode(frac):
div, rem = divmod(frac, 1)
if rem == 0.5:
unicode = "½"
elif rem == 0.25:
unicode = "¼"
elif rem == 0.75:
unicode = "¾"
elif rem == 0:
unicode = ""
else:
unicode = rem
if div == 0:
h = ""
else:
h = int(div)
return f"{h}{unicode}"
def modify_event(event):
"""Modify the event if it contains 'DICOS' in the SUMMARY."""
global week_dict
global latest_goal
global latest_week
global deficit
if event.name is not None and "DICOS" in event.name:
length = (event.end - event.begin).seconds / 3600
money_made = divmod(length * NETTO_STUNDE, 1)
# Calculate total hours for DICOS events in the same week
year, week, _ = event.begin.isocalendar()
if week != latest_week:
try:
deficit = latest_goal - week_dict[f"{year}_{latest_week}"]
except KeyError:
deficit = 0
week_dict[f"{year}_{week}"] = length + (week_dict[f"{year}_{week}"] if f"{year}_{week}" in week_dict else 0)
progress = week_dict[f"{year}_{week}"]
goal = WEEKLY + deficit
if week != latest_week:
latest_goal = goal
latest_week = week
new_description = [event.description.split("\n")[0] or "::"]
new_description.append("")
new_description.append(f"Netto: {money_made[0]:.0f},{int(money_made[1] * 10):02d}")
new_description.append(f"This weeks porgress: ({fraction_to_unicode(progress)}/{fraction_to_unicode(goal)})")
new_description.append(f"This weeks deficit: {fraction_to_unicode(deficit)}")
event.description = "\n".join(new_description)
event.name = f"DICOS {fraction_to_unicode(length)}"
return event
def process_ics_file(filepath):
"""Read, modify, and overwrite an ICS file."""
with open(filepath, 'r') as f:
calendar = Calendar(f.read())
modified = False
for event in calendar.events:
if event.name is not None and 'DICOS' in event.name:
event = modify_event(event)
modified = True
if modified:
with open(filepath, 'w') as f:
f.writelines(calendar.serialize_iter())
def get_event_start_time(filepath):
"""Extract the event's start time from an ICS file."""
with open(filepath, 'r') as f:
calendar = Calendar(f.read())
for event in calendar.events:
return event.begin.datetime
else:
return datetime(year=1, month=1, day=1)
if __name__ == "__main__":
directory = "/var/lib/radicale/collections/collection-root/nx2/experience"
ics_files = glob(os.path.join(directory, "*.ics"))
if not ics_files:
print("No ICS files found in the directory.")
sorted_files = sorted(ics_files, key=get_event_start_time)
for ics_file in sorted_files:
process_ics_file(ics_file)
print("Processing complete.")
'');
in ''
${nx_cal_dicos}/bin/nx_cal_dicos
'';
serviceConfig = {
Type = "oneshot";
User = "radicale";
};
};
}