]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/lib/local-actor.ts
Try to fix weird CI test crashes
[github/Chocobozzz/PeerTube.git] / server / lib / local-actor.ts
CommitLineData
4bbfc6c6 1import 'multer'
f4796856
C
2import { queue } from 'async'
3import * as LRUCache from 'lru-cache'
ea54cd04 4import { join } from 'path'
ea54cd04 5import { getLowercaseExtension } from '@server/helpers/core-utils'
d4a8e7a6 6import { buildUUID } from '@server/helpers/uuid'
136d7efd
C
7import { ActorModel } from '@server/models/actor/actor'
8import { ActivityPubActorType, ActorImageType } from '@shared/models'
f4796856
C
9import { retryTransactionWrapper } from '../helpers/database-utils'
10import { processImage } from '../helpers/image-utils'
11import { downloadImage } from '../helpers/requests'
6dd9de95 12import { CONFIG } from '../initializers/config'
136d7efd 13import { ACTOR_IMAGES_SIZE, LRU_CACHE, QUEUE_CONCURRENCY, WEBSERVER } from '../initializers/constants'
74dc3bca 14import { sequelizeTypescript } from '../initializers/database'
136d7efd
C
15import { MAccountDefault, MActor, MChannelDefault } from '../types/models'
16import { deleteActorImageInstance, updateActorImageInstance } from './activitypub/actors'
f4796856 17import { sendUpdateActor } from './activitypub/send'
4bbfc6c6 18
136d7efd
C
19function buildActorInstance (type: ActivityPubActorType, url: string, preferredUsername: string) {
20 return new ActorModel({
21 type,
22 url,
23 preferredUsername,
24 publicKey: null,
25 privateKey: null,
26 followersCount: 0,
27 followingCount: 0,
28 inboxUrl: url + '/inbox',
29 outboxUrl: url + '/outbox',
30 sharedInboxUrl: WEBSERVER.URL + '/inbox',
31 followersUrl: url + '/followers',
32 followingUrl: url + '/following'
33 }) as MActor
34}
35
2cb03dc1 36async function updateLocalActorImageFile (
1ea7da81 37 accountOrChannel: MAccountDefault | MChannelDefault,
2cb03dc1
C
38 imagePhysicalFile: Express.Multer.File,
39 type: ActorImageType
453e83ea 40) {
2cb03dc1
C
41 const imageSize = type === ActorImageType.AVATAR
42 ? ACTOR_IMAGES_SIZE.AVATARS
43 : ACTOR_IMAGES_SIZE.BANNERS
e08ff02a 44
ea54cd04 45 const extension = getLowercaseExtension(imagePhysicalFile.filename)
2cb03dc1 46
d4a8e7a6 47 const imageName = buildUUID() + extension
2cb03dc1
C
48 const destination = join(CONFIG.STORAGE.ACTOR_IMAGES, imageName)
49 await processImage(imagePhysicalFile.path, destination, imageSize)
4bbfc6c6 50
4a534352
C
51 return retryTransactionWrapper(() => {
52 return sequelizeTypescript.transaction(async t => {
2cb03dc1
C
53 const actorImageInfo = {
54 name: imageName,
557b13ae 55 fileUrl: null,
84531547
C
56 height: imageSize.height,
57 width: imageSize.width,
557b13ae
C
58 onDisk: true
59 }
60
213e30ef 61 const updatedActor = await updateActorImageInstance(accountOrChannel.Actor, type, actorImageInfo, t)
4a534352 62 await updatedActor.save({ transaction: t })
4bbfc6c6 63
4a534352 64 await sendUpdateActor(accountOrChannel, t)
4bbfc6c6 65
2cb03dc1
C
66 return type === ActorImageType.AVATAR
67 ? updatedActor.Avatar
68 : updatedActor.Banner
4a534352 69 })
4bbfc6c6
C
70 })
71}
72
2cb03dc1 73async function deleteLocalActorImageFile (accountOrChannel: MAccountDefault | MChannelDefault, type: ActorImageType) {
1ea7da81
RK
74 return retryTransactionWrapper(() => {
75 return sequelizeTypescript.transaction(async t => {
2cb03dc1 76 const updatedActor = await deleteActorImageInstance(accountOrChannel.Actor, type, t)
1ea7da81
RK
77 await updatedActor.save({ transaction: t })
78
79 await sendUpdateActor(accountOrChannel, t)
80
81 return updatedActor.Avatar
82 })
83 })
84}
85
2cb03dc1 86type DownloadImageQueueTask = { fileUrl: string, filename: string, type: ActorImageType }
557b13ae
C
87
88const downloadImageQueue = queue<DownloadImageQueueTask, Error>((task, cb) => {
2cb03dc1
C
89 const size = task.type === ActorImageType.AVATAR
90 ? ACTOR_IMAGES_SIZE.AVATARS
91 : ACTOR_IMAGES_SIZE.BANNERS
92
93 downloadImage(task.fileUrl, CONFIG.STORAGE.ACTOR_IMAGES, task.filename, size)
557b13ae
C
94 .then(() => cb())
95 .catch(err => cb(err))
f4796856 96}, QUEUE_CONCURRENCY.ACTOR_PROCESS_IMAGE)
557b13ae 97
f4796856 98function pushActorImageProcessInQueue (task: DownloadImageQueueTask) {
ba5a8d89 99 return new Promise<void>((res, rej) => {
557b13ae
C
100 downloadImageQueue.push(task, err => {
101 if (err) return rej(err)
102
103 return res()
104 })
105 })
106}
107
108// Unsafe so could returns paths that does not exist anymore
f4796856 109const actorImagePathUnsafeCache = new LRUCache<string, string>({ max: LRU_CACHE.ACTOR_IMAGE_STATIC.MAX_SIZE })
557b13ae 110
4bbfc6c6 111export {
f4796856 112 actorImagePathUnsafeCache,
2cb03dc1
C
113 updateLocalActorImageFile,
114 deleteLocalActorImageFile,
136d7efd
C
115 pushActorImageProcessInQueue,
116 buildActorInstance
4bbfc6c6 117}