go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/blogctl/pkg/cmd/new.go (about) 1 /* 2 3 Copyright (c) 2023 - Present. Will Charczuk. All rights reserved. 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository. 5 6 */ 7 8 package cmd 9 10 import ( 11 "fmt" 12 "os" 13 "path/filepath" 14 "strings" 15 "time" 16 17 "github.com/urfave/cli/v2" 18 "go.charczuk.com/sdk/logutil" 19 "go.charczuk.com/sdk/slant" 20 21 "go.charczuk.com/projects/blogctl/pkg/config" 22 "go.charczuk.com/projects/blogctl/pkg/constants" 23 "go.charczuk.com/projects/blogctl/pkg/engine" 24 "go.charczuk.com/projects/blogctl/pkg/model" 25 ) 26 27 // New returns a new post command. 28 func New() *cli.Command { 29 return &cli.Command{ 30 Name: "new", 31 Usage: "Create a new blog post from a file", 32 ArgsUsage: "[IMAGE_PATH]", 33 Flags: []cli.Flag{ 34 &cli.StringFlag{Name: "title", Usage: "The title (optional, will default to the file name)"}, 35 &cli.StringFlag{Name: "location", Usage: "The location (optional)"}, 36 &cli.StringFlag{Name: "posted", Usage: "The posted effective date (optional)"}, 37 &cli.StringSliceFlag{Name: "tag", Usage: "The metadata tags (optional)"}, 38 }, 39 Action: func(ctx *cli.Context) error { 40 imagePath := ctx.Args().First() 41 if imagePath == "" { 42 return fmt.Errorf("must provide a [IMAGE_PATH]") 43 } 44 45 cfg, persistentFlags, cfgPaths, err := config.ReadConfig(ctx) 46 if err != nil { 47 return err 48 } 49 50 log := Logger("new") 51 slant.Print(os.Stdout, "BLOGCTL") 52 53 if len(cfgPaths) > 0 { 54 logutil.Infof(log, "using config path(s): %s", strings.Join(cfgPaths, ", ")) 55 } 56 57 captureDate, err := engine.ExtractCaptureDate(imagePath) 58 if err != nil { 59 logutil.Error(log, err) 60 } 61 62 var postedDate time.Time 63 if posted := ctx.String("posted"); posted != "" { 64 postedDate, err = time.Parse("2006-01-02", posted) 65 if err != nil { 66 return err 67 } 68 } else if !captureDate.IsZero() { 69 postedDate = captureDate 70 } 71 logutil.Infof(log, "using posted date: %v", postedDate) 72 73 title := ctx.String("title") 74 if title == "" { 75 title = filepath.Base(imagePath) 76 } 77 logutil.Infof(log, "using title: %v", title) 78 79 tags := ctx.StringSlice("tag") 80 if len(tags) > 0 { 81 logutil.Infof(log, "using tags: %v", strings.Join(tags, ", ")) 82 } 83 84 path := fmt.Sprintf("%s/%s-%s", cfg.PostsPathOrDefault(), postedDate.Format("2006-01-02"), engine.Slugify(title)) 85 86 if persistentFlags.DryRun { 87 logutil.Infof(log, "[DRY-RUN] writing new post to %s", path) 88 return nil 89 } 90 91 logutil.Infof(log, "writing new post to %s", path) 92 if _, err := os.Stat(path); err == nil { 93 return fmt.Errorf("post directory already exists, aborting") 94 } 95 fullPath := filepath.Join(path, filepath.Base(imagePath)) 96 if err := engine.Copy(imagePath, fullPath); err != nil { 97 return err 98 } 99 100 meta := model.Meta{ 101 Title: title, 102 Location: ctx.String("location"), 103 Captured: captureDate, 104 Posted: postedDate, 105 Tags: tags, 106 } 107 return engine.WriteYAML(filepath.Join(path, constants.FileMeta), meta) 108 }, 109 } 110 }