diff options
author | Rigel Kent <sendmemail@rigelk.eu> | 2020-06-27 13:12:30 +0200 |
---|---|---|
committer | Rigel Kent <sendmemail@rigelk.eu> | 2020-06-27 13:20:59 +0200 |
commit | 00494d6e2ae915741f47869dcd359d9728a0af91 (patch) | |
tree | 9642f3d5bf1565d3b8d60d3ad06495fefce80c23 /server | |
parent | 2c318664305fd2723586ad939e64f958d9d447ff (diff) | |
download | PeerTube-00494d6e2ae915741f47869dcd359d9728a0af91.tar.gz PeerTube-00494d6e2ae915741f47869dcd359d9728a0af91.tar.zst PeerTube-00494d6e2ae915741f47869dcd359d9728a0af91.zip |
allow limiting video-comments rss feeds to an account or video channel
Diffstat (limited to 'server')
-rw-r--r-- | server/controllers/feeds.ts | 55 | ||||
-rw-r--r-- | server/middlewares/validators/feeds.ts | 6 | ||||
-rw-r--r-- | server/models/video/video-comment.ts | 34 |
3 files changed, 78 insertions, 17 deletions
diff --git a/server/controllers/feeds.ts b/server/controllers/feeds.ts index cb82bfc6d..bfcd3fe36 100644 --- a/server/controllers/feeds.ts +++ b/server/controllers/feeds.ts | |||
@@ -27,6 +27,7 @@ feedsRouter.get('/feeds/video-comments.:format', | |||
27 | 'Content-Type' | 27 | 'Content-Type' |
28 | ] | 28 | ] |
29 | })(ROUTE_CACHE_LIFETIME.FEEDS)), | 29 | })(ROUTE_CACHE_LIFETIME.FEEDS)), |
30 | asyncMiddleware(videoFeedsValidator), | ||
30 | asyncMiddleware(videoCommentsFeedsValidator), | 31 | asyncMiddleware(videoCommentsFeedsValidator), |
31 | asyncMiddleware(generateVideoCommentsFeed) | 32 | asyncMiddleware(generateVideoCommentsFeed) |
32 | ) | 33 | ) |
@@ -58,13 +59,36 @@ async function generateVideoCommentsFeed (req: express.Request, res: express.Res | |||
58 | const start = 0 | 59 | const start = 0 |
59 | 60 | ||
60 | const video = res.locals.videoAll | 61 | const video = res.locals.videoAll |
61 | const videoId: number = video ? video.id : undefined | 62 | const account = res.locals.account |
63 | const videoChannel = res.locals.videoChannel | ||
62 | 64 | ||
63 | const comments = await VideoCommentModel.listForFeed(start, FEEDS.COUNT, videoId) | 65 | const comments = await VideoCommentModel.listForFeed({ |
66 | start, | ||
67 | count: FEEDS.COUNT, | ||
68 | videoId: video ? video.id : undefined, | ||
69 | accountId: account ? account.id : undefined, | ||
70 | videoChannelId: videoChannel ? videoChannel.id : undefined | ||
71 | }) | ||
64 | 72 | ||
65 | const name = video ? video.name : CONFIG.INSTANCE.NAME | 73 | let name: string |
66 | const description = video ? video.description : CONFIG.INSTANCE.DESCRIPTION | 74 | let description: string |
67 | const feed = initFeed(name, description) | 75 | |
76 | if (videoChannel) { | ||
77 | name = videoChannel.getDisplayName() | ||
78 | description = videoChannel.description | ||
79 | } else if (account) { | ||
80 | name = account.getDisplayName() | ||
81 | description = account.description | ||
82 | } else { | ||
83 | name = video ? video.name : CONFIG.INSTANCE.NAME | ||
84 | description = video ? video.description : CONFIG.INSTANCE.DESCRIPTION | ||
85 | } | ||
86 | const feed = initFeed({ | ||
87 | name, | ||
88 | description, | ||
89 | resourceType: 'video-comments', | ||
90 | queryString: new URL(WEBSERVER.URL + req.originalUrl).search | ||
91 | }) | ||
68 | 92 | ||
69 | // Adding video items to the feed, one at a time | 93 | // Adding video items to the feed, one at a time |
70 | for (const comment of comments) { | 94 | for (const comment of comments) { |
@@ -116,7 +140,12 @@ async function generateVideoFeed (req: express.Request, res: express.Response) { | |||
116 | description = CONFIG.INSTANCE.DESCRIPTION | 140 | description = CONFIG.INSTANCE.DESCRIPTION |
117 | } | 141 | } |
118 | 142 | ||
119 | const feed = initFeed(name, description) | 143 | const feed = initFeed({ |
144 | name, | ||
145 | description, | ||
146 | resourceType: 'videos', | ||
147 | queryString: new URL(WEBSERVER.URL + req.url).search | ||
148 | }) | ||
120 | 149 | ||
121 | const resultList = await VideoModel.listForApi({ | 150 | const resultList = await VideoModel.listForApi({ |
122 | start, | 151 | start, |
@@ -207,8 +236,14 @@ async function generateVideoFeed (req: express.Request, res: express.Response) { | |||
207 | return sendFeed(feed, req, res) | 236 | return sendFeed(feed, req, res) |
208 | } | 237 | } |
209 | 238 | ||
210 | function initFeed (name: string, description: string) { | 239 | function initFeed (parameters: { |
240 | name: string | ||
241 | description: string | ||
242 | resourceType?: 'videos' | 'video-comments' | ||
243 | queryString?: string | ||
244 | }) { | ||
211 | const webserverUrl = WEBSERVER.URL | 245 | const webserverUrl = WEBSERVER.URL |
246 | const { name, description, resourceType, queryString } = parameters | ||
212 | 247 | ||
213 | return new Feed({ | 248 | return new Feed({ |
214 | title: name, | 249 | title: name, |
@@ -222,9 +257,9 @@ function initFeed (name: string, description: string) { | |||
222 | ` and potential licenses granted by each content's rightholder.`, | 257 | ` and potential licenses granted by each content's rightholder.`, |
223 | generator: `Toraifōsu`, // ^.~ | 258 | generator: `Toraifōsu`, // ^.~ |
224 | feedLinks: { | 259 | feedLinks: { |
225 | json: `${webserverUrl}/feeds/videos.json`, | 260 | json: `${webserverUrl}/feeds/${resourceType}.json${queryString}`, |
226 | atom: `${webserverUrl}/feeds/videos.atom`, | 261 | atom: `${webserverUrl}/feeds/${resourceType}.atom${queryString}`, |
227 | rss: `${webserverUrl}/feeds/videos.xml` | 262 | rss: `${webserverUrl}/feeds/${resourceType}.xml${queryString}` |
228 | }, | 263 | }, |
229 | author: { | 264 | author: { |
230 | name: 'Instance admin of ' + CONFIG.INSTANCE.NAME, | 265 | name: 'Instance admin of ' + CONFIG.INSTANCE.NAME, |
diff --git a/server/middlewares/validators/feeds.ts b/server/middlewares/validators/feeds.ts index f34c2b174..c3de0f5fe 100644 --- a/server/middlewares/validators/feeds.ts +++ b/server/middlewares/validators/feeds.ts | |||
@@ -70,6 +70,12 @@ const videoCommentsFeedsValidator = [ | |||
70 | 70 | ||
71 | if (areValidationErrors(req, res)) return | 71 | if (areValidationErrors(req, res)) return |
72 | 72 | ||
73 | if (req.query.videoId && (req.query.videoChannelId || req.query.videoChannelName)) { | ||
74 | return res.status(400).send({ | ||
75 | message: 'videoId cannot be mixed with a channel filter' | ||
76 | }).end() | ||
77 | } | ||
78 | |||
73 | if (req.query.videoId && !await doesVideoExist(req.query.videoId, res)) return | 79 | if (req.query.videoId && !await doesVideoExist(req.query.videoId, res)) return |
74 | 80 | ||
75 | return next() | 81 | return next() |
diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts index 091cc2a88..c465eb3e7 100644 --- a/server/models/video/video-comment.ts +++ b/server/models/video/video-comment.ts | |||
@@ -427,8 +427,31 @@ export class VideoCommentModel extends Model<VideoCommentModel> { | |||
427 | return VideoCommentModel.findAndCountAll<MComment>(query) | 427 | return VideoCommentModel.findAndCountAll<MComment>(query) |
428 | } | 428 | } |
429 | 429 | ||
430 | static async listForFeed (start: number, count: number, videoId?: number): Promise<MCommentOwnerVideoFeed[]> { | 430 | static async listForFeed (parameters: { |
431 | start: number | ||
432 | count: number | ||
433 | videoId?: number | ||
434 | accountId?: number | ||
435 | videoChannelId?: number | ||
436 | }): Promise<MCommentOwnerVideoFeed[]> { | ||
431 | const serverActor = await getServerActor() | 437 | const serverActor = await getServerActor() |
438 | const { start, count, videoId, accountId, videoChannelId } = parameters | ||
439 | |||
440 | const accountExclusion = { | ||
441 | [Op.notIn]: Sequelize.literal( | ||
442 | '(' + buildBlockedAccountSQL([ serverActor.Account.id, '"Video->VideoChannel"."accountId"' ]) + ')' | ||
443 | ) | ||
444 | } | ||
445 | const accountWhere = accountId | ||
446 | ? { | ||
447 | [Op.and]: { | ||
448 | ...accountExclusion, | ||
449 | [Op.eq]: accountId | ||
450 | } | ||
451 | } | ||
452 | : accountExclusion | ||
453 | |||
454 | const videoChannelWhere = videoChannelId ? { id: videoChannelId } : undefined | ||
432 | 455 | ||
433 | const query = { | 456 | const query = { |
434 | order: [ [ 'createdAt', 'DESC' ] ] as Order, | 457 | order: [ [ 'createdAt', 'DESC' ] ] as Order, |
@@ -436,11 +459,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> { | |||
436 | limit: count, | 459 | limit: count, |
437 | where: { | 460 | where: { |
438 | deletedAt: null, | 461 | deletedAt: null, |
439 | accountId: { | 462 | accountId: accountWhere |
440 | [Op.notIn]: Sequelize.literal( | ||
441 | '(' + buildBlockedAccountSQL([ serverActor.Account.id, '"Video->VideoChannel"."accountId"' ]) + ')' | ||
442 | ) | ||
443 | } | ||
444 | }, | 463 | }, |
445 | include: [ | 464 | include: [ |
446 | { | 465 | { |
@@ -454,7 +473,8 @@ export class VideoCommentModel extends Model<VideoCommentModel> { | |||
454 | { | 473 | { |
455 | attributes: [ 'accountId' ], | 474 | attributes: [ 'accountId' ], |
456 | model: VideoChannelModel.unscoped(), | 475 | model: VideoChannelModel.unscoped(), |
457 | required: true | 476 | required: true, |
477 | where: videoChannelWhere | ||
458 | } | 478 | } |
459 | ] | 479 | ] |
460 | } | 480 | } |