/* Copyright © 2024 Tianyu Liu */ package cmd import ( "context" "fmt" "log/slog" "net/http" "os" "os/signal" "syscall" "time" "github.com/gorilla/mux" "github.com/spf13/cobra" "github.com/spf13/viper" pooRecorder "github.com/t-liu93/home-automation-backend/components" "github.com/t-liu93/home-automation-backend/util/notion" ) var port string // serveCmd represents the serve command var serveCmd = &cobra.Command{ Use: "serve", Short: "Server automation backend", Run: serve, } func initUtil() { // init notion if viper.InConfig("notion.token") { notion.Init(viper.GetString("notion.token")) } else { slog.Error("Notion token not found in config file, exiting..") os.Exit(1) } } func initComponent() { // init pooRecorder pooRecorder.Init() } func serve(cmd *cobra.Command, args []string) { slog.Info("Starting server...") viper.SetConfigName("config") // name of config file (without extension) viper.SetConfigType("yaml") viper.AddConfigPath("$HOME/.config/home-automation") viper.AddConfigPath(".") // optionally look for config in the working directory err := viper.ReadInConfig() if err != nil { slog.Error(fmt.Sprintf("Cannot read config file, %s, exiting..", err)) os.Exit(1) } viper.WatchConfig() if viper.InConfig("port") { port = viper.GetString("port") } else { slog.Error("Port not found in config file, exiting..") os.Exit(1) } initUtil() initComponent() // routing router := mux.NewRouter() router.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("OK")) }).Methods("GET") router.HandleFunc("/poo/record", pooRecorder.HandleRecordPoo).Methods("POST") srv := &http.Server{ Addr: ":" + port, Handler: router, } stop := make(chan os.Signal, 1) signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM) go func() { if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { slog.Error(fmt.Sprintf("ListenAndServe error: %v", err)) os.Exit(1) } }() slog.Info(fmt.Sprintln("Server started on port", port)) <-stop slog.Info(fmt.Sprintln("Shutting down the server...")) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { slog.Error(fmt.Sprintf("Server Shutdown Failed:%+v", err)) os.Exit(1) } slog.Info(fmt.Sprintln("Server gracefully stopped")) } func init() { rootCmd.AddCommand(serveCmd) // Here you will define your flags and configuration settings. // Cobra supports Persistent Flags which will work for this command // and all subcommands, e.g.: // serveCmd.PersistentFlags().String("foo", "", "A help for foo") // Cobra supports local flags which will only run when this command // is called directly, e.g.: // serveCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") serveCmd.Flags().StringVarP(&port, "port", "p", "18881", "Port to listen on") }