package api import ( "errors" "fmt" "log/slog" "net/http" "time" "github.com/go-chi/chi/v5" "github.com/go-chi/render" "github.com/google/uuid" ) type Message struct { ID uuid.UUID Channel Channel Created time.Time Content string Audio File } type MessagePayload struct { *Message } func GetMessage(w http.ResponseWriter, r *http.Request) { slog.Debug("message: entering GetMessage handler") messageID := chi.URLParam(r, "messageID") parsed, err := uuid.Parse(messageID) if err != nil { render.Render(w, r, ErrInvalidRequest(err)) return } msg, err := dbGetMessage(parsed.String()) if err != nil { if errors.Is(err, ErrMessageNotFound) { render.Render(w, r, ErrNotFound) } else { slog.Error("message: failed to fetch message", "messageid", parsed.String(), "error", err) render.Render(w, r, ErrInternal(err)) } return } slog.Debug("message: rendering message", "messageid", msg.ID) if err := render.Render(w, r, NewMessagePayloadResponse(msg)); err != nil { slog.Error("message: failed to render message", "messageid", parsed.String(), "error", err) render.Render(w, r, ErrInternal(err)) } } func ListMessages(w http.ResponseWriter, r *http.Request) { slog.Debug("message: entering ListMessages handler") channelID := chi.URLParam(r, "channelID") parsed, err := uuid.Parse(channelID) if err != nil { render.Render(w, r, ErrInvalidRequest(err)) return } var from, to *time.Time if v := r.URL.Query().Get("from"); v != "" { t, err := time.Parse(time.RFC3339, v) if err != nil { render.Render(w, r, ErrInvalidRequest(fmt.Errorf("invalid 'from' timestamp: %w", err))) return } from = &t } if v := r.URL.Query().Get("to"); v != "" { t, err := time.Parse(time.RFC3339, v) if err != nil { render.Render(w, r, ErrInvalidRequest(fmt.Errorf("invalid 'to' timestamp: %w", err))) return } to = &t } messages, err := dbGetMessagesByChannel(parsed.String(), from, to) if err != nil { if errors.Is(err, ErrMessageNotFound) { render.Render(w, r, ErrNotFound) } else { slog.Error("message: failed to fetch messages", "channelid", parsed.String(), "error", err) render.Render(w, r, ErrInternal(err)) } return } slog.Debug("message: successfully fetched messages", "channelid", parsed.String(), "count", len(messages)) if err := render.RenderList(w, r, NewMessageListResponse(messages)); err != nil { slog.Error("message: failed to render message list", "channelid", parsed.String(), "error", err) render.Render(w, r, ErrInternal(err)) } }