]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/lib/local-actor.ts
Improve views/viewers documentation
[github/Chocobozzz/PeerTube.git] / server / lib / local-actor.ts
CommitLineData
f4796856 1import { queue } from 'async'
d0800f76 2import { remove } from 'fs-extra'
41fb13c3 3import LRUCache from 'lru-cache'
ea54cd04 4import { join } from 'path'
136d7efd 5import { ActorModel } from '@server/models/actor/actor'
0628157f
C
6import { getLowercaseExtension } from '@shared/core-utils'
7import { buildUUID } from '@shared/extra-utils'
136d7efd 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 15import { MAccountDefault, MActor, MChannelDefault } from '../types/models'
d0800f76 16import { deleteActorImages, updateActorImages } 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
d0800f76 36async function updateLocalActorImageFiles (
1ea7da81 37 accountOrChannel: MAccountDefault | MChannelDefault,
2cb03dc1
C
38 imagePhysicalFile: Express.Multer.File,
39 type: ActorImageType
453e83ea 40) {
d0800f76 41 const processImageSize = async (imageSize: { width: number, height: number }) => {
42 const extension = getLowercaseExtension(imagePhysicalFile.filename)
43
44 const imageName = buildUUID() + extension
45 const destination = join(CONFIG.STORAGE.ACTOR_IMAGES, imageName)
46 await processImage(imagePhysicalFile.path, destination, imageSize, true)
47
48 return {
49 imageName,
50 imageSize
51 }
52 }
53
54 const processedImages = await Promise.all(ACTOR_IMAGES_SIZE[type].map(processImageSize))
55 await remove(imagePhysicalFile.path)
56
57 return retryTransactionWrapper(() => sequelizeTypescript.transaction(async t => {
58 const actorImagesInfo = processedImages.map(({ imageName, imageSize }) => ({
59 name: imageName,
60 fileUrl: null,
61 height: imageSize.height,
62 width: imageSize.width,
63 onDisk: true
64 }))
65
66 const updatedActor = await updateActorImages(accountOrChannel.Actor, type, actorImagesInfo, t)
67 await updatedActor.save({ transaction: t })
68
69 await sendUpdateActor(accountOrChannel, t)
70
71 return type === ActorImageType.AVATAR
72 ? updatedActor.Avatars
73 : updatedActor.Banners
74 }))
4bbfc6c6
C
75}
76
2cb03dc1 77async function deleteLocalActorImageFile (accountOrChannel: MAccountDefault | MChannelDefault, type: ActorImageType) {
1ea7da81
RK
78 return retryTransactionWrapper(() => {
79 return sequelizeTypescript.transaction(async t => {
d0800f76 80 const updatedActor = await deleteActorImages(accountOrChannel.Actor, type, t)
1ea7da81
RK
81 await updatedActor.save({ transaction: t })
82
83 await sendUpdateActor(accountOrChannel, t)
84
d0800f76 85 return updatedActor.Avatars
1ea7da81
RK
86 })
87 })
88}
89
d0800f76 90type DownloadImageQueueTask = {
91 fileUrl: string
92 filename: string
93 type: ActorImageType
94 size: typeof ACTOR_IMAGES_SIZE[ActorImageType][0]
95}
557b13ae
C
96
97const downloadImageQueue = queue<DownloadImageQueueTask, Error>((task, cb) => {
d0800f76 98 downloadImage(task.fileUrl, CONFIG.STORAGE.ACTOR_IMAGES, task.filename, task.size)
557b13ae
C
99 .then(() => cb())
100 .catch(err => cb(err))
f4796856 101}, QUEUE_CONCURRENCY.ACTOR_PROCESS_IMAGE)
557b13ae 102
f4796856 103function pushActorImageProcessInQueue (task: DownloadImageQueueTask) {
ba5a8d89 104 return new Promise<void>((res, rej) => {
557b13ae
C
105 downloadImageQueue.push(task, err => {
106 if (err) return rej(err)
107
108 return res()
109 })
110 })
111}
112
113// Unsafe so could returns paths that does not exist anymore
f4796856 114const actorImagePathUnsafeCache = new LRUCache<string, string>({ max: LRU_CACHE.ACTOR_IMAGE_STATIC.MAX_SIZE })
557b13ae 115
4bbfc6c6 116export {
f4796856 117 actorImagePathUnsafeCache,
d0800f76 118 updateLocalActorImageFiles,
2cb03dc1 119 deleteLocalActorImageFile,
136d7efd
C
120 pushActorImageProcessInQueue,
121 buildActorInstance
4bbfc6c6 122}