Ryanhub - file viewer
filename: assistant/server/calendar.go
branch: main
back to repo
package server

import (
	"net/http"
	"strconv"

	"assistant/memory"
	"assistant/util"
)

func (a *API) requireStore(w http.ResponseWriter) *memory.Store {
	if a.Store == nil {
		_ = util.WriteJSON(w, http.StatusServiceUnavailable, map[string]string{"error": "memory store not configured"})
		return nil
	}
	return a.Store
}

func (a *API) handleCalendarItemsGET(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}
	st := a.requireStore(w)
	if st == nil {
		return
	}
	from := r.URL.Query().Get("from")
	to := r.URL.Query().Get("to")
	items, err := st.ListCalendarRange(from, to)
	if err != nil {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
		return
	}
	rev, _ := st.CalendarRevision()
	_ = util.WriteJSON(w, http.StatusOK, map[string]any{"items": items, "revision": rev})
}

func (a *API) handleCalendarItemGET(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}
	st := a.requireStore(w)
	if st == nil {
		return
	}
	idStr := r.PathValue("id")
	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil || id <= 0 {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid id"})
		return
	}
	it, err := st.GetCalendarItem(id)
	if err != nil {
		_ = util.WriteJSON(w, http.StatusNotFound, map[string]string{"error": "not found"})
		return
	}
	rev, _ := st.CalendarRevision()
	_ = util.WriteJSON(w, http.StatusOK, map[string]any{"item": it, "revision": rev})
}

func (a *API) handleCalendarItemsPOST(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}
	st := a.requireStore(w)
	if st == nil {
		return
	}
	var body memory.CalendarInput
	if err := util.DecodeJSON(r.Body, 1<<20, &body); err != nil {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid JSON body"})
		return
	}
	body.Source = "manual"
	id, err := st.AddCalendarItem(body)
	if err != nil {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
		return
	}
	rev, _ := st.CalendarRevision()
	_ = util.WriteJSON(w, http.StatusOK, map[string]any{"id": id, "revision": rev})
}

func (a *API) handleCalendarItemPUT(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPut {
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}
	st := a.requireStore(w)
	if st == nil {
		return
	}
	idStr := r.PathValue("id")
	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil || id <= 0 {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid id"})
		return
	}
	var body memory.CalendarInput
	if err := util.DecodeJSON(r.Body, 1<<20, &body); err != nil {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid JSON body"})
		return
	}
	body.Source = "manual"
	if err := st.UpdateCalendarItem(id, body); err != nil {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
		return
	}
	rev, _ := st.CalendarRevision()
	_ = util.WriteJSON(w, http.StatusOK, map[string]any{"ok": true, "revision": rev})
}

func (a *API) handleCalendarItemDELETE(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodDelete {
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}
	st := a.requireStore(w)
	if st == nil {
		return
	}
	idStr := r.PathValue("id")
	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil || id <= 0 {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid id"})
		return
	}
	if err := st.DeleteCalendarItem(id); err != nil {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
		return
	}
	rev, _ := st.CalendarRevision()
	_ = util.WriteJSON(w, http.StatusOK, map[string]any{"ok": true, "revision": rev})
}

func (a *API) handleCalendarPendingGET(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}
	st := a.requireStore(w)
	if st == nil {
		return
	}
	_ = st.ExpireOldCalendarPending()
	list, err := st.ListCalendarPending()
	if err != nil {
		_ = util.WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
		return
	}
	rev, _ := st.CalendarRevision()
	_ = util.WriteJSON(w, http.StatusOK, map[string]any{"pending": list, "revision": rev})
}

func (a *API) handleCalendarPendingConfirm(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}
	st := a.requireStore(w)
	if st == nil {
		return
	}
	idStr := r.PathValue("id")
	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil || id <= 0 {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid id"})
		return
	}
	if err := st.ApplyCalendarPending(id); err != nil {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
		return
	}
	rev, _ := st.CalendarRevision()
	_ = util.WriteJSON(w, http.StatusOK, map[string]any{"ok": true, "revision": rev})
}

func (a *API) handleCalendarPendingUpdate(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPut {
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}
	st := a.requireStore(w)
	if st == nil {
		return
	}
	idStr := r.PathValue("id")
	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil || id <= 0 {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid id"})
		return
	}
	var body memory.CalendarPendingEditInput
	if err := util.DecodeJSON(r.Body, 1<<20, &body); err != nil {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid JSON body"})
		return
	}
	if err := st.UpdateCalendarPendingItem(id, body); err != nil {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
		return
	}
	rev, _ := st.CalendarRevision()
	_ = util.WriteJSON(w, http.StatusOK, map[string]any{"ok": true, "revision": rev})
}

func (a *API) handleCalendarPendingReject(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}
	st := a.requireStore(w)
	if st == nil {
		return
	}
	idStr := r.PathValue("id")
	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil || id <= 0 {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid id"})
		return
	}
	if err := st.RejectCalendarPending(id); err != nil {
		_ = util.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
		return
	}
	rev, _ := st.CalendarRevision()
	_ = util.WriteJSON(w, http.StatusOK, map[string]any{"ok": true, "revision": rev})
}