mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-06-10 06:10:46 +00:00
bdb60de7ae
- Update go.mod and Dockerfile to Go 1.26 - Apply `go fix ./...` stdlib modernizations across 170+ files - Add `go fix` to post-implementation checklist in CLAUDE.md - Fix go fix misapplied rewrite in loop_history.go
165 lines
3.8 KiB
Go
165 lines
3.8 KiB
Go
package cmd
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"text/tabwriter"
|
|
"time"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/nextlevelbuilder/goclaw/internal/store"
|
|
"github.com/nextlevelbuilder/goclaw/pkg/protocol"
|
|
)
|
|
|
|
func cronCmd() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "cron",
|
|
Short: "Manage scheduled cron jobs",
|
|
}
|
|
cmd.AddCommand(cronListCmd())
|
|
cmd.AddCommand(cronDeleteCmd())
|
|
cmd.AddCommand(cronToggleCmd())
|
|
return cmd
|
|
}
|
|
|
|
func cronListCmd() *cobra.Command {
|
|
var jsonOutput bool
|
|
var showDisabled bool
|
|
cmd := &cobra.Command{
|
|
Use: "list",
|
|
Short: "List all cron jobs",
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
cronListRPC(showDisabled, jsonOutput)
|
|
},
|
|
}
|
|
cmd.Flags().BoolVar(&jsonOutput, "json", false, "output as JSON")
|
|
cmd.Flags().BoolVar(&showDisabled, "all", false, "include disabled jobs")
|
|
return cmd
|
|
}
|
|
|
|
func cronDeleteCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "delete [jobId]",
|
|
Short: "Delete a cron job",
|
|
Args: cobra.ExactArgs(1),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
cronDeleteRPC(args[0])
|
|
},
|
|
}
|
|
}
|
|
|
|
func cronToggleCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "toggle [jobId] [true|false]",
|
|
Short: "Enable or disable a cron job",
|
|
Args: cobra.ExactArgs(2),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
enabled := args[1] == "true" || args[1] == "1" || args[1] == "on"
|
|
cronToggleRPC(args[0], enabled)
|
|
},
|
|
}
|
|
}
|
|
|
|
// --- RPC implementations ---
|
|
|
|
func cronListRPC(showDisabled, jsonOutput bool) {
|
|
requireGateway()
|
|
|
|
params, _ := json.Marshal(map[string]any{"includeDisabled": showDisabled})
|
|
resp, err := gatewayRPC(protocol.MethodCronList, params)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
if !resp.OK {
|
|
fmt.Fprintf(os.Stderr, "Failed: %s\n", resp.Error.Message)
|
|
os.Exit(1)
|
|
}
|
|
|
|
raw, _ := json.Marshal(resp.Payload)
|
|
var result struct {
|
|
Jobs []store.CronJob `json:"jobs"`
|
|
}
|
|
if err := json.Unmarshal(raw, &result); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error parsing response: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
printCronJobs(result.Jobs, jsonOutput)
|
|
}
|
|
|
|
func cronDeleteRPC(jobID string) {
|
|
requireGateway()
|
|
|
|
params, _ := json.Marshal(map[string]string{"jobId": jobID})
|
|
resp, err := gatewayRPC(protocol.MethodCronDelete, params)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
if !resp.OK {
|
|
fmt.Fprintf(os.Stderr, "Failed: %s\n", resp.Error.Message)
|
|
os.Exit(1)
|
|
}
|
|
fmt.Printf("Deleted job %s\n", jobID)
|
|
}
|
|
|
|
func cronToggleRPC(jobID string, enabled bool) {
|
|
requireGateway()
|
|
|
|
params, _ := json.Marshal(map[string]any{"jobId": jobID, "enabled": enabled})
|
|
resp, err := gatewayRPC(protocol.MethodCronToggle, params)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
if !resp.OK {
|
|
fmt.Fprintf(os.Stderr, "Failed: %s\n", resp.Error.Message)
|
|
os.Exit(1)
|
|
}
|
|
fmt.Printf("Job %s enabled=%v\n", jobID, enabled)
|
|
}
|
|
|
|
// --- Shared display ---
|
|
|
|
func printCronJobs(jobs []store.CronJob, jsonOutput bool) {
|
|
if jsonOutput {
|
|
data, _ := json.MarshalIndent(jobs, "", " ")
|
|
fmt.Println(string(data))
|
|
return
|
|
}
|
|
|
|
if len(jobs) == 0 {
|
|
fmt.Println("No cron jobs configured.")
|
|
return
|
|
}
|
|
|
|
tw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
|
fmt.Fprintf(tw, "ID\tNAME\tENABLED\tSCHEDULE\tLAST RUN\n")
|
|
for _, j := range jobs {
|
|
schedule := j.Schedule.Kind
|
|
if j.Schedule.Expr != "" {
|
|
schedule = j.Schedule.Expr
|
|
} else if j.Schedule.EveryMS != nil {
|
|
d := time.Duration(*j.Schedule.EveryMS) * time.Millisecond
|
|
schedule = "every " + d.String()
|
|
}
|
|
|
|
lastRun := "never"
|
|
if j.State.LastRunAtMS != nil {
|
|
lastRun = time.UnixMilli(*j.State.LastRunAtMS).Format(time.DateTime)
|
|
}
|
|
|
|
idShort := j.ID
|
|
if len(idShort) > 8 {
|
|
idShort = idShort[:8]
|
|
}
|
|
|
|
fmt.Fprintf(tw, "%s\t%s\t%v\t%s\t%s\n",
|
|
idShort, j.Name, j.Enabled, schedule, lastRun)
|
|
}
|
|
tw.Flush()
|
|
}
|