1 import { remove } from 'fs-extra'
2 import { join } from 'path'
3 import { AfterDestroy, AllowNull, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
4 import { v4 as uuidv4 } from 'uuid'
5 import { MActorImageFormattable } from '@server/types/models'
6 import { ActorImageType } from '@shared/models'
7 import { ActorImage } from '../../../shared/models/actors/actor-image.model'
8 import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
9 import { logger } from '../../helpers/logger'
10 import { CONFIG } from '../../initializers/config'
11 import { LAZY_STATIC_PATHS } from '../../initializers/constants'
12 import { throwIfNotValid } from '../utils'
15 tableName: 'actorImage',
18 fields: [ 'filename' ],
23 export class ActorImageModel extends Model {
30 @Is('ActorImageFileUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'fileUrl', true))
49 static removeFilesAndSendDelete (instance: ActorImageModel) {
50 logger.info('Removing actor image file %s.', instance.filename)
52 // Don't block the transaction
53 instance.removeImage()
54 .catch(err => logger.error('Cannot remove actor image file %s.', instance.filename, err))
57 static generateFilename () {
58 return uuidv4() + '.jpg'
61 static loadByName (filename: string) {
68 return ActorImageModel.findOne(query)
71 toFormattedJSON (this: MActorImageFormattable): ActorImage {
73 path: this.getStaticPath(),
74 createdAt: this.createdAt,
75 updatedAt: this.updatedAt
80 if (this.type === ActorImageType.AVATAR) {
81 return join(LAZY_STATIC_PATHS.AVATARS, this.filename)
84 return join(LAZY_STATIC_PATHS.BANNERS, this.filename)
88 return join(CONFIG.STORAGE.ACTOR_IMAGES, this.filename)
92 const imagePath = join(CONFIG.STORAGE.ACTOR_IMAGES, this.filename)
93 return remove(imagePath)