package clientfiles import ( "fmt" "github.com/EQEmuTools/spire/internal/database" "github.com/EQEmuTools/spire/internal/http/routes" "github.com/EQEmuTools/spire/internal/models" "github.com/labstack/echo/v4" "golang.org/x/text/language" "golang.org/x/text/message" "io/ioutil" "math/rand" "net/http" "os" "path/filepath" "strings" ) type Controller struct { exporter *Exporter importer *Importer db *database.Resolver } func NewController( exporter *Exporter, importer *Importer, db *database.Resolver, ) *Controller { return &Controller{ exporter: exporter, importer: importer, db: db, } } func (f *Controller) Routes() []*routes.Route { return []*routes.Route{ routes.RegisterRoute(http.MethodGet, "client-files/export/spells", f.exportSpells, nil), routes.RegisterRoute(http.MethodGet, "client-files/export/dbstr", f.exportDbStr, nil), routes.RegisterRoute(http.MethodPost, "client-files/import/file", f.importFile, nil), } } func (f *Controller) exportSpells(c echo.Context) error { // todo, bubble error handling // quick and dirty for now db := f.db.Get(&models.SpellsNew{}, c) contents := f.exporter.ExportSpells(db) folderPath := filepath.Join(os.TempDir(), "spell-export", randomString(10)) err := os.MkdirAll(folderPath, os.ModePerm) if err != nil { return c.JSON( http.StatusInternalServerError, echo.Map{"error": fmt.Sprintf("Error creating temp path [%v]", err.Error())}, ) } filePath := filepath.Join(folderPath, "spells_us.txt") err = os.WriteFile(filePath, []byte(contents), 0755) if err != nil { return c.JSON( http.StatusInternalServerError, echo.Map{"error": fmt.Sprintf("Error writing file [%v]", err.Error())}, ) } return c.Attachment(filePath, "spells_us.txt") } func (f *Controller) exportDbStr(c echo.Context) error { // todo, bubble error handling // quick and dirty for now db := f.db.Get(&models.DbStr{}, c) contents := f.exporter.ExportDbStr(db) folderPath := filepath.Join(os.TempDir(), "dbstr-export", randomString(10)) err := os.MkdirAll(folderPath, os.ModePerm) if err != nil { return c.JSON( http.StatusInternalServerError, echo.Map{"error": fmt.Sprintf("Error creating temp path [%v]", err.Error())}, ) } filePath := filepath.Join(folderPath, "dbstr_us.txt") err = os.WriteFile(filePath, []byte(contents), 0755) if err != nil { return c.JSON( http.StatusInternalServerError, echo.Map{"error": fmt.Sprintf("Error writing file [%v]", err.Error())}, ) } return c.Attachment(filePath, "dbstr_us.txt") } func (f *Controller) importFile(c echo.Context) error { file, err := c.FormFile("file") if err != nil { return err } src, err := file.Open() if err != nil { return err } defer src.Close() fileName := file.Filename if !strings.Contains(fileName, "spells_us") && !strings.Contains(fileName, "dbstr_us") { return c.HTML( http.StatusInternalServerError, fmt.Sprintf("File not valid"), ) } fileBytes, err := ioutil.ReadAll(src) if err != nil { return c.HTML( http.StatusInternalServerError, fmt.Sprintf("Error [%v]", err.Error()), ) } fileContents := string(fileBytes) r := ImportResult{} if strings.Contains(fileName, "spells_us") { db := f.db.Get(&models.DbStr{}, c) r, err = f.importer.ImportSpells(db, fileContents) if err != nil { return c.HTML( http.StatusInternalServerError, fmt.Sprintf("Error [%v]", err.Error()), ) } } if strings.Contains(fileName, "dbstr_us") { db := f.db.Get(&models.DbStr{}, c) r, err = f.importer.ImportDbStr(db, fileContents) if err != nil { return c.HTML( http.StatusInternalServerError, fmt.Sprintf("Error [%v]", err.Error()), ) } } // for commify p := message.NewPrinter(language.English) return c.HTML( http.StatusOK, p.Sprintf("Success! Table [%v] Deleted [%d] Imported [%d]", r.Table, r.DroppedRows, r.ImportedRows), ) } func randomInt(min, max int) int { return min + rand.Intn(max-min) } func randomString(len int) string { bytes := make([]byte, len) for i := 0; i < len; i++ { bytes[i] = byte(randomInt(65, 90)) } return string(bytes) }