aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2022-06-27 10:36:16 +0200
committerChocobozzz <me@florianbigard.com>2022-06-27 10:36:16 +0200
commit41e74ec9cd6076109c91128047d8b866c36a3005 (patch)
treec70c6c00913f42c19064e24cd725ded83f71a70a
parent7a5c3d77fedd9099d1711feecfa975856750bcdf (diff)
downloadPeerTube-41e74ec9cd6076109c91128047d8b866c36a3005.tar.gz
PeerTube-41e74ec9cd6076109c91128047d8b866c36a3005.tar.zst
PeerTube-41e74ec9cd6076109c91128047d8b866c36a3005.zip
Fix broken feeds with published live
-rw-r--r--server/controllers/feeds.ts12
-rw-r--r--server/tests/feeds/feeds.ts82
-rw-r--r--shared/server-commands/feeds/feeds-command.ts21
3 files changed, 64 insertions, 51 deletions
diff --git a/server/controllers/feeds.ts b/server/controllers/feeds.ts
index c929a6726..ad93d700f 100644
--- a/server/controllers/feeds.ts
+++ b/server/controllers/feeds.ts
@@ -312,11 +312,13 @@ function addVideosToFeed (feed: Feed, videos: VideoModel[]) {
312 torrents, 312 torrents,
313 313
314 // Enclosure 314 // Enclosure
315 video: { 315 video: videoFiles.length !== 0
316 url: videoFiles[0].url, 316 ? {
317 length: videoFiles[0].fileSize, 317 url: videoFiles[0].url,
318 type: videoFiles[0].type 318 length: videoFiles[0].fileSize,
319 }, 319 type: videoFiles[0].type
320 }
321 : undefined,
320 322
321 // Media RSS 323 // Media RSS
322 videos: videoFiles, 324 videos: videoFiles,
diff --git a/server/tests/feeds/feeds.ts b/server/tests/feeds/feeds.ts
index ba3292a94..c7331d544 100644
--- a/server/tests/feeds/feeds.ts
+++ b/server/tests/feeds/feeds.ts
@@ -99,17 +99,17 @@ describe('Test syndication feeds', () => {
99 99
100 it('Should be well formed XML (covers RSS 2.0 and ATOM 1.0 endpoints)', async function () { 100 it('Should be well formed XML (covers RSS 2.0 and ATOM 1.0 endpoints)', async function () {
101 for (const feed of [ 'video-comments' as 'video-comments', 'videos' as 'videos' ]) { 101 for (const feed of [ 'video-comments' as 'video-comments', 'videos' as 'videos' ]) {
102 const rss = await servers[0].feed.getXML({ feed }) 102 const rss = await servers[0].feed.getXML({ feed, ignoreCache: true })
103 expect(rss).xml.to.be.valid() 103 expect(rss).xml.to.be.valid()
104 104
105 const atom = await servers[0].feed.getXML({ feed, format: 'atom' }) 105 const atom = await servers[0].feed.getXML({ feed, format: 'atom', ignoreCache: true })
106 expect(atom).xml.to.be.valid() 106 expect(atom).xml.to.be.valid()
107 } 107 }
108 }) 108 })
109 109
110 it('Should be well formed JSON (covers JSON feed 1.0 endpoint)', async function () { 110 it('Should be well formed JSON (covers JSON feed 1.0 endpoint)', async function () {
111 for (const feed of [ 'video-comments' as 'video-comments', 'videos' as 'videos' ]) { 111 for (const feed of [ 'video-comments' as 'video-comments', 'videos' as 'videos' ]) {
112 const jsonText = await servers[0].feed.getJSON({ feed }) 112 const jsonText = await servers[0].feed.getJSON({ feed, ignoreCache: true })
113 expect(JSON.parse(jsonText)).to.be.jsonSchema({ type: 'object' }) 113 expect(JSON.parse(jsonText)).to.be.jsonSchema({ type: 'object' })
114 } 114 }
115 }) 115 })
@@ -154,7 +154,7 @@ describe('Test syndication feeds', () => {
154 154
155 it('Should contain a valid enclosure (covers RSS 2.0 endpoint)', async function () { 155 it('Should contain a valid enclosure (covers RSS 2.0 endpoint)', async function () {
156 for (const server of servers) { 156 for (const server of servers) {
157 const rss = await server.feed.getXML({ feed: 'videos' }) 157 const rss = await server.feed.getXML({ feed: 'videos', ignoreCache: true })
158 expect(XMLValidator.validate(rss)).to.be.true 158 expect(XMLValidator.validate(rss)).to.be.true
159 159
160 const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false }) 160 const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false })
@@ -171,7 +171,7 @@ describe('Test syndication feeds', () => {
171 171
172 it('Should contain a valid \'attachments\' object (covers JSON feed 1.0 endpoint)', async function () { 172 it('Should contain a valid \'attachments\' object (covers JSON feed 1.0 endpoint)', async function () {
173 for (const server of servers) { 173 for (const server of servers) {
174 const json = await server.feed.getJSON({ feed: 'videos' }) 174 const json = await server.feed.getJSON({ feed: 'videos', ignoreCache: true })
175 const jsonObj = JSON.parse(json) 175 const jsonObj = JSON.parse(json)
176 expect(jsonObj.items.length).to.be.equal(2) 176 expect(jsonObj.items.length).to.be.equal(2)
177 expect(jsonObj.items[0].attachments).to.exist 177 expect(jsonObj.items[0].attachments).to.exist
@@ -184,7 +184,7 @@ describe('Test syndication feeds', () => {
184 184
185 it('Should filter by account', async function () { 185 it('Should filter by account', async function () {
186 { 186 {
187 const json = await servers[0].feed.getJSON({ feed: 'videos', query: { accountId: rootAccountId } }) 187 const json = await servers[0].feed.getJSON({ feed: 'videos', query: { accountId: rootAccountId }, ignoreCache: true })
188 const jsonObj = JSON.parse(json) 188 const jsonObj = JSON.parse(json)
189 expect(jsonObj.items.length).to.be.equal(1) 189 expect(jsonObj.items.length).to.be.equal(1)
190 expect(jsonObj.items[0].title).to.equal('my super name for server 1') 190 expect(jsonObj.items[0].title).to.equal('my super name for server 1')
@@ -192,7 +192,7 @@ describe('Test syndication feeds', () => {
192 } 192 }
193 193
194 { 194 {
195 const json = await servers[0].feed.getJSON({ feed: 'videos', query: { accountId: userAccountId } }) 195 const json = await servers[0].feed.getJSON({ feed: 'videos', query: { accountId: userAccountId }, ignoreCache: true })
196 const jsonObj = JSON.parse(json) 196 const jsonObj = JSON.parse(json)
197 expect(jsonObj.items.length).to.be.equal(1) 197 expect(jsonObj.items.length).to.be.equal(1)
198 expect(jsonObj.items[0].title).to.equal('user video') 198 expect(jsonObj.items[0].title).to.equal('user video')
@@ -201,14 +201,14 @@ describe('Test syndication feeds', () => {
201 201
202 for (const server of servers) { 202 for (const server of servers) {
203 { 203 {
204 const json = await server.feed.getJSON({ feed: 'videos', query: { accountName: 'root@localhost:' + servers[0].port } }) 204 const json = await server.feed.getJSON({ feed: 'videos', query: { accountName: 'root@' + servers[0].host }, ignoreCache: true })
205 const jsonObj = JSON.parse(json) 205 const jsonObj = JSON.parse(json)
206 expect(jsonObj.items.length).to.be.equal(1) 206 expect(jsonObj.items.length).to.be.equal(1)
207 expect(jsonObj.items[0].title).to.equal('my super name for server 1') 207 expect(jsonObj.items[0].title).to.equal('my super name for server 1')
208 } 208 }
209 209
210 { 210 {
211 const json = await server.feed.getJSON({ feed: 'videos', query: { accountName: 'john@localhost:' + servers[0].port } }) 211 const json = await server.feed.getJSON({ feed: 'videos', query: { accountName: 'john@' + servers[0].host }, ignoreCache: true })
212 const jsonObj = JSON.parse(json) 212 const jsonObj = JSON.parse(json)
213 expect(jsonObj.items.length).to.be.equal(1) 213 expect(jsonObj.items.length).to.be.equal(1)
214 expect(jsonObj.items[0].title).to.equal('user video') 214 expect(jsonObj.items[0].title).to.equal('user video')
@@ -218,7 +218,7 @@ describe('Test syndication feeds', () => {
218 218
219 it('Should filter by video channel', async function () { 219 it('Should filter by video channel', async function () {
220 { 220 {
221 const json = await servers[0].feed.getJSON({ feed: 'videos', query: { videoChannelId: rootChannelId } }) 221 const json = await servers[0].feed.getJSON({ feed: 'videos', query: { videoChannelId: rootChannelId }, ignoreCache: true })
222 const jsonObj = JSON.parse(json) 222 const jsonObj = JSON.parse(json)
223 expect(jsonObj.items.length).to.be.equal(1) 223 expect(jsonObj.items.length).to.be.equal(1)
224 expect(jsonObj.items[0].title).to.equal('my super name for server 1') 224 expect(jsonObj.items[0].title).to.equal('my super name for server 1')
@@ -226,7 +226,7 @@ describe('Test syndication feeds', () => {
226 } 226 }
227 227
228 { 228 {
229 const json = await servers[0].feed.getJSON({ feed: 'videos', query: { videoChannelId: userChannelId } }) 229 const json = await servers[0].feed.getJSON({ feed: 'videos', query: { videoChannelId: userChannelId }, ignoreCache: true })
230 const jsonObj = JSON.parse(json) 230 const jsonObj = JSON.parse(json)
231 expect(jsonObj.items.length).to.be.equal(1) 231 expect(jsonObj.items.length).to.be.equal(1)
232 expect(jsonObj.items[0].title).to.equal('user video') 232 expect(jsonObj.items[0].title).to.equal('user video')
@@ -235,16 +235,16 @@ describe('Test syndication feeds', () => {
235 235
236 for (const server of servers) { 236 for (const server of servers) {
237 { 237 {
238 const query = { videoChannelName: 'root_channel@localhost:' + servers[0].port } 238 const query = { videoChannelName: 'root_channel@' + servers[0].host }
239 const json = await server.feed.getJSON({ feed: 'videos', query }) 239 const json = await server.feed.getJSON({ feed: 'videos', query, ignoreCache: true })
240 const jsonObj = JSON.parse(json) 240 const jsonObj = JSON.parse(json)
241 expect(jsonObj.items.length).to.be.equal(1) 241 expect(jsonObj.items.length).to.be.equal(1)
242 expect(jsonObj.items[0].title).to.equal('my super name for server 1') 242 expect(jsonObj.items[0].title).to.equal('my super name for server 1')
243 } 243 }
244 244
245 { 245 {
246 const query = { videoChannelName: 'john_channel@localhost:' + servers[0].port } 246 const query = { videoChannelName: 'john_channel@' + servers[0].host }
247 const json = await server.feed.getJSON({ feed: 'videos', query }) 247 const json = await server.feed.getJSON({ feed: 'videos', query, ignoreCache: true })
248 const jsonObj = JSON.parse(json) 248 const jsonObj = JSON.parse(json)
249 expect(jsonObj.items.length).to.be.equal(1) 249 expect(jsonObj.items.length).to.be.equal(1)
250 expect(jsonObj.items[0].title).to.equal('user video') 250 expect(jsonObj.items[0].title).to.equal('user video')
@@ -259,7 +259,7 @@ describe('Test syndication feeds', () => {
259 259
260 await waitJobs([ serverHLSOnly ]) 260 await waitJobs([ serverHLSOnly ])
261 261
262 const json = await serverHLSOnly.feed.getJSON({ feed: 'videos' }) 262 const json = await serverHLSOnly.feed.getJSON({ feed: 'videos', ignoreCache: true })
263 const jsonObj = JSON.parse(json) 263 const jsonObj = JSON.parse(json)
264 expect(jsonObj.items.length).to.be.equal(1) 264 expect(jsonObj.items.length).to.be.equal(1)
265 expect(jsonObj.items[0].attachments).to.exist 265 expect(jsonObj.items[0].attachments).to.exist
@@ -282,7 +282,7 @@ describe('Test syndication feeds', () => {
282 }) 282 })
283 liveId = uuid 283 liveId = uuid
284 284
285 const json = await servers[0].feed.getJSON({ feed: 'videos' }) 285 const json = await servers[0].feed.getJSON({ feed: 'videos', ignoreCache: true })
286 286
287 const jsonObj = JSON.parse(json) 287 const jsonObj = JSON.parse(json)
288 expect(jsonObj.items.length).to.be.equal(2) 288 expect(jsonObj.items.length).to.be.equal(2)
@@ -290,19 +290,19 @@ describe('Test syndication feeds', () => {
290 expect(jsonObj.items[1].title).to.equal('user video') 290 expect(jsonObj.items[1].title).to.equal('user video')
291 }) 291 })
292 292
293 it('Should not display published live videos', async function () { 293 it('Should display published live videos', async function () {
294 this.timeout(120000) 294 this.timeout(120000)
295 295
296 const ffmpeg = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveId, copyCodecs: true, fixtureName: 'video_short.mp4' }) 296 const ffmpeg = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveId, copyCodecs: true, fixtureName: 'video_short.mp4' })
297 await servers[0].live.waitUntilPublished({ videoId: liveId }) 297 await servers[0].live.waitUntilPublished({ videoId: liveId })
298 298
299 const json = await servers[0].feed.getJSON({ feed: 'videos' }) 299 const json = await servers[0].feed.getJSON({ feed: 'videos', ignoreCache: true })
300 300
301 const jsonObj = JSON.parse(json) 301 const jsonObj = JSON.parse(json)
302 expect(jsonObj.items.length).to.be.equal(3) 302 expect(jsonObj.items.length).to.be.equal(3)
303 expect(jsonObj.items[0].title).to.equal('my super name for server 1') 303 expect(jsonObj.items[0].title).to.equal('live')
304 expect(jsonObj.items[1].title).to.equal('user video') 304 expect(jsonObj.items[1].title).to.equal('my super name for server 1')
305 expect(jsonObj.items[2].title).to.equal('live video') 305 expect(jsonObj.items[2].title).to.equal('user video')
306 306
307 await stopFfmpeg(ffmpeg) 307 await stopFfmpeg(ffmpeg)
308 }) 308 })
@@ -312,7 +312,7 @@ describe('Test syndication feeds', () => {
312 312
313 it('Should contain valid comments (covers JSON feed 1.0 endpoint) and not from unlisted videos', async function () { 313 it('Should contain valid comments (covers JSON feed 1.0 endpoint) and not from unlisted videos', async function () {
314 for (const server of servers) { 314 for (const server of servers) {
315 const json = await server.feed.getJSON({ feed: 'video-comments' }) 315 const json = await server.feed.getJSON({ feed: 'video-comments', ignoreCache: true })
316 316
317 const jsonObj = JSON.parse(json) 317 const jsonObj = JSON.parse(json)
318 expect(jsonObj.items.length).to.be.equal(2) 318 expect(jsonObj.items.length).to.be.equal(2)
@@ -324,12 +324,12 @@ describe('Test syndication feeds', () => {
324 it('Should not list comments from muted accounts or instances', async function () { 324 it('Should not list comments from muted accounts or instances', async function () {
325 this.timeout(30000) 325 this.timeout(30000)
326 326
327 const remoteHandle = 'root@localhost:' + servers[0].port 327 const remoteHandle = 'root@' + servers[0].host
328 328
329 await servers[1].blocklist.addToServerBlocklist({ account: remoteHandle }) 329 await servers[1].blocklist.addToServerBlocklist({ account: remoteHandle })
330 330
331 { 331 {
332 const json = await servers[1].feed.getJSON({ feed: 'video-comments', query: { version: 2 } }) 332 const json = await servers[1].feed.getJSON({ feed: 'video-comments', ignoreCache: true })
333 const jsonObj = JSON.parse(json) 333 const jsonObj = JSON.parse(json)
334 expect(jsonObj.items.length).to.be.equal(0) 334 expect(jsonObj.items.length).to.be.equal(0)
335 } 335 }
@@ -342,7 +342,7 @@ describe('Test syndication feeds', () => {
342 await servers[0].comments.createThread({ videoId: videoUUID, text: 'super comment' }) 342 await servers[0].comments.createThread({ videoId: videoUUID, text: 'super comment' })
343 await waitJobs(servers) 343 await waitJobs(servers)
344 344
345 const json = await servers[1].feed.getJSON({ feed: 'video-comments', query: { version: 3 } }) 345 const json = await servers[1].feed.getJSON({ feed: 'video-comments', ignoreCache: true })
346 const jsonObj = JSON.parse(json) 346 const jsonObj = JSON.parse(json)
347 expect(jsonObj.items.length).to.be.equal(3) 347 expect(jsonObj.items.length).to.be.equal(3)
348 } 348 }
@@ -350,7 +350,7 @@ describe('Test syndication feeds', () => {
350 await servers[1].blocklist.addToMyBlocklist({ account: remoteHandle }) 350 await servers[1].blocklist.addToMyBlocklist({ account: remoteHandle })
351 351
352 { 352 {
353 const json = await servers[1].feed.getJSON({ feed: 'video-comments', query: { version: 4 } }) 353 const json = await servers[1].feed.getJSON({ feed: 'video-comments', ignoreCache: true })
354 const jsonObj = JSON.parse(json) 354 const jsonObj = JSON.parse(json)
355 expect(jsonObj.items.length).to.be.equal(2) 355 expect(jsonObj.items.length).to.be.equal(2)
356 } 356 }
@@ -381,7 +381,7 @@ describe('Test syndication feeds', () => {
381 expect(body.total).to.equal(0) 381 expect(body.total).to.equal(0)
382 382
383 const query = { accountId: feeduserAccountId, token: feeduserFeedToken } 383 const query = { accountId: feeduserAccountId, token: feeduserFeedToken }
384 const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query }) 384 const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query, ignoreCache: true })
385 const jsonObj = JSON.parse(json) 385 const jsonObj = JSON.parse(json)
386 expect(jsonObj.items.length).to.be.equal(0) // no subscription, it should not list the instance's videos but list 0 videos 386 expect(jsonObj.items.length).to.be.equal(0) // no subscription, it should not list the instance's videos but list 0 videos
387 } 387 }
@@ -389,12 +389,12 @@ describe('Test syndication feeds', () => {
389 389
390 it('Should fail with an invalid token', async function () { 390 it('Should fail with an invalid token', async function () {
391 const query = { accountId: feeduserAccountId, token: 'toto' } 391 const query = { accountId: feeduserAccountId, token: 'toto' }
392 await servers[0].feed.getJSON({ feed: 'subscriptions', query, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) 392 await servers[0].feed.getJSON({ feed: 'subscriptions', query, expectedStatus: HttpStatusCode.FORBIDDEN_403, ignoreCache: true })
393 }) 393 })
394 394
395 it('Should fail with a token of another user', async function () { 395 it('Should fail with a token of another user', async function () {
396 const query = { accountId: feeduserAccountId, token: userFeedToken } 396 const query = { accountId: feeduserAccountId, token: userFeedToken }
397 await servers[0].feed.getJSON({ feed: 'subscriptions', query, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) 397 await servers[0].feed.getJSON({ feed: 'subscriptions', query, expectedStatus: HttpStatusCode.FORBIDDEN_403, ignoreCache: true })
398 }) 398 })
399 399
400 it('Should list no videos for a user with videos but no subscriptions', async function () { 400 it('Should list no videos for a user with videos but no subscriptions', async function () {
@@ -402,7 +402,7 @@ describe('Test syndication feeds', () => {
402 expect(body.total).to.equal(0) 402 expect(body.total).to.equal(0)
403 403
404 const query = { accountId: userAccountId, token: userFeedToken } 404 const query = { accountId: userAccountId, token: userFeedToken }
405 const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query }) 405 const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query, ignoreCache: true })
406 const jsonObj = JSON.parse(json) 406 const jsonObj = JSON.parse(json)
407 expect(jsonObj.items.length).to.be.equal(0) // no subscription, it should not list the instance's videos but list 0 videos 407 expect(jsonObj.items.length).to.be.equal(0) // no subscription, it should not list the instance's videos but list 0 videos
408 }) 408 })
@@ -410,7 +410,7 @@ describe('Test syndication feeds', () => {
410 it('Should list self videos for a user with a subscription to themselves', async function () { 410 it('Should list self videos for a user with a subscription to themselves', async function () {
411 this.timeout(30000) 411 this.timeout(30000)
412 412
413 await servers[0].subscriptions.add({ token: userAccessToken, targetUri: 'john_channel@localhost:' + servers[0].port }) 413 await servers[0].subscriptions.add({ token: userAccessToken, targetUri: 'john_channel@' + servers[0].host })
414 await waitJobs(servers) 414 await waitJobs(servers)
415 415
416 { 416 {
@@ -418,8 +418,8 @@ describe('Test syndication feeds', () => {
418 expect(body.total).to.equal(1) 418 expect(body.total).to.equal(1)
419 expect(body.data[0].name).to.equal('user video') 419 expect(body.data[0].name).to.equal('user video')
420 420
421 const query = { accountId: userAccountId, token: userFeedToken, version: 1 } 421 const query = { accountId: userAccountId, token: userFeedToken }
422 const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query }) 422 const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query, ignoreCache: true })
423 const jsonObj = JSON.parse(json) 423 const jsonObj = JSON.parse(json)
424 expect(jsonObj.items.length).to.be.equal(1) // subscribed to self, it should not list the instance's videos but list john's 424 expect(jsonObj.items.length).to.be.equal(1) // subscribed to self, it should not list the instance's videos but list john's
425 } 425 }
@@ -428,15 +428,15 @@ describe('Test syndication feeds', () => {
428 it('Should list videos of a user\'s subscription', async function () { 428 it('Should list videos of a user\'s subscription', async function () {
429 this.timeout(30000) 429 this.timeout(30000)
430 430
431 await servers[0].subscriptions.add({ token: userAccessToken, targetUri: 'root_channel@localhost:' + servers[0].port }) 431 await servers[0].subscriptions.add({ token: userAccessToken, targetUri: 'root_channel@' + servers[0].host })
432 await waitJobs(servers) 432 await waitJobs(servers)
433 433
434 { 434 {
435 const body = await servers[0].subscriptions.listVideos({ token: userAccessToken }) 435 const body = await servers[0].subscriptions.listVideos({ token: userAccessToken })
436 expect(body.total).to.equal(2, "there should be 2 videos part of the subscription") 436 expect(body.total).to.equal(2, "there should be 2 videos part of the subscription")
437 437
438 const query = { accountId: userAccountId, token: userFeedToken, version: 2 } 438 const query = { accountId: userAccountId, token: userFeedToken }
439 const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query }) 439 const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query, ignoreCache: true })
440 const jsonObj = JSON.parse(json) 440 const jsonObj = JSON.parse(json)
441 expect(jsonObj.items.length).to.be.equal(2) // subscribed to root, it should not list the instance's videos but list root/john's 441 expect(jsonObj.items.length).to.be.equal(2) // subscribed to root, it should not list the instance's videos but list root/john's
442 } 442 }
@@ -445,16 +445,16 @@ describe('Test syndication feeds', () => {
445 it('Should renew the token, and so have an invalid old token', async function () { 445 it('Should renew the token, and so have an invalid old token', async function () {
446 await servers[0].users.renewMyScopedTokens({ token: userAccessToken }) 446 await servers[0].users.renewMyScopedTokens({ token: userAccessToken })
447 447
448 const query = { accountId: userAccountId, token: userFeedToken, version: 3 } 448 const query = { accountId: userAccountId, token: userFeedToken }
449 await servers[0].feed.getJSON({ feed: 'subscriptions', query, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) 449 await servers[0].feed.getJSON({ feed: 'subscriptions', query, expectedStatus: HttpStatusCode.FORBIDDEN_403, ignoreCache: true })
450 }) 450 })
451 451
452 it('Should succeed with the new token', async function () { 452 it('Should succeed with the new token', async function () {
453 const token = await servers[0].users.getMyScopedTokens({ token: userAccessToken }) 453 const token = await servers[0].users.getMyScopedTokens({ token: userAccessToken })
454 userFeedToken = token.feedToken 454 userFeedToken = token.feedToken
455 455
456 const query = { accountId: userAccountId, token: userFeedToken, version: 4 } 456 const query = { accountId: userAccountId, token: userFeedToken }
457 await servers[0].feed.getJSON({ feed: 'subscriptions', query }) 457 await servers[0].feed.getJSON({ feed: 'subscriptions', query, ignoreCache: true })
458 }) 458 })
459 459
460 }) 460 })
diff --git a/shared/server-commands/feeds/feeds-command.ts b/shared/server-commands/feeds/feeds-command.ts
index 3c95f9536..939b18dee 100644
--- a/shared/server-commands/feeds/feeds-command.ts
+++ b/shared/server-commands/feeds/feeds-command.ts
@@ -1,4 +1,4 @@
1 1import { buildUUID } from '@shared/extra-utils'
2import { HttpStatusCode } from '@shared/models' 2import { HttpStatusCode } from '@shared/models'
3import { AbstractCommand, OverrideCommandOptions } from '../shared' 3import { AbstractCommand, OverrideCommandOptions } from '../shared'
4 4
@@ -8,16 +8,22 @@ export class FeedCommand extends AbstractCommand {
8 8
9 getXML (options: OverrideCommandOptions & { 9 getXML (options: OverrideCommandOptions & {
10 feed: FeedType 10 feed: FeedType
11 ignoreCache: boolean
11 format?: string 12 format?: string
12 }) { 13 }) {
13 const { feed, format } = options 14 const { feed, format, ignoreCache } = options
14 const path = '/feeds/' + feed + '.xml' 15 const path = '/feeds/' + feed + '.xml'
15 16
17 const query: { [id: string]: string } = {}
18
19 if (ignoreCache) query.v = buildUUID()
20 if (format) query.format = format
21
16 return this.getRequestText({ 22 return this.getRequestText({
17 ...options, 23 ...options,
18 24
19 path, 25 path,
20 query: format ? { format } : undefined, 26 query,
21 accept: 'application/xml', 27 accept: 'application/xml',
22 implicitToken: false, 28 implicitToken: false,
23 defaultExpectedStatus: HttpStatusCode.OK_200 29 defaultExpectedStatus: HttpStatusCode.OK_200
@@ -26,16 +32,21 @@ export class FeedCommand extends AbstractCommand {
26 32
27 getJSON (options: OverrideCommandOptions & { 33 getJSON (options: OverrideCommandOptions & {
28 feed: FeedType 34 feed: FeedType
35 ignoreCache: boolean
29 query?: { [ id: string ]: any } 36 query?: { [ id: string ]: any }
30 }) { 37 }) {
31 const { feed, query } = options 38 const { feed, query = {}, ignoreCache } = options
32 const path = '/feeds/' + feed + '.json' 39 const path = '/feeds/' + feed + '.json'
33 40
41 const cacheQuery = ignoreCache
42 ? { v: buildUUID() }
43 : {}
44
34 return this.getRequestText({ 45 return this.getRequestText({
35 ...options, 46 ...options,
36 47
37 path, 48 path,
38 query, 49 query: { ...query, ...cacheQuery },
39 accept: 'application/json', 50 accept: 'application/json',
40 implicitToken: false, 51 implicitToken: false,
41 defaultExpectedStatus: HttpStatusCode.OK_200 52 defaultExpectedStatus: HttpStatusCode.OK_200