1// Copyright 2017 Frédéric Guillot. All rights reserved.
2// Use of this source code is governed by the Apache 2.0
3// license that can be found in the LICENSE file.
4
5package api // import "miniflux.app/api"
6
7import (
8	json_parser "encoding/json"
9	"net/http"
10	"time"
11
12	"miniflux.app/http/request"
13	"miniflux.app/http/response/json"
14	"miniflux.app/model"
15	feedHandler "miniflux.app/reader/handler"
16	"miniflux.app/validator"
17)
18
19func (h *handler) createFeed(w http.ResponseWriter, r *http.Request) {
20	userID := request.UserID(r)
21
22	var feedCreationRequest model.FeedCreationRequest
23	if err := json_parser.NewDecoder(r.Body).Decode(&feedCreationRequest); err != nil {
24		json.BadRequest(w, r, err)
25		return
26	}
27
28	if validationErr := validator.ValidateFeedCreation(h.store, userID, &feedCreationRequest); validationErr != nil {
29		json.BadRequest(w, r, validationErr.Error())
30		return
31	}
32
33	feed, err := feedHandler.CreateFeed(h.store, userID, &feedCreationRequest)
34	if err != nil {
35		json.ServerError(w, r, err)
36		return
37	}
38
39	json.Created(w, r, &feedCreationResponse{FeedID: feed.ID})
40}
41
42func (h *handler) refreshFeed(w http.ResponseWriter, r *http.Request) {
43	feedID := request.RouteInt64Param(r, "feedID")
44	userID := request.UserID(r)
45
46	if !h.store.FeedExists(userID, feedID) {
47		json.NotFound(w, r)
48		return
49	}
50
51	err := feedHandler.RefreshFeed(h.store, userID, feedID)
52	if err != nil {
53		json.ServerError(w, r, err)
54		return
55	}
56
57	json.NoContent(w, r)
58}
59
60func (h *handler) refreshAllFeeds(w http.ResponseWriter, r *http.Request) {
61	userID := request.UserID(r)
62	jobs, err := h.store.NewUserBatch(userID, h.store.CountFeeds(userID))
63	if err != nil {
64		json.ServerError(w, r, err)
65		return
66	}
67
68	go func() {
69		h.pool.Push(jobs)
70	}()
71
72	json.NoContent(w, r)
73}
74
75func (h *handler) updateFeed(w http.ResponseWriter, r *http.Request) {
76	var feedModificationRequest model.FeedModificationRequest
77	if err := json_parser.NewDecoder(r.Body).Decode(&feedModificationRequest); err != nil {
78		json.BadRequest(w, r, err)
79		return
80	}
81
82	userID := request.UserID(r)
83	feedID := request.RouteInt64Param(r, "feedID")
84
85	originalFeed, err := h.store.FeedByID(userID, feedID)
86	if err != nil {
87		json.NotFound(w, r)
88		return
89	}
90
91	if originalFeed == nil {
92		json.NotFound(w, r)
93		return
94	}
95
96	if validationErr := validator.ValidateFeedModification(h.store, userID, &feedModificationRequest); validationErr != nil {
97		json.BadRequest(w, r, validationErr.Error())
98		return
99	}
100
101	feedModificationRequest.Patch(originalFeed)
102	if err := h.store.UpdateFeed(originalFeed); err != nil {
103		json.ServerError(w, r, err)
104		return
105	}
106
107	originalFeed, err = h.store.FeedByID(userID, feedID)
108	if err != nil {
109		json.ServerError(w, r, err)
110		return
111	}
112
113	json.Created(w, r, originalFeed)
114}
115
116func (h *handler) markFeedAsRead(w http.ResponseWriter, r *http.Request) {
117	feedID := request.RouteInt64Param(r, "feedID")
118	userID := request.UserID(r)
119
120	feed, err := h.store.FeedByID(userID, feedID)
121	if err != nil {
122		json.NotFound(w, r)
123		return
124	}
125
126	if feed == nil {
127		json.NotFound(w, r)
128		return
129	}
130
131	if err := h.store.MarkFeedAsRead(userID, feedID, time.Now()); err != nil {
132		json.ServerError(w, r, err)
133		return
134	}
135
136	json.NoContent(w, r)
137}
138
139func (h *handler) getCategoryFeeds(w http.ResponseWriter, r *http.Request) {
140	userID := request.UserID(r)
141	categoryID := request.RouteInt64Param(r, "categoryID")
142
143	category, err := h.store.Category(userID, categoryID)
144	if err != nil {
145		json.ServerError(w, r, err)
146		return
147	}
148
149	if category == nil {
150		json.NotFound(w, r)
151		return
152	}
153
154	feeds, err := h.store.FeedsByCategoryWithCounters(userID, categoryID)
155	if err != nil {
156		json.ServerError(w, r, err)
157		return
158	}
159
160	json.OK(w, r, feeds)
161}
162
163func (h *handler) getFeeds(w http.ResponseWriter, r *http.Request) {
164	feeds, err := h.store.Feeds(request.UserID(r))
165	if err != nil {
166		json.ServerError(w, r, err)
167		return
168	}
169
170	json.OK(w, r, feeds)
171}
172
173func (h *handler) getFeed(w http.ResponseWriter, r *http.Request) {
174	feedID := request.RouteInt64Param(r, "feedID")
175	feed, err := h.store.FeedByID(request.UserID(r), feedID)
176	if err != nil {
177		json.ServerError(w, r, err)
178		return
179	}
180
181	if feed == nil {
182		json.NotFound(w, r)
183		return
184	}
185
186	json.OK(w, r, feed)
187}
188
189func (h *handler) removeFeed(w http.ResponseWriter, r *http.Request) {
190	feedID := request.RouteInt64Param(r, "feedID")
191	userID := request.UserID(r)
192
193	if !h.store.FeedExists(userID, feedID) {
194		json.NotFound(w, r)
195		return
196	}
197
198	if err := h.store.RemoveFeed(userID, feedID); err != nil {
199		json.ServerError(w, r, err)
200		return
201	}
202
203	json.NoContent(w, r)
204}
205