]>
Commit | Line | Data |
---|---|---|
4bbfc6c6 | 1 | import 'multer' |
f4796856 C |
2 | import { queue } from 'async' |
3 | import * as LRUCache from 'lru-cache' | |
4bbfc6c6 | 4 | import { extname, join } from 'path' |
bdd428a6 | 5 | import { v4 as uuidv4 } from 'uuid' |
2cb03dc1 | 6 | import { ActorImageType } from '@shared/models' |
f4796856 C |
7 | import { retryTransactionWrapper } from '../helpers/database-utils' |
8 | import { processImage } from '../helpers/image-utils' | |
9 | import { downloadImage } from '../helpers/requests' | |
6dd9de95 | 10 | import { CONFIG } from '../initializers/config' |
2cb03dc1 | 11 | import { ACTOR_IMAGES_SIZE, LRU_CACHE, QUEUE_CONCURRENCY } from '../initializers/constants' |
74dc3bca | 12 | import { sequelizeTypescript } from '../initializers/database' |
26d6bf65 | 13 | import { MAccountDefault, MChannelDefault } from '../types/models' |
2cb03dc1 | 14 | import { deleteActorImageInstance, updateActorImageInstance } from './activitypub/actor' |
f4796856 | 15 | import { sendUpdateActor } from './activitypub/send' |
4bbfc6c6 | 16 | |
2cb03dc1 | 17 | async function updateLocalActorImageFile ( |
1ea7da81 | 18 | accountOrChannel: MAccountDefault | MChannelDefault, |
2cb03dc1 C |
19 | imagePhysicalFile: Express.Multer.File, |
20 | type: ActorImageType | |
453e83ea | 21 | ) { |
2cb03dc1 C |
22 | const imageSize = type === ActorImageType.AVATAR |
23 | ? ACTOR_IMAGES_SIZE.AVATARS | |
24 | : ACTOR_IMAGES_SIZE.BANNERS | |
e08ff02a | 25 | |
2cb03dc1 C |
26 | const extension = extname(imagePhysicalFile.filename) |
27 | ||
28 | const imageName = uuidv4() + extension | |
29 | const destination = join(CONFIG.STORAGE.ACTOR_IMAGES, imageName) | |
30 | await processImage(imagePhysicalFile.path, destination, imageSize) | |
4bbfc6c6 | 31 | |
4a534352 C |
32 | return retryTransactionWrapper(() => { |
33 | return sequelizeTypescript.transaction(async t => { | |
2cb03dc1 C |
34 | const actorImageInfo = { |
35 | name: imageName, | |
557b13ae | 36 | fileUrl: null, |
84531547 C |
37 | height: imageSize.height, |
38 | width: imageSize.width, | |
557b13ae C |
39 | onDisk: true |
40 | } | |
41 | ||
213e30ef | 42 | const updatedActor = await updateActorImageInstance(accountOrChannel.Actor, type, actorImageInfo, t) |
4a534352 | 43 | await updatedActor.save({ transaction: t }) |
4bbfc6c6 | 44 | |
4a534352 | 45 | await sendUpdateActor(accountOrChannel, t) |
4bbfc6c6 | 46 | |
2cb03dc1 C |
47 | return type === ActorImageType.AVATAR |
48 | ? updatedActor.Avatar | |
49 | : updatedActor.Banner | |
4a534352 | 50 | }) |
4bbfc6c6 C |
51 | }) |
52 | } | |
53 | ||
2cb03dc1 | 54 | async function deleteLocalActorImageFile (accountOrChannel: MAccountDefault | MChannelDefault, type: ActorImageType) { |
1ea7da81 RK |
55 | return retryTransactionWrapper(() => { |
56 | return sequelizeTypescript.transaction(async t => { | |
2cb03dc1 | 57 | const updatedActor = await deleteActorImageInstance(accountOrChannel.Actor, type, t) |
1ea7da81 RK |
58 | await updatedActor.save({ transaction: t }) |
59 | ||
60 | await sendUpdateActor(accountOrChannel, t) | |
61 | ||
62 | return updatedActor.Avatar | |
63 | }) | |
64 | }) | |
65 | } | |
66 | ||
2cb03dc1 | 67 | type DownloadImageQueueTask = { fileUrl: string, filename: string, type: ActorImageType } |
557b13ae C |
68 | |
69 | const downloadImageQueue = queue<DownloadImageQueueTask, Error>((task, cb) => { | |
2cb03dc1 C |
70 | const size = task.type === ActorImageType.AVATAR |
71 | ? ACTOR_IMAGES_SIZE.AVATARS | |
72 | : ACTOR_IMAGES_SIZE.BANNERS | |
73 | ||
74 | downloadImage(task.fileUrl, CONFIG.STORAGE.ACTOR_IMAGES, task.filename, size) | |
557b13ae C |
75 | .then(() => cb()) |
76 | .catch(err => cb(err)) | |
f4796856 | 77 | }, QUEUE_CONCURRENCY.ACTOR_PROCESS_IMAGE) |
557b13ae | 78 | |
f4796856 | 79 | function pushActorImageProcessInQueue (task: DownloadImageQueueTask) { |
ba5a8d89 | 80 | return new Promise<void>((res, rej) => { |
557b13ae C |
81 | downloadImageQueue.push(task, err => { |
82 | if (err) return rej(err) | |
83 | ||
84 | return res() | |
85 | }) | |
86 | }) | |
87 | } | |
88 | ||
89 | // Unsafe so could returns paths that does not exist anymore | |
f4796856 | 90 | const actorImagePathUnsafeCache = new LRUCache<string, string>({ max: LRU_CACHE.ACTOR_IMAGE_STATIC.MAX_SIZE }) |
557b13ae | 91 | |
4bbfc6c6 | 92 | export { |
f4796856 | 93 | actorImagePathUnsafeCache, |
2cb03dc1 C |
94 | updateLocalActorImageFile, |
95 | deleteLocalActorImageFile, | |
f4796856 | 96 | pushActorImageProcessInQueue |
4bbfc6c6 | 97 | } |