category.js 4.3 KB

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