func (h *handler) handleUnreadItems(w http.ResponseWriter, r *http.Request) {
	userID := request.UserID(r)
	logger.Debug("[Fever] Fetching unread items for user #%d", userID)
	builder := h.store.NewEntryQueryBuilder(userID)
	builder.WithStatus(model.EntryStatusUnread)
	rawEntryIDs, err := builder.GetEntryIDs()
	if err != nil {
		json.ServerError(w, r, err)
		return
	}
	var itemIDs []string
	for _, entryID := range rawEntryIDs {
		itemIDs = append(itemIDs, strconv.FormatInt(entryID, 10))
	}
	var result unreadResponse
	result.ItemIDs = strings.Join(itemIDs, ",")
	result.SetCommonValues()
	json.OK(w, r, result)
}
/*
The unread_item_ids and saved_item_ids arguments can be used to keep your local cache synced
with the remote Fever installation.

A request with the unread_item_ids argument will return one additional member:
unread_item_ids (string/comma-separated list of positive integers)
package fever  
import (
	"net/http"
	"strconv"
	"strings"
	"time"
	"miniflux.app/http/request"
	"miniflux.app/http/response/json"
	"miniflux.app/integration"
	"miniflux.app/logger"
	"miniflux.app/model"
	"miniflux.app/storage"
	"github.com/gorilla/mux"
)
func Serve(router *mux.Router, store *storage.Storage) {
	handler := &handler{store}
	sr := router.PathPrefix("/fever").Subrouter()
	sr.Use(newMiddleware(store).serve)
	sr.HandleFunc("/", handler.serve).Name("feverEndpoint")
}
type handler struct {
	store *storage.Storage
}
func (h *handler) serve(w http.ResponseWriter, r *http.Request) {
	switch {
	case request.HasQueryParam(r, "groups"):
		h.handleGroups(w, r)
	case request.HasQueryParam(r, "feeds"):
		h.handleFeeds(w, r)
	case request.HasQueryParam(r, "favicons"):
		h.handleFavicons(w, r)
	case request.HasQueryParam(r, "unread_item_ids"):
		h.handleUnreadItems(w, r)
	case request.HasQueryParam(r, "saved_item_ids"):
		h.handleSavedItems(w, r)
	case request.HasQueryParam(r, "items"):
		h.handleItems(w, r)
	case r.FormValue("mark") == "item":
		h.handleWriteItems(w, r)
	case r.FormValue("mark") == "feed":
		h.handleWriteFeeds(w, r)
	case r.FormValue("mark") == "group":
		h.handleWriteGroups(w, r)
	default:
		json.OK(w, r, newBaseResponse())
	}
}
func (h *handler) handleGroups(w http.ResponseWriter, r *http.Request) {
	userID := request.UserID(r)
	logger.Debug("[Fever] Fetching groups for user #%d", userID)
	categories, err := h.store.Categories(userID)
	if err != nil {
		json.ServerError(w, r, err)
		return
	}
	feeds, err := h.store.Feeds(userID)
	if err != nil {
		json.ServerError(w, r, err)
		return
	}
	var result groupsResponse
	for _, category := range categories {
		result.Groups = append(result.Groups, group{ID: category.ID, Title: category.Title})
	}
	result.FeedsGroups = h.buildFeedGroups(feeds)
	result.SetCommonValues()
	json.OK(w, r, result)
}
func (h *handler) handleFeeds(w http.ResponseWriter, r *http.Request) {
	userID := request.UserID(r)
	logger.Debug("[Fever] Fetching feeds for userID=%d", userID)
	feeds, err := h.store.Feeds(userID)
	if err != nil {
		json.ServerError(w, r, err)
		return
	}
	var result feedsResponse
	result.Feeds = make([]feed, 0)
	for _, f := range feeds {
		subscripion := feed{
			ID:          f.ID,
			Title:       f.Title,
			URL:         f.FeedURL,
			SiteURL:     f.SiteURL,
			IsSpark:     0,
			LastUpdated: f.CheckedAt.Unix(),
		}
		if f.Icon != nil {
			subscripion.FaviconID = f.Icon.IconID
		}
		result.Feeds = append(result.Feeds, subscripion)
	}
	result.FeedsGroups = h.buildFeedGroups(feeds)
	result.SetCommonValues()
	json.OK(w, r, result)
}
func (h *handler) handleFavicons(w http.ResponseWriter, r *http.Request) {
	userID := request.UserID(r)
	logger.Debug("[Fever] Fetching favicons for user #%d", userID)
	icons, err := h.store.Icons(userID)
	if err != nil {
		json.ServerError(w, r, err)
		return
	}
	var result faviconsResponse
	for _, i := range icons {
		result.Favicons = append(result.Favicons, favicon{
			ID:   i.ID,
			Data: i.DataURL(),
		})
	}
	result.SetCommonValues()
	json.OK(w, r, result)
}
func (h *handler) handleItems(w http.ResponseWriter, r *http.Request) {
	var result itemsResponse
	userID := request.UserID(r)
	builder := h.store.NewEntryQueryBuilder(userID)
	builder.WithoutStatus(model.EntryStatusRemoved)
	builder.WithLimit(50)
	builder.WithOrder("id")
	builder.WithDirection(model.DefaultSortingDirection)
	switch {
	case request.HasQueryParam(r, "since_id"):
		sinceID := request.QueryInt64Param(r, "since_id", 0)
		if sinceID > 0 {
			logger.Debug("[Fever] Fetching items since #%d for user #%d", sinceID, userID)
			builder.AfterEntryID(sinceID)
		}
	case request.HasQueryParam(r, "max_id"):
		maxID := request.QueryInt64Param(r, "max_id", 0)
		if maxID == 0 {
			logger.Debug("[Fever] Fetching most recent items for user #%d", userID)
			builder.WithDirection("desc")
		} else if maxID > 0 {
			logger.Debug("[Fever] Fetching items before #%d for user #%d", maxID, userID)
			builder.BeforeEntryID(maxID)
			builder.WithDirection("desc")
		}
	case request.HasQueryParam(r, "with_ids"):
		csvItemIDs := request.QueryStringParam(r, "with_ids", "")
		if csvItemIDs != "" {
			var itemIDs []int64
			for _, strItemID := range strings.Split(csvItemIDs, ",") {
				strItemID = strings.TrimSpace(strItemID)
				itemID, _ := strconv.ParseInt(strItemID, 10, 64)
				itemIDs = append(itemIDs, itemID)
			}
			builder.WithEntryIDs(itemIDs)
		}
	default:
		logger.Debug("[Fever] Fetching oldest items for user #%d", userID)
	}
	entries, err := builder.GetEntries()
	if err != nil {
		json.ServerError(w, r, err)
		return
	}
	builder = h.store.NewEntryQueryBuilder(userID)
	builder.WithoutStatus(model.EntryStatusRemoved)
	result.Total, err = builder.CountEntries()
	if err != nil {
		json.ServerError(w, r, err)
		return
	}
	result.Items = make([]item, 0)
	for _, entry := range entries {
		isRead := 0
		if entry.Status == model.EntryStatusRead {
			isRead = 1
		}
		isSaved := 0
		if entry.Starred {
			isSaved = 1
		}
		result.Items = append(result.Items, item{
			ID:        entry.ID,
			FeedID:    entry.FeedID,
			Title:     entry.Title,
			Author:    entry.Author,
			HTML:      entry.Content,
			URL:       entry.URL,
			IsSaved:   isSaved,
			IsRead:    isRead,
			CreatedAt: entry.Date.Unix(),
		})
	}
	result.SetCommonValues()
	json.OK(w, r, result)
}