category.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. let express = require('express')
  2. let router = express.Router()
  3. const Errors = require('../lib/errors')
  4. let pagination = require('../lib/pagination')
  5. let { Category, Post, Thread, User } = require('../models')
  6. router.get('/', async (req, res) => {
  7. try {
  8. let categories = await Category.findAll()
  9. res.json(categories)
  10. } catch (e) {
  11. res.status(500)
  12. res.json({
  13. errors: [Errors.unknown]
  14. })
  15. }
  16. })
  17. router.get('/:category', async (req, res) => {
  18. function concatenateThreads(threads) {
  19. let processedThreads = []
  20. threads.forEach(category => {
  21. let jsonCategory = category.toJSON()
  22. processedThreads.push(...jsonCategory.Threads)
  23. })
  24. return processedThreads
  25. }
  26. try {
  27. let threads, threadsLatestPost, resThreads, user
  28. let { from, limit } = pagination.getPaginationProps(req.query)
  29. if(req.query.username) {
  30. user = await User.findOne({ where: { username: req.query.username }})
  31. }
  32. function threadInclude(order) {
  33. let options = {
  34. model: Thread,
  35. limit,
  36. where: {
  37. id: { $gte: from }
  38. },
  39. include: [
  40. Category,
  41. { model: User, attributes: ['username', 'createdAt', 'id', 'color'] },
  42. {
  43. model: Post, limit: 1, order: [['id', order]], include:
  44. [{ model: User, attributes: ['username', 'id'] }]
  45. }
  46. ]
  47. }
  48. if(user) {
  49. options.where.userId = user.id
  50. }
  51. return [options]
  52. }
  53. if(req.params.category === 'ALL') {
  54. threads = await Category.findAll({ include: threadInclude('ASC') })
  55. threadsLatestPost = await Category.findAll({ include: threadInclude('DESC') })
  56. } else {
  57. threads = await Category.findOne({
  58. where: { name: req.params.category },
  59. include: threadInclude('ASC')
  60. })
  61. threadsLatestPost = await Category.findOne({
  62. where: { name: req.params.category },
  63. include: threadInclude('DESC')
  64. })
  65. }
  66. if(!threads) throw Errors.invalidParameter('id', 'thread does not exist')
  67. if(Array.isArray(threads)) {
  68. resThreads = {
  69. name: 'All',
  70. value: 'ALL',
  71. Threads: concatenateThreads(threads),
  72. meta: {}
  73. }
  74. threadsLatestPost = { Threads: concatenateThreads(threadsLatestPost) }
  75. } else {
  76. resThreads = threads.toJSON()
  77. resThreads.meta = {}
  78. }
  79. threadsLatestPost.Threads.forEach((thread, i) => {
  80. let first = resThreads.Threads[i].Posts[0]
  81. let latest = thread.Posts[0]
  82. if(first.id === latest.id) return
  83. resThreads.Threads[i].Posts.push(latest)
  84. })
  85. let nextId = await pagination.getNextId(Thread, user ? { userId: user.id } : {}, resThreads.Threads)
  86. if(nextId) {
  87. resThreads.meta.nextURL =
  88. `/api/v1/category/${req.params.category}?&limit=${limit}&from=${nextId + 1}`
  89. if(user) {
  90. resThreads.meta.nextURL += '&username=' + user.username
  91. }
  92. resThreads.meta.nextThreadsCount = await pagination.getNextCount(
  93. Thread, resThreads.Threads, limit,
  94. { userId: user.id }
  95. )
  96. } else {
  97. resThreads.meta.nextURL = null
  98. resThreads.meta.nextThreadsCount = 0
  99. }
  100. res.json(resThreads)
  101. } catch (e) {
  102. if(e.name === 'invalidParameter') {
  103. res.status(400)
  104. res.json({
  105. errors: [e]
  106. })
  107. } else {
  108. console.log(e)
  109. res.status(500)
  110. res.json({
  111. errors: [Errors.unknown]
  112. })
  113. }
  114. }
  115. })
  116. router.all('*', (req, res, next) => {
  117. if(!req.session.loggedIn || !req.session.admin) {
  118. res.status(401)
  119. res.json({
  120. errors: [Errors.requestNotAuthorized]
  121. })
  122. } else {
  123. next()
  124. }
  125. })
  126. router.post('/', async (req, res) => {
  127. let validationErrors = []
  128. try {
  129. if(req.body.name === undefined) {
  130. validationErrors.push(Errors.missingParameter('name'))
  131. } else if(typeof req.body.name !== 'string') {
  132. validationErrors.push(Errors.invalidParameterType('name', 'string'))
  133. } else if(!req.body.name.length) {
  134. validationErrors.push(Errors.parameterLengthTooSmall('name', '0'))
  135. }
  136. if(validationErrors.length) throw Errors.VALIDAITON_ERROR
  137. let category = await Category.create({
  138. name: req.body.name
  139. })
  140. res.json(category.toJSON())
  141. } catch (e) {
  142. if(e === Errors.VALIDAITON_ERROR) {
  143. res.status(400)
  144. res.json({
  145. errors: validationErrors
  146. })
  147. } else if(e.name === 'SequelizeUniqueConstraintError') {
  148. res.status(400)
  149. res.json({
  150. errors: [Errors.categoryAlreadyExists]
  151. })
  152. } else {
  153. res.status(500)
  154. res.json({
  155. errors: [Errors.unknown]
  156. })
  157. }
  158. }
  159. })
  160. module.exports = router