/* Copyright © 2023 Philipp Wolfer This file is part of Scotty. Scotty is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Scotty is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Scotty. If not, see . */ package cmd import ( "fmt" "sync" "time" "github.com/spf13/cobra" "github.com/spf13/viper" "go.uploadedlobster.com/scotty/internal/backends" "go.uploadedlobster.com/scotty/internal/models" "go.uploadedlobster.com/scotty/internal/storage" ) // lovesCmd represents the loves command var lovesCmd = &cobra.Command{ Use: "loves", Short: "Transfer loves between two services", Long: `Transfers loves between two configured services.`, Run: func(cmd *cobra.Command, args []string) { sourceName, sourceConfig := getConfigFromFlag(cmd, "from") targetName, targetConfig := getConfigFromFlag(cmd, "to") fmt.Printf("Transferring loves from %s to %s...\n", sourceName, targetName) // Setup database db, err := storage.New(viper.GetString("database")) cobra.CheckErr(err) // Initialize backends exportBackend, err := backends.ResolveBackend[models.LovesExport](sourceConfig) cobra.CheckErr(err) importBackend, err := backends.ResolveBackend[models.LovesImport](targetConfig) cobra.CheckErr(err) // Authenticate backends, if needed _, err = backends.Authenticate(sourceName, exportBackend, db, viper.GetViper()) cobra.CheckErr(err) _, err = backends.Authenticate(targetName, importBackend, db, viper.GetViper()) cobra.CheckErr(err) // Read timestamp timestamp := time.Unix(getInt64FromFlag(cmd, "timestamp"), 0) if timestamp == time.Unix(0, 0) { timestamp, err = db.GetImportTimestamp(sourceName, targetName, "loves") cobra.CheckErr(err) } fmt.Printf("From timestamp: %v (%v)\n", timestamp, timestamp.Unix()) // Prepare progress bars exportProgress := make(chan models.Progress) importProgress := make(chan models.Progress) var wg sync.WaitGroup progress := progressBar(&wg, exportProgress, importProgress) // Export from source exportChan := make(chan models.LovesResult, 1000) go exportBackend.ExportLoves(timestamp, exportChan, exportProgress) // Import into target resultChan := make(chan models.ImportResult) var processor = backends.LovesImportProcessor{ Backend: importBackend, } go processor.Process(exportChan, resultChan, importProgress) result := <-resultChan close(exportProgress) wg.Wait() progress.Wait() if result.Error != nil { fmt.Printf("Import failed, last reported timestamp was %v (%v)\n", result.LastTimestamp, result.LastTimestamp.Unix()) cobra.CheckErr(result.Error) } fmt.Printf("Imported %v of %v loves into %v.\n", result.ImportCount, result.TotalCount, targetName) // Update timestamp if result.LastTimestamp.Unix() < timestamp.Unix() { result.LastTimestamp = timestamp } fmt.Printf("Latest timestamp: %v (%v)\n", result.LastTimestamp, result.LastTimestamp.Unix()) err = db.SetImportTimestamp(sourceName, targetName, "loves", result.LastTimestamp) cobra.CheckErr(err) // Print errors if len(result.ImportErrors) > 0 { fmt.Printf("\nDuring the import the following errors occurred:\n") for _, err := range result.ImportErrors { fmt.Printf("Error: %v\n", err) } } }, } func init() { beamCmd.AddCommand(lovesCmd) // Here you will define your flags and configuration settings. // Cobra supports Persistent Flags which will work for this command // and all subcommands, e.g.: // lovesCmd.PersistentFlags().String("foo", "", "A help for foo") // Cobra supports local flags which will only run when this command // is called directly, e.g.: // lovesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") }