package main import ( "context" "encoding/json" "errors" "net/http" "git.cin.su/m/Assistant/contracts/continuity" "git.cin.su/m/Assistant/contracts/identity" ) type attentionRepository interface { AttentionByOwner(context.Context, identity.PrincipalID, int) ([]continuity.AttentionItem, error) } func registerCreatorAttentionRoutes(mux *http.ServeMux, identityClient creatorIdentityClient, repository attentionRepository) { mux.HandleFunc("GET /v1/creator/attention", func(w http.ResponseWriter, r *http.Request) { session, ok := creatorSessionForAttention(w, r, identityClient) if !ok { return } limit, err := parseListLimit(r.URL.Query().Get("limit")) if err != nil { http.Error(w, "invalid attention limit", http.StatusBadRequest) return } items, err := repository.AttentionByOwner(r.Context(), session.PrincipalID, limit) if err != nil { http.Error(w, "attention unavailable", http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") w.Header().Set("Cache-Control", "no-store") _ = json.NewEncoder(w).Encode(continuity.AttentionListResult{Items: items}) }) mux.HandleFunc("GET /v1/creator/today", func(w http.ResponseWriter, r *http.Request) { session, ok := creatorSessionForAttention(w, r, identityClient) if !ok { return } items, err := repository.AttentionByOwner(r.Context(), session.PrincipalID, 50) if err != nil { http.Error(w, "today unavailable", http.StatusInternalServerError) return } result := continuity.TodayResult{Items: make([]continuity.TodayItem, 0, len(items))} for _, item := range items { result.Items = append(result.Items, continuity.TodayItem{ Title: item.Summary, WhenUnixMillis: item.DueAtUnixMillis, AttentionLevel: item.Level, AttentionState: item.State, HumanState: humanAttentionState(item.State), DeliveryState: humanDeliveryState(item), SourceDescription: humanAttentionSource(item.SourceKind), ResponseHint: humanResponseHint(item), }) } w.Header().Set("Content-Type", "application/json") w.Header().Set("Cache-Control", "no-store") _ = json.NewEncoder(w).Encode(result) }) } func creatorSessionForAttention(w http.ResponseWriter, r *http.Request, identityClient creatorIdentityClient) (identity.CreatorSession, bool) { session, err := identityClient.Session(r.Context(), r.Header.Get("Authorization")) if errors.Is(err, errCreatorSessionDenied) { http.Error(w, "creator session denied", http.StatusUnauthorized) return identity.CreatorSession{}, false } if err != nil { http.Error(w, "identity service unavailable", http.StatusServiceUnavailable) return identity.CreatorSession{}, false } return session, true } func humanAttentionState(state continuity.AttentionState) string { switch state { case continuity.AttentionPending: return "ожидает внимания" case continuity.AttentionDelivering: return "доставляется" case continuity.AttentionDelivered: return "доставлено" case continuity.AttentionResolved: return "закрыто" case continuity.AttentionSuppressed: return "скрыто" case continuity.AttentionExpired: return "истекло" case continuity.AttentionFailed: return "не доставлено" default: return "состояние уточняется" } } func humanResponseHint(item continuity.AttentionItem) string { if item.State == continuity.AttentionDelivered || item.State == continuity.AttentionPending || item.State == continuity.AttentionFailed { return "Можно ответить: «Готово», «Отложи на 10 минут» или «Отмени»." } if item.ResponseOutcome != "" { return "Ответ записан: " + string(item.ResponseOutcome) } return "" } func humanDeliveryState(item continuity.AttentionItem) string { if item.State == continuity.AttentionDelivered { return "уведомление отправлено" } if item.State == continuity.AttentionDelivering { return "уведомление отправляется" } return "уведомление ещё не отправлено" } func humanAttentionSource(kind continuity.AttentionSourceKind) string { if kind == continuity.AttentionSourceProspectiveReminder { return "напоминание" } return "событие Домового" }