summaryrefslogtreecommitdiff
path: root/lib/calendars.nix
blob: 265ee20bd29d4ad8e5cddf8ca90c44515451d78d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
{lib, config, pkgs, ...}:
let
  # names mapped to unique identifiers of calendars
  calendars = {
    unschedule = "3e40534f-bfb9-b973-f615-f958a6361e95";
    ymca-open-swim = "066441A6-B48F-439B-9BD0-5D0FA8F4CB6F";
    scheduling = "8fd24d42-2294-9bc3-cece-3922c7cd4d09";
    fasting-schedule = "e2ad2353-f91e-76c9-fb0f-2c8722ed9d2a";
    ben-shared = "ben";
    kate = "0962a74ab76a97543b485d2a583caa271042baab9d64437ae6c3bc8a50df1f08";
    training = "eb5dfe0a-0e60-b7e5-eb7a-3b980b50b195";
  };

  getCals = ls: lib.attrsets.attrVals ls calendars;

  common = {
    vdirsyncer = {
      enable = true;
      auth = "basic";
      conflictResolution = "remote wins";
      metadata = [
        "displayname"
        "description"
      ];
      timeRange = {
        # sync 1 year before and after now
        start = "datetime.now() - timedelta(days=365)";
        end = "datetime.now() + timedelta(days=365)";
      };
    };

    radicale = {
      passwordCommand = ["${pkgs.pass}/bin/pass" "cal.bensima.com"];
      type = "caldav";
      url = "https://cal.bensima.com";
      userName = "ben";
    };
    khal = {
      enable = true;
      type = "discover";
    };
  };
in {
  accounts.calendar.basePath = "Calendars";
  accounts.calendar.accounts = {
    "bensima_personal" = {
      primaryCollection = "Unschedule";
      remote = common.radicale;
      vdirsyncer = common.vdirsyncer // {
        collections = getCals ["unschedule" "ymca-open-swim" "fasting-schedule" "training"];
      };
      khal = common.khal // {
        addresses = ["ben@bensima.com" "ben@bsima.me"];
        color = "#800080";
      };
    };

    "bensima_scheduling" = {
      primaryCollection = "Scheduling";
      remote = common.radicale;
      vdirsyncer = common.vdirsyncer // {
        collections = getCals ["scheduling"];
      };
      # no khal, just sync this in the background
    };

    "bensima_shared" = {
      remote = common.radicale // {url = "https://cal.bensima.com/shared/ben";};
      vdirsyncer = common.vdirsyncer // {collections = getCals ["ben-shared"];};
      khal = common.khal // {color = "#097969";};
    };

    "icloud" = {
      remote = {
        passwordCommand = ["${pkgs.pass}/bin/pass" "icloud.com/vdirsyncer"];
        type = "caldav";
        url = "https://caldav.icloud.com";
        userName = "bsima@icloud.com";
      };
      vdirsyncer = common.vdirsyncer // {collections = getCals ["kate"];};
      khal = common.khal // {color = "#FAA0A0";};
    };
  };

  programs.khal = {
    enable = true;
    locale = {
      # these need to match org-mode formats for khalel
      weeknumbers = "left";
      timeformat = "%H:%M";
      dateformat = "%Y-%m-%d";
      longdateformat = "%Y-%m-%d %a";
      datetimeformat = "%Y-%m-%d %H:%M";
      longdatetimeformat = "%Y-%m-%d %H:%M";
    };
  };

  programs.vdirsyncer.enable = true;
  services.vdirsyncer.enable = true;

  # autosync ben-shared and scheduling, this must be hand-written and appended
  # to the generated config file
  services.vdirsyncer.configFile = "${config.xdg.configHome}/vdirsyncer/merged.conf";
  xdg.configFile."vdirsyncer/merged.conf".text = let
    wrap = s: ''"${s}"'';
    join = l: lib.strings.concatStringsSep ", " l;
    pair = pre: cals: "[${wrap pre}, ${join (map wrap (getCals cals))}]";
    generatedConfig = builtins.readFile "${config.xdg.configFile."vdirsyncer/config".source}";
  in ''
    ${generatedConfig}

    ### Manual Pairings

    [pair shared_to_scheduling]
    a = "calendar_bensima_shared_remote"
    b = "calendar_bensima_scheduling_remote"
    collections = [${pair "a_to_b" ["ben-shared" "scheduling"]}]
    conflict_resolution = "a wins"
  '';
}