diff options
author | Alecks Gates <agates@mail.agates.io> | 2023-06-05 02:00:30 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-05 09:00:30 +0200 |
commit | 1ed1994fffb18a2b0bd74e49b50067ab047f8ab8 (patch) | |
tree | 9f06f52d9a376e75066a4a6f01079cb96de1ba6a | |
parent | 9a64621975097f648f6bf19f15b03ba3820918f2 (diff) | |
download | PeerTube-1ed1994fffb18a2b0bd74e49b50067ab047f8ab8.tar.gz PeerTube-1ed1994fffb18a2b0bd74e49b50067ab047f8ab8.tar.zst PeerTube-1ed1994fffb18a2b0bd74e49b50067ab047f8ab8.zip |
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>
-rw-r--r-- | server/controllers/feeds/shared/common-feed-utils.ts | 10 | ||||
-rw-r--r-- | server/controllers/feeds/video-podcast-feeds.ts | 20 | ||||
-rw-r--r-- | server/middlewares/validators/feeds.ts | 2 | ||||
-rw-r--r-- | 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 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { maxBy } from 'lodash' | ||
2 | import { Feed } from '@peertube/feed' | 3 | import { Feed } from '@peertube/feed' |
3 | import { CustomTag, CustomXMLNS, Person } from '@peertube/feed/lib/typings' | 4 | import { CustomTag, CustomXMLNS, Person } from '@peertube/feed/lib/typings' |
4 | import { mdToOneLinePlainText } from '@server/helpers/markdown' | 5 | import { mdToOneLinePlainText } from '@server/helpers/markdown' |
@@ -104,11 +105,13 @@ export async function buildFeedMetadata (options: { | |||
104 | accountLink = videoChannel.Account.getClientUrl() | 105 | accountLink = videoChannel.Account.getClientUrl() |
105 | 106 | ||
106 | if (videoChannel.Actor.hasImage(ActorImageType.AVATAR)) { | 107 | if (videoChannel.Actor.hasImage(ActorImageType.AVATAR)) { |
107 | imageUrl = WEBSERVER.URL + videoChannel.Actor.Avatars[0].getStaticPath() | 108 | const videoChannelAvatar = maxBy(videoChannel.Actor.Avatars, 'width') |
109 | imageUrl = WEBSERVER.URL + videoChannelAvatar.getStaticPath() | ||
108 | } | 110 | } |
109 | 111 | ||
110 | if (videoChannel.Account.Actor.hasImage(ActorImageType.AVATAR)) { | 112 | if (videoChannel.Account.Actor.hasImage(ActorImageType.AVATAR)) { |
111 | accountImageUrl = WEBSERVER.URL + videoChannel.Account.Actor.Avatars[0].getStaticPath() | 113 | const accountAvatar = maxBy(videoChannel.Account.Actor.Avatars, 'width') |
114 | accountImageUrl = WEBSERVER.URL + accountAvatar.getStaticPath() | ||
112 | } | 115 | } |
113 | 116 | ||
114 | user = await UserModel.loadById(videoChannel.Account.userId) | 117 | user = await UserModel.loadById(videoChannel.Account.userId) |
@@ -120,7 +123,8 @@ export async function buildFeedMetadata (options: { | |||
120 | accountLink = link | 123 | accountLink = link |
121 | 124 | ||
122 | if (account.Actor.hasImage(ActorImageType.AVATAR)) { | 125 | if (account.Actor.hasImage(ActorImageType.AVATAR)) { |
123 | imageUrl = WEBSERVER.URL + account.Actor.Avatars[0].getStaticPath() | 126 | const accountAvatar = maxBy(account.Actor.Avatars, 'width') |
127 | imageUrl = WEBSERVER.URL + accountAvatar?.getStaticPath() | ||
124 | accountImageUrl = imageUrl | 128 | accountImageUrl = imageUrl |
125 | } | 129 | } |
126 | 130 | ||
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 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { maxBy } from 'lodash' | ||
2 | import { extname } from 'path' | 3 | import { extname } from 'path' |
3 | import { Feed } from '@peertube/feed' | 4 | import { Feed } from '@peertube/feed' |
4 | import { CustomTag, CustomXMLNS, LiveItemStatus } from '@peertube/feed/lib/typings' | 5 | import { CustomTag, CustomXMLNS, LiveItemStatus } from '@peertube/feed/lib/typings' |
@@ -141,8 +142,21 @@ async function generatePodcastItem (options: { | |||
141 | href: account.getClientUrl() | 142 | href: account.getClientUrl() |
142 | } | 143 | } |
143 | 144 | ||
145 | const commonAttributes = getCommonVideoFeedAttributes(video) | ||
146 | const guid = liveItem | ||
147 | ? `${video.uuid}_${video.publishedAt.toISOString()}` | ||
148 | : commonAttributes.link | ||
149 | |||
150 | let personImage: string | ||
151 | |||
152 | if (account.Actor.hasImage(ActorImageType.AVATAR)) { | ||
153 | const avatar = maxBy(account.Actor.Avatars, 'width') | ||
154 | personImage = WEBSERVER.URL + avatar.getStaticPath() | ||
155 | } | ||
156 | |||
144 | return { | 157 | return { |
145 | ...getCommonVideoFeedAttributes(video), | 158 | guid, |
159 | ...commonAttributes, | ||
146 | 160 | ||
147 | trackers: video.getTrackerUrls(), | 161 | trackers: video.getTrackerUrls(), |
148 | 162 | ||
@@ -151,9 +165,7 @@ async function generatePodcastItem (options: { | |||
151 | { | 165 | { |
152 | ...author, | 166 | ...author, |
153 | 167 | ||
154 | img: account.Actor.hasImage(ActorImageType.AVATAR) | 168 | img: personImage |
155 | ? WEBSERVER.URL + account.Actor.Avatars[0].getStaticPath() | ||
156 | : undefined | ||
157 | } | 169 | } |
158 | ], | 170 | ], |
159 | 171 | ||
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 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { param, query } from 'express-validator' | 2 | import { param, query } from 'express-validator' |
3 | import { HttpStatusCode } from '../../../shared/models/http/http-error-codes' | 3 | import { HttpStatusCode } from '@shared/models' |
4 | import { isValidRSSFeed } from '../../helpers/custom-validators/feeds' | 4 | import { isValidRSSFeed } from '../../helpers/custom-validators/feeds' |
5 | import { exists, isIdOrUUIDValid, isIdValid, toCompleteUUID } from '../../helpers/custom-validators/misc' | 5 | import { exists, isIdOrUUIDValid, isIdValid, toCompleteUUID } from '../../helpers/custom-validators/misc' |
6 | import { buildPodcastGroupsCache } from '../cache' | 6 | 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', () => { | |||
177 | const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false }) | 177 | const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false }) |
178 | const xmlDoc = parser.parse(rss) | 178 | const xmlDoc = parser.parse(rss) |
179 | 179 | ||
180 | const itemGuid = xmlDoc.rss.channel.item.guid | ||
181 | expect(itemGuid).to.exist | ||
182 | expect(itemGuid['@_isPermaLink']).to.equal(true) | ||
183 | |||
180 | const enclosure = xmlDoc.rss.channel.item.enclosure | 184 | const enclosure = xmlDoc.rss.channel.item.enclosure |
181 | expect(enclosure).to.exist | 185 | expect(enclosure).to.exist |
182 | const alternateEnclosure = xmlDoc.rss.channel.item['podcast:alternateEnclosure'] | 186 | const alternateEnclosure = xmlDoc.rss.channel.item['podcast:alternateEnclosure'] |
@@ -202,6 +206,10 @@ describe('Test syndication feeds', () => { | |||
202 | const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false }) | 206 | const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false }) |
203 | const xmlDoc = parser.parse(rss) | 207 | const xmlDoc = parser.parse(rss) |
204 | 208 | ||
209 | const itemGuid = xmlDoc.rss.channel.item.guid | ||
210 | expect(itemGuid).to.exist | ||
211 | expect(itemGuid['@_isPermaLink']).to.equal(true) | ||
212 | |||
205 | const enclosure = xmlDoc.rss.channel.item.enclosure | 213 | const enclosure = xmlDoc.rss.channel.item.enclosure |
206 | const alternateEnclosure = xmlDoc.rss.channel.item['podcast:alternateEnclosure'] | 214 | const alternateEnclosure = xmlDoc.rss.channel.item['podcast:alternateEnclosure'] |
207 | expect(alternateEnclosure).to.exist | 215 | expect(alternateEnclosure).to.exist |
@@ -286,6 +294,8 @@ describe('Test syndication feeds', () => { | |||
286 | const xmlDoc = parser.parse(rss) | 294 | const xmlDoc = parser.parse(rss) |
287 | const liveItem = xmlDoc.rss.channel['podcast:liveItem'] | 295 | const liveItem = xmlDoc.rss.channel['podcast:liveItem'] |
288 | expect(liveItem.title).to.equal('live-0') | 296 | expect(liveItem.title).to.equal('live-0') |
297 | expect(liveItem.guid['@_isPermaLink']).to.equal(false) | ||
298 | expect(liveItem.guid['#text']).to.contain(`${uuid}_`) | ||
289 | expect(liveItem['@_status']).to.equal('live') | 299 | expect(liveItem['@_status']).to.equal('live') |
290 | 300 | ||
291 | const enclosure = liveItem.enclosure | 301 | const enclosure = liveItem.enclosure |