diff options
author | Chocobozzz <me@florianbigard.com> | 2017-12-27 16:11:53 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2017-12-27 16:11:53 +0100 |
commit | 4635f59d7c3fea4b97029f10886c62fdf38b2084 (patch) | |
tree | d97357a00042bbfb33c4177ee24c01171d28dfce /server | |
parent | ea44f375f5d3da06ca0aebfe871b9f924a26ec29 (diff) | |
download | PeerTube-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.ts | 12 | ||||
-rw-r--r-- | server/lib/video-comment.ts | 12 | ||||
-rw-r--r-- | server/middlewares/validators/pagination.ts | 4 | ||||
-rw-r--r-- | server/models/video/video-comment.ts | 42 | ||||
-rw-r--r-- | server/tests/api/video-comments.ts | 18 |
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 @@ | |||
1 | import * as Sequelize from 'sequelize' | 1 | import * as Sequelize from 'sequelize' |
2 | import { ResultList } from '../../shared/models' | 2 | import { ResultList } from '../../shared/models' |
3 | import { VideoCommentThreadTree } from '../../shared/models/videos/video-comment.model' | 3 | import { VideoCommentThreadTree } from '../../shared/models/videos/video-comment.model' |
4 | import { AccountModel } from '../models/account/account' | ||
4 | import { VideoModel } from '../models/video/video' | 5 | import { VideoModel } from '../models/video/video' |
5 | import { VideoCommentModel } from '../models/video/video-comment' | 6 | import { VideoCommentModel } from '../models/video/video-comment' |
6 | import { getVideoCommentActivityPubUrl, sendVideoRateChangeToFollowers } from './activitypub' | 7 | import { getVideoCommentActivityPubUrl } from './activitypub' |
7 | import { sendCreateVideoCommentToOrigin, sendCreateVideoCommentToVideoFollowers } from './activitypub/send' | 8 | import { sendCreateVideoCommentToOrigin, sendCreateVideoCommentToVideoFollowers } from './activitypub/send' |
8 | 9 | ||
9 | async function createVideoComment (obj: { | 10 | async 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' | |||
4 | import { areValidationErrors } from './utils' | 4 | import { areValidationErrors } from './utils' |
5 | 5 | ||
6 | const paginationValidator = [ | 6 | const 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' | |||
8 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub' | 8 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub' |
9 | import { CONSTRAINTS_FIELDS } from '../../initializers' | 9 | import { CONSTRAINTS_FIELDS } from '../../initializers' |
10 | import { AccountModel } from '../account/account' | 10 | import { AccountModel } from '../account/account' |
11 | import { ActorModel } from '../activitypub/actor' | ||
12 | import { ServerModel } from '../server/server' | ||
11 | import { getSort, throwIfNotValid } from '../utils' | 13 | import { getSort, throwIfNotValid } from '../utils' |
12 | import { VideoModel } from './video' | 14 | import { VideoModel } from './video' |
13 | 15 | ||
14 | enum ScopeNames { | 16 | enum 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 () { |