package main import ( "bufio" "fmt" "github.com/schollz/progressbar/v3" "github.com/skip2/go-qrcode" "io/ioutil" "os" "path" "path/filepath" "runtime" "strconv" "strings" ) var VersionNum = "dev" func handleErr(format string, args ...interface{}) { fmt.Printf(format, args...) os.Exit(1) } func readText() (text string, err error) { cr := bufio.NewReader(os.Stdin) text, err = cr.ReadString('\n') return } // One QR Code for each line of a file const modeLine int = 1 // One QR Code for each text file const modeFile int = 2 func getMode() int { fmt.Println("Available Modes:") fmt.Println("1: Generate one QR-Code for each line of text in each text file") fmt.Println("2: Generate one QR-Code for each text file") fmt.Println("What mode should the tool use? [1]") modeStr, err := readText() if err != nil { handleErr("Could not get mode: %s", err) } modeStr = strings.Trim(modeStr, "\n") modeStr = strings.Trim(modeStr, "\r") switch modeStr { case "": fallthrough case "1": return modeLine case "2": return modeFile default: handleErr("Unknown mode '%s'", modeStr) } return 0 } func createQrCode(filenameWithoutSuffix, outPath, content string) { outfile := path.Join(outPath, filenameWithoutSuffix+".png") err := qrcode.WriteFile(content, qrcode.Low, 2048, outfile) if err != nil { handleErr("Could not create qr code for file '%s.txt': %s", filenameWithoutSuffix, err) } } func main() { fmt.Printf("Bulk QR Code generate tool, Version %s\n\r", VersionNum) // 1. Get directory cwd, err := os.Getwd() if err != nil { handleErr("Could not get current working dir: %s", err) } fmt.Printf("Enter the directory path with text files [%s]\n\r", cwd) workingDir, err := readText() if err != nil { handleErr("Could not get current dir: %s", err) } if workingDir == "" || workingDir == "\n" || workingDir == "\n\r" || workingDir == "\r\n" { workingDir = cwd } // 1.1 Operating Mode mode := getMode() // Out directory outBasePath := path.Join(workingDir, "qrcodes") if err := os.MkdirAll(outBasePath, os.ModePerm); err != nil { handleErr("Could not create output folder: %s", err) } // 2. Get Files files, err := filepath.Glob(path.Join(workingDir, "/*.txt")) if err != nil { handleErr("Could not get files: %s", err) } fmt.Printf("Generating QR Codes from %d files in %s...\n\r", len(files), workingDir) bar := progressbar.Default(int64(len(files))) for _, file := range files { f, err := os.Open(file) if err != nil { handleErr("Could not open file '%s': %s", file, err) } if !strings.HasSuffix(f.Name(), ".txt") { continue } fNameNoSuffix := strings.TrimSuffix(path.Base(filepath.ToSlash(f.Name())), path.Ext(file)) var outPath = outBasePath if mode == modeLine { outPath = path.Join(outBasePath, fNameNoSuffix) if err := os.MkdirAll(outPath, os.ModePerm); err != nil { handleErr("Could not create output folder: %s", err) } } // 3. Generate QR-Codes and save if mode == modeFile { content, err := ioutil.ReadFile(file) if err != nil { handleErr("Could not open file '%s': %s", f.Name(), err) } createQrCode(fNameNoSuffix, outPath, string(content)) } if mode == modeLine { scanner := bufio.NewScanner(f) i := 0 for scanner.Scan() { createQrCode(fNameNoSuffix+"_"+strconv.Itoa(i), outPath, scanner.Text()) i++ } if err := scanner.Err(); err != nil { handleErr("Could not read file '%s': %s", f.Name(), err) } } _ = bar.Add(1) } // 4. Done fmt.Println("Done!") if runtime.GOOS == "windows" { fmt.Println("Press enter to close this window...") _, _ = readText() } }