141 lines
3.9 KiB
Nix
141 lines
3.9 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
|
|
|
|
try:
|
|
new_description = [event.description.split("\n")[0]]
|
|
except AttributeError:
|
|
new_description = ["::"]
|
|
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"You're {fraction_to_unicode(abs(deficit))}h in the {'plus' if deficit < 0 else 'minus'} this week.")
|
|
|
|
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";
|
|
};
|
|
};
|
|
}
|