aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorRigel Kent <sendmemail@rigelk.eu>2020-06-27 13:12:30 +0200
committerRigel Kent <sendmemail@rigelk.eu>2020-06-27 13:20:59 +0200
commit00494d6e2ae915741f47869dcd359d9728a0af91 (patch)
tree9642f3d5bf1565d3b8d60d3ad06495fefce80c23 /server
parent2c318664305fd2723586ad939e64f958d9d447ff (diff)
downloadPeerTube-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.ts55
-rw-r--r--server/middlewares/validators/feeds.ts6
-rw-r--r--server/models/video/video-comment.ts34
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
210function initFeed (name: string, description: string) { 239function 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 }