clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

main
tinyrelay / tinyclient / chat_pages.go
chat_pages.go 2.3K
1package tinyclient23import (4 "encoding/json"5 "net/http"6 "strings"7)89func (a *App) handleChatRoute(w http.ResponseWriter, r *http.Request) bool {10 path := r.URL.Path11 if path != "/rooms" && path != "/chat" && !strings.HasPrefix(path, "/chat/") {12 return false13 }14 if r.Method != http.MethodGet && r.Method != http.MethodHead {15 http.Error(w, "method not allowed", http.StatusMethodNotAllowed)16 return true17 }18 if path == "/rooms" {19 target := requestPrefix(r) + "/chat"20 if r.URL.RawQuery != "" {21 target += "?" + r.URL.RawQuery22 }23 http.Redirect(w, r, target, http.StatusMovedPermanently)24 return true25 }26 if path == "/chat/activity" {27 a.chatActivityHTTP(w, r)28 return true29 }30 if path == "/chat/events" {31 a.directMessagesJSON(w, r)32 return true33 }34 actor, _ := a.resolveActor(r)35 data := PageData{Tab: "chat", Title: "Chat | " + a.backend.Slug(), Query: r.URL.Query()}36 if path != "/chat" {37 peer, ok := strings.CutPrefix(path, "/chat/dm/")38 if !ok || !eventIDPattern.MatchString(peer) {39 http.NotFound(w, r)40 return true41 }42 data.Tab, data.View, data.Title = "direct", peer, "Direct chat | "+a.backend.Slug()43 }44 if data.Tab == "chat" {45 result, err, typed := a.typedRoomResult(r.Context(), roomPath{tab: "rooms"}, r.URL.Query(), actor)46 if !typed {47 params, _ := json.Marshal(map[string]any{"limit": 100, "cursor": r.URL.Query().Get("cursor")})48 result, err = a.backend.Query(r.Context(), "browserooms", []json.RawMessage{params}, actor)49 }50 data.Event, data.Feed = result, browseRows(result)51 data.Rooms = data.Feed52 if err != nil {53 data.Error = err.Error()54 }55 } else {56 data.Rooms = a.roomList(r.Context(), actor)57 }58 a.render(w, r, data)59 return true60}6162func (a *App) directMessagesJSON(w http.ResponseWriter, r *http.Request) {63 w.Header().Set("Cache-Control", "private, no-store")64 actor, err := a.resolveActor(r)65 if err != nil || actor == "" {66 http.Error(w, "Sign in to open direct chats.", http.StatusUnauthorized)67 return68 }69 params, _ := json.Marshal(map[string]any{"limit": 50, "cursor": r.URL.Query().Get("cursor")})70 result, err := a.backend.Query(r.Context(), "browsedirectmessages", []json.RawMessage{params}, actor)71 if err != nil {72 http.Error(w, err.Error(), publicErrorStatus(err))73 return74 }75 w.Header().Set("Content-Type", "application/json; charset=utf-8")76 _ = json.NewEncoder(w).Encode(result)77}