diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2023-03-08 08:56:09 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-08 08:56:09 +0900 |
| commit | 4c2f7c64cc2b70bd7b686e9ece1ebbc30eeab511 (patch) | |
| tree | 0d1ce1e7b3cd567c98205343e1e550cc47c714fa /packages/backend/src/core | |
| parent | refactor(dev): separate test workflows (diff) | |
| download | sharkey-4c2f7c64cc2b70bd7b686e9ece1ebbc30eeab511.tar.gz sharkey-4c2f7c64cc2b70bd7b686e9ece1ebbc30eeab511.tar.bz2 sharkey-4c2f7c64cc2b70bd7b686e9ece1ebbc30eeab511.zip | |
feat: Per-user renote mute (#10249)
* feat: per-user renote muting
From FoundKey/c414f24a2c https://akkoma.dev/FoundKeyGang/FoundKey
* Update ja-JP.yml
* Delete renote-muting.ts
* rename
* fix ids
* lint
* fix
* Update CHANGELOG.md
* リノートをミュートしたユーザー一覧を見れるように
* :art:
* add test
* fix test
---------
Co-authored-by: Hélène <pleroma-dev@helene.moe>
Diffstat (limited to 'packages/backend/src/core')
| -rw-r--r-- | packages/backend/src/core/CoreModule.ts | 6 | ||||
| -rw-r--r-- | packages/backend/src/core/QueryService.ts | 26 | ||||
| -rw-r--r-- | packages/backend/src/core/entities/RenoteMutingEntityService.ts | 47 | ||||
| -rw-r--r-- | packages/backend/src/core/entities/UserEntityService.ts | 13 |
4 files changed, 89 insertions, 3 deletions
diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts index 491d8ab113..1fd2d15004 100644 --- a/packages/backend/src/core/CoreModule.ts +++ b/packages/backend/src/core/CoreModule.ts @@ -82,6 +82,7 @@ import { HashtagEntityService } from './entities/HashtagEntityService.js'; import { InstanceEntityService } from './entities/InstanceEntityService.js'; import { ModerationLogEntityService } from './entities/ModerationLogEntityService.js'; import { MutingEntityService } from './entities/MutingEntityService.js'; +import { RenoteMutingEntityService } from './entities/RenoteMutingEntityService.js'; import { NoteEntityService } from './entities/NoteEntityService.js'; import { NoteFavoriteEntityService } from './entities/NoteFavoriteEntityService.js'; import { NoteReactionEntityService } from './entities/NoteReactionEntityService.js'; @@ -203,6 +204,7 @@ const $HashtagEntityService: Provider = { provide: 'HashtagEntityService', useEx const $InstanceEntityService: Provider = { provide: 'InstanceEntityService', useExisting: InstanceEntityService }; const $ModerationLogEntityService: Provider = { provide: 'ModerationLogEntityService', useExisting: ModerationLogEntityService }; const $MutingEntityService: Provider = { provide: 'MutingEntityService', useExisting: MutingEntityService }; +const $RenoteMutingEntityService: Provider = { provide: 'RenoteMutingEntityService', useExisting: RenoteMutingEntityService }; const $NoteEntityService: Provider = { provide: 'NoteEntityService', useExisting: NoteEntityService }; const $NoteFavoriteEntityService: Provider = { provide: 'NoteFavoriteEntityService', useExisting: NoteFavoriteEntityService }; const $NoteReactionEntityService: Provider = { provide: 'NoteReactionEntityService', useExisting: NoteReactionEntityService }; @@ -325,6 +327,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting InstanceEntityService, ModerationLogEntityService, MutingEntityService, + RenoteMutingEntityService, NoteEntityService, NoteFavoriteEntityService, NoteReactionEntityService, @@ -442,6 +445,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $InstanceEntityService, $ModerationLogEntityService, $MutingEntityService, + $RenoteMutingEntityService, $NoteEntityService, $NoteFavoriteEntityService, $NoteReactionEntityService, @@ -559,6 +563,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting InstanceEntityService, ModerationLogEntityService, MutingEntityService, + RenoteMutingEntityService, NoteEntityService, NoteFavoriteEntityService, NoteReactionEntityService, @@ -675,6 +680,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $InstanceEntityService, $ModerationLogEntityService, $MutingEntityService, + $RenoteMutingEntityService, $NoteEntityService, $NoteFavoriteEntityService, $NoteReactionEntityService, diff --git a/packages/backend/src/core/QueryService.ts b/packages/backend/src/core/QueryService.ts index c334d749e6..0cee2076bf 100644 --- a/packages/backend/src/core/QueryService.ts +++ b/packages/backend/src/core/QueryService.ts @@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Brackets, ObjectLiteral } from 'typeorm'; import { DI } from '@/di-symbols.js'; import type { User } from '@/models/entities/User.js'; -import type { UserProfilesRepository, FollowingsRepository, ChannelFollowingsRepository, MutedNotesRepository, BlockingsRepository, NoteThreadMutingsRepository, MutingsRepository } from '@/models/index.js'; +import type { UserProfilesRepository, FollowingsRepository, ChannelFollowingsRepository, MutedNotesRepository, BlockingsRepository, NoteThreadMutingsRepository, MutingsRepository, RenoteMutingsRepository } from '@/models/index.js'; import { bindThis } from '@/decorators.js'; import type { SelectQueryBuilder } from 'typeorm'; @@ -29,6 +29,9 @@ export class QueryService { @Inject(DI.mutingsRepository) private mutingsRepository: MutingsRepository, + + @Inject(DI.renoteMutingsRepository) + private renoteMutingsRepository: RenoteMutingsRepository, ) { } @@ -269,5 +272,24 @@ export class QueryService { q.setParameters({ meId: me.id }); } } -} + @bindThis + public generateMutedUserRenotesQueryForNotes(q: SelectQueryBuilder<any>, me: { id: User['id'] }): void { + const mutingQuery = this.renoteMutingsRepository.createQueryBuilder('renote_muting') + .select('renote_muting.muteeId') + .where('renote_muting.muterId = :muterId', { muterId: me.id }); + + q.andWhere(new Brackets(qb => { + qb + .where(new Brackets(qb => { + qb.where('note.renoteId IS NOT NULL'); + qb.andWhere('note.text IS NULL'); + qb.andWhere(`note.userId NOT IN (${ mutingQuery.getQuery() })`); + })) + .orWhere('note.renoteId IS NULL') + .orWhere('note.text IS NOT NULL'); + })); + + q.setParameters(mutingQuery.getParameters()); + } +} diff --git a/packages/backend/src/core/entities/RenoteMutingEntityService.ts b/packages/backend/src/core/entities/RenoteMutingEntityService.ts new file mode 100644 index 0000000000..66ee7305a1 --- /dev/null +++ b/packages/backend/src/core/entities/RenoteMutingEntityService.ts @@ -0,0 +1,47 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { DI } from '@/di-symbols.js'; +import type { RenoteMutingsRepository } from '@/models/index.js'; +import { awaitAll } from '@/misc/prelude/await-all.js'; +import type { Packed } from '@/misc/schema.js'; +import type { } from '@/models/entities/Blocking.js'; +import type { User } from '@/models/entities/User.js'; +import type { RenoteMuting } from '@/models/entities/RenoteMuting.js'; +import { bindThis } from '@/decorators.js'; +import { UserEntityService } from './UserEntityService.js'; + +@Injectable() +export class RenoteMutingEntityService { + constructor( + @Inject(DI.renoteMutingsRepository) + private renoteMutingsRepository: RenoteMutingsRepository, + + private userEntityService: UserEntityService, + ) { + } + + @bindThis + public async pack( + src: RenoteMuting['id'] | RenoteMuting, + me?: { id: User['id'] } | null | undefined, + ): Promise<Packed<'RenoteMuting'>> { + const muting = typeof src === 'object' ? src : await this.renoteMutingsRepository.findOneByOrFail({ id: src }); + + return await awaitAll({ + id: muting.id, + createdAt: muting.createdAt.toISOString(), + muteeId: muting.muteeId, + mutee: this.userEntityService.pack(muting.muteeId, me, { + detail: true, + }), + }); + } + + @bindThis + public packMany( + mutings: any[], + me: { id: User['id'] }, + ) { + return Promise.all(mutings.map(x => this.pack(x, me))); + } +} + diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index 3635643218..e7aa885f3c 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -12,7 +12,7 @@ import { Cache } from '@/misc/cache.js'; import type { Instance } from '@/models/entities/Instance.js'; import type { LocalUser, RemoteUser, User } from '@/models/entities/User.js'; import { birthdaySchema, descriptionSchema, localUsernameSchema, locationSchema, nameSchema, passwordSchema } from '@/models/entities/User.js'; -import type { UsersRepository, UserSecurityKeysRepository, FollowingsRepository, FollowRequestsRepository, BlockingsRepository, MutingsRepository, DriveFilesRepository, NoteUnreadsRepository, ChannelFollowingsRepository, NotificationsRepository, UserNotePiningsRepository, UserProfilesRepository, InstancesRepository, AnnouncementReadsRepository, AnnouncementsRepository, AntennaNotesRepository, PagesRepository, UserProfile } from '@/models/index.js'; +import type { UsersRepository, UserSecurityKeysRepository, FollowingsRepository, FollowRequestsRepository, BlockingsRepository, MutingsRepository, DriveFilesRepository, NoteUnreadsRepository, ChannelFollowingsRepository, NotificationsRepository, UserNotePiningsRepository, UserProfilesRepository, InstancesRepository, AnnouncementReadsRepository, AnnouncementsRepository, AntennaNotesRepository, PagesRepository, UserProfile, RenoteMutingsRepository } from '@/models/index.js'; import { bindThis } from '@/decorators.js'; import { RoleService } from '@/core/RoleService.js'; import type { OnModuleInit } from '@nestjs/common'; @@ -78,6 +78,9 @@ export class UserEntityService implements OnModuleInit { @Inject(DI.mutingsRepository) private mutingsRepository: MutingsRepository, + @Inject(DI.renoteMutingsRepository) + private renoteMutingsRepository: RenoteMutingsRepository, + @Inject(DI.driveFilesRepository) private driveFilesRepository: DriveFilesRepository, @@ -195,6 +198,13 @@ export class UserEntityService implements OnModuleInit { }, take: 1, }).then(n => n > 0), + isRenoteMuted: this.renoteMutingsRepository.count({ + where: { + muterId: me, + muteeId: target, + }, + take: 1, + }).then(n => n > 0), }); } @@ -493,6 +503,7 @@ export class UserEntityService implements OnModuleInit { isBlocking: relation.isBlocking, isBlocked: relation.isBlocked, isMuted: relation.isMuted, + isRenoteMuted: relation.isRenoteMuted, } : {}), } as Promiseable<Packed<'User'>> as Promiseable<IsMeAndIsUserDetailed<ExpectsMe, D>>; |