package api import ( "context" "fmt" "html/template" "io/fs" "log" "net/http" "sprintpadawan/lib" ) var templates *template.Template func InitTemplates(fsys fs.FS) { templates = template.Must(template.New("").Funcs(template.FuncMap{ "scaleToOptions": scaleToOptions, "derefInt": func(i *int) int { if i == nil { return 0 } return *i }, "slice": func(s string, start, end int) string { if len(s) == 0 { return "" } if start < 0 { start = 0 } if end > len(s) || end <= 0 { end = len(s) } if start > end { return "" } return s[start:end] }, "dict": func(values ...interface{}) (map[string]interface{}, error) { if len(values)%2 != 0 { return nil, fmt.Errorf("odd number of arguments to dict") } d := make(map[string]interface{}) for i := 0; i < len(values); i += 2 { key, ok := values[i].(string) if !ok { return nil, fmt.Errorf("dict keys must be strings") } d[key] = values[i+1] } return d, nil }, }).ParseFS(fsys, "templates/*.html")) } func isHTMX(r *http.Request) bool { return r.Header.Get("HX-Request") == "true" } func renderTemplate(w http.ResponseWriter, name string, data interface{}) { w.Header().Set("Content-Type", "text/html; charset=utf-8") if err := templates.ExecuteTemplate(w, name, data); err != nil { log.Printf("template error (%s): %v", name, err) http.Error(w, "internal server error", http.StatusInternalServerError) } } func renderRoomStories(w http.ResponseWriter, roomID int, user *lib.User) { room, err := lib.GetRoomByID(roomID) if err != nil { http.Error(w, "room not found", http.StatusNotFound) return } data, err := buildRoomData(room, user) if err != nil { http.Error(w, "failed to load room data", http.StatusInternalServerError) return } renderTemplate(w, "stories-panel", data) } func renderRoomMembers(w http.ResponseWriter, roomID int, user *lib.User) { room, err := lib.GetRoomByID(roomID) if err != nil { http.Error(w, "room not found", http.StatusNotFound) return } data, err := buildRoomData(room, user) if err != nil { http.Error(w, "failed to load room data", http.StatusInternalServerError) return } renderTemplate(w, "members-panel", data) } func requireAuth(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie("session_token") if err != nil { http.Redirect(w, r, "/login", http.StatusSeeOther) return } user, err := lib.GetUserFromSession(cookie.Value) if err != nil || user == nil { http.Redirect(w, r, "/login", http.StatusSeeOther) return } ctx := context.WithValue(r.Context(), userKey, user) next.ServeHTTP(w, r.WithContext(ctx)) } } func isLoggedIn(r *http.Request) bool { cookie, err := r.Cookie("session_token") if err != nil { return false } user, err := lib.GetUserFromSession(cookie.Value) return err == nil && user != nil }