2024-11-21 14:59:10 -08:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
2024-11-22 15:01:49 -08:00
|
|
|
"html/template"
|
2024-11-21 21:42:03 -08:00
|
|
|
"log"
|
2024-11-21 14:59:10 -08:00
|
|
|
"net/http"
|
|
|
|
|
"os"
|
2024-11-22 15:01:49 -08:00
|
|
|
"strings"
|
2024-11-21 14:59:10 -08:00
|
|
|
)
|
|
|
|
|
|
2024-11-21 21:42:03 -08:00
|
|
|
type PHandler struct {
|
2025-08-20 22:42:21 -07:00
|
|
|
tmpl *template.Template
|
|
|
|
|
pd *pdClient
|
|
|
|
|
gc *garminClient
|
|
|
|
|
garminIMEI string
|
|
|
|
|
garminSender string
|
|
|
|
|
mux *http.ServeMux
|
2024-11-21 21:42:03 -08:00
|
|
|
}
|
|
|
|
|
|
2025-08-20 22:42:21 -07:00
|
|
|
func NewPHandler(pdRoutingKey, garminApiKey, garminIMEI, garminSender string) (*PHandler, error) {
|
2024-11-22 15:01:49 -08:00
|
|
|
tmpl := template.New("index.html")
|
|
|
|
|
|
|
|
|
|
tmpl.Funcs(template.FuncMap{
|
|
|
|
|
"replaceAll": func(o, n, s string) string { return strings.ReplaceAll(s, o, n) },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
tmpl, err := tmpl.ParseFiles("static/index.html")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("static/index.html: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-25 18:01:37 -06:00
|
|
|
ph := &PHandler{
|
2025-08-20 22:42:21 -07:00
|
|
|
tmpl: tmpl,
|
|
|
|
|
pd: newPDClient(pdRoutingKey),
|
|
|
|
|
gc: newGarminClient(garminApiKey),
|
|
|
|
|
garminIMEI: garminIMEI,
|
|
|
|
|
garminSender: garminSender,
|
|
|
|
|
mux: http.NewServeMux(),
|
2024-11-25 18:01:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ph.mux.HandleFunc("/{$}", ph.serveRoot)
|
|
|
|
|
|
|
|
|
|
return ph, nil
|
2024-11-21 21:42:03 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ph *PHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
2024-11-25 18:01:37 -06:00
|
|
|
ph.mux.ServeHTTP(w, r)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ph *PHandler) serveRoot(w http.ResponseWriter, r *http.Request) {
|
2024-11-21 21:42:03 -08:00
|
|
|
err := r.ParseForm()
|
|
|
|
|
if err != nil {
|
2024-11-26 13:26:26 -06:00
|
|
|
sendError(w, http.StatusBadRequest, "Parse form: %s", err)
|
2024-11-21 21:42:03 -08:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-25 18:01:37 -06:00
|
|
|
log.Printf("%s %s %s", r.RemoteAddr, r.URL.Path, r.Form.Encode())
|
2024-11-22 13:49:31 -08:00
|
|
|
|
2024-11-23 06:35:38 -08:00
|
|
|
m := r.Form.Get("m")
|
|
|
|
|
if m == "" {
|
2024-11-22 15:01:49 -08:00
|
|
|
err = ph.tmpl.Execute(w, ph.envs())
|
|
|
|
|
if err != nil {
|
2024-11-26 13:26:26 -06:00
|
|
|
sendError(w, http.StatusInternalServerError, "Execute template %s: %s", ph.tmpl.Name(), err)
|
2024-11-22 15:01:49 -08:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-21 21:42:03 -08:00
|
|
|
return
|
|
|
|
|
}
|
2024-11-21 14:59:10 -08:00
|
|
|
|
2025-08-20 22:42:21 -07:00
|
|
|
err = ph.sendAlert(m)
|
2024-11-21 21:42:03 -08:00
|
|
|
if err != nil {
|
2025-08-20 22:48:00 -07:00
|
|
|
sendError(w, http.StatusInternalServerError, "%s", err)
|
2024-11-22 15:01:49 -08:00
|
|
|
return
|
2024-11-21 21:42:03 -08:00
|
|
|
}
|
2024-11-26 13:26:26 -06:00
|
|
|
sendResponse(w, "Page sent")
|
2024-11-25 18:01:37 -06:00
|
|
|
}
|
|
|
|
|
|
2025-08-20 22:42:21 -07:00
|
|
|
func (ph *PHandler) sendAlert(m string) error {
|
|
|
|
|
err := ph.pd.sendAlert(m)
|
|
|
|
|
if err != nil {
|
2025-08-20 22:48:00 -07:00
|
|
|
return fmt.Errorf("Error sending to PagerDuty: %w", err)
|
2025-08-20 22:42:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = ph.gc.sendMessage(ph.garminIMEI, ph.garminSender, m)
|
|
|
|
|
if err != nil {
|
2025-08-20 22:48:00 -07:00
|
|
|
return fmt.Errorf("Error sending to Garmin: %w", err)
|
2025-08-20 22:42:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-22 15:01:49 -08:00
|
|
|
var allowedEnvs = []string{
|
2024-11-22 22:09:29 -08:00
|
|
|
"SHORT_NAME",
|
|
|
|
|
"CONTACT_NAME",
|
2024-11-22 15:01:49 -08:00
|
|
|
"CONTACT_PHONE",
|
2024-11-22 21:14:28 -08:00
|
|
|
"CONTACT_SMS",
|
|
|
|
|
"CONTACT_IMESSAGE",
|
|
|
|
|
"CONTACT_WHATSAPP",
|
|
|
|
|
"CONTACT_PAGE_EMAIL",
|
2024-11-22 15:01:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ph *PHandler) envs() map[string]string {
|
|
|
|
|
envs := map[string]string{}
|
|
|
|
|
|
|
|
|
|
for _, k := range allowedEnvs {
|
|
|
|
|
v := os.Getenv(k)
|
|
|
|
|
if v != "" {
|
|
|
|
|
envs[k] = v
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return envs
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-21 21:42:03 -08:00
|
|
|
func main() {
|
2025-08-20 22:42:21 -07:00
|
|
|
pdRoutingKey := os.Getenv("PD_ROUTING_KEY")
|
|
|
|
|
if pdRoutingKey == "" {
|
2024-11-22 13:49:31 -08:00
|
|
|
log.Fatalf("please set PD_ROUTING_KEY")
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-20 22:42:21 -07:00
|
|
|
garminApiKey := os.Getenv("GARMIN_API_KEY")
|
|
|
|
|
if garminApiKey == "" {
|
|
|
|
|
log.Fatalf("please set GARMIN_API_KEY")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
garminIMEI := os.Getenv("GARMIN_IMEI")
|
|
|
|
|
if garminIMEI == "" {
|
|
|
|
|
log.Fatalf("please set GARMIN_IMEI")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
garminSender := os.Getenv("GARMIN_SENDER")
|
|
|
|
|
if garminSender == "" {
|
|
|
|
|
log.Fatalf("please set GARMIN_SENDER")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ph, err := NewPHandler(pdRoutingKey, garminApiKey, garminIMEI, garminSender)
|
2024-11-22 15:01:49 -08:00
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("NewPHandler: %s", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
http.Handle("/", ph)
|
2024-11-21 14:59:10 -08:00
|
|
|
|
|
|
|
|
port := os.Getenv("PORT")
|
|
|
|
|
if port == "" {
|
|
|
|
|
port = "80"
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-21 21:42:03 -08:00
|
|
|
bind := fmt.Sprintf(":%s", port)
|
|
|
|
|
log.Printf("listening on %s", bind)
|
2024-11-21 14:59:10 -08:00
|
|
|
|
2024-11-21 21:42:03 -08:00
|
|
|
if err := http.ListenAndServe(bind, nil); err != nil {
|
2024-11-22 13:49:31 -08:00
|
|
|
log.Fatalf("listen: %s", err)
|
2024-11-21 14:59:10 -08:00
|
|
|
}
|
|
|
|
|
}
|