hivedav

A curlable free/busy scheduler with CalDAV integration
git clone https://git.in0rdr.ch/hivedav.git
Log | Files | Refs | Pull requests | README | LICENSE

README.md (7191B)


      1 # HiveDAV
      2 
      3 A curlable free/busy scheduler with CalDAV integration.
      4 
      5 ## Running the Server
      6 ```bash
      7 go run .
      8 ```
      9 
     10 ## Usage
     11 For example, to get the availability in the next week:
     12 ```
     13 curl http://127.0.0.1:3737/week/$(date +%Y)/$(($(date +%W)+1))
     14 ```
     15 
     16 To query the availability in the current week:
     17 ```
     18 curl http://127.0.0.1:3737
     19 ```
     20 
     21 ## Building
     22 ```bash
     23 make
     24 ```
     25 
     26 * The [sqlite3 driver](https://github.com/mattn/go-sqlite3) requires gcc and `CGO_ENABLED=1`
     27 
     28 ## Linting
     29 ```bash
     30 make fmt
     31 ```
     32 
     33 ## Testing
     34 Run tests:
     35 ```bash
     36 make test
     37 ```
     38 
     39 Generate test coverage report:
     40 ```bash
     41 make test/cover
     42 ```
     43 
     44 ## Configuration
     45 The application is configurable through environment variables or the
     46 `./app.env` file:
     47 
     48 ```bash
     49 # Optional
     50 #HIVEDAV_LISTEN_ADDRESS=127.0.0.1
     51 #HIVEDAV_LISTEN_PORT=3737
     52 # only useful for discovery of the calendar when HIVEDAV_CALDAV_HOST is set
     53 #HIVEDAV_CALENDAR=0
     54 #HIVEDAV_HORIZON=1
     55 #HIVEDAV_BOOKING_SUBJ="HiveDAV Booking"
     56 #HIVEDAV_BOOKING_REMINDER=15
     57 #HIVEDAV_SMTP_PORT=587
     58 #HIVEDAV_SMTP_STARTTLS=true
     59 
     60 # Required
     61 HIVEDAV_HOST=hivedav.example.com
     62 # an absolute uri to a caldav calendar, mutually exclusive with HIVEDAV_CALDAV_HOST
     63 HIVEDAV_CALDAV_URI=
     64 # the host for caldav discovery might have a port, mutually exclusive with HIVEDAV_CALDAV_URI
     65 HIVEDAV_CALDAV_HOST=
     66 HIVEDAV_CALDAV_USER=
     67 # make sure to quote in single quotes to properly esacpe special chars
     68 HIVEDAV_CALDAV_PASSWORD=''
     69 HIVEDAV_REFRESH_INTERVAL=30
     70 HIVEDAV_SMTP_HOST=
     71 HIVEDAV_SMTP_USER=
     72 # make sure to quote in single quotes to properly esacpe special chars
     73 HIVEDAV_SMTP_PASSWORD=''
     74 ```
     75 
     76 There is an example config file provided in `./app.env.example`.
     77 
     78 * `HIVEDAV_CALDAV_URI` is an absolute uri to a calendar resource on a caldav
     79   server. No discovery is performed. You either have to define
     80   `HIVEDAV_CALDAV_URI` or `HIVEDAV_CALDAV_HOST`.
     81 * With `HIVEDAV_CALDAV_HOST`, HiveDAV performs a discovery of the calendar uri
     82   using `HIVEDAV_CALENDAR`.
     83 * The `HIVEDAV_LISTEN_*` variables specify the http server `ADDRESS` and `PORT`
     84   (bind address and port)
     85 * The `HIVEDAV_CALENDAR` is a number that points to the index of the calendar
     86   collection in the ["calendar home
     87 set"](https://www.rfc-editor.org/rfc/rfc4791.html#section-6.2.1) which should
     88 be used to read availability data
     89 * The `HIVEDAV_HORIZON` (number in years) limits recurring events without end
     90   time. 0 means that only recurring events in the current year are shown.
     91 Unique events are not affected by `HIVEDAV_HORIZON`.
     92 * `HIVEDAV_BOOKING_SUBJ` is the subject of the calendar invite for new booking
     93   requests
     94 * `HIVEDAV_BOOKING_REMINDER` is the reminder time in minutes before the start
     95   of the calendar appointment
     96 * `HIVEDAV_HOST` is the fqdn of the HiveDAV service. It is used to print the
     97   help commands in the curlable interface.
     98 * `HIVEDAV_CALDAV_*` are settings to connect to the CalDAV server for fetching
     99   the avialability data
    100 * TODO: specify calendar using the "Name" propery
    101 * `HIVEDAV_REFRESH_INTERVAL` is the time in minutes between the automatic
    102   refresh of the database with the latest availability data from the CalDAV
    103 server. A [cron job](https://pkg.go.dev/github.com/robfig/cron) automatically
    104 downloads the latest events from the CalDAV server after that time. Defaults to
    105 30 minutes.
    106 * The `HIVEDAV_SMTP_*` settings are required to send out the ical invites for
    107   new appointments.
    108 
    109 ## Storage
    110 The application stores the event start/end times in an sqlite database in the
    111 directory where the process is running.
    112 
    113 The schema of the `availability` table is very simple and straight forward:
    114 
    115 ```bash
    116 sqlite3 app.db ".schema availability"
    117 var create_availability = `CREATE TABLE IF NOT EXISTS availability (
    118 			   id INTEGER NOT NULL PRIMARY KEY,
    119 			   start DATETIME NOT NULL,
    120 			   end DATETIME NOT NULL,
    121 			   recurring BOOL NOT NULL);`
    122 ```
    123 
    124 To show the current availability time slots:
    125 ```bash
    126 sqlite3 app.db "select * from availability;" | less
    127 sqlite3 app.db "select * from availability where start between '2023-01-01' and '2023-02-01';" | less
    128 ```
    129 
    130 There exists another table `availability_1` which is used to store the new
    131 availability time slots during an availability update ("CalDAV request").
    132 During this CalDAV request, the table `availability_1` is used to temporarily
    133 store the new availability. After the update is done, the temporary table is
    134 set as the "current" availability. The application only reads availability from
    135 the `availability` table, not from the temporary `availability_1` table.
    136 
    137 ## CalDAV Requests
    138 The CalDAV requests in the `caldav` module are used to query:
    139 * the user principal
    140 * the calendar home set
    141 * the calendar from the home set (`HIVEDAV_CALENDAR`) used as source of
    142   availability data
    143 
    144 The CalDAV requests are mad according to the examples in
    145 https://sabre.io/dav/building-a-caldav-client.
    146 
    147 The requests are kept very simple intentionally with libraries included in Go:
    148 * The requests only use the `net/http` library to do the HTTP requests.
    149 * The response is parsed using the `encoding/xml` library
    150 
    151 No external library was used perform the requests, because these libraries
    152 typically assume specific behavior for the remote CalDAV server. Unfortunately,
    153 the servers vary in their behavior quite a lot. For instance, certain servers
    154 don't support the [`calendar-query
    155 REPORT`](https://www.rfc-editor.org/rfc/rfc4791.html#section-7.8). To make this
    156 application work with as many remote servers as possible, all events from the
    157 remote calendar are fetched during an update and the availability data is
    158 stored in a local database for further processing.
    159 
    160 For more information refer to [`./docs/CALDAV.md`](./docs/CALDAV.md)
    161 
    162 ## Availability Query
    163 
    164 - s: start time
    165 - e: end time
    166 - ?: sql query parameter (start/end)
    167 - |: time slot (1h)
    168 
    169 The (un)availability query returns true if an existing appointment is found
    170 (unavailable, no free time slot). It returns false, when there exists no
    171 existing calendar entry during the time slot (available).
    172 
    173 ```
    174 //  e ?   ?
    175 //  - |   |   false
    176 //
    177 //  s e   ?
    178 //  - +   |   false
    179 //
    180 //  s ? e ?
    181 //  - | - |   true (2)
    182 //
    183 //  s ?   e
    184 //  - |   +   true (2)
    185 //
    186 //  s ?   ? e
    187 //  - |   | - true (3)
    188 //
    189 //    s e ?
    190 //    + - |   true (1)
    191 //
    192 //    s   e
    193 //    +   +   true (3)
    194 //
    195 //    s   ? e
    196 //    +   | - true (1)
    197 //
    198 //    ? s e
    199 //    | - +   true (1)
    200 //
    201 //    ? s ? e
    202 //    | - | - true (1)
    203 //
    204 //    ?   s e
    205 //    |   + - false
    206 ```
    207 
    208 Note:
    209 The calendar does not show events marked with the
    210 (X-MICROSOFT-CDO-INTENDEDSTATUS") "FREE" status. This can be helpful to skip
    211 certain "reminders" in your calendar, which should not be considered as
    212 "blocked time" (e.g., full day events).
    213 
    214 TODO:
    215 - Time slots are 1h each (TODO: make it configurable)
    216 - Picture for the query
    217 
    218 ## Development & Contributions
    219 * All source code is available in this repository. Contributions are always
    220   welcome! Pull requests at https://pr.in0rdr.ch/repos/hivedav
    221 * A [Kanban
    222   board](https://board.in0rdr.ch/public/board/01171363fae4b8b81af1579708f7cda6d389062f05b75db860621eaed32b)
    223 documents plans, todos and decisions for further development of the project.
    224 
    225 ## Community and Support
    226 For question and support visit
    227 [#p0c/libera](https://web.libera.chat/gamja/#p0c) on IRC.