1 import { remove } from 'fs-extra'
2 import { join } from 'path'
15 } from 'sequelize-typescript'
16 import { MActorImage, MActorImageFormattable } from '@server/types/models'
17 import { getLowercaseExtension } from '@shared/core-utils'
18 import { ActivityIconObject, ActorImageType } from '@shared/models'
19 import { AttributesOnly } from '@shared/typescript-utils'
20 import { ActorImage } from '../../../shared/models/actors/actor-image.model'
21 import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
22 import { logger } from '../../helpers/logger'
23 import { CONFIG } from '../../initializers/config'
24 import { LAZY_STATIC_PATHS, MIMETYPES, WEBSERVER } from '../../initializers/constants'
25 import { throwIfNotValid } from '../utils'
26 import { ActorModel } from './actor'
29 tableName: 'actorImage',
32 fields: [ 'filename' ],
36 fields: [ 'actorId', 'type', 'width' ],
41 export class ActorImageModel extends Model<Partial<AttributesOnly<ActorImageModel>>> {
58 @Is('ActorImageFileUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'fileUrl', true))
76 @ForeignKey(() => ActorModel)
80 @BelongsTo(() => ActorModel, {
89 static removeFilesAndSendDelete (instance: ActorImageModel) {
90 logger.info('Removing actor image file %s.', instance.filename)
92 // Don't block the transaction
93 instance.removeImage()
94 .catch(err => logger.error('Cannot remove actor image file %s.', instance.filename, err))
97 static loadByName (filename: string) {
104 return ActorImageModel.findOne(query)
107 static getImageUrl (image: MActorImage) {
108 if (!image) return undefined
110 return WEBSERVER.URL + image.getStaticPath()
113 toFormattedJSON (this: MActorImageFormattable): ActorImage {
116 path: this.getStaticPath(),
117 createdAt: this.createdAt,
118 updatedAt: this.updatedAt
122 toActivityPubObject (): ActivityIconObject {
123 const extension = getLowercaseExtension(this.filename)
127 mediaType: MIMETYPES.IMAGE.EXT_MIMETYPE[extension],
130 url: ActorImageModel.getImageUrl(this)
136 case ActorImageType.AVATAR:
137 return join(LAZY_STATIC_PATHS.AVATARS, this.filename)
139 case ActorImageType.BANNER:
140 return join(LAZY_STATIC_PATHS.BANNERS, this.filename)
145 return join(CONFIG.STORAGE.ACTOR_IMAGES, this.filename)
149 const imagePath = join(CONFIG.STORAGE.ACTOR_IMAGES, this.filename)
150 return remove(imagePath)