artbound.go (view raw)
1package main
2
3import (
4 "bytes"
5 "encoding/json"
6 "html/template"
7 "log"
8 "net/http"
9 "net/url"
10 "os"
11 "time"
12
13 "github.com/BiRabittoh/artbound-go/cache"
14 "github.com/joho/godotenv"
15)
16
17var templatesDirectory = "templates/"
18var indexTemplate = template.Must(template.ParseFiles(templatesDirectory + "index.html"))
19var helpTemplate = template.Must(template.ParseFiles(templatesDirectory + "help.html"))
20
21type TemplateData struct {
22 Emoji EmojiDict
23 LastUpdated string
24 CurrentMonth string
25}
26
27func indexHandler(db *cache.DB) http.HandlerFunc {
28 return func(w http.ResponseWriter, r *http.Request) {
29 if r.Method != http.MethodGet {
30 http.Error(w, "Please use GET.", http.StatusMethodNotAllowed)
31 return
32 }
33
34 lastUpdated := db.LastUpdated.Format("02/01/2006 15:04")
35 currentMonth := time.Now().Format("2006-01")
36 templateData := &TemplateData{defaultEmojis, lastUpdated, currentMonth}
37 buf := &bytes.Buffer{}
38 err := indexTemplate.Execute(buf, templateData)
39 if err != nil {
40 http.Error(w, err.Error(), http.StatusInternalServerError)
41 return
42 }
43 buf.WriteTo(w)
44 }
45}
46
47func helpHandler(w http.ResponseWriter, r *http.Request) {
48 if r.Method != http.MethodGet {
49 http.Error(w, "Please use GET.", http.StatusMethodNotAllowed)
50 return
51 }
52
53 buf := &bytes.Buffer{}
54 err := helpTemplate.Execute(buf, defaultEmojis)
55 if err != nil {
56 http.Error(w, err.Error(), http.StatusInternalServerError)
57 return
58 }
59 buf.WriteTo(w)
60}
61
62func clearHandler(db *cache.DB) http.HandlerFunc {
63 return func(w http.ResponseWriter, r *http.Request) {
64 if r.Method != http.MethodPost {
65 http.Error(w, "Please use POST.", http.StatusMethodNotAllowed)
66 return
67 }
68 err := db.Clear()
69 if err != nil {
70 log.Fatal("Error:", err)
71 http.Error(w, "Could not delete cache.", http.StatusInternalServerError)
72 }
73 http.Error(w, "Done.", http.StatusOK)
74 }
75}
76
77func updateHandler(db *cache.DB) http.HandlerFunc {
78 return func(w http.ResponseWriter, r *http.Request) {
79 if r.Method != http.MethodPost {
80 http.Error(w, "Please use POST.", http.StatusMethodNotAllowed)
81 return
82 }
83 p := db.UpdateCall()
84 w.Header().Set("Content-Type", "application/json")
85 w.WriteHeader(http.StatusCreated)
86 json.NewEncoder(w).Encode(p)
87 }
88}
89
90func getHandler(db *cache.DB) http.HandlerFunc {
91 return func(w http.ResponseWriter, r *http.Request) {
92 u, err := url.Parse(r.URL.String())
93 if err != nil {
94 log.Fatal("Could not parse URL.")
95 http.Error(w, err.Error(), http.StatusInternalServerError)
96 return
97 }
98
99 month := u.Query().Get("month")
100 entries, err := db.GetEntries(month)
101 if err != nil {
102 log.Fatal("Could not get entries for month", month)
103 http.Error(w, err.Error(), http.StatusInternalServerError)
104 return
105 }
106
107 w.Header().Set("Content-Type", "application/json")
108 w.WriteHeader(http.StatusCreated)
109 json.NewEncoder(w).Encode(entries)
110 }
111}
112
113func main() {
114 err := godotenv.Load()
115 if err != nil {
116 log.Println("No .env file provided.")
117 }
118
119 port := os.Getenv("PORT")
120 if port == "" {
121 port = "3000"
122 }
123
124 spreadsheetId := os.Getenv("SPREADSHEET_ID")
125 if spreadsheetId == "" {
126 log.Fatal("Please fill out SPREADSHEET_ID in .env")
127 os.Exit(1)
128 }
129
130 spreadsheetRange := os.Getenv("SPREADSHEET_RANGE")
131 if spreadsheetRange == "" {
132 log.Fatal("Please fill out SPREADSHEET_RANGE in .env")
133 os.Exit(1)
134 }
135
136 fs := http.FileServer(http.Dir("./static"))
137 db := cache.InitDB(spreadsheetId, spreadsheetRange)
138
139 r := http.NewServeMux()
140 r.HandleFunc("/", indexHandler(db))
141 r.HandleFunc("/clear", clearHandler(db))
142 r.HandleFunc("/update", updateHandler(db))
143 r.HandleFunc("/get", getHandler(db))
144 r.HandleFunc("/help", helpHandler)
145 r.Handle("/static/", http.StripPrefix("/static/", fs))
146
147 log.Println("Serving on port", port)
148 err = http.ListenAndServe(":"+port, r)
149 if err != nil {
150 log.Fatal(err)
151 }
152}