video-comment.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { ResultList, VideoCommentThreadTree } from '@peertube/peertube-models'
  2. import { logger } from '@server/helpers/logger.js'
  3. import { sequelizeTypescript } from '@server/initializers/database.js'
  4. import express from 'express'
  5. import cloneDeep from 'lodash-es/cloneDeep.js'
  6. import * as Sequelize from 'sequelize'
  7. import { VideoCommentModel } from '../models/video/video-comment.js'
  8. import {
  9. MAccountDefault,
  10. MComment,
  11. MCommentFormattable,
  12. MCommentOwnerVideo,
  13. MCommentOwnerVideoReply,
  14. MVideoFullLight
  15. } from '../types/models/index.js'
  16. import { sendCreateVideoComment, sendDeleteVideoComment } from './activitypub/send/index.js'
  17. import { getLocalVideoCommentActivityPubUrl } from './activitypub/url.js'
  18. import { Hooks } from './plugins/hooks.js'
  19. async function removeComment (commentArg: MComment, req: express.Request, res: express.Response) {
  20. let videoCommentInstanceBefore: MCommentOwnerVideo
  21. await sequelizeTypescript.transaction(async t => {
  22. const comment = await VideoCommentModel.loadByUrlAndPopulateAccountAndVideo(commentArg.url, t)
  23. videoCommentInstanceBefore = cloneDeep(comment)
  24. if (comment.isOwned() || comment.Video.isOwned()) {
  25. await sendDeleteVideoComment(comment, t)
  26. }
  27. comment.markAsDeleted()
  28. await comment.save({ transaction: t })
  29. logger.info('Video comment %d deleted.', comment.id)
  30. })
  31. Hooks.runAction('action:api.video-comment.deleted', { comment: videoCommentInstanceBefore, req, res })
  32. }
  33. async function createVideoComment (obj: {
  34. text: string
  35. inReplyToComment: MComment | null
  36. video: MVideoFullLight
  37. account: MAccountDefault
  38. }, t: Sequelize.Transaction) {
  39. let originCommentId: number | null = null
  40. let inReplyToCommentId: number | null = null
  41. if (obj.inReplyToComment && obj.inReplyToComment !== null) {
  42. originCommentId = obj.inReplyToComment.originCommentId || obj.inReplyToComment.id
  43. inReplyToCommentId = obj.inReplyToComment.id
  44. }
  45. const comment = await VideoCommentModel.create({
  46. text: obj.text,
  47. originCommentId,
  48. inReplyToCommentId,
  49. videoId: obj.video.id,
  50. accountId: obj.account.id,
  51. url: new Date().toISOString()
  52. }, { transaction: t, validate: false })
  53. comment.url = getLocalVideoCommentActivityPubUrl(obj.video, comment)
  54. const savedComment: MCommentOwnerVideoReply = await comment.save({ transaction: t })
  55. savedComment.InReplyToVideoComment = obj.inReplyToComment
  56. savedComment.Video = obj.video
  57. savedComment.Account = obj.account
  58. await sendCreateVideoComment(savedComment, t)
  59. return savedComment
  60. }
  61. function buildFormattedCommentTree (resultList: ResultList<MCommentFormattable>): VideoCommentThreadTree {
  62. // Comments are sorted by id ASC
  63. const comments = resultList.data
  64. const comment = comments.shift()
  65. const thread: VideoCommentThreadTree = {
  66. comment: comment.toFormattedJSON(),
  67. children: []
  68. }
  69. const idx = {
  70. [comment.id]: thread
  71. }
  72. while (comments.length !== 0) {
  73. const childComment = comments.shift()
  74. const childCommentThread: VideoCommentThreadTree = {
  75. comment: childComment.toFormattedJSON(),
  76. children: []
  77. }
  78. const parentCommentThread = idx[childComment.inReplyToCommentId]
  79. // Maybe the parent comment was blocked by the admin/user
  80. if (!parentCommentThread) continue
  81. parentCommentThread.children.push(childCommentThread)
  82. idx[childComment.id] = childCommentThread
  83. }
  84. return thread
  85. }
  86. // ---------------------------------------------------------------------------
  87. export {
  88. removeComment,
  89. createVideoComment,
  90. buildFormattedCommentTree
  91. }