hivedav

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

commit 91fff6f662c37479795ffa75e3538af64c82cd9f
parent d3843602523f61028af77f7fbb2e6c732918dea1
Author: Andreas Gruhler <andreas.gruhler@adfinis.com>
Date:   Mon, 18 Sep 2023 23:00:24 +0200

feat: add HIVEDAV_REFRESH_INTERVAL

Diffstat:
MREADME.md | 7+++++++
Mapp.env.example | 1+
Mconfig/config.go | 17+++++++++++------
Mmain.go | 13+++++++++----
Mserver.go | 1+
5 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md @@ -55,6 +55,7 @@ The application is configurable through environment variables or the HIVEDAV_CALDAV_URI= HIVEDAV_CALDAV_USER= HIVEDAV_CALDAV_PASSWORD= +HIVEDAV_REFRESH_INTERVAL=30 ``` There is an example config file provided in `./app.env.example`. @@ -66,6 +67,12 @@ be used to read availability data. TODO: specify calendar using the "Name" propery +`HIVEDAV_REFRESH_INTERVAL` is the time in minutes between the automatic refresh +of the database with the latest availability data from the CalDAV server. A +[cron job](https://pkg.go.dev/github.com/robfig/cron) automatically downloads +the latest events from the CalDAV server after that time. Defaults to 30 +minutes. + ## Storage The application stores the event start/end times in an sqlite database in the directory where the process is running. diff --git a/app.env.example b/app.env.example @@ -4,3 +4,4 @@ #HIVEDAV_CALENDAR=0 #HIVEDAV_CALDAV_USER= #HIVEDAV_CALDAV_PASSWORD= +#HIVEDAV_REFRESH_INTERVAL=30 diff --git a/config/config.go b/config/config.go @@ -6,12 +6,13 @@ import ( ) type Config struct { - ListenAddress string `mapstructure:"HIVEDAV_LISTEN_ADDRESS"` - ListenPort int `mapstructure:"HIVEDAV_LISTEN_PORT"` - CaldavUri string `mapstructure:"HIVEDAV_CALDAV_URI"` - Calendar int `mapstructure:"HIVEDAV_CALENDAR"` - CaldavUser string `mapstructure:"HIVEDAV_CALDAV_USER"` - CaldavPassword string `mapstructure:"HIVEDAV_CALDAV_PASSWORD"` + ListenAddress string `mapstructure:"HIVEDAV_LISTEN_ADDRESS"` + ListenPort int `mapstructure:"HIVEDAV_LISTEN_PORT"` + CaldavUri string `mapstructure:"HIVEDAV_CALDAV_URI"` + Calendar int `mapstructure:"HIVEDAV_CALENDAR"` + CaldavUser string `mapstructure:"HIVEDAV_CALDAV_USER"` + CaldavPassword string `mapstructure:"HIVEDAV_CALDAV_PASSWORD"` + RefreshInterval int `mapstructure:"HIVEDAV_REFRESH_INTERVAL"` } func (c *Config) LoadConfig(path string) (*Config, error) { @@ -25,6 +26,7 @@ func (c *Config) LoadConfig(path string) (*Config, error) { viper.SetDefault("HIVEDAV_LISTEN_PORT", 3737) viper.SetDefault("HIVEDAV_LISTEN_ADDRESS", "[::]") viper.SetDefault("HIVEDAV_CALENDAR", 0) + viper.SetDefault("HIVEDAV_REFRESH_INTERVAL", 30) err := viper.ReadInConfig() if err != nil { @@ -61,6 +63,9 @@ func (c *Config) LoadConfig(path string) (*Config, error) { if viper.IsSet("CALDAV_PASSWORD") { c.CaldavPassword = viper.GetString("CALDAV_PASSWORD") } + if viper.IsSet("REFRESH_INTERVAL") { + c.RefreshInterval = viper.GetInt("REFRESH_INTERVAL") + } return c, nil } diff --git a/main.go b/main.go @@ -8,6 +8,7 @@ import ( "hivedav/config" "log" "net/http" + "time" ) var hivedavVersion = "v0.2-nightly" @@ -27,13 +28,14 @@ func main() { } log.Printf("Starting hivedav %s 🍯\n", hivedavVersion) + log.Printf("Cron availability update is %d minutes ⏰\n", conf.RefreshInterval) log.Println("Reading availability from:", conf.CaldavUri) log.Println("Reading as user:", conf.CaldavUser) c := cron.New() - c.AddFunc("@every 30m", func() { updateDatabase(server) }) + c.AddFunc(fmt.Sprintf("@every %dm", conf.RefreshInterval), func() { updateDatabase(server, c) }) + go updateDatabase(server, c) c.Start() - go updateDatabase(server) router := httprouter.New() router.GET("/", server.Index) @@ -44,7 +46,9 @@ func main() { log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%d", conf.ListenAddress, conf.ListenPort), router)) } -func updateDatabase(s *Server) { +func updateDatabase(s *Server, c *cron.Cron) { + log.Println("Starting availability update 🔄") + // Find current user principal userPrincipal, err := caldav.UserPrincipal(s.config.CaldavUri, s.config.CaldavUser, s.config.CaldavPassword) if err != nil { @@ -65,7 +69,7 @@ func updateDatabase(s *Server) { log.Fatal("Error reading calendar URI: ", err) } log.Printf("Using calendar %d in homeset with URI '%s'\n", s.config.Calendar, calendarUri) - log.Println("⏳ Fetching availability from CalDAV server, please wait..") + log.Println("Fetching availability from CalDAV server, please wait.. ⏳") // Get availability data for the calendar specified in the config calData, err := caldav.GetAvailability(s.config.CaldavUri, s.config.CaldavUser, s.config.CaldavPassword, calendarUri) @@ -79,4 +83,5 @@ func updateDatabase(s *Server) { } log.Println("Ready. Database was initialized with latest CalDAV availability data.") + log.Printf("Next automatic refresh of the db (cron): %v\n", c.Entries()[0].Schedule.Next(time.Now()).Format("2006-01-02 15:04")) } diff --git a/server.go b/server.go @@ -424,6 +424,7 @@ func parseTime(timeStr string, offset time.Duration) (time.Time, error) { // https://github.com/kelseyhightower/app-healthz func (s *Server) Healthz(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { + w.Header().Set("Content-Type", "application/json") var count = 0 row := s.db.QueryRow("SELECT count(*) FROM availability")