]>
Commit | Line | Data |
---|---|---|
cde3d90d | 1 | import express from 'express' |
444c0a0e | 2 | import { cloneDeep } from 'lodash' |
bf1f6508 | 3 | import * as Sequelize from 'sequelize' |
444c0a0e C |
4 | import { logger } from '@server/helpers/logger' |
5 | import { sequelizeTypescript } from '@server/initializers/database' | |
bf1f6508 | 6 | import { ResultList } from '../../shared/models' |
2b02c520 | 7 | import { VideoCommentThreadTree } from '../../shared/models/videos/comment/video-comment.model' |
bf1f6508 | 8 | import { VideoCommentModel } from '../models/video/video-comment' |
cde3d90d C |
9 | import { |
10 | MAccountDefault, | |
11 | MComment, | |
12 | MCommentFormattable, | |
13 | MCommentOwnerVideo, | |
14 | MCommentOwnerVideoReply, | |
15 | MVideoFullLight | |
16 | } from '../types/models' | |
444c0a0e | 17 | import { sendCreateVideoComment, sendDeleteVideoComment } from './activitypub/send' |
de94ac86 | 18 | import { getLocalVideoCommentActivityPubUrl } from './activitypub/url' |
444c0a0e C |
19 | import { Hooks } from './plugins/hooks' |
20 | ||
cde3d90d C |
21 | async function removeComment (commentArg: MComment, req: express.Request, res: express.Response) { |
22 | let videoCommentInstanceBefore: MCommentOwnerVideo | |
444c0a0e C |
23 | |
24 | await sequelizeTypescript.transaction(async t => { | |
cde3d90d C |
25 | const comment = await VideoCommentModel.loadByUrlAndPopulateAccountAndVideo(commentArg.url, t) |
26 | ||
27 | videoCommentInstanceBefore = cloneDeep(comment) | |
28 | ||
29 | if (comment.isOwned() || comment.Video.isOwned()) { | |
30 | await sendDeleteVideoComment(comment, t) | |
444c0a0e C |
31 | } |
32 | ||
cde3d90d | 33 | comment.markAsDeleted() |
444c0a0e | 34 | |
cde3d90d | 35 | await comment.save({ transaction: t }) |
444c0a0e | 36 | |
cde3d90d C |
37 | logger.info('Video comment %d deleted.', comment.id) |
38 | }) | |
444c0a0e | 39 | |
7226e90f | 40 | Hooks.runAction('action:api.video-comment.deleted', { comment: videoCommentInstanceBefore, req, res }) |
444c0a0e | 41 | } |
bf1f6508 C |
42 | |
43 | async function createVideoComment (obj: { | |
a1587156 C |
44 | text: string |
45 | inReplyToComment: MComment | null | |
46 | video: MVideoFullLight | |
453e83ea | 47 | account: MAccountDefault |
bf1f6508 | 48 | }, t: Sequelize.Transaction) { |
c1e791ba RK |
49 | let originCommentId: number | null = null |
50 | let inReplyToCommentId: number | null = null | |
d3ea8975 | 51 | |
c1e791ba | 52 | if (obj.inReplyToComment && obj.inReplyToComment !== null) { |
ea44f375 | 53 | originCommentId = obj.inReplyToComment.originCommentId || obj.inReplyToComment.id |
4635f59d | 54 | inReplyToCommentId = obj.inReplyToComment.id |
bf1f6508 C |
55 | } |
56 | ||
57 | const comment = await VideoCommentModel.create({ | |
58 | text: obj.text, | |
59 | originCommentId, | |
4635f59d | 60 | inReplyToCommentId, |
bf1f6508 | 61 | videoId: obj.video.id, |
4635f59d | 62 | accountId: obj.account.id, |
970ceac0 C |
63 | url: new Date().toISOString() |
64 | }, { transaction: t, validate: false }) | |
bf1f6508 | 65 | |
de94ac86 | 66 | comment.url = getLocalVideoCommentActivityPubUrl(obj.video, comment) |
bf1f6508 | 67 | |
453e83ea | 68 | const savedComment: MCommentOwnerVideoReply = await comment.save({ transaction: t }) |
ea44f375 C |
69 | savedComment.InReplyToVideoComment = obj.inReplyToComment |
70 | savedComment.Video = obj.video | |
4635f59d | 71 | savedComment.Account = obj.account |
ea44f375 | 72 | |
07197db4 | 73 | await sendCreateVideoComment(savedComment, t) |
ea44f375 C |
74 | |
75 | return savedComment | |
bf1f6508 C |
76 | } |
77 | ||
cde3d90d | 78 | function buildFormattedCommentTree (resultList: ResultList<MCommentFormattable>): VideoCommentThreadTree { |
bf1f6508 C |
79 | // Comments are sorted by id ASC |
80 | const comments = resultList.data | |
81 | ||
82 | const comment = comments.shift() | |
d3ea8975 | 83 | const thread: VideoCommentThreadTree = { |
bf1f6508 C |
84 | comment: comment.toFormattedJSON(), |
85 | children: [] | |
86 | } | |
87 | const idx = { | |
88 | [comment.id]: thread | |
89 | } | |
90 | ||
91 | while (comments.length !== 0) { | |
92 | const childComment = comments.shift() | |
93 | ||
d3ea8975 | 94 | const childCommentThread: VideoCommentThreadTree = { |
bf1f6508 C |
95 | comment: childComment.toFormattedJSON(), |
96 | children: [] | |
97 | } | |
98 | ||
99 | const parentCommentThread = idx[childComment.inReplyToCommentId] | |
7ad9b984 C |
100 | // Maybe the parent comment was blocked by the admin/user |
101 | if (!parentCommentThread) continue | |
bf1f6508 C |
102 | |
103 | parentCommentThread.children.push(childCommentThread) | |
104 | idx[childComment.id] = childCommentThread | |
105 | } | |
106 | ||
107 | return thread | |
108 | } | |
109 | ||
110 | // --------------------------------------------------------------------------- | |
111 | ||
112 | export { | |
444c0a0e | 113 | removeComment, |
bf1f6508 | 114 | createVideoComment, |
eae0365b | 115 | buildFormattedCommentTree |
bf1f6508 | 116 | } |