From d0800f7661f13fabe7bb6f4aa0ea50764f106405 Mon Sep 17 00:00:00 2001 From: kontrollanten <6680299+kontrollanten@users.noreply.github.com> Date: Mon, 28 Feb 2022 08:34:43 +0100 Subject: Implement avatar miniatures (#4639) * client: remove unused file * refactor(client/my-actor-avatar): size from input Read size from component input instead of scss, to make it possible to use smaller avatar images when implemented. * implement avatar miniatures close #4560 * fix(test): max file size * fix(search-index): normalize res acc to avatarMini * refactor avatars to an array * client/search: resize channel avatar to 120 * refactor(client/videos): remove unused function * client(actor-avatar): set default size * fix tests and avatars full result When findOne is used only an array containting one avatar is returned. * update migration version and version notations * server/search: harmonize normalizing * Cleanup avatar miniature PR Co-authored-by: Chocobozzz --- scripts/migrations/peertube-4.2.ts | 106 +++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 scripts/migrations/peertube-4.2.ts (limited to 'scripts/migrations') diff --git a/scripts/migrations/peertube-4.2.ts b/scripts/migrations/peertube-4.2.ts new file mode 100644 index 000000000..045c3e511 --- /dev/null +++ b/scripts/migrations/peertube-4.2.ts @@ -0,0 +1,106 @@ +import { minBy } from 'lodash' +import { join } from 'path' +import { processImage } from '@server/helpers/image-utils' +import { CONFIG } from '@server/initializers/config' +import { ACTOR_IMAGES_SIZE } from '@server/initializers/constants' +import { updateActorImages } from '@server/lib/activitypub/actors' +import { sendUpdateActor } from '@server/lib/activitypub/send' +import { getBiggestActorImage } from '@server/lib/actor-image' +import { JobQueue } from '@server/lib/job-queue' +import { AccountModel } from '@server/models/account/account' +import { ActorModel } from '@server/models/actor/actor' +import { VideoChannelModel } from '@server/models/video/video-channel' +import { MAccountDefault, MActorDefault, MChannelDefault } from '@server/types/models' +import { getLowercaseExtension } from '@shared/core-utils' +import { buildUUID } from '@shared/extra-utils' +import { ActorImageType } from '@shared/models' +import { initDatabaseModels } from '../../server/initializers/database' + +run() + .then(() => process.exit(0)) + .catch(err => { + console.error(err) + process.exit(-1) + }) + +async function run () { + console.log('Generate avatar miniatures from existing avatars.') + + await initDatabaseModels(true) + JobQueue.Instance.init(true) + + const accounts: AccountModel[] = await AccountModel.findAll({ + include: [ + { + model: ActorModel, + required: true, + where: { + serverId: null + } + }, + { + model: VideoChannelModel, + include: [ + { + model: AccountModel + } + ] + } + ] + }) + + for (const account of accounts) { + try { + await generateSmallerAvatarIfNeeded(account) + } catch (err) { + console.error(`Cannot process account avatar ${account.name}`, err) + } + + for (const videoChannel of account.VideoChannels) { + try { + await generateSmallerAvatarIfNeeded(videoChannel) + } catch (err) { + console.error(`Cannot process channel avatar ${videoChannel.name}`, err) + } + } + } + + console.log('Generation finished!') +} + +async function generateSmallerAvatarIfNeeded (accountOrChannel: MAccountDefault | MChannelDefault) { + const avatars = accountOrChannel.Actor.Avatars + if (avatars.length !== 1) { + return + } + + console.log(`Processing ${accountOrChannel.name}.`) + + await generateSmallerAvatar(accountOrChannel.Actor) + accountOrChannel.Actor = Object.assign(accountOrChannel.Actor, { Server: null }) + + return sendUpdateActor(accountOrChannel, undefined) +} + +async function generateSmallerAvatar (actor: MActorDefault) { + const bigAvatar = getBiggestActorImage(actor.Avatars) + + const imageSize = minBy(ACTOR_IMAGES_SIZE[ActorImageType.AVATAR], 'width') + const sourceFilename = bigAvatar.filename + + const newImageName = buildUUID() + getLowercaseExtension(sourceFilename) + const source = join(CONFIG.STORAGE.ACTOR_IMAGES, sourceFilename) + const destination = join(CONFIG.STORAGE.ACTOR_IMAGES, newImageName) + + await processImage(source, destination, imageSize, true) + + const actorImageInfo = { + name: newImageName, + fileUrl: null, + height: imageSize.height, + width: imageSize.width, + onDisk: true + } + + await updateActorImages(actor, ActorImageType.AVATAR, [ actorImageInfo ], undefined) +} -- cgit v1.2.3