aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2017-12-27 16:11:53 +0100
committerChocobozzz <me@florianbigard.com>2017-12-27 16:11:53 +0100
commit4635f59d7c3fea4b97029f10886c62fdf38b2084 (patch)
treed97357a00042bbfb33c4177ee24c01171d28dfce /server
parentea44f375f5d3da06ca0aebfe871b9f924a26ec29 (diff)
downloadPeerTube-4635f59d7c3fea4b97029f10886c62fdf38b2084.tar.gz
PeerTube-4635f59d7c3fea4b97029f10886c62fdf38b2084.tar.zst
PeerTube-4635f59d7c3fea4b97029f10886c62fdf38b2084.zip
Add video comment components
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/videos/comment.ts12
-rw-r--r--server/lib/video-comment.ts12
-rw-r--r--server/middlewares/validators/pagination.ts4
-rw-r--r--server/models/video/video-comment.ts42
-rw-r--r--server/tests/api/video-comments.ts18
5 files changed, 68 insertions, 20 deletions
diff --git a/server/controllers/api/videos/comment.ts b/server/controllers/api/videos/comment.ts
index e9dbb6d1b..276948098 100644
--- a/server/controllers/api/videos/comment.ts
+++ b/server/controllers/api/videos/comment.ts
@@ -66,9 +66,7 @@ async function addVideoCommentThreadRetryWrapper (req: express.Request, res: exp
66 const comment = await retryTransactionWrapper(addVideoCommentThread, options) 66 const comment = await retryTransactionWrapper(addVideoCommentThread, options)
67 67
68 res.json({ 68 res.json({
69 comment: { 69 comment: comment.toFormattedJSON()
70 id: comment.id
71 }
72 }).end() 70 }).end()
73} 71}
74 72
@@ -80,7 +78,7 @@ function addVideoCommentThread (req: express.Request, res: express.Response) {
80 text: videoCommentInfo.text, 78 text: videoCommentInfo.text,
81 inReplyToComment: null, 79 inReplyToComment: null,
82 video: res.locals.video, 80 video: res.locals.video,
83 accountId: res.locals.oauth.token.User.Account.id 81 account: res.locals.oauth.token.User.Account
84 }, t) 82 }, t)
85 }) 83 })
86} 84}
@@ -94,9 +92,7 @@ async function addVideoCommentReplyRetryWrapper (req: express.Request, res: expr
94 const comment = await retryTransactionWrapper(addVideoCommentReply, options) 92 const comment = await retryTransactionWrapper(addVideoCommentReply, options)
95 93
96 res.json({ 94 res.json({
97 comment: { 95 comment: comment.toFormattedJSON()
98 id: comment.id
99 }
100 }).end() 96 }).end()
101} 97}
102 98
@@ -108,7 +104,7 @@ function addVideoCommentReply (req: express.Request, res: express.Response, next
108 text: videoCommentInfo.text, 104 text: videoCommentInfo.text,
109 inReplyToComment: res.locals.videoComment, 105 inReplyToComment: res.locals.videoComment,
110 video: res.locals.video, 106 video: res.locals.video,
111 accountId: res.locals.oauth.token.User.Account.id 107 account: res.locals.oauth.token.User.Account
112 }, t) 108 }, t)
113 }) 109 })
114} 110}
diff --git a/server/lib/video-comment.ts b/server/lib/video-comment.ts
index ef6a8f097..0d744c526 100644
--- a/server/lib/video-comment.ts
+++ b/server/lib/video-comment.ts
@@ -1,29 +1,32 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import { ResultList } from '../../shared/models' 2import { ResultList } from '../../shared/models'
3import { VideoCommentThreadTree } from '../../shared/models/videos/video-comment.model' 3import { VideoCommentThreadTree } from '../../shared/models/videos/video-comment.model'
4import { AccountModel } from '../models/account/account'
4import { VideoModel } from '../models/video/video' 5import { VideoModel } from '../models/video/video'
5import { VideoCommentModel } from '../models/video/video-comment' 6import { VideoCommentModel } from '../models/video/video-comment'
6import { getVideoCommentActivityPubUrl, sendVideoRateChangeToFollowers } from './activitypub' 7import { getVideoCommentActivityPubUrl } from './activitypub'
7import { sendCreateVideoCommentToOrigin, sendCreateVideoCommentToVideoFollowers } from './activitypub/send' 8import { sendCreateVideoCommentToOrigin, sendCreateVideoCommentToVideoFollowers } from './activitypub/send'
8 9
9async function createVideoComment (obj: { 10async function createVideoComment (obj: {
10 text: string, 11 text: string,
11 inReplyToComment: VideoCommentModel, 12 inReplyToComment: VideoCommentModel,
12 video: VideoModel 13 video: VideoModel
13 accountId: number 14 account: AccountModel
14}, t: Sequelize.Transaction) { 15}, t: Sequelize.Transaction) {
15 let originCommentId: number = null 16 let originCommentId: number = null
17 let inReplyToCommentId: number = null
16 18
17 if (obj.inReplyToComment) { 19 if (obj.inReplyToComment) {
18 originCommentId = obj.inReplyToComment.originCommentId || obj.inReplyToComment.id 20 originCommentId = obj.inReplyToComment.originCommentId || obj.inReplyToComment.id
21 inReplyToCommentId = obj.inReplyToComment.id
19 } 22 }
20 23
21 const comment = await VideoCommentModel.create({ 24 const comment = await VideoCommentModel.create({
22 text: obj.text, 25 text: obj.text,
23 originCommentId, 26 originCommentId,
24 inReplyToCommentId: obj.inReplyToComment.id, 27 inReplyToCommentId,
25 videoId: obj.video.id, 28 videoId: obj.video.id,
26 accountId: obj.accountId, 29 accountId: obj.account.id,
27 url: 'fake url' 30 url: 'fake url'
28 }, { transaction: t, validate: false }) 31 }, { transaction: t, validate: false })
29 32
@@ -32,6 +35,7 @@ async function createVideoComment (obj: {
32 const savedComment = await comment.save({ transaction: t }) 35 const savedComment = await comment.save({ transaction: t })
33 savedComment.InReplyToVideoComment = obj.inReplyToComment 36 savedComment.InReplyToVideoComment = obj.inReplyToComment
34 savedComment.Video = obj.video 37 savedComment.Video = obj.video
38 savedComment.Account = obj.account
35 39
36 if (savedComment.Video.isOwned()) { 40 if (savedComment.Video.isOwned()) {
37 await sendCreateVideoCommentToVideoFollowers(savedComment, t) 41 await sendCreateVideoCommentToVideoFollowers(savedComment, t)
diff --git a/server/middlewares/validators/pagination.ts b/server/middlewares/validators/pagination.ts
index 0895b4eb8..25debfa6e 100644
--- a/server/middlewares/validators/pagination.ts
+++ b/server/middlewares/validators/pagination.ts
@@ -4,8 +4,8 @@ import { logger } from '../../helpers'
4import { areValidationErrors } from './utils' 4import { areValidationErrors } from './utils'
5 5
6const paginationValidator = [ 6const paginationValidator = [
7 query('start').optional().isInt().withMessage('Should have a number start'), 7 query('start').optional().isInt({ min: 0 }).withMessage('Should have a number start'),
8 query('count').optional().isInt().withMessage('Should have a number count'), 8 query('count').optional().isInt({ min: 0 }).withMessage('Should have a number count'),
9 9
10 (req: express.Request, res: express.Response, next: express.NextFunction) => { 10 (req: express.Request, res: express.Response, next: express.NextFunction) => {
11 logger.debug('Checking pagination parameters', { parameters: req.query }) 11 logger.debug('Checking pagination parameters', { parameters: req.query })
diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts
index 25cd6d563..a3e8c48d4 100644
--- a/server/models/video/video-comment.ts
+++ b/server/models/video/video-comment.ts
@@ -8,18 +8,48 @@ import { VideoComment } from '../../../shared/models/videos/video-comment.model'
8import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub' 8import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub'
9import { CONSTRAINTS_FIELDS } from '../../initializers' 9import { CONSTRAINTS_FIELDS } from '../../initializers'
10import { AccountModel } from '../account/account' 10import { AccountModel } from '../account/account'
11import { ActorModel } from '../activitypub/actor'
12import { ServerModel } from '../server/server'
11import { getSort, throwIfNotValid } from '../utils' 13import { getSort, throwIfNotValid } from '../utils'
12import { VideoModel } from './video' 14import { VideoModel } from './video'
13 15
14enum ScopeNames { 16enum ScopeNames {
15 WITH_ACCOUNT = 'WITH_ACCOUNT', 17 WITH_ACCOUNT = 'WITH_ACCOUNT',
16 WITH_IN_REPLY_TO = 'WITH_IN_REPLY_TO' 18 WITH_IN_REPLY_TO = 'WITH_IN_REPLY_TO',
19 ATTRIBUTES_FOR_API = 'ATTRIBUTES_FOR_API'
17} 20}
18 21
19@Scopes({ 22@Scopes({
23 [ScopeNames.ATTRIBUTES_FOR_API]: {
24 attributes: {
25 include: [
26 [
27 Sequelize.literal(
28 '(SELECT COUNT("replies"."id") ' +
29 'FROM "videoComment" AS "replies" ' +
30 'WHERE "replies"."originCommentId" = "VideoCommentModel"."id")'
31 ),
32 'totalReplies'
33 ]
34 ]
35 }
36 },
20 [ScopeNames.WITH_ACCOUNT]: { 37 [ScopeNames.WITH_ACCOUNT]: {
21 include: [ 38 include: [
22 () => AccountModel 39 {
40 model: () => AccountModel,
41 include: [
42 {
43 model: () => ActorModel,
44 include: [
45 {
46 model: () => ServerModel,
47 required: false
48 }
49 ]
50 }
51 ]
52 }
23 ] 53 ]
24 }, 54 },
25 [ScopeNames.WITH_IN_REPLY_TO]: { 55 [ScopeNames.WITH_IN_REPLY_TO]: {
@@ -149,7 +179,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
149 } 179 }
150 180
151 return VideoCommentModel 181 return VideoCommentModel
152 .scope([ ScopeNames.WITH_ACCOUNT ]) 182 .scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.ATTRIBUTES_FOR_API ])
153 .findAndCountAll(query) 183 .findAndCountAll(query)
154 .then(({ rows, count }) => { 184 .then(({ rows, count }) => {
155 return { total: count, data: rows } 185 return { total: count, data: rows }
@@ -169,7 +199,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
169 } 199 }
170 200
171 return VideoCommentModel 201 return VideoCommentModel
172 .scope([ ScopeNames.WITH_ACCOUNT ]) 202 .scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.ATTRIBUTES_FOR_API ])
173 .findAndCountAll(query) 203 .findAndCountAll(query)
174 .then(({ rows, count }) => { 204 .then(({ rows, count }) => {
175 return { total: count, data: rows } 205 return { total: count, data: rows }
@@ -186,8 +216,10 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
186 videoId: this.videoId, 216 videoId: this.videoId,
187 createdAt: this.createdAt, 217 createdAt: this.createdAt,
188 updatedAt: this.updatedAt, 218 updatedAt: this.updatedAt,
219 totalReplies: this.get('totalReplies') || 0,
189 account: { 220 account: {
190 name: this.Account.name 221 name: this.Account.name,
222 host: this.Account.Actor.getHost()
191 } 223 }
192 } as VideoComment 224 } as VideoComment
193 } 225 }
diff --git a/server/tests/api/video-comments.ts b/server/tests/api/video-comments.ts
index 2f1e6260a..2c7d1c6e2 100644
--- a/server/tests/api/video-comments.ts
+++ b/server/tests/api/video-comments.ts
@@ -39,7 +39,18 @@ describe('Test video comments', function () {
39 it('Should create a thread in this video', async function () { 39 it('Should create a thread in this video', async function () {
40 const text = 'my super first comment' 40 const text = 'my super first comment'
41 41
42 await addVideoCommentThread(server.url, server.accessToken, videoUUID, text) 42 const res = await addVideoCommentThread(server.url, server.accessToken, videoUUID, text)
43 const comment = res.body
44
45 expect(comment.inReplyToCommentId).to.be.null
46 expect(comment.text).equal('my super first comment')
47 expect(comment.videoId).to.equal(videoId)
48 expect(comment.id).to.equal(comment.threadId)
49 expect(comment.account.name).to.equal('root')
50 expect(comment.account.host).to.equal('localhost:9001')
51 expect(comment.totalReplies).to.equal(0)
52 expect(dateIsValid(comment.createdAt as string)).to.be.true
53 expect(dateIsValid(comment.updatedAt as string)).to.be.true
43 }) 54 })
44 55
45 it('Should list threads of this video', async function () { 56 it('Should list threads of this video', async function () {
@@ -55,6 +66,8 @@ describe('Test video comments', function () {
55 expect(comment.videoId).to.equal(videoId) 66 expect(comment.videoId).to.equal(videoId)
56 expect(comment.id).to.equal(comment.threadId) 67 expect(comment.id).to.equal(comment.threadId)
57 expect(comment.account.name).to.equal('root') 68 expect(comment.account.name).to.equal('root')
69 expect(comment.account.host).to.equal('localhost:9001')
70 expect(comment.totalReplies).to.equal(0)
58 expect(dateIsValid(comment.createdAt as string)).to.be.true 71 expect(dateIsValid(comment.createdAt as string)).to.be.true
59 expect(dateIsValid(comment.updatedAt as string)).to.be.true 72 expect(dateIsValid(comment.updatedAt as string)).to.be.true
60 73
@@ -120,8 +133,11 @@ describe('Test video comments', function () {
120 expect(res.body.data).to.have.lengthOf(3) 133 expect(res.body.data).to.have.lengthOf(3)
121 134
122 expect(res.body.data[0].text).to.equal('my super first comment') 135 expect(res.body.data[0].text).to.equal('my super first comment')
136 expect(res.body.data[0].totalReplies).to.equal(2)
123 expect(res.body.data[1].text).to.equal('super thread 2') 137 expect(res.body.data[1].text).to.equal('super thread 2')
138 expect(res.body.data[1].totalReplies).to.equal(1)
124 expect(res.body.data[2].text).to.equal('super thread 3') 139 expect(res.body.data[2].text).to.equal('super thread 3')
140 expect(res.body.data[2].totalReplies).to.equal(0)
125 }) 141 })
126 142
127 after(async function () { 143 after(async function () {