Blame


1 5e70998a 2022-04-12 o package mailmux
2 5e70998a 2022-04-12 o
3 5e70998a 2022-04-12 o import (
4 5e70998a 2022-04-12 o "bufio"
5 5e70998a 2022-04-12 o "errors"
6 5e70998a 2022-04-12 o "fmt"
7 5e70998a 2022-04-12 o "io"
8 5e70998a 2022-04-12 o "math/rand"
9 5e70998a 2022-04-12 o "os"
10 5e70998a 2022-04-12 o "strings"
11 5e70998a 2022-04-12 o )
12 5e70998a 2022-04-12 o
13 5e70998a 2022-04-12 o func randomLine(f *os.File) (string, error) {
14 5e70998a 2022-04-12 o fi, err := f.Stat()
15 5e70998a 2022-04-12 o if err != nil {
16 5e70998a 2022-04-12 o return "", err
17 5e70998a 2022-04-12 o }
18 5e70998a 2022-04-12 o offset := rand.Int63n(fi.Size())
19 5e70998a 2022-04-12 o offset, err = f.Seek(offset, io.SeekStart)
20 5e70998a 2022-04-12 o if err != nil {
21 5e70998a 2022-04-12 o return "", err
22 5e70998a 2022-04-12 o }
23 5e70998a 2022-04-12 o
24 5e70998a 2022-04-12 o br := bufio.NewReader(f)
25 5e70998a 2022-04-12 o for {
26 5e70998a 2022-04-12 o b, err := br.ReadByte()
27 5e70998a 2022-04-12 o if b == '\n' {
28 5e70998a 2022-04-12 o break
29 5e70998a 2022-04-12 o }
30 5e70998a 2022-04-12 o if err != nil {
31 5e70998a 2022-04-12 o return "", err
32 5e70998a 2022-04-12 o }
33 5e70998a 2022-04-12 o }
34 5e70998a 2022-04-12 o line, err := br.ReadString('\n')
35 5e70998a 2022-04-12 o if errors.Is(err, io.EOF) {
36 5e70998a 2022-04-12 o // the file ends without a newline - no problem
37 5e70998a 2022-04-12 o } else if err != nil {
38 5e70998a 2022-04-12 o return "", err
39 5e70998a 2022-04-12 o }
40 5e70998a 2022-04-12 o
41 5e70998a 2022-04-12 o line = strings.TrimSpace(line)
42 5e70998a 2022-04-12 o if line == "" {
43 5e70998a 2022-04-12 o // empty line. we're either at the end or hit a blank line. try again
44 5e70998a 2022-04-12 o return randomLine(f)
45 5e70998a 2022-04-12 o }
46 5e70998a 2022-04-12 o return line, nil
47 5e70998a 2022-04-12 o }
48 5e70998a 2022-04-12 o
49 861fc513 2022-04-12 o // RandomUsername generates a random username from the dictionary file at dictpath.
50 861fc513 2022-04-12 o // The dictionary file should be a newline delimited text file, one word per line.
51 861fc513 2022-04-12 o // On Unix systems, the file /usr/share/dic/words is a suitable file.
52 8d82f4f7 2022-04-12 o func RandomUsername(dictpath string) (string, error) {
53 5e70998a 2022-04-12 o f, err := os.Open(dictpath)
54 5e70998a 2022-04-12 o if err != nil {
55 5e70998a 2022-04-12 o return "", fmt.Errorf("open dictionary: %w", err)
56 5e70998a 2022-04-12 o }
57 5e70998a 2022-04-12 o defer f.Close()
58 5e70998a 2022-04-12 o
59 5e70998a 2022-04-12 o first, err := randomLine(f)
60 5e70998a 2022-04-12 o if err != nil {
61 5e70998a 2022-04-12 o return "", fmt.Errorf("first random word: %w", err)
62 5e70998a 2022-04-12 o }
63 5e70998a 2022-04-12 o first = strings.ToLower(first)
64 5e70998a 2022-04-12 o second, err := randomLine(f)
65 5e70998a 2022-04-12 o if err != nil {
66 5e70998a 2022-04-12 o return "", fmt.Errorf("second random word: %w", err)
67 5e70998a 2022-04-12 o }
68 5e70998a 2022-04-12 o second = strings.ToLower(second)
69 5e70998a 2022-04-12 o
70 5e70998a 2022-04-12 o return fmt.Sprintf("%s_%s%02d", first, second, rand.Intn(99)), nil
71 5e70998a 2022-04-12 o }