summaryrefslogtreecommitdiffstats
path: root/main.go
blob: 31fa5eae532316a578d78662c1db8d0787b730c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"
)

type provider struct {
	name   string
	secret string
}

func newProvider(line string) *provider {
	split := strings.SplitN(line, ",", 2)
	if len(split) != 2 {
		return nil
	}

	p := &provider{name: strings.TrimSpace(split[0])}
	secret := strings.TrimSpace(split[1])
	secret = strings.Replace(secret, " ", "", -1)
	secret = strings.ToUpper(secret)
	p.secret = secret

	return p
}

var nameLength int
var format string

func main() {
	ps := parseStdin()

	format = "%-" + strconv.Itoa(nameLength) + "s %s (%ds) \n"

	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	go func() {
		for {
			displayCodes(ps)
			time.Sleep(500 * time.Millisecond)
			clearOutput(len(ps))
		}
	}()

	for {
		select {
		case <-sigChan:
			return
		}
	}
}

const (
	keyEscape = 27
)

func clearOutput(rows int) {
	up := []byte{keyEscape, '[', 'A'}
	clear := []byte{keyEscape, '[', '2', 'K'}
	for j := 0; j < rows; j++ {
		os.Stdout.Write(clear)
		os.Stdout.Write(up)
	}
}

func displayCodes(ps []provider) {
	for _, p := range ps {
		c, t := Code(p.secret)
		fmt.Fprintf(os.Stdout, format, p.name, c, t)
	}
}

func parseStdin() []provider {
	nameLength = 0
	bio := bufio.NewReader(os.Stdin)
	var ps []provider

	for {
		line, hasMoreInLine, err := bio.ReadLine()
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Fprintf(os.Stderr, "Could not read from stdin: %v\n", err)
			os.Exit(1)
		}
		if hasMoreInLine {
			fmt.Fprintf(os.Stderr, "Line too long: %s\n", line)
			os.Exit(1)
		}

		p := newProvider(string(line))
		if p == nil {
			fmt.Fprintf(os.Stderr, "Invalid input format: %q\n", line)
			os.Exit(1)
		}

		if nameLength < len(p.name) {
			nameLength = len(p.name)
		}

		ps = append(ps, *p)
	}

	nameLength += 1

	return ps
}