enclosing rooms.Room into roomTableData, with methods to be used in tempalte to get other template related derived data structures
241 lines
7.0 KiB
Go
241 lines
7.0 KiB
Go
package routes
|
|
|
|
import (
|
|
"bytes"
|
|
"embed"
|
|
"fmt"
|
|
"html/template"
|
|
"log"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"sunshine.industries/some-automoderation/rooms"
|
|
"sunshine.industries/some-automoderation/sessions"
|
|
)
|
|
|
|
const roomPath = "/room/"
|
|
const raiseHandPath = "/rooms/raise/"
|
|
const subscribeRoomPath = "/rooms/subscribe"
|
|
|
|
// registering all routes for page and logic of /room/:roomName
|
|
func registerPageRoutes(
|
|
templateFs *embed.FS,
|
|
sessionSM sessions.SessionManagement,
|
|
roomsM rooms.RoomManager,
|
|
) {
|
|
http.Handle(roomPath, // ending in / captures all following path sections, i.e room name
|
|
http.StripPrefix(roomPath, roomPageRoute(templateFs, roomsM, sessionSM)))
|
|
|
|
http.Handle(raiseHandPath, // ending in / captures all following path sections, i.e gesture num
|
|
authedPageMiddleware(
|
|
sessionSM,
|
|
http.StripPrefix(raiseHandPath, raiseGestureHandRoute(roomsM))))
|
|
|
|
http.Handle("/rooms/releaseHand",
|
|
authedPageMiddleware(sessionSM, releaseHandRoute(roomsM)))
|
|
|
|
http.Handle(subscribeRoomPath,
|
|
authedPageMiddleware(
|
|
sessionSM,
|
|
http.StripPrefix(subscribeRoomPath, streamingRoomStates(templateFs, roomsM))))
|
|
|
|
http.HandleFunc("/rooms/preview-templates", roomTemplatesPreview(templateFs))
|
|
}
|
|
|
|
func streamingRoomStates(
|
|
templateFs *embed.FS,
|
|
roomsM rooms.RoomManager,
|
|
) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
r.ParseForm()
|
|
roomName := r.FormValue("roomName")
|
|
defer log.Printf("/rooms/subscribe/%s stream ended\n", roomName)
|
|
|
|
session, found := getContextSession(r.Context())
|
|
if !found {
|
|
log.Printf("/rooms/raiseGesture session not found, should be impossible")
|
|
// TODO return error i guess
|
|
return
|
|
}
|
|
if session.RoomId != roomName {
|
|
// not authorized
|
|
log.Printf("/rooms/streamingRoom got unauth with session.RoomId (%s) != roomName (%s)", session.RoomId, roomName)
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
return
|
|
}
|
|
log.Printf("Starting stream for room %s for %d\n", roomName, session.PersonId)
|
|
w.Header().Set("Cache-Control", "no-cache")
|
|
w.Header().Set("Connection", "keep-alive")
|
|
w.Header().Set("Content-Type", "text/event-stream")
|
|
|
|
templFile := "templates/room.gohtml"
|
|
tableTemplates := "templates/tableTemplates.gohtml"
|
|
tmpl := template.Must(
|
|
template.New("").ParseFS(templateFs, tableTemplates, templFile))
|
|
|
|
roomStream := roomsM.Subscribe(r.Context(), roomName)
|
|
for room := range roomStream {
|
|
// log.Printf("/rooms/streamingRoom iterating with %+v", room)
|
|
fmt.Fprint(w, "data: ")
|
|
|
|
var buffer bytes.Buffer
|
|
|
|
roomTemplateData := roomTableData{
|
|
Room: &room,
|
|
currentPerson: session.PersonId,
|
|
}
|
|
err := tmpl.ExecuteTemplate(&buffer, "simpleRoomShow", &roomTemplateData)
|
|
if err != nil {
|
|
log.Printf("/rooms/subscribe/%s got error on template %s", roomName, err)
|
|
}
|
|
|
|
templateStr := buffer.String()
|
|
templateLine := strings.ReplaceAll(templateStr, "\n", "")
|
|
fmt.Fprint(w, templateLine)
|
|
|
|
fmt.Fprint(w, "\n\n")
|
|
w.(http.Flusher).Flush()
|
|
}
|
|
}
|
|
}
|
|
|
|
// if currently speaking? i guess first lower the hand and then raise new
|
|
func raiseGestureHandRoute(
|
|
roomsM rooms.RoomManager,
|
|
) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
gestureInd, err := strconv.Atoi(r.URL.Path)
|
|
gesture, found := rooms.GestureFromInt(gestureInd)
|
|
if err != nil || !found {
|
|
log.Printf("/rooms/raiseGesture error %s gettin hand symbol index from path %s\n", err, r.URL.Path)
|
|
return
|
|
}
|
|
log.Printf("/rooms/raiseGesture successfully got gesture %d : %s", gesture, gesture.String())
|
|
session, found := getContextSession(r.Context())
|
|
if !found {
|
|
log.Printf("/rooms/raiseGesture session not found, should be impossible")
|
|
// TODO return error i guess
|
|
return
|
|
}
|
|
var outerClosureRoom rooms.Room
|
|
err = roomsM.Update(r.Context(), session.RoomId, func(fromRoom rooms.Room) (toRoom rooms.Room) {
|
|
toRoom = fromRoom.RaiseHand(session.PersonId, gesture)
|
|
outerClosureRoom = toRoom
|
|
return toRoom
|
|
})
|
|
if err != nil {
|
|
log.Printf("/rooms/raiseGesture error saving hand: %s\n", err)
|
|
return
|
|
// TODO return error i guess
|
|
}
|
|
log.Printf(">> i attempt to get room with closure: %+v\n", outerClosureRoom)
|
|
w.WriteHeader(http.StatusNoContent)
|
|
|
|
// then htmx style i'll need to re-render the room, i suppose
|
|
// oh, not really, the SSE should send the updated room state
|
|
}
|
|
}
|
|
|
|
func releaseHandRoute(
|
|
roomsM rooms.RoomManager,
|
|
) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
session, found := getContextSession(r.Context())
|
|
if !found {
|
|
log.Printf("/rooms/releaseHand session not found, should be impossible")
|
|
// TODO return error i guess
|
|
return
|
|
}
|
|
err := roomsM.Update(r.Context(), session.RoomId, func(fromRoom rooms.Room) (toRoom rooms.Room) {
|
|
toRoom = fromRoom
|
|
toRoom.ReleaseHand(session.PersonId)
|
|
return toRoom
|
|
})
|
|
if err != nil {
|
|
log.Printf("/rooms/releaseHand error saving hand: %s\n", err)
|
|
return
|
|
// TODO return error i guess
|
|
}
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
}
|
|
|
|
func roomPageRoute(
|
|
templateFs *embed.FS,
|
|
roomsM rooms.RoomManager,
|
|
sessionSM sessions.SessionManagement,
|
|
) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
roomName := r.URL.Path
|
|
if roomName == "" {
|
|
log.Printf("access to empty room")
|
|
// TODO return error i suppose
|
|
w.Header().Add("HX-Redirect", "/")
|
|
return
|
|
}
|
|
|
|
// check session,
|
|
session, err := getRequestSession(r, sessionSM)
|
|
if err != nil || session.RoomId != roomName {
|
|
log.Printf("not authed with session %+v | error %s, but for wrong room, trying to access %s", session, err, roomName)
|
|
renderLoginPage(w, roomName)
|
|
return
|
|
}
|
|
|
|
room, found, err := roomsM.Get(roomName)
|
|
if err != nil || !found {
|
|
log.Printf("/room room for name %s not found or err: %s / found %t", roomName, err, found)
|
|
// TODO here should be append to error place
|
|
w.Header().Add("HX-Redirect", "/")
|
|
return
|
|
}
|
|
|
|
// now we should have a session for this specific room
|
|
fmt.Printf("all checks for room %s passed with %+v", roomName, session)
|
|
|
|
templFile := "templates/room.gohtml"
|
|
baseFile := "templates/base.gohtml"
|
|
tableTemplates := "templates/tableTemplates.gohtml"
|
|
tmpl := template.Must(
|
|
template.New("").ParseFS(templateFs, tableTemplates, templFile, baseFile))
|
|
|
|
type GestureData struct {
|
|
Name string
|
|
Url string
|
|
}
|
|
var gesturesData []GestureData
|
|
for gesture := rooms.ChangeTopic; gesture <= rooms.Meta; gesture++ {
|
|
gesturesData = append(gesturesData, GestureData{
|
|
Name: gesture.String(),
|
|
Url: fmt.Sprintf("%s%d", raiseHandPath, gesture),
|
|
})
|
|
}
|
|
|
|
contentData := struct {
|
|
Room *roomTableData
|
|
Gestures []GestureData
|
|
}{
|
|
Room: &roomTableData{
|
|
Room: &room,
|
|
currentPerson: session.PersonId,
|
|
},
|
|
Gestures: gesturesData,
|
|
}
|
|
data := pageData{
|
|
Base: baseData{
|
|
Title: "room-lala-from-base",
|
|
},
|
|
Content: contentData,
|
|
Header: headerData{
|
|
Title: room.Name,
|
|
},
|
|
}
|
|
|
|
err = tmpl.ExecuteTemplate(w, "full-page", data)
|
|
if err != nil {
|
|
log.Printf("/room/%s my error in executing template, huh\n %s", roomName, err)
|
|
}
|
|
}
|
|
}
|