package cronjobs import ( "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/core" "github.com/robfig/cron/v3" "github.com/seriousm4x/upsnap/logger" "github.com/seriousm4x/upsnap/networking" ) var ( PingRunning = false WakeShutdownRunning = false CronPing = cron.New(cron.WithParser(cron.NewParser( cron.SecondOptional | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow, ))) CronWakeShutdown = cron.New(cron.WithParser(cron.NewParser( cron.SecondOptional | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow, ))) ) func SetPingJobs(app *pocketbase.PocketBase) { // remove existing jobs for _, job := range CronPing.Entries() { CronPing.Remove(job.ID) } settingsPrivateRecords, err := app.FindAllRecords("settings_private") if err != nil { logger.Error.Println(err) } CronPing.AddFunc(settingsPrivateRecords[0].GetString("interval"), func() { // skip cron if no realtime clients connected and lazy_ping is turned on realtimeClients := len(app.SubscriptionsBroker().Clients()) if realtimeClients == 0 && settingsPrivateRecords[0].GetBool("lazy_ping") { return } devices, err := app.FindAllRecords("devices") if err != nil { logger.Error.Println(err) return } // expand ports field expandFetchFunc := func(c *core.Collection, ids []string) ([]*core.Record, error) { return app.FindRecordsByIds(c.Id, ids, nil) } merr := app.ExpandRecords(devices, []string{"ports"}, expandFetchFunc) if len(merr) > 0 { return } for _, device := range devices { // ping device go func(d *core.Record) { status := d.GetString("status") if status == "pending" { return } isUp, err := networking.PingDevice(d) if err != nil { logger.Error.Println(err) } if isUp { if status == "online" { return } d.Set("status", "online") if err := app.Save(d); err != nil { logger.Error.Println("Failed to save record:", err) } } else { if status == "offline" { return } d.Set("status", "offline") if err := app.Save(d); err != nil { logger.Error.Println("Failed to save record:", err) } } }(device) // ping ports go func(d *core.Record) { ports, err := app.FindRecordsByIds("ports", d.GetStringSlice("ports")) if err != nil { logger.Error.Println(err) } for _, port := range ports { isUp, err := networking.CheckPort(d.GetString("ip"), port.GetString("number")) if err != nil { logger.Error.Println("Failed to check port:", err) } if isUp != port.GetBool("status") { port.Set("status", isUp) if err := app.Save(port); err != nil { logger.Error.Println("Failed to save record:", err) } } } }(device) } }) } func SetWakeShutdownJobs(app *pocketbase.PocketBase) { // remove existing jobs for _, job := range CronWakeShutdown.Entries() { CronWakeShutdown.Remove(job.ID) } devices, err := app.FindAllRecords("devices") if err != nil { logger.Error.Println(err) return } for _, dev := range devices { wake_cron := dev.GetString("wake_cron") wake_cron_enabled := dev.GetBool("wake_cron_enabled") shutdown_cron := dev.GetString("shutdown_cron") shutdown_cron_enabled := dev.GetBool("shutdown_cron_enabled") if wake_cron_enabled && wake_cron != "" { _, err := CronWakeShutdown.AddFunc(wake_cron, func() { d, err := app.FindRecordById("devices", dev.Id) if err != nil { logger.Error.Println(err) return } if d.GetString("status") == "pending" { return } isOnline, err := networking.PingDevice(d) if err != nil { logger.Error.Println(err) return } if isOnline { return } d.Set("status", "pending") if err := app.Save(d); err != nil { logger.Error.Println("Failed to save record:", err) return } if err := networking.WakeDevice(d); err != nil { logger.Error.Println(err) d.Set("status", "offline") } else { d.Set("status", "online") } if err := app.Save(d); err != nil { logger.Error.Println("Failed to save record:", err) } }) if err != nil { logger.Error.Printf("device %s: %+v", dev.GetString("name"), err) } } if shutdown_cron_enabled && shutdown_cron != "" { _, err := CronWakeShutdown.AddFunc(shutdown_cron, func() { d, err := app.FindRecordById("devices", dev.Id) if err != nil { logger.Error.Println(err) return } if d.GetString("status") == "pending" { return } isOnline, err := networking.PingDevice(d) if err != nil { logger.Error.Println(err) return } if !isOnline { return } status := d.GetString("status") if status != "online" { return } d.Set("status", "pending") if err := app.Save(d); err != nil { logger.Error.Println("Failed to save record:", err) } if err := networking.ShutdownDevice(d); err != nil { logger.Error.Println(err) d.Set("status", "online") } else { d.Set("status", "offline") } if err := app.Save(d); err != nil { logger.Error.Println("Failed to save record:", err) } }) if err != nil { logger.Error.Printf("device %s: %+v", dev.GetString("name"), err) } } } } func StartWakeShutdown() { WakeShutdownRunning = true go CronWakeShutdown.Run() } func StopWakeShutdown() { if WakeShutdownRunning { logger.Info.Println("Stopping wake/shutdown cronjob") CronWakeShutdown.Stop() } WakeShutdownRunning = false } func StartPing() { PingRunning = true go CronPing.Run() } func StopPing() { if PingRunning { logger.Info.Println("Stopping wake/shutdown cronjob") CronPing.Stop() } PingRunning = false } func StopAll() { StopPing() StopWakeShutdown() }