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