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(name, summary string) *GenerateCommand { command := GenerateCommand{ FlagSet: flag.NewFlagSet(name, flag.ExitOnError), summary: summary, } command.StringVar(&command.input, "input", "", "specify the CV JSON file that you want to input to the builder.") command.StringVar(&command.output, "output", "cv.pdf", "specify the name of the output CV file.") command.IntVar(&command.employmentHistory, "employment-history", 10, "show employment history within these number of years.") command.BoolVar(&command.verbose, "verbose", false, "set to true to enable verbose logging.") command.Usage = usageFunc(command.Name(), command.summary, command.FlagSet) return &command } func (c *GenerateCommand) Run() error { if c.input == "" { return noInputSpecifiedError{} } historyLimit := time.Now().AddDate(-1*c.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, c.input, historyLimit, c.verbose) if err != nil { return fmt.Errorf("unable to create the PDF file; %w", err) } if err := copyfile(filepath.Join(tempDir, "cv.pdf"), c.output); err != nil { return fmt.Errorf("unable to copy %s to %s; %w", pdfFileName, c.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 }