package main import ( "context" "flag" "fmt" "os" "os/signal" "syscall" "git.5iot.com/iotlcm-public/iotlcm-bot/internal/archive" "git.5iot.com/iotlcm-public/iotlcm-bot/internal/config" "git.5iot.com/iotlcm-public/iotlcm-bot/internal/feishu" "git.5iot.com/iotlcm-public/iotlcm-bot/internal/notify" "git.5iot.com/iotlcm-public/iotlcm-bot/internal/render" "git.5iot.com/iotlcm-public/iotlcm-bot/internal/state" ) func main() { if len(os.Args) < 2 { usage() } switch os.Args[1] { case "render": renderCommand(os.Args[2:]) case "send": sendCommand(os.Args[2:]) case "send-text": sendTextCommand(os.Args[2:]) case "watch": watchCommand(os.Args[2:]) default: usage() } } func renderCommand(args []string) { fs := flag.NewFlagSet("render", flag.ExitOnError) file := fs.String("file", "", "path to a Worker Run JSON") environment := fs.String("environment", "preview", "environment label") jsonOutput := fs.Bool("json", false, "print Feishu interactive-card JSON") fs.Parse(args) if *file == "" { fmt.Fprintln(os.Stderr, "render requires --file") os.Exit(2) } a, err := archive.Load(*file) if err != nil { fail(err) } if *jsonOutput { body, err := render.Card(a, *environment) if err != nil { fail(err) } fmt.Println(string(body)) return } fmt.Println(render.Text(a, *environment)) } func sendCommand(args []string) { fs := flag.NewFlagSet("send", flag.ExitOnError) file := fs.String("file", "", "path to a Worker Run JSON") configPath := fs.String("config", "", "path to YAML config") force := fs.Bool("force", false, "send even when the Run was already marked sent") fs.Parse(args) if *file == "" || *configPath == "" { fmt.Fprintln(os.Stderr, "send requires --file and --config") os.Exit(2) } cfg, err := config.Load(*configPath) if err != nil { fail(err) } if err := cfg.ValidateSend(); err != nil { fail(err) } client := feishu.NewClient(cfg.Feishu.AppID, cfg.Feishu.AppSecret, cfg.Feishu.ChatID) svc := notify.New(cfg.ArchiveDir, cfg.Environment, cfg.PollDuration, state.New(cfg.StateDir), client, notify.DefaultLogger()) if err := svc.SendFile(context.Background(), *file, *force); err != nil { fail(err) } } func sendTextCommand(args []string) { fs := flag.NewFlagSet("send-text", flag.ExitOnError) configPath := fs.String("config", "", "path to YAML config") text := fs.String("text", "", "text to send") fs.Parse(args) if *configPath == "" || *text == "" { fmt.Fprintln(os.Stderr, "send-text requires --config and --text") os.Exit(2) } cfg, err := config.Load(*configPath) if err != nil { fail(err) } if err := cfg.ValidateSend(); err != nil { fail(err) } client := feishu.NewClient(cfg.Feishu.AppID, cfg.Feishu.AppSecret, cfg.Feishu.ChatID) if err := client.SendText(context.Background(), *text); err != nil { fail(err) } fmt.Println("Feishu text message sent") } func watchCommand(args []string) { fs := flag.NewFlagSet("watch", flag.ExitOnError) configPath := fs.String("config", "", "path to YAML config") fs.Parse(args) if *configPath == "" { fmt.Fprintln(os.Stderr, "watch requires --config") os.Exit(2) } cfg, err := config.Load(*configPath) if err != nil { fail(err) } if err := cfg.ValidateSend(); err != nil { fail(err) } ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() client := feishu.NewClient(cfg.Feishu.AppID, cfg.Feishu.AppSecret, cfg.Feishu.ChatID) svc := notify.New(cfg.ArchiveDir, cfg.Environment, cfg.PollDuration, state.New(cfg.StateDir), client, notify.DefaultLogger()) if err := svc.Watch(ctx); err != nil && err != context.Canceled { fail(err) } } func usage() { fmt.Fprintln(os.Stderr, "usage: iotlcm-bot [options]") os.Exit(2) } func fail(err error) { fmt.Fprintln(os.Stderr, "iotlcm-bot:", err); os.Exit(1) }