diff --git a/Directory.json b/Directory.json new file mode 100644 index 0000000..c8bbf39 --- /dev/null +++ b/Directory.json @@ -0,0 +1 @@ +{"dir":""} diff --git a/cmd/client.go b/cmd/client.go index 40e9a4a..7a10214 100644 --- a/cmd/client.go +++ b/cmd/client.go @@ -64,6 +64,7 @@ func ClientLoop(cmd *cobra.Command, args []string) { } switch selectedOption { + case "Upload File": path, err := promptForFilePath() @@ -147,6 +148,29 @@ func ClientLoop(cmd *cobra.Command, args []string) { log.Warn("ssh request for finish-file-upload failed", "reply", string(reply)) continue } + + case "Add Directory to Sync": + dir, err := promptForDirectory() + if err != nil { + log.Error("Could not get directory for sync", "err", err) + continue + } + + if dir == "" { + dir = "./.data" // Default directory + } + + log.Infof("Updating Directory.json with directory: %s", dir) + + // Update the JSON file + configPath := "Directory.json" + err = updateDirectoryInConfig(configPath, dir) + if err != nil { + log.Error("Failed to update directory in config file", "err", err) + continue + } + + log.Infof("Directory.json updated successfully with: %s", dir) case "Exit": fmt.Println("Exiting client.") _, _, err := sshC.SendRequest("close-connection", false, []byte(worker.Ip)) @@ -185,6 +209,25 @@ func SendWorkerDetails(worker server.Worker, sshC *ssh.Client) error { return nil } +func promptForDirectory() (string, error) { + var directory string + directoryPrompt := huh.NewForm( + huh.NewGroup( + huh.NewInput(). + Title("Enter Directory to watch"). + Prompt("? "). + Placeholder(".data"). + Suggestions([]string{"./.data"}). + Value(&directory), + ), + ) + err := directoryPrompt.Run() + if err != nil { + return "", err + } + return directory, nil +} + func promptForIP() (string, error) { var ip string ipPrompt := huh.NewForm( @@ -214,6 +257,7 @@ func promptForAction() (string, error) { Options( huh.NewOption("Upload File", "Upload File"), huh.NewOption("List Directory", "List Directory"), + huh.NewOption("Add Directory to Sync", "Add Directory to Sync"), huh.NewOption("Exit", "Exit"), ). Value(&selectedOption), @@ -256,6 +300,40 @@ func validateFilePath(input string) error { return nil } +func updateDirectoryInConfig(path, newDir string) error { + config := server.Config{} + + if _, err := os.Stat(path); os.IsNotExist(err) { + config.Directory = newDir + } else { + file, err := os.Open(path) + if err != nil { + return fmt.Errorf("failed to open config file: %w", err) + } + defer file.Close() + + decoder := json.NewDecoder(file) + if err := decoder.Decode(&config); err != nil { + return fmt.Errorf("failed to parse config file: %w", err) + } + + config.Directory = newDir + } + + file, err := os.Create(path) + if err != nil { + return fmt.Errorf("failed to create or truncate config file: %w", err) + } + defer file.Close() + + encoder := json.NewEncoder(file) + if err := encoder.Encode(&config); err != nil { + return fmt.Errorf("failed to write updated config to file: %w", err) + } + + return nil +} + func init() { // Persistent flags for subcommands rootCmd.AddCommand(clientCmd) diff --git a/server/worker.go b/server/worker.go index 48db36e..1374522 100644 --- a/server/worker.go +++ b/server/worker.go @@ -1,10 +1,12 @@ package server import ( - "log" + "encoding/json" "os" + "path/filepath" "github.com/bsach64/goback/utils" + "github.com/charmbracelet/log" ) // Worker is just a usual SFTP server that handles the file request @@ -20,17 +22,25 @@ type Worker struct { func (w *Worker) StartSFTPServer() { wd, err := os.Getwd() if err != nil { - log.Fatalf("Cannot get the working directory: %v", err) + log.Errorf("Cannot get the working directory: %v", err) } - rsaPath := wd + "/private/id_rsa" + rsaPath := filepath.Join(wd, "private", "id_rsa") + configPath := filepath.Join(wd, "Directory.json") - // Start directory watcher - watcher, err := utils.WatchDirectory(wd + "/.data") - if err != nil { - log.Fatalf("Error while creating watcher: %v", err) + config := readConf(configPath) + + watchDir := filepath.Join(wd, config.Directory) + + if config.Directory != "" { + watcher, err := utils.WatchDirectory(watchDir) + if err != nil { + log.Errorf("Error while creating watcher: %v", err) + defer watcher.Close() // Ensure the watcher is cleaned up on server shutdown + } + } else { + log.Info("No directory is being watched you can add using", "command", "Add Directory to Sync") } - defer watcher.Close() // Ensure the watcher is cleaned up on server shutdown sftpServer := New(w.Ip, rsaPath, w.Port) w.sftpServer = &sftpServer @@ -45,3 +55,39 @@ func (w *Worker) StartSFTPServer() { // Keep the worker process alive select {} } + +type Config struct { + Directory string `json:"dir"` +} + +func readConf(path string) Config { + config := Config{} + + if _, err := os.Stat(path); os.IsNotExist(err) { + config.Directory = "./.data" + file, err := os.Create(path) + if err != nil { + log.Fatalf("Failed to create config file: %v", err) + } + defer file.Close() + + encoder := json.NewEncoder(file) + if err := encoder.Encode(config); err != nil { + log.Fatalf("Failed to write default config to file: %v", err) + } + log.Printf("Config file created with default directory: %s", config.Directory) + } else { + file, err := os.Open(path) + if err != nil { + log.Fatalf("Failed to open config file: %v", err) + } + defer file.Close() + + decoder := json.NewDecoder(file) + if err := decoder.Decode(&config); err != nil { + log.Fatalf("Failed to parse config file: %v", err) + } + } + + return config +}