diff --git a/CHANGELOG_CHERRYPICK.md b/CHANGELOG_CHERRYPICK.md index fea2acf26f..9a8d240b62 100644 --- a/CHANGELOG_CHERRYPICK.md +++ b/CHANGELOG_CHERRYPICK.md @@ -32,6 +32,7 @@ Misskey의 전체 변경 사항을 확인하려면, [CHANGELOG.md#2024xx](CHANGE - Fix: 타임라인 노트의 리액션 뷰어에 리모트 서버의 커스텀 이모지가 표시되지 않음 ### Server +- Feat: 리모트 유저의 아바타 장식을 여러 개 불러올 수 있음([yunochi/misskey@696787b](https://github.com/yunochi/misskey/commit/696787b38bac31e7586899a5a59611a6fe50b9a1), [yunochi/misskey@4a5fcfe](https://github.com/yunochi/misskey/commit/4a5fcfe43880f08380541caa6b7593b90306d103)) - Fix: 유니코드 이모지로 리액션한 경우에도 리액션 알림에 `:`가 표시됨 --- diff --git a/packages/backend/src/core/AvatarDecorationService.ts b/packages/backend/src/core/AvatarDecorationService.ts index 8dbd6745ef..e151abd7f2 100644 --- a/packages/backend/src/core/AvatarDecorationService.ts +++ b/packages/backend/src/core/AvatarDecorationService.ts @@ -21,6 +21,7 @@ import type { Config } from '@/config.js'; @Injectable() export class AvatarDecorationService implements OnApplicationShutdown { public cache: MemorySingleCache; + public cacheWithRemote: MemorySingleCache; constructor( @Inject(DI.config) @@ -137,16 +138,15 @@ export class AvatarDecorationService implements OnApplicationShutdown { }); const userData: any = await res.json(); - const avatarDecorations = userData.avatarDecorations?.[0]; + const userAvatarDecorations = userData.avatarDecorations ?? undefined; - if (!avatarDecorations) { + if (!userAvatarDecorations || userAvatarDecorations.length === 0) { const updates = {} as Partial; updates.avatarDecorations = []; await this.usersRepository.update({ id: user.id }, updates); return; } - const avatarDecorationId = avatarDecorations.id; const instanceHost = instance.host; const decorationApiUrl = `https://${instanceHost}/api/get-avatar-decorations`; const allRes = await this.httpRequestService.send(decorationApiUrl, { @@ -154,46 +154,61 @@ export class AvatarDecorationService implements OnApplicationShutdown { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({}), }); + const allDecorations: any = await allRes.json(); - let name; - let description; - for (const decoration of allDecorations) { - if (decoration.id === avatarDecorationId) { - name = decoration.name; - description = decoration.description; - break; - } - } - const existingDecoration = await this.avatarDecorationsRepository.findOneBy({ - host: userHost, - remoteId: avatarDecorationId, - }); - const decorationData = { - name: name, - description: description, - url: this.getProxiedUrl(avatarDecorations.url, 'static'), - remoteId: avatarDecorationId, - host: userHost, - }; - if (existingDecoration == null) { - await this.create(decorationData); - } else { - await this.update(existingDecoration.id, decorationData); - } - const findDecoration = await this.avatarDecorationsRepository.findOneBy({ - host: userHost, - remoteId: avatarDecorationId, - }); const updates = {} as Partial; - updates.avatarDecorations = [{ - id: findDecoration?.id ?? '', - angle: avatarDecorations.angle ?? 0, - flipH: avatarDecorations.flipH ?? false, - offsetX: avatarDecorations.offsetX ?? 0, - offsetY: avatarDecorations.offsetY ?? 0, - scale: avatarDecorations.scale ?? 1, - opacity: avatarDecorations.opacity ?? 1, - }]; + updates.avatarDecorations = []; + + for (const avatarDecoration of userAvatarDecorations) { + let name; + let description; + const avatarDecorationId = avatarDecoration.id; + + for (const decoration of allDecorations) { + // eslint-disable-next-line eqeqeq + if (decoration.id == avatarDecorationId) { + name = decoration.name; + description = decoration.description; + break; + } + } + + const existingDecoration = await this.avatarDecorationsRepository.findOneBy({ + host: userHost, + remoteId: avatarDecorationId, + }); + + const decorationData = { + name: name, + description: description, + url: this.getProxiedUrl(avatarDecoration.url, 'static'), + remoteId: avatarDecorationId, + host: userHost, + }; + + if (existingDecoration == null) { + await this.create(decorationData); + this.cacheWithRemote.delete(); + } else { + await this.update(existingDecoration.id, decorationData); + this.cacheWithRemote.delete(); + } + + const findDecoration = await this.avatarDecorationsRepository.findOneBy({ + host: userHost, + remoteId: avatarDecorationId, + }); + + updates.avatarDecorations.push({ + id: findDecoration?.id ?? '', + angle: userAvatarDecorations.angle ?? 0, + flipH: userAvatarDecorations.flipH ?? false, + offsetX: userAvatarDecorations.offsetX ?? 0, + offsetY: userAvatarDecorations.offsetY ?? 0, + scale: userAvatarDecorations.scale ?? 1, + opacity: userAvatarDecorations.opacity ?? 1, + }); + } await this.usersRepository.update({ id: user.id }, updates); } @@ -220,7 +235,7 @@ export class AvatarDecorationService implements OnApplicationShutdown { if (!withRemote) { return this.cache.fetch(() => this.avatarDecorationsRepository.find({ where: { host: IsNull() } })); } else { - return this.cache.fetch(() => this.avatarDecorationsRepository.find()); + return this.cacheWithRemote.fetch(() => this.avatarDecorationsRepository.find()); } }