]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Use largest avatar in RSS feeds, unique guid for liveItems (#5817)
authorAlecks Gates <agates@mail.agates.io>
Mon, 5 Jun 2023 07:00:30 +0000 (02:00 -0500)
committerGitHub <noreply@github.com>
Mon, 5 Jun 2023 07:00:30 +0000 (09:00 +0200)
* Attempt to get largest avatar size

* WIP live guid changes

* Use largest avatar version in feeds

* Misc variable names/import changes

* Update podcast feed tests for guid changes

* More <guid> testing

* Lint fix

* Styling

---------

Co-authored-by: Chocobozzz <me@florianbigard.com>
server/controllers/feeds/shared/common-feed-utils.ts
server/controllers/feeds/video-podcast-feeds.ts
server/middlewares/validators/feeds.ts
server/tests/feeds/feeds.ts

index 375c2814bb743ef148ef8c3fb6b8c9d891009968..8f35a8b350f2708b0e7835e1b575ba59e501f095 100644 (file)
@@ -1,4 +1,5 @@
 import express from 'express'
+import { maxBy } from 'lodash'
 import { Feed } from '@peertube/feed'
 import { CustomTag, CustomXMLNS, Person } from '@peertube/feed/lib/typings'
 import { mdToOneLinePlainText } from '@server/helpers/markdown'
@@ -104,11 +105,13 @@ export async function buildFeedMetadata (options: {
     accountLink = videoChannel.Account.getClientUrl()
 
     if (videoChannel.Actor.hasImage(ActorImageType.AVATAR)) {
-      imageUrl = WEBSERVER.URL + videoChannel.Actor.Avatars[0].getStaticPath()
+      const videoChannelAvatar = maxBy(videoChannel.Actor.Avatars, 'width')
+      imageUrl = WEBSERVER.URL + videoChannelAvatar.getStaticPath()
     }
 
     if (videoChannel.Account.Actor.hasImage(ActorImageType.AVATAR)) {
-      accountImageUrl = WEBSERVER.URL + videoChannel.Account.Actor.Avatars[0].getStaticPath()
+      const accountAvatar = maxBy(videoChannel.Account.Actor.Avatars, 'width')
+      accountImageUrl = WEBSERVER.URL + accountAvatar.getStaticPath()
     }
 
     user = await UserModel.loadById(videoChannel.Account.userId)
@@ -120,7 +123,8 @@ export async function buildFeedMetadata (options: {
     accountLink = link
 
     if (account.Actor.hasImage(ActorImageType.AVATAR)) {
-      imageUrl = WEBSERVER.URL + account.Actor.Avatars[0].getStaticPath()
+      const accountAvatar = maxBy(account.Actor.Avatars, 'width')
+      imageUrl = WEBSERVER.URL + accountAvatar?.getStaticPath()
       accountImageUrl = imageUrl
     }
 
index 45d31c7812b14d3055d6d2391cc207bf9fed60e2..f63f6ee63e6c6d4a732d27301f275961ba741a1c 100644 (file)
@@ -1,4 +1,5 @@
 import express from 'express'
+import { maxBy } from 'lodash'
 import { extname } from 'path'
 import { Feed } from '@peertube/feed'
 import { CustomTag, CustomXMLNS, LiveItemStatus } from '@peertube/feed/lib/typings'
@@ -141,8 +142,21 @@ async function generatePodcastItem (options: {
     href: account.getClientUrl()
   }
 
+  const commonAttributes = getCommonVideoFeedAttributes(video)
+  const guid = liveItem
+    ? `${video.uuid}_${video.publishedAt.toISOString()}`
+    : commonAttributes.link
+
+  let personImage: string
+
+  if (account.Actor.hasImage(ActorImageType.AVATAR)) {
+    const avatar = maxBy(account.Actor.Avatars, 'width')
+    personImage = WEBSERVER.URL + avatar.getStaticPath()
+  }
+
   return {
-    ...getCommonVideoFeedAttributes(video),
+    guid,
+    ...commonAttributes,
 
     trackers: video.getTrackerUrls(),
 
@@ -151,9 +165,7 @@ async function generatePodcastItem (options: {
       {
         ...author,
 
-        img: account.Actor.hasImage(ActorImageType.AVATAR)
-          ? WEBSERVER.URL + account.Actor.Avatars[0].getStaticPath()
-          : undefined
+        img: personImage
       }
     ],
 
index ee8615caefb96e5b97eb83bb7e7ca7a40cddde25..9673a6613684b9ccf18de886a3196805bd408abb 100644 (file)
@@ -1,6 +1,6 @@
 import express from 'express'
 import { param, query } from 'express-validator'
-import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
+import { HttpStatusCode } from '@shared/models'
 import { isValidRSSFeed } from '../../helpers/custom-validators/feeds'
 import { exists, isIdOrUUIDValid, isIdValid, toCompleteUUID } from '../../helpers/custom-validators/misc'
 import { buildPodcastGroupsCache } from '../cache'
index 57eefff6d7cb44a0f2cf617a76c0bd3fb3b85c5e..286c03596a12a1d5aab2157b953e9451d03157ac 100644 (file)
@@ -177,6 +177,10 @@ describe('Test syndication feeds', () => {
         const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false })
         const xmlDoc = parser.parse(rss)
 
+        const itemGuid = xmlDoc.rss.channel.item.guid
+        expect(itemGuid).to.exist
+        expect(itemGuid['@_isPermaLink']).to.equal(true)
+
         const enclosure = xmlDoc.rss.channel.item.enclosure
         expect(enclosure).to.exist
         const alternateEnclosure = xmlDoc.rss.channel.item['podcast:alternateEnclosure']
@@ -202,6 +206,10 @@ describe('Test syndication feeds', () => {
         const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false })
         const xmlDoc = parser.parse(rss)
 
+        const itemGuid = xmlDoc.rss.channel.item.guid
+        expect(itemGuid).to.exist
+        expect(itemGuid['@_isPermaLink']).to.equal(true)
+
         const enclosure = xmlDoc.rss.channel.item.enclosure
         const alternateEnclosure = xmlDoc.rss.channel.item['podcast:alternateEnclosure']
         expect(alternateEnclosure).to.exist
@@ -286,6 +294,8 @@ describe('Test syndication feeds', () => {
         const xmlDoc = parser.parse(rss)
         const liveItem = xmlDoc.rss.channel['podcast:liveItem']
         expect(liveItem.title).to.equal('live-0')
+        expect(liveItem.guid['@_isPermaLink']).to.equal(false)
+        expect(liveItem.guid['#text']).to.contain(`${uuid}_`)
         expect(liveItem['@_status']).to.equal('live')
 
         const enclosure = liveItem.enclosure