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.