-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into external-resources
- Loading branch information
Showing
41 changed files
with
974 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
packages/backend/migration/1697847397844-avatar-decoration.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* | ||
* SPDX-FileCopyrightText: syuilo and other misskey contributors | ||
* SPDX-License-Identifier: AGPL-3.0-only | ||
*/ | ||
|
||
export class AvatarDecoration1697847397844 { | ||
name = 'AvatarDecoration1697847397844' | ||
|
||
async up(queryRunner) { | ||
await queryRunner.query(`CREATE TABLE "avatar_decoration" ("id" character varying(32) NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE, "url" character varying(1024) NOT NULL, "name" character varying(256) NOT NULL, "description" character varying(2048) NOT NULL, "roleIdsThatCanBeUsedThisDecoration" character varying(128) array NOT NULL DEFAULT '{}', CONSTRAINT "PK_b6de9296f6097078e1dc53f7603" PRIMARY KEY ("id"))`); | ||
await queryRunner.query(`ALTER TABLE "user" ADD "avatarDecorations" character varying(512) array NOT NULL DEFAULT '{}'`); | ||
} | ||
|
||
async down(queryRunner) { | ||
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarDecorations"`); | ||
await queryRunner.query(`DROP TABLE "avatar_decoration"`); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
/* | ||
* SPDX-FileCopyrightText: syuilo and other misskey contributors | ||
* SPDX-License-Identifier: AGPL-3.0-only | ||
*/ | ||
|
||
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; | ||
import * as Redis from 'ioredis'; | ||
import type { AvatarDecorationsRepository, MiAvatarDecoration, MiUser } from '@/models/_.js'; | ||
import { IdService } from '@/core/IdService.js'; | ||
import { GlobalEventService } from '@/core/GlobalEventService.js'; | ||
import { DI } from '@/di-symbols.js'; | ||
import { bindThis } from '@/decorators.js'; | ||
import { MemorySingleCache } from '@/misc/cache.js'; | ||
import type { GlobalEvents } from '@/core/GlobalEventService.js'; | ||
import { ModerationLogService } from '@/core/ModerationLogService.js'; | ||
|
||
@Injectable() | ||
export class AvatarDecorationService implements OnApplicationShutdown { | ||
public cache: MemorySingleCache<MiAvatarDecoration[]>; | ||
|
||
constructor( | ||
@Inject(DI.redisForSub) | ||
private redisForSub: Redis.Redis, | ||
|
||
@Inject(DI.avatarDecorationsRepository) | ||
private avatarDecorationsRepository: AvatarDecorationsRepository, | ||
|
||
private idService: IdService, | ||
private moderationLogService: ModerationLogService, | ||
private globalEventService: GlobalEventService, | ||
) { | ||
this.cache = new MemorySingleCache<MiAvatarDecoration[]>(1000 * 60 * 30); | ||
|
||
this.redisForSub.on('message', this.onMessage); | ||
} | ||
|
||
@bindThis | ||
private async onMessage(_: string, data: string): Promise<void> { | ||
const obj = JSON.parse(data); | ||
|
||
if (obj.channel === 'internal') { | ||
const { type, body } = obj.message as GlobalEvents['internal']['payload']; | ||
switch (type) { | ||
case 'avatarDecorationCreated': | ||
case 'avatarDecorationUpdated': | ||
case 'avatarDecorationDeleted': { | ||
this.cache.delete(); | ||
break; | ||
} | ||
default: | ||
break; | ||
} | ||
} | ||
} | ||
|
||
@bindThis | ||
public async create(options: Partial<MiAvatarDecoration>, moderator?: MiUser): Promise<MiAvatarDecoration> { | ||
const created = await this.avatarDecorationsRepository.insert({ | ||
id: this.idService.gen(), | ||
...options, | ||
}).then(x => this.avatarDecorationsRepository.findOneByOrFail(x.identifiers[0])); | ||
|
||
this.globalEventService.publishInternalEvent('avatarDecorationCreated', created); | ||
|
||
if (moderator) { | ||
this.moderationLogService.log(moderator, 'createAvatarDecoration', { | ||
avatarDecorationId: created.id, | ||
avatarDecoration: created, | ||
}); | ||
} | ||
|
||
return created; | ||
} | ||
|
||
@bindThis | ||
public async update(id: MiAvatarDecoration['id'], params: Partial<MiAvatarDecoration>, moderator?: MiUser): Promise<void> { | ||
const avatarDecoration = await this.avatarDecorationsRepository.findOneByOrFail({ id }); | ||
|
||
const date = new Date(); | ||
await this.avatarDecorationsRepository.update(avatarDecoration.id, { | ||
updatedAt: date, | ||
...params, | ||
}); | ||
|
||
const updated = await this.avatarDecorationsRepository.findOneByOrFail({ id: avatarDecoration.id }); | ||
this.globalEventService.publishInternalEvent('avatarDecorationUpdated', updated); | ||
|
||
if (moderator) { | ||
this.moderationLogService.log(moderator, 'updateAvatarDecoration', { | ||
avatarDecorationId: avatarDecoration.id, | ||
before: avatarDecoration, | ||
after: updated, | ||
}); | ||
} | ||
} | ||
|
||
@bindThis | ||
public async delete(id: MiAvatarDecoration['id'], moderator?: MiUser): Promise<void> { | ||
const avatarDecoration = await this.avatarDecorationsRepository.findOneByOrFail({ id }); | ||
|
||
await this.avatarDecorationsRepository.delete({ id: avatarDecoration.id }); | ||
this.globalEventService.publishInternalEvent('avatarDecorationDeleted', avatarDecoration); | ||
|
||
if (moderator) { | ||
this.moderationLogService.log(moderator, 'deleteAvatarDecoration', { | ||
avatarDecorationId: avatarDecoration.id, | ||
avatarDecoration: avatarDecoration, | ||
}); | ||
} | ||
} | ||
|
||
@bindThis | ||
public async getAll(noCache = false): Promise<MiAvatarDecoration[]> { | ||
if (noCache) { | ||
this.cache.delete(); | ||
} | ||
return this.cache.fetch(() => this.avatarDecorationsRepository.find()); | ||
} | ||
|
||
@bindThis | ||
public dispose(): void { | ||
this.redisForSub.off('message', this.onMessage); | ||
} | ||
|
||
@bindThis | ||
public onApplicationShutdown(signal?: string | undefined): void { | ||
this.dispose(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* SPDX-FileCopyrightText: syuilo and other misskey contributors | ||
* SPDX-License-Identifier: AGPL-3.0-only | ||
*/ | ||
|
||
import { Entity, PrimaryColumn, Index, Column, ManyToOne, JoinColumn } from 'typeorm'; | ||
import { id } from './util/id.js'; | ||
|
||
@Entity('avatar_decoration') | ||
export class MiAvatarDecoration { | ||
@PrimaryColumn(id()) | ||
public id: string; | ||
|
||
@Column('timestamp with time zone', { | ||
nullable: true, | ||
}) | ||
public updatedAt: Date | null; | ||
|
||
@Column('varchar', { | ||
length: 1024, | ||
}) | ||
public url: string; | ||
|
||
@Column('varchar', { | ||
length: 256, | ||
}) | ||
public name: string; | ||
|
||
@Column('varchar', { | ||
length: 2048, | ||
}) | ||
public description: string; | ||
|
||
// TODO: 定期ジョブで存在しなくなったロールIDを除去するようにする | ||
@Column('varchar', { | ||
array: true, length: 128, default: '{}', | ||
}) | ||
public roleIdsThatCanBeUsedThisDecoration: string[]; | ||
} |
Oops, something went wrong.