main.go (view raw)
1package main
2
3import (
4 "encoding/csv"
5 "encoding/json"
6 "errors"
7 "flag"
8 "fmt"
9 "log"
10 "net/http"
11 "os"
12 "strings"
13 "time"
14)
15
16type Habit struct {
17 Time time.Time `json:"time"`
18 Activity string `json:"activity"`
19 Notes string `json:"notes,omitempty"`
20}
21
22func (h Habit) String() string {
23 t := h.Time.Format(time.RFC1123Z)
24 return fmt.Sprintf(
25 "time: %s activity: %s notes: %s",
26 t,
27 h.Activity,
28 h.Notes,
29 )
30}
31
32func (h Habit) WriteTSV(fname string) error {
33 record := []string{}
34
35 f, err := os.OpenFile(fname, os.O_APPEND|os.O_WRONLY, 0644)
36 if err != nil {
37 return err
38 }
39
40 w := csv.NewWriter(f)
41 w.Comma = '\t'
42 t := h.Time.Format(time.RFC1123)
43
44 record = append(record, t, h.Activity, h.Notes)
45 if err := w.Write(record); err != nil {
46 return err
47 }
48
49 w.Flush()
50 if err := w.Error(); err != nil {
51 return err
52 }
53
54 defer f.Close()
55
56 return nil
57}
58
59func getKey(r *http.Request) string {
60 var key string
61 header := r.Header.Get("Authorization")
62 key = strings.Split(header, " ")[1]
63 return key
64}
65
66func main() {
67 hFile := *flag.String("f", "./habits.tsv", "csv file to store habit data")
68 secretKey := *flag.String("key", "secret", "auth key to be passed as bearer token")
69 flag.Parse()
70
71 if _, err := os.Stat(hFile); errors.Is(err, os.ErrNotExist) {
72 _, err := os.Create(hFile)
73 if err != nil {
74 log.Fatalf(err.Error())
75 }
76 }
77
78 http.HandleFunc("/submit", func(w http.ResponseWriter, r *http.Request) {
79 h := Habit{}
80 key := getKey(r)
81 if secretKey != key {
82 log.Printf("incorrect key: %v\n", key)
83 w.WriteHeader(401)
84 }
85 json.NewDecoder(r.Body).Decode(&h)
86 log.Printf(h.String())
87
88 if err := h.WriteTSV(hFile); err != nil {
89 log.Printf("error: %v\n", err)
90 w.WriteHeader(500)
91 }
92 w.WriteHeader(204)
93 })
94
95 http.ListenAndServe(":8585", nil)
96}