package service import ( "database/sql" "encoding/json/v2" "errors" "log/slog" "net/http" ) func (svc *Service) listConversations(w http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() log = ctx.Value(logKey).(*slog.Logger) ) rows, err := svc.dbr.SelectConversationsUserId(ctx, "default") if err != nil { log.ErrorContext( ctx, "failed to list conversations", slog.Any("error", err), ) http.Error( w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, ) return } w.Header().Set("Content-Type", "application/json") if err := json.MarshalWrite(w, rows); err != nil { log.ErrorContext( ctx, "failed to encode conversations response", slog.Any("error", err), ) } } func (svc *Service) createConversation(w http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() log = ctx.Value(logKey).(*slog.Logger) req struct { Title *string `json:"title"` SystemMessage *string `json:"system_message"` } ) r.Body = http.MaxBytesReader(w, r.Body, 32<<20) if err := json.UnmarshalRead(r.Body, &req); err != nil { log.ErrorContext( ctx, "failed to decode request", slog.Any("error", err), ) http.Error(w, "invalid request", http.StatusBadRequest) return } system := svc.cfg.SystemMessage if req.SystemMessage != nil { system = *req.SystemMessage } saved, _, err := svc.newConversation( ctx, "default", req.Title, system, ) if err != nil { log.ErrorContext( ctx, "failed to create conversation", slog.Any("error", err), ) http.Error( w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, ) return } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) if err := json.MarshalWrite(w, saved); err != nil { log.ErrorContext( ctx, "failed to encode conversation response", slog.Any("error", err), ) } } func (svc *Service) getConversationHandler( w http.ResponseWriter, r *http.Request, ) { var ( ctx = r.Context() log = ctx.Value(logKey).(*slog.Logger) ) saved, err := svc.dbr.SelectConversationIdUserId( ctx, r.PathValue("id"), "default", ) if errors.Is(err, sql.ErrNoRows) { http.NotFound(w, r) return } if err != nil { log.ErrorContext( ctx, "failed to load conversation", slog.Any("error", err), ) http.Error( w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, ) return } w.Header().Set("Content-Type", "application/json") if err := json.MarshalWrite(w, saved); err != nil { log.ErrorContext( ctx, "failed to encode conversation response", slog.Any("error", err), ) } } func (svc *Service) deleteConversation(w http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() log = ctx.Value(logKey).(*slog.Logger) id = r.PathValue("id") ) if _, err := svc.dbr.SelectConversationIdUserId( ctx, id, "default", ); err != nil { if errors.Is(err, sql.ErrNoRows) { http.NotFound(w, r) return } log.ErrorContext( ctx, "failed to load conversation", slog.Any("error", err), ) http.Error( w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, ) return } c, err := svc.getConversation(ctx, id) if errors.Is(err, sql.ErrNoRows) { http.NotFound(w, r) return } if err != nil { log.ErrorContext( ctx, "failed to get conversation handle", slog.Any("error", err), ) http.Error( w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, ) return } if err := c.Delete(ctx); err != nil { log.ErrorContext( ctx, "failed to delete conversation", slog.Any("error", err), ) http.Error( w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, ) return } svc.mu.Lock() delete(svc.conversations, id) svc.mu.Unlock() w.WriteHeader(http.StatusNoContent) }