package api import ( "errors" "log/slog" "net/http" "time" "github.com/go-chi/chi/v5" "github.com/go-chi/render" "github.com/google/uuid" ) func GetChannel(w http.ResponseWriter, r *http.Request) { slog.Debug("channel: entering GetChannel handler") channelID := chi.URLParam(r, "channelID") parsed, err := uuid.Parse(channelID) if err != nil { render.Render(w, r, ErrInvalidRequest(err)) return } channel, err := dbGetChannel(parsed.String()) if err != nil { if errors.Is(err, ErrChannelNotFound) { render.Render(w, r, ErrNotFound) } else { slog.Error("channel: failed to fetch channel", "channelid", parsed.String(), "error", err) render.Render(w, r, ErrInternal(err)) } return } slog.Debug("channel: rendering channel", "channelid", channel.ID, "channelname", channel.Name) if err := render.Render(w, r, NewChannelPayloadResponse(channel)); err != nil { slog.Error("channel: failed to render channel", "channelid", parsed.String(), "error", err) render.Render(w, r, ErrInternal(err)) } } func ListChannels(w http.ResponseWriter, r *http.Request) { slog.Debug("channel: entering ListChannels handler") dbChannels, err := dbGetAllChannels() if err != nil { if errors.Is(err, ErrChannelNotFound) { render.Render(w, r, ErrNotFound) } else { slog.Error("channel: failed to fetch channels", "error", err) render.Render(w, r, ErrInternal(err)) } return } slog.Debug("channel: successfully fetched channels", "count", len(dbChannels)) if err := render.RenderList(w, r, NewChannelListResponse(dbChannels)); err != nil { slog.Error("channel: failed to render channel list response", "error", err) render.Render(w, r, ErrInternal(err)) return } } func newChannelID() uuid.UUID { return uuid.New() } func NewChannel(w http.ResponseWriter, r *http.Request) { slog.Debug("channel: entering NewChannel handler") err := r.ParseMultipartForm(64 << 10) if err != nil { slog.Error("channel: failed to parse multipartform", "error", err) http.Error(w, "Unable to parse form", http.StatusBadRequest) return } newChannelName := r.FormValue("name") newChannelType := r.FormValue("type") newChannelLocation := r.FormValue("location") newChannelNotes := r.FormValue("notes") if newChannelName == "" { slog.Error("channel: channelname is empty") http.Error(w, "Channel name cannot be empty", http.StatusBadRequest) return } newChannel := Channel{ ID: newChannelID(), Name: newChannelName, Created: time.Now(), Type: newChannelType, Location: newChannelLocation, Notes: newChannelNotes, } slog.Debug("channel: adding new channel to database", "channelid", newChannel.ID, "channelname", newChannel.Name) err = dbAddChannel(&newChannel) if err != nil { slog.Error("channel: failed to add new channel", "channelid", newChannel.ID, "channelname", newChannel.Name) render.Render(w, r, ErrInternal(err)) return } slog.Debug("channel: successfully added new channel", "channelid", newChannel.ID, "channelname", newChannel.Name) render.Render(w, r, NewChannelPayloadResponse(&newChannel)) } func DeleteChannel(w http.ResponseWriter, r *http.Request) { slog.Debug("channel: entering DeleteChannel handler") channelID := chi.URLParam(r, "channelID") parsed, err := uuid.Parse(channelID) if err != nil { render.Render(w, r, ErrInvalidRequest(err)) return } err = dbDeleteChannel(parsed.String()) if err != nil { if errors.Is(err, ErrChannelNotFound) { render.Render(w, r, ErrNotFound) } else { slog.Error("channel: failed to delete channel", "channelid", parsed.String(), "error", err) render.Render(w, r, ErrInternal(err)) } return } slog.Debug("channel: deleted channel", "channelid", parsed.String()) w.Write([]byte("Channel deleted successfully")) } type Channel struct { ID uuid.UUID Name string Created time.Time Type string Location string Notes string } type channelKey struct{} type ChannelPayload struct { *Channel }