feed.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package api // import "miniflux.app/v2/internal/api"
  4. import (
  5. json_parser "encoding/json"
  6. "net/http"
  7. "time"
  8. "miniflux.app/v2/internal/http/request"
  9. "miniflux.app/v2/internal/http/response/json"
  10. "miniflux.app/v2/internal/model"
  11. feedHandler "miniflux.app/v2/internal/reader/handler"
  12. "miniflux.app/v2/internal/validator"
  13. )
  14. func (h *handler) createFeed(w http.ResponseWriter, r *http.Request) {
  15. userID := request.UserID(r)
  16. var feedCreationRequest model.FeedCreationRequest
  17. if err := json_parser.NewDecoder(r.Body).Decode(&feedCreationRequest); err != nil {
  18. json.BadRequest(w, r, err)
  19. return
  20. }
  21. // Make the feed category optional for clients who don't support categories.
  22. if feedCreationRequest.CategoryID == 0 {
  23. category, err := h.store.FirstCategory(userID)
  24. if err != nil {
  25. json.ServerError(w, r, err)
  26. return
  27. }
  28. feedCreationRequest.CategoryID = category.ID
  29. }
  30. if validationErr := validator.ValidateFeedCreation(h.store, userID, &feedCreationRequest); validationErr != nil {
  31. json.BadRequest(w, r, validationErr.Error())
  32. return
  33. }
  34. feed, err := feedHandler.CreateFeed(h.store, userID, &feedCreationRequest)
  35. if err != nil {
  36. json.ServerError(w, r, err)
  37. return
  38. }
  39. json.Created(w, r, &feedCreationResponse{FeedID: feed.ID})
  40. }
  41. func (h *handler) refreshFeed(w http.ResponseWriter, r *http.Request) {
  42. feedID := request.RouteInt64Param(r, "feedID")
  43. userID := request.UserID(r)
  44. if !h.store.FeedExists(userID, feedID) {
  45. json.NotFound(w, r)
  46. return
  47. }
  48. err := feedHandler.RefreshFeed(h.store, userID, feedID, false)
  49. if err != nil {
  50. json.ServerError(w, r, err)
  51. return
  52. }
  53. json.NoContent(w, r)
  54. }
  55. func (h *handler) refreshAllFeeds(w http.ResponseWriter, r *http.Request) {
  56. userID := request.UserID(r)
  57. jobs, err := h.store.NewUserBatch(userID, h.store.CountFeeds(userID))
  58. if err != nil {
  59. json.ServerError(w, r, err)
  60. return
  61. }
  62. go func() {
  63. h.pool.Push(jobs)
  64. }()
  65. json.NoContent(w, r)
  66. }
  67. func (h *handler) updateFeed(w http.ResponseWriter, r *http.Request) {
  68. var feedModificationRequest model.FeedModificationRequest
  69. if err := json_parser.NewDecoder(r.Body).Decode(&feedModificationRequest); err != nil {
  70. json.BadRequest(w, r, err)
  71. return
  72. }
  73. userID := request.UserID(r)
  74. feedID := request.RouteInt64Param(r, "feedID")
  75. originalFeed, err := h.store.FeedByID(userID, feedID)
  76. if err != nil {
  77. json.NotFound(w, r)
  78. return
  79. }
  80. if originalFeed == nil {
  81. json.NotFound(w, r)
  82. return
  83. }
  84. if validationErr := validator.ValidateFeedModification(h.store, userID, &feedModificationRequest); validationErr != nil {
  85. json.BadRequest(w, r, validationErr.Error())
  86. return
  87. }
  88. feedModificationRequest.Patch(originalFeed)
  89. if err := h.store.UpdateFeed(originalFeed); err != nil {
  90. json.ServerError(w, r, err)
  91. return
  92. }
  93. originalFeed, err = h.store.FeedByID(userID, feedID)
  94. if err != nil {
  95. json.ServerError(w, r, err)
  96. return
  97. }
  98. json.Created(w, r, originalFeed)
  99. }
  100. func (h *handler) markFeedAsRead(w http.ResponseWriter, r *http.Request) {
  101. feedID := request.RouteInt64Param(r, "feedID")
  102. userID := request.UserID(r)
  103. feed, err := h.store.FeedByID(userID, feedID)
  104. if err != nil {
  105. json.NotFound(w, r)
  106. return
  107. }
  108. if feed == nil {
  109. json.NotFound(w, r)
  110. return
  111. }
  112. if err := h.store.MarkFeedAsRead(userID, feedID, time.Now()); err != nil {
  113. json.ServerError(w, r, err)
  114. return
  115. }
  116. json.NoContent(w, r)
  117. }
  118. func (h *handler) getCategoryFeeds(w http.ResponseWriter, r *http.Request) {
  119. userID := request.UserID(r)
  120. categoryID := request.RouteInt64Param(r, "categoryID")
  121. category, err := h.store.Category(userID, categoryID)
  122. if err != nil {
  123. json.ServerError(w, r, err)
  124. return
  125. }
  126. if category == nil {
  127. json.NotFound(w, r)
  128. return
  129. }
  130. feeds, err := h.store.FeedsByCategoryWithCounters(userID, categoryID)
  131. if err != nil {
  132. json.ServerError(w, r, err)
  133. return
  134. }
  135. json.OK(w, r, feeds)
  136. }
  137. func (h *handler) getFeeds(w http.ResponseWriter, r *http.Request) {
  138. feeds, err := h.store.Feeds(request.UserID(r))
  139. if err != nil {
  140. json.ServerError(w, r, err)
  141. return
  142. }
  143. json.OK(w, r, feeds)
  144. }
  145. func (h *handler) fetchCounters(w http.ResponseWriter, r *http.Request) {
  146. counters, err := h.store.FetchCounters(request.UserID(r))
  147. if err != nil {
  148. json.ServerError(w, r, err)
  149. return
  150. }
  151. json.OK(w, r, counters)
  152. }
  153. func (h *handler) getFeed(w http.ResponseWriter, r *http.Request) {
  154. feedID := request.RouteInt64Param(r, "feedID")
  155. feed, err := h.store.FeedByID(request.UserID(r), feedID)
  156. if err != nil {
  157. json.ServerError(w, r, err)
  158. return
  159. }
  160. if feed == nil {
  161. json.NotFound(w, r)
  162. return
  163. }
  164. json.OK(w, r, feed)
  165. }
  166. func (h *handler) removeFeed(w http.ResponseWriter, r *http.Request) {
  167. feedID := request.RouteInt64Param(r, "feedID")
  168. userID := request.UserID(r)
  169. if !h.store.FeedExists(userID, feedID) {
  170. json.NotFound(w, r)
  171. return
  172. }
  173. if err := h.store.RemoveFeed(userID, feedID); err != nil {
  174. json.ServerError(w, r, err)
  175. return
  176. }
  177. json.NoContent(w, r)
  178. }