From 1ed1994fffb18a2b0bd74e49b50067ab047f8ab8 Mon Sep 17 00:00:00 2001 From: Alecks Gates Date: Mon, 5 Jun 2023 02:00:30 -0500 Subject: [PATCH] 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 testing * Lint fix * Styling --------- Co-authored-by: Chocobozzz --- .../feeds/shared/common-feed-utils.ts | 10 +++++++--- .../controllers/feeds/video-podcast-feeds.ts | 20 +++++++++++++++---- server/middlewares/validators/feeds.ts | 2 +- server/tests/feeds/feeds.ts | 10 ++++++++++ 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/server/controllers/feeds/shared/common-feed-utils.ts b/server/controllers/feeds/shared/common-feed-utils.ts index 375c2814b..8f35a8b35 100644 --- a/server/controllers/feeds/shared/common-feed-utils.ts +++ b/server/controllers/feeds/shared/common-feed-utils.ts @@ -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 } diff --git a/server/controllers/feeds/video-podcast-feeds.ts b/server/controllers/feeds/video-podcast-feeds.ts index 45d31c781..f63f6ee63 100644 --- a/server/controllers/feeds/video-podcast-feeds.ts +++ b/server/controllers/feeds/video-podcast-feeds.ts @@ -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 } ], diff --git a/server/middlewares/validators/feeds.ts b/server/middlewares/validators/feeds.ts index ee8615cae..9673a6613 100644 --- a/server/middlewares/validators/feeds.ts +++ b/server/middlewares/validators/feeds.ts @@ -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' diff --git a/server/tests/feeds/feeds.ts b/server/tests/feeds/feeds.ts index 57eefff6d..286c03596 100644 --- a/server/tests/feeds/feeds.ts +++ b/server/tests/feeds/feeds.ts @@ -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 -- 2.41.0