// `portr watch` — long-running mode that re-runs checks on a timer.
//
// See mercemay.top/src/portr/ for context.
package cmd
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"time"
"github.com/spf13/cobra"
"github.com/mercemay/portr/internal/check"
"github.com/mercemay/portr/internal/tui"
)
var (
watchInterval time.Duration
watchTUI bool
)
var watchCmd = &cobra.Command{
Use: "watch",
Short: "Periodically re-check targets (optional TUI)",
RunE: func(cmd *cobra.Command, _ []string) error {
cfg, err := loadConfig()
if err != nil {
return err
}
ctx, cancel := signal.NotifyContext(cmd.Context(), os.Interrupt, syscall.SIGTERM)
defer cancel()
if watchTUI {
tui.Apply()
return tui.New(cfg).Run(ctx)
}
t := time.NewTicker(watchInterval)
defer t.Stop()
for {
rep, err := check.Run(ctx, cfg)
if err != nil {
return err
}
open, closed := rep.Summary()
fmt.Fprintf(os.Stderr, "%s %d open / %d closed\n",
time.Now().Format(time.RFC3339), open, closed)
select {
case <-ctx.Done():
return nil
case <-t.C:
}
}
},
}
func init() {
watchCmd.Flags().DurationVar(&watchInterval, "interval", 30*time.Second, "time between checks")
watchCmd.Flags().BoolVar(&watchTUI, "tui", false, "interactive TUI instead of log lines")
_ = context.Canceled // keep context imported across refactors
}