1 import * as express from 'express'
2 import { ResultList } from '../../../../shared/models'
3 import { VideoCommentCreate } from '../../../../shared/models/videos/video-comment.model'
4 import { retryTransactionWrapper } from '../../../helpers/database-utils'
5 import { getFormattedObjects } from '../../../helpers/utils'
6 import { sequelizeTypescript } from '../../../initializers'
7 import { buildFormattedCommentTree, createVideoComment } from '../../../lib/video-comment'
8 import { asyncMiddleware, authenticate, paginationValidator, setPagination, setVideoCommentThreadsSort } from '../../../middlewares'
9 import { videoCommentThreadsSortValidator } from '../../../middlewares/validators'
11 addVideoCommentReplyValidator, addVideoCommentThreadValidator, listVideoCommentThreadsValidator,
12 listVideoThreadCommentsValidator
13 } from '../../../middlewares/validators/video-comments'
14 import { VideoModel } from '../../../models/video/video'
15 import { VideoCommentModel } from '../../../models/video/video-comment'
17 const videoCommentRouter = express.Router()
19 videoCommentRouter.get('/:videoId/comment-threads',
21 videoCommentThreadsSortValidator,
22 setVideoCommentThreadsSort,
24 asyncMiddleware(listVideoCommentThreadsValidator),
25 asyncMiddleware(listVideoThreads)
27 videoCommentRouter.get('/:videoId/comment-threads/:threadId',
28 asyncMiddleware(listVideoThreadCommentsValidator),
29 asyncMiddleware(listVideoThreadComments)
32 videoCommentRouter.post('/:videoId/comment-threads',
34 asyncMiddleware(addVideoCommentThreadValidator),
35 asyncMiddleware(addVideoCommentThreadRetryWrapper)
37 videoCommentRouter.post('/:videoId/comments/:commentId',
39 asyncMiddleware(addVideoCommentReplyValidator),
40 asyncMiddleware(addVideoCommentReplyRetryWrapper)
43 // ---------------------------------------------------------------------------
49 // ---------------------------------------------------------------------------
51 async function listVideoThreads (req: express.Request, res: express.Response, next: express.NextFunction) {
52 const video = res.locals.video as VideoModel
53 let resultList: ResultList<VideoCommentModel>
55 if (video.commentsEnabled === true) {
56 resultList = await VideoCommentModel.listThreadsForApi(video.id, req.query.start, req.query.count, req.query.sort)
64 return res.json(getFormattedObjects(resultList.data, resultList.total))
67 async function listVideoThreadComments (req: express.Request, res: express.Response, next: express.NextFunction) {
68 const video = res.locals.video as VideoModel
69 let resultList: ResultList<VideoCommentModel>
71 if (video.commentsEnabled === true) {
72 resultList = await VideoCommentModel.listThreadCommentsForApi(res.locals.video.id, res.locals.videoCommentThread.id)
80 return res.json(buildFormattedCommentTree(resultList))
83 async function addVideoCommentThreadRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
85 arguments: [ req, res ],
86 errorMessage: 'Cannot insert the video comment thread with many retries.'
89 const comment = await retryTransactionWrapper(addVideoCommentThread, options)
92 comment: comment.toFormattedJSON()
96 function addVideoCommentThread (req: express.Request, res: express.Response) {
97 const videoCommentInfo: VideoCommentCreate = req.body
99 return sequelizeTypescript.transaction(async t => {
100 return createVideoComment({
101 text: videoCommentInfo.text,
102 inReplyToComment: null,
103 video: res.locals.video,
104 account: res.locals.oauth.token.User.Account
109 async function addVideoCommentReplyRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
111 arguments: [ req, res ],
112 errorMessage: 'Cannot insert the video comment reply with many retries.'
115 const comment = await retryTransactionWrapper(addVideoCommentReply, options)
118 comment: comment.toFormattedJSON()
122 function addVideoCommentReply (req: express.Request, res: express.Response, next: express.NextFunction) {
123 const videoCommentInfo: VideoCommentCreate = req.body
125 return sequelizeTypescript.transaction(async t => {
126 return createVideoComment({
127 text: videoCommentInfo.text,
128 inReplyToComment: res.locals.videoComment,
129 video: res.locals.video,
130 account: res.locals.oauth.token.User.Account