Use largest avatar in RSS feeds, unique guid for liveItems (#5817)

* 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>
pull/5840/head
Alecks Gates 2023-06-05 02:00:30 -05:00 committed by GitHub
parent 9a64621975
commit 1ed1994fff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 8 deletions

View File

@ -1,4 +1,5 @@
import express from 'express' import express from 'express'
import { maxBy } from 'lodash'
import { Feed } from '@peertube/feed' import { Feed } from '@peertube/feed'
import { CustomTag, CustomXMLNS, Person } from '@peertube/feed/lib/typings' import { CustomTag, CustomXMLNS, Person } from '@peertube/feed/lib/typings'
import { mdToOneLinePlainText } from '@server/helpers/markdown' import { mdToOneLinePlainText } from '@server/helpers/markdown'
@ -104,11 +105,13 @@ export async function buildFeedMetadata (options: {
accountLink = videoChannel.Account.getClientUrl() accountLink = videoChannel.Account.getClientUrl()
if (videoChannel.Actor.hasImage(ActorImageType.AVATAR)) { 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)) { 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) user = await UserModel.loadById(videoChannel.Account.userId)
@ -120,7 +123,8 @@ export async function buildFeedMetadata (options: {
accountLink = link accountLink = link
if (account.Actor.hasImage(ActorImageType.AVATAR)) { 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 accountImageUrl = imageUrl
} }

View File

@ -1,4 +1,5 @@
import express from 'express' import express from 'express'
import { maxBy } from 'lodash'
import { extname } from 'path' import { extname } from 'path'
import { Feed } from '@peertube/feed' import { Feed } from '@peertube/feed'
import { CustomTag, CustomXMLNS, LiveItemStatus } from '@peertube/feed/lib/typings' import { CustomTag, CustomXMLNS, LiveItemStatus } from '@peertube/feed/lib/typings'
@ -141,8 +142,21 @@ async function generatePodcastItem (options: {
href: account.getClientUrl() 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 { return {
...getCommonVideoFeedAttributes(video), guid,
...commonAttributes,
trackers: video.getTrackerUrls(), trackers: video.getTrackerUrls(),
@ -151,9 +165,7 @@ async function generatePodcastItem (options: {
{ {
...author, ...author,
img: account.Actor.hasImage(ActorImageType.AVATAR) img: personImage
? WEBSERVER.URL + account.Actor.Avatars[0].getStaticPath()
: undefined
} }
], ],

View File

@ -1,6 +1,6 @@
import express from 'express' import express from 'express'
import { param, query } from 'express-validator' 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 { isValidRSSFeed } from '../../helpers/custom-validators/feeds'
import { exists, isIdOrUUIDValid, isIdValid, toCompleteUUID } from '../../helpers/custom-validators/misc' import { exists, isIdOrUUIDValid, isIdValid, toCompleteUUID } from '../../helpers/custom-validators/misc'
import { buildPodcastGroupsCache } from '../cache' import { buildPodcastGroupsCache } from '../cache'

View File

@ -177,6 +177,10 @@ describe('Test syndication feeds', () => {
const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false }) const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false })
const xmlDoc = parser.parse(rss) 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 enclosure = xmlDoc.rss.channel.item.enclosure
expect(enclosure).to.exist expect(enclosure).to.exist
const alternateEnclosure = xmlDoc.rss.channel.item['podcast:alternateEnclosure'] 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 parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false })
const xmlDoc = parser.parse(rss) 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 enclosure = xmlDoc.rss.channel.item.enclosure
const alternateEnclosure = xmlDoc.rss.channel.item['podcast:alternateEnclosure'] const alternateEnclosure = xmlDoc.rss.channel.item['podcast:alternateEnclosure']
expect(alternateEnclosure).to.exist expect(alternateEnclosure).to.exist
@ -286,6 +294,8 @@ describe('Test syndication feeds', () => {
const xmlDoc = parser.parse(rss) const xmlDoc = parser.parse(rss)
const liveItem = xmlDoc.rss.channel['podcast:liveItem'] const liveItem = xmlDoc.rss.channel['podcast:liveItem']
expect(liveItem.title).to.equal('live-0') 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') expect(liveItem['@_status']).to.equal('live')
const enclosure = liveItem.enclosure const enclosure = liveItem.enclosure