1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-03 17:59:37 +02:00

Add ability to customize instance logo

This commit is contained in:
Chocobozzz 2025-06-19 14:25:54 +02:00
parent f5fd593976
commit c0f4de6077
No known key found for this signature in database
GPG key ID: 583A612D890159BE
96 changed files with 1910 additions and 532 deletions

View file

@ -0,0 +1,96 @@
import { LogoType, UploadImageType, UploadImageType_Type } from '@peertube/peertube-models'
import { buildUUID, getLowercaseExtension } from '@peertube/peertube-node-utils'
import { buildImageSize } from '@server/helpers/image-utils.js'
import { UploadImageModel } from '@server/models/application/upload-image.js'
import { remove } from 'fs-extra/esm'
import { retryTransactionWrapper } from '../helpers/database-utils.js'
import { UPLOAD_IMAGES_SIZE } from '../initializers/constants.js'
import { sequelizeTypescript } from '../initializers/database.js'
import { MActorUploadImages } from '../types/models/index.js'
import { processImageFromWorker } from './worker/parent-process.js'
export async function replaceUploadImage (options: {
actor: MActorUploadImages
imagePhysicalFile: { path: string }
type: UploadImageType_Type
}) {
const { actor, imagePhysicalFile, type } = options
const processImageSize = async (imageSizeArg: { width: number, height: number }) => {
const imageSize = await buildImageSize(imagePhysicalFile.path, imageSizeArg)
const extension = getLowercaseExtension(imagePhysicalFile.path)
const imageName = buildUUID() + extension
const destination = UploadImageModel.getPathOf(imageName)
await processImageFromWorker({ path: imagePhysicalFile.path, destination, newSize: imageSize, keepOriginal: true })
return { imageName, imageSize }
}
const processedImages = await Promise.all(UPLOAD_IMAGES_SIZE[type].map(processImageSize))
await remove(imagePhysicalFile.path)
return retryTransactionWrapper(() =>
sequelizeTypescript.transaction(async t => {
const imagesToDelete = await UploadImageModel.listByActorAndType(actor, type, t)
for (const toDelete of imagesToDelete) {
await toDelete.destroy({ transaction: t })
actor.UploadImages = actor.UploadImages.filter(image => image.id !== toDelete.id)
}
for (const toCreate of processedImages) {
const uploadImage = await UploadImageModel.create({
filename: toCreate.imageName,
height: toCreate.imageSize.height,
width: toCreate.imageSize.width,
fileUrl: null,
type,
actorId: actor.id
}, { transaction: t })
actor.UploadImages.push(uploadImage)
}
})
)
}
export async function deleteUploadImages (options: {
actor: MActorUploadImages
type: UploadImageType_Type
}) {
const { actor, type } = options
return retryTransactionWrapper(() => {
return sequelizeTypescript.transaction(async t => {
const imagesToDelete = await UploadImageModel.listByActorAndType(actor, type, t)
for (const toDelete of imagesToDelete) {
await toDelete.destroy({ transaction: t })
}
actor.UploadImages = []
})
})
}
export function logoTypeToUploadImageEnum (logoType: LogoType) {
switch (logoType) {
case 'favicon':
return UploadImageType.INSTANCE_FAVICON
case 'header-wide':
return UploadImageType.INSTANCE_HEADER_WIDE
case 'header-square':
return UploadImageType.INSTANCE_HEADER_SQUARE
case 'opengraph':
return UploadImageType.INSTANCE_OPENGRAPH
default:
return logoType satisfies never
}
}