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.Println("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.Println("Could not parse URL.")
95 http.Error(w, err.Error(), http.StatusInternalServerError)
96 return
97 }
98
99 month := u.Query().Get("month")
100 if month == "" {
101 http.Error(w, "\"month\" parameter is required.", http.StatusBadRequest)
102 return
103 }
104 entries, err := db.GetEntries(month)
105 if err != nil {
106 http.Error(w, "Could not get entries.", http.StatusInternalServerError)
107 return
108 }
109
110 w.Header().Set("Content-Type", "application/json")
111 w.WriteHeader(http.StatusCreated)
112
113 if len(entries) == 0 {
114 w.Write([]byte("[]"))
115 return
116 }
117 json.NewEncoder(w).Encode(entries)
118 }
119}
120
121func main() {
122 err := godotenv.Load()
123 if err != nil {
124 log.Println("No .env file provided.")
125 }
126
127 port := os.Getenv("PORT")
128 if port == "" {
129 port = "3000"
130 }
131
132 spreadsheetId := os.Getenv("SPREADSHEET_ID")
133 if spreadsheetId == "" {
134 log.Fatal("Please fill out SPREADSHEET_ID in .env")
135 }
136
137 spreadsheetRange := os.Getenv("SPREADSHEET_RANGE")
138 if spreadsheetRange == "" {
139 log.Fatal("Please fill out SPREADSHEET_RANGE in .env")
140 }
141
142 fs := http.FileServer(http.Dir("./static"))
143 db := cache.InitDB(spreadsheetId, spreadsheetRange)
144
145 r := http.NewServeMux()
146 r.HandleFunc("/", indexHandler(db))
147 r.HandleFunc("/clear", clearHandler(db))
148 r.HandleFunc("/update", updateHandler(db))
149 r.HandleFunc("/get", getHandler(db))
150 r.HandleFunc("/help", helpHandler)
151 r.Handle("/static/", http.StripPrefix("/static/", fs))
152
153 log.Println("Serving on port", port)
154 err = http.ListenAndServe(":"+port, r)
155 if err != nil {
156 log.Fatal(err)
157 }
158}