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 { buildSQLAttributes, throwIfNotValid } from '../shared'
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 // ---------------------------------------------------------------------------
99 static getSQLAttributes (tableName: string, aliasPrefix = '') {
100 return buildSQLAttributes({
107 // ---------------------------------------------------------------------------
109 static loadByName (filename: string) {
116 return ActorImageModel.findOne(query)
119 static getImageUrl (image: MActorImage) {
120 if (!image) return undefined
122 return WEBSERVER.URL + image.getStaticPath()
125 toFormattedJSON (this: MActorImageFormattable): ActorImage {
128 path: this.getStaticPath(),
129 createdAt: this.createdAt,
130 updatedAt: this.updatedAt
134 toActivityPubObject (): ActivityIconObject {
135 const extension = getLowercaseExtension(this.filename)
139 mediaType: MIMETYPES.IMAGE.EXT_MIMETYPE[extension],
142 url: ActorImageModel.getImageUrl(this)
148 case ActorImageType.AVATAR:
149 return join(LAZY_STATIC_PATHS.AVATARS, this.filename)
151 case ActorImageType.BANNER:
152 return join(LAZY_STATIC_PATHS.BANNERS, this.filename)
155 throw new Error('Unknown actor image type: ' + this.type)
160 return join(CONFIG.STORAGE.ACTOR_IMAGES, this.filename)
164 const imagePath = join(CONFIG.STORAGE.ACTOR_IMAGES, this.filename)
165 return remove(imagePath)