PeerTube/server/lib/activitypub/actors/image.ts

113 lines
3.1 KiB
TypeScript
Raw Normal View History

2021-06-03 16:02:29 +02:00
import { Transaction } from 'sequelize/types'
import { logger } from '@server/helpers/logger'
import { ActorImageModel } from '@server/models/actor/actor-image'
import { MActorImage, MActorImages } from '@server/types/models'
import { ActorImageType } from '@shared/models'
type ImageInfo = {
name: string
fileUrl: string
height: number
width: number
onDisk?: boolean
}
async function updateActorImages (actor: MActorImages, type: ActorImageType, imagesInfo: ImageInfo[], t: Transaction) {
2022-09-16 14:49:08 +02:00
const getAvatarsOrBanners = () => {
const result = type === ActorImageType.AVATAR
? actor.Avatars
: actor.Banners
return result || []
}
2021-06-03 16:02:29 +02:00
if (imagesInfo.length === 0) {
await deleteActorImages(actor, type, t)
}
2022-09-16 14:49:08 +02:00
// Cleanup old images that did not have a width
for (const oldImageModel of getAvatarsOrBanners()) {
if (oldImageModel.width) continue
await safeDeleteActorImage(actor, oldImageModel, type, t)
}
for (const imageInfo of imagesInfo) {
2022-09-16 14:49:08 +02:00
const oldImageModel = getAvatarsOrBanners().find(i => imageInfo.width && i.width === imageInfo.width)
2021-06-03 16:02:29 +02:00
if (oldImageModel) {
// Don't update the avatar if the file URL did not change
2022-09-16 14:49:08 +02:00
if (imageInfo.fileUrl && oldImageModel.fileUrl === imageInfo.fileUrl) {
continue
}
2021-06-03 16:02:29 +02:00
await safeDeleteActorImage(actor, oldImageModel, type, t)
2021-06-03 16:02:29 +02:00
}
const imageModel = await ActorImageModel.create({
filename: imageInfo.name,
onDisk: imageInfo.onDisk ?? false,
fileUrl: imageInfo.fileUrl,
height: imageInfo.height,
width: imageInfo.width,
type,
actorId: actor.id
2021-06-03 16:02:29 +02:00
}, { transaction: t })
addActorImage(actor, type, imageModel)
2021-06-03 16:02:29 +02:00
}
return actor
}
async function deleteActorImages (actor: MActorImages, type: ActorImageType, t: Transaction) {
2021-06-03 16:02:29 +02:00
try {
const association = buildAssociationName(type)
2021-06-03 16:02:29 +02:00
for (const image of actor[association]) {
await image.destroy({ transaction: t })
2021-06-03 16:02:29 +02:00
}
actor[association] = []
2021-06-03 16:02:29 +02:00
} catch (err) {
logger.error('Cannot remove old image of actor %s.', actor.url, { err })
}
return actor
}
async function safeDeleteActorImage (actor: MActorImages, toDelete: MActorImage, type: ActorImageType, t: Transaction) {
try {
await toDelete.destroy({ transaction: t })
const association = buildAssociationName(type)
actor[association] = actor[association].filter(image => image.id !== toDelete.id)
} catch (err) {
logger.error('Cannot remove old actor image of actor %s.', actor.url, { err })
}
}
2021-06-03 16:02:29 +02:00
// ---------------------------------------------------------------------------
export {
ImageInfo,
updateActorImages,
deleteActorImages
2021-06-03 16:02:29 +02:00
}
// ---------------------------------------------------------------------------
function addActorImage (actor: MActorImages, type: ActorImageType, imageModel: MActorImage) {
const association = buildAssociationName(type)
if (!actor[association]) actor[association] = []
actor[association].push(imageModel)
}
2021-06-03 16:02:29 +02:00
function buildAssociationName (type: ActorImageType) {
return type === ActorImageType.AVATAR
? 'Avatars'
: 'Banners'
2021-06-03 16:02:29 +02:00
}