From 1ed1994fffb18a2b0bd74e49b50067ab047f8ab8 Mon Sep 17 00:00:00 2001 From: Alecks Gates Date: Mon, 5 Jun 2023 02:00:30 -0500 Subject: 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 --- server/controllers/feeds/shared/common-feed-utils.ts | 10 +++++++--- server/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(-) (limited to 'server') 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 -- cgit v1.2.3 From 8715c76356f3f3a6bce29a65f08743a0aff6be69 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 5 Jun 2023 08:53:31 +0200 Subject: More specific message when signup is not allowed --- server/lib/signup.ts | 6 +++--- server/middlewares/validators/user-registrations.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'server') diff --git a/server/lib/signup.ts b/server/lib/signup.ts index f19232621..6702c22cb 100644 --- a/server/lib/signup.ts +++ b/server/lib/signup.ts @@ -15,11 +15,11 @@ async function isSignupAllowed (options: { const { signupMode } = options if (CONFIG.SIGNUP.ENABLED === false) { - return { allowed: false } + return { allowed: false, errorMessage: 'User registration is not allowed' } } if (signupMode === 'direct-registration' && CONFIG.SIGNUP.REQUIRES_APPROVAL === true) { - return { allowed: false } + return { allowed: false, errorMessage: 'User registration requires approval' } } // No limit and signup is enabled @@ -29,7 +29,7 @@ async function isSignupAllowed (options: { const totalUsers = await UserModel.countTotal() - return { allowed: totalUsers < CONFIG.SIGNUP.LIMIT } + return { allowed: totalUsers < CONFIG.SIGNUP.LIMIT, errorMessage: 'User limit is reached on this instance' } } function isSignupAllowedForCurrentIP (ip: string) { diff --git a/server/middlewares/validators/user-registrations.ts b/server/middlewares/validators/user-registrations.ts index fcf655a2c..47397391b 100644 --- a/server/middlewares/validators/user-registrations.ts +++ b/server/middlewares/validators/user-registrations.ts @@ -59,7 +59,7 @@ function ensureUserRegistrationAllowedFactory (signupMode: SignupMode) { if (allowedResult.allowed === false) { return res.fail({ status: HttpStatusCode.FORBIDDEN_403, - message: allowedResult.errorMessage || 'User registration is not enabled, user limit is reached or registration requires approval.' + message: allowedResult.errorMessage || 'User registration is not allowed' }) } -- cgit v1.2.3