From db67e8bc169f0fdda5f518bb59b1d85396eca942 Mon Sep 17 00:00:00 2001 From: rot1024 Date: Mon, 11 Dec 2023 15:23:54 +0900 Subject: [PATCH] feat(server): subcommand to set up city items --- .../cmsintegrationv3/service_setup.go | 11 +- .../cmsintegrationv3/service_setup_test.go | 2 +- server/main.go | 12 ++- server/tool.go | 102 ++++++++++++++++++ 4 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 server/tool.go diff --git a/server/cmsintegration/cmsintegrationv3/service_setup.go b/server/cmsintegration/cmsintegrationv3/service_setup.go index fb4ddde72..b85f45a0a 100644 --- a/server/cmsintegration/cmsintegrationv3/service_setup.go +++ b/server/cmsintegration/cmsintegrationv3/service_setup.go @@ -19,6 +19,7 @@ type SetupCityItemsInput struct { Force bool `json:"force"` Offset int `json:"offset"` Limit int `json:"limit"` + DryRun bool `json:"dryrun"` } type SetupCSVItem struct { @@ -29,7 +30,7 @@ type SetupCSVItem struct { Features []string `json:"features"` } -func SetupCityItems(ctx context.Context, s *Services, inp SetupCityItemsInput, onprogress func(i, l int)) error { +func SetupCityItems(ctx context.Context, s *Services, inp SetupCityItemsInput, onprogress func(i, l int, c SetupCSVItem)) error { if inp.ProjectID == "" { return fmt.Errorf("modelId is required") } @@ -79,7 +80,7 @@ func SetupCityItems(ctx context.Context, s *Services, inp SetupCityItemsInput, o } if inp.Offset > 0 { - setupItems = setupItems[inp.Offset:] + setupItems = setupItems[inp.Offset+1:] } if inp.Limit > 0 { @@ -98,7 +99,11 @@ func SetupCityItems(ctx context.Context, s *Services, inp SetupCityItemsInput, o // process cities for i, item := range setupItems { if onprogress != nil { - onprogress(i, len(setupItems)) + onprogress(i, len(setupItems), item) + } + + if inp.DryRun { + continue } cityItem := &CityItem{ diff --git a/server/cmsintegration/cmsintegrationv3/service_setup_test.go b/server/cmsintegration/cmsintegrationv3/service_setup_test.go index cd58e62c3..0cfe713c0 100644 --- a/server/cmsintegration/cmsintegrationv3/service_setup_test.go +++ b/server/cmsintegration/cmsintegrationv3/service_setup_test.go @@ -170,7 +170,7 @@ func TestSetupCityItems(t *testing.T) { DataURL: "https://example.com/data.csv", } - onprogress := func(i, l int) {} + onprogress := func(i, l int, c SetupCSVItem) {} t.Run("success", func(t *testing.T) { createdItems = nil diff --git a/server/main.go b/server/main.go index 7a1b46e21..df7f01e32 100644 --- a/server/main.go +++ b/server/main.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "net/http" + "os" "reflect" "runtime" "runtime/debug" @@ -23,15 +24,20 @@ import ( ) func main() { - log.Infof("reearth-plateauview\n") - conf := lo.Must(NewConfig()) - log.Infof("config: %s", conf.Print()) + + if len(os.Args) > 1 && os.Args[1] != "" { + tool(conf, os.Args[1:]) + return + } main2(conf) } func main2(conf *Config) { + log.Infof("reearth-plateauview\n") + log.Infof("config: %s", conf.Print()) + if conf.GCParcent > 0 { debug.SetGCPercent(conf.GCParcent) } diff --git a/server/tool.go b/server/tool.go new file mode 100644 index 000000000..bcbf05070 --- /dev/null +++ b/server/tool.go @@ -0,0 +1,102 @@ +package main + +import ( + "context" + "errors" + "flag" + "fmt" + "net/http" + "os" + + "github.com/eukarya-inc/reearth-plateauview/server/cmsintegration/cmsintegrationv3" + cms "github.com/reearth/reearth-cms-api/go" + "github.com/samber/lo" +) + +func tool(conf *Config, args []string) { + subommand := args[0] + var err error + + switch subommand { + case "setup-city-items": + err = setupCityItems(conf, args[1:]) + case "help": + err = help(conf) + default: + err = errors.New("invalid subcommand") + } + + if err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func help(*Config) error { + fmt.Println(`Usage: plateauview [arguments] [options] [flags]`) + return nil +} + +func setupCityItems(conf *Config, args []string) error { + println("setup-city-items") + + var base, token, file string + inp := cmsintegrationv3.SetupCityItemsInput{} + + flags := flag.NewFlagSet("setup-city-items", flag.ExitOnError) + flags.StringVar(&base, "base", conf.CMS_BaseURL, "CMS base URL") + flags.StringVar(&token, "token", conf.CMS_Token, "CMS token") + flags.StringVar(&inp.ProjectID, "project", "", "project ID") + flags.StringVar(&file, "file", "", "file path") + flags.BoolVar(&inp.Force, "force", false, "force") + flags.IntVar(&inp.Offset, "offset", 0, "offset") + flags.IntVar(&inp.Limit, "limit", 0, "limit") + flags.BoolVar(&inp.DryRun, "dryrun", false, "dryrun") + if err := flags.Parse(args); err != nil { + return err + } + + if base == "" || token == "" || inp.ProjectID == "" || file == "" { + if base == "" { + fmt.Println("CMS base URL is required") + } + if token == "" { + fmt.Println("CMS token is required") + } + if inp.ProjectID == "" { + fmt.Println("project is required") + } + if file == "" { + fmt.Println("file is required") + } + return errors.New("CMS base URL, CMS token, project, and file are required") + } + + fmt.Printf("base: %s\nproject: %s\nfile: %s\nforce: %t\noffset: %d\nlimit: %d\ndryrun: %t\n", base, inp.ProjectID, file, inp.Force, inp.Offset, inp.Limit, inp.DryRun) + + f, err := os.Open(file) + if err != nil { + return fmt.Errorf("failed to open file: %w", err) + } + + defer f.Close() + + inp.DataBody = f + err = cmsintegrationv3.SetupCityItems( + context.Background(), + &cmsintegrationv3.Services{ + CMS: lo.Must(cms.New(base, token)), + HTTP: http.DefaultClient, + }, + inp, + func(i, l int, item cmsintegrationv3.SetupCSVItem) { + fmt.Printf("processing %d/%d %s\n", i, l, item.Name) + }, + ) + + if err != nil { + return fmt.Errorf("failed to setup city items: %w", err) + } + + return nil +}