entry.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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. package api // import "miniflux.app/api"
  5. import (
  6. "errors"
  7. "net/http"
  8. "time"
  9. "miniflux.app/http/request"
  10. "miniflux.app/http/response/json"
  11. "miniflux.app/model"
  12. "miniflux.app/storage"
  13. )
  14. // GetFeedEntry is the API handler to get a single feed entry.
  15. func (c *Controller) GetFeedEntry(w http.ResponseWriter, r *http.Request) {
  16. feedID := request.RouteInt64Param(r, "feedID")
  17. entryID := request.RouteInt64Param(r, "entryID")
  18. builder := c.store.NewEntryQueryBuilder(request.UserID(r))
  19. builder.WithFeedID(feedID)
  20. builder.WithEntryID(entryID)
  21. entry, err := builder.GetEntry()
  22. if err != nil {
  23. json.ServerError(w, r, err)
  24. return
  25. }
  26. if entry == nil {
  27. json.NotFound(w, r)
  28. return
  29. }
  30. json.OK(w, r, entry)
  31. }
  32. // GetEntry is the API handler to get a single entry.
  33. func (c *Controller) GetEntry(w http.ResponseWriter, r *http.Request) {
  34. entryID := request.RouteInt64Param(r, "entryID")
  35. builder := c.store.NewEntryQueryBuilder(request.UserID(r))
  36. builder.WithEntryID(entryID)
  37. entry, err := builder.GetEntry()
  38. if err != nil {
  39. json.ServerError(w, r, err)
  40. return
  41. }
  42. if entry == nil {
  43. json.NotFound(w, r)
  44. return
  45. }
  46. json.OK(w, r, entry)
  47. }
  48. // GetFeedEntries is the API handler to get all feed entries.
  49. func (c *Controller) GetFeedEntries(w http.ResponseWriter, r *http.Request) {
  50. feedID := request.RouteInt64Param(r, "feedID")
  51. status := request.QueryStringParam(r, "status", "")
  52. if status != "" {
  53. if err := model.ValidateEntryStatus(status); err != nil {
  54. json.BadRequest(w, r, err)
  55. return
  56. }
  57. }
  58. order := request.QueryStringParam(r, "order", model.DefaultSortingOrder)
  59. if err := model.ValidateEntryOrder(order); err != nil {
  60. json.BadRequest(w, r, err)
  61. return
  62. }
  63. direction := request.QueryStringParam(r, "direction", model.DefaultSortingDirection)
  64. if err := model.ValidateDirection(direction); err != nil {
  65. json.BadRequest(w, r, err)
  66. return
  67. }
  68. limit := request.QueryIntParam(r, "limit", 100)
  69. offset := request.QueryIntParam(r, "offset", 0)
  70. if err := model.ValidateRange(offset, limit); err != nil {
  71. json.BadRequest(w, r, err)
  72. return
  73. }
  74. builder := c.store.NewEntryQueryBuilder(request.UserID(r))
  75. builder.WithFeedID(feedID)
  76. builder.WithStatus(status)
  77. builder.WithOrder(order)
  78. builder.WithDirection(direction)
  79. builder.WithOffset(offset)
  80. builder.WithLimit(limit)
  81. configureFilters(builder, r)
  82. entries, err := builder.GetEntries()
  83. if err != nil {
  84. json.ServerError(w, r, err)
  85. return
  86. }
  87. count, err := builder.CountEntries()
  88. if err != nil {
  89. json.ServerError(w, r, err)
  90. return
  91. }
  92. json.OK(w, r, &entriesResponse{Total: count, Entries: entries})
  93. }
  94. // GetEntries is the API handler to fetch entries.
  95. func (c *Controller) GetEntries(w http.ResponseWriter, r *http.Request) {
  96. status := request.QueryStringParam(r, "status", "")
  97. if status != "" {
  98. if err := model.ValidateEntryStatus(status); err != nil {
  99. json.BadRequest(w, r, err)
  100. return
  101. }
  102. }
  103. order := request.QueryStringParam(r, "order", model.DefaultSortingOrder)
  104. if err := model.ValidateEntryOrder(order); err != nil {
  105. json.BadRequest(w, r, err)
  106. return
  107. }
  108. direction := request.QueryStringParam(r, "direction", model.DefaultSortingDirection)
  109. if err := model.ValidateDirection(direction); err != nil {
  110. json.BadRequest(w, r, err)
  111. return
  112. }
  113. limit := request.QueryIntParam(r, "limit", 100)
  114. offset := request.QueryIntParam(r, "offset", 0)
  115. if err := model.ValidateRange(offset, limit); err != nil {
  116. json.BadRequest(w, r, err)
  117. return
  118. }
  119. builder := c.store.NewEntryQueryBuilder(request.UserID(r))
  120. builder.WithStatus(status)
  121. builder.WithOrder(order)
  122. builder.WithDirection(direction)
  123. builder.WithOffset(offset)
  124. builder.WithLimit(limit)
  125. configureFilters(builder, r)
  126. entries, err := builder.GetEntries()
  127. if err != nil {
  128. json.ServerError(w, r, err)
  129. return
  130. }
  131. count, err := builder.CountEntries()
  132. if err != nil {
  133. json.ServerError(w, r, err)
  134. return
  135. }
  136. json.OK(w, r, &entriesResponse{Total: count, Entries: entries})
  137. }
  138. // SetEntryStatus is the API handler to change the status of entries.
  139. func (c *Controller) SetEntryStatus(w http.ResponseWriter, r *http.Request) {
  140. entryIDs, status, err := decodeEntryStatusPayload(r.Body)
  141. if err != nil {
  142. json.BadRequest(w , r, errors.New("Invalid JSON payload"))
  143. return
  144. }
  145. if err := model.ValidateEntryStatus(status); err != nil {
  146. json.BadRequest(w, r, err)
  147. return
  148. }
  149. if err := c.store.SetEntriesStatus(request.UserID(r), entryIDs, status); err != nil {
  150. json.ServerError(w, r, err)
  151. return
  152. }
  153. json.NoContent(w, r)
  154. }
  155. // ToggleBookmark is the API handler to toggle bookmark status.
  156. func (c *Controller) ToggleBookmark(w http.ResponseWriter, r *http.Request) {
  157. entryID := request.RouteInt64Param(r, "entryID")
  158. if err := c.store.ToggleBookmark(request.UserID(r), entryID); err != nil {
  159. json.ServerError(w, r, err)
  160. return
  161. }
  162. json.NoContent(w, r)
  163. }
  164. func configureFilters(builder *storage.EntryQueryBuilder, r *http.Request) {
  165. beforeEntryID := request.QueryInt64Param(r, "before_entry_id", 0)
  166. if beforeEntryID != 0 {
  167. builder.BeforeEntryID(beforeEntryID)
  168. }
  169. afterEntryID := request.QueryInt64Param(r, "after_entry_id", 0)
  170. if afterEntryID != 0 {
  171. builder.AfterEntryID(afterEntryID)
  172. }
  173. beforeTimestamp := request.QueryInt64Param(r, "before", 0)
  174. if beforeTimestamp != 0 {
  175. builder.BeforeDate(time.Unix(beforeTimestamp, 0))
  176. }
  177. afterTimestamp := request.QueryInt64Param(r, "after", 0)
  178. if afterTimestamp != 0 {
  179. builder.AfterDate(time.Unix(afterTimestamp, 0))
  180. }
  181. if request.HasQueryParam(r, "starred") {
  182. builder.WithStarred()
  183. }
  184. searchQuery := request.QueryStringParam(r, "search", "")
  185. if searchQuery != "" {
  186. builder.WithSearchQuery(searchQuery)
  187. }
  188. }