package cmd import ( "flag" "fmt" "io" "log/slog" "os" "path/filepath" "time" "codeflow.dananglin.me.uk/apollo/spruce/internal/pdf" ) type GenerateCommand struct { *flag.FlagSet summary string input string output string employmentHistory int verbose bool } type noInputSpecifiedError struct{} func (e noInputSpecifiedError) Error() string { return "no input file specified, please set the --input field" } func NewGenerateCommand() *GenerateCommand { gc := GenerateCommand{ FlagSet: flag.NewFlagSet("generate", flag.ExitOnError), summary: "Generate a PDF file from an existing CV JSON file.", } gc.StringVar(&gc.input, "input", "", "specify the CV JSON file that you want to input to the builder.") gc.StringVar(&gc.output, "output", "cv.pdf", "specify the name of the output CV file.") gc.IntVar(&gc.employmentHistory, "employment-history", 10, "show employment history within these number of years.") gc.BoolVar(&gc.verbose, "verbose", false, "set to true to enable verbose logging.") gc.Usage = usageFunc(gc.Name(), gc.summary, gc.FlagSet) return &gc } func (g *GenerateCommand) Run() error { if g.input == "" { return noInputSpecifiedError{} } historyLimit := time.Now().AddDate(-1*g.employmentHistory, 0, 0) tempDir, err := os.MkdirTemp("/tmp", "cv-builder-") if err != nil { return fmt.Errorf("unable to create a temporary directory; %w", err) } defer func() { err := os.RemoveAll(tempDir) if err != nil { slog.Warn(fmt.Sprintf("WARN: An error occurred when removing the temporary directory; %v", err)) } }() pdfFileName, err := pdf.Generate(tempDir, g.input, historyLimit, g.verbose) if err != nil { return fmt.Errorf("unable to create the PDF file; %w", err) } if err := copyfile(filepath.Join(tempDir, "cv.pdf"), g.output); err != nil { return fmt.Errorf("unable to copy %s to %s; %w", pdfFileName, g.output, err) } return nil } func copyfile(source, destination string) error { inputFile, err := os.Open(source) if err != nil { return fmt.Errorf("unable to open %s; %w", source, err) } defer inputFile.Close() outputFile, err := os.Create(destination) if err != nil { return fmt.Errorf("unable to create %s; %w", destination, err) } defer outputFile.Close() _, err = io.Copy(outputFile, inputFile) if err != nil { return fmt.Errorf("unable to copy %s to %s; %w", source, destination, err) } slog.Info("File successfully copied.", "source", source, "destination", destination) return nil }