Mod: UserReactionBlockingServiceとUserBlockingServiceを統合

This commit is contained in:
鴇峰 朔華 2024-11-18 21:46:28 +09:00
parent 0301e86aff
commit da94dbee00
7 changed files with 81 additions and 139 deletions

View File

@ -58,7 +58,6 @@ import { S3Service } from './S3Service.js';
import { SignupService } from './SignupService.js'; import { SignupService } from './SignupService.js';
import { WebAuthnService } from './WebAuthnService.js'; import { WebAuthnService } from './WebAuthnService.js';
import { UserBlockingService } from './UserBlockingService.js'; import { UserBlockingService } from './UserBlockingService.js';
import { UserReactionBlockingService } from './UserReactionBlockingService.js';
import { CacheService } from './CacheService.js'; import { CacheService } from './CacheService.js';
import { UserService } from './UserService.js'; import { UserService } from './UserService.js';
import { UserFollowingService } from './UserFollowingService.js'; import { UserFollowingService } from './UserFollowingService.js';
@ -203,7 +202,6 @@ const $S3Service: Provider = { provide: 'S3Service', useExisting: S3Service };
const $SignupService: Provider = { provide: 'SignupService', useExisting: SignupService }; const $SignupService: Provider = { provide: 'SignupService', useExisting: SignupService };
const $WebAuthnService: Provider = { provide: 'WebAuthnService', useExisting: WebAuthnService }; const $WebAuthnService: Provider = { provide: 'WebAuthnService', useExisting: WebAuthnService };
const $UserBlockingService: Provider = { provide: 'UserBlockingService', useExisting: UserBlockingService }; const $UserBlockingService: Provider = { provide: 'UserBlockingService', useExisting: UserBlockingService };
const $UserReactionBlockingService: Provider = { provide: 'UserReactionBlockingService', useExisting: UserReactionBlockingService };
const $CacheService: Provider = { provide: 'CacheService', useExisting: CacheService }; const $CacheService: Provider = { provide: 'CacheService', useExisting: CacheService };
const $UserService: Provider = { provide: 'UserService', useExisting: UserService }; const $UserService: Provider = { provide: 'UserService', useExisting: UserService };
const $UserFollowingService: Provider = { provide: 'UserFollowingService', useExisting: UserFollowingService }; const $UserFollowingService: Provider = { provide: 'UserFollowingService', useExisting: UserFollowingService };
@ -355,7 +353,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
SignupService, SignupService,
WebAuthnService, WebAuthnService,
UserBlockingService, UserBlockingService,
UserReactionBlockingService,
CacheService, CacheService,
UserService, UserService,
UserFollowingService, UserFollowingService,
@ -503,7 +500,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$SignupService, $SignupService,
$WebAuthnService, $WebAuthnService,
$UserBlockingService, $UserBlockingService,
$UserReactionBlockingService,
$CacheService, $CacheService,
$UserService, $UserService,
$UserFollowingService, $UserFollowingService,
@ -652,7 +648,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
SignupService, SignupService,
WebAuthnService, WebAuthnService,
UserBlockingService, UserBlockingService,
UserReactionBlockingService,
CacheService, CacheService,
UserService, UserService,
UserFollowingService, UserFollowingService,
@ -799,7 +794,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$SignupService, $SignupService,
$WebAuthnService, $WebAuthnService,
$UserBlockingService, $UserBlockingService,
$UserReactionBlockingService,
$CacheService, $CacheService,
$UserService, $UserService,
$UserFollowingService, $UserFollowingService,

View File

@ -30,7 +30,6 @@ import { trackPromise } from '@/misc/promise-tracker.js';
import { isQuote, isRenote } from '@/misc/is-renote.js'; import { isQuote, isRenote } from '@/misc/is-renote.js';
import { ReactionsBufferingService } from '@/core/ReactionsBufferingService.js'; import { ReactionsBufferingService } from '@/core/ReactionsBufferingService.js';
import { PER_NOTE_REACTION_USER_PAIR_CACHE_MAX } from '@/const.js'; import { PER_NOTE_REACTION_USER_PAIR_CACHE_MAX } from '@/const.js';
import { BlockingReactionUserService } from '@/core/BlockingReactionUserService.js';
const FALLBACK = '\u2764'; const FALLBACK = '\u2764';
@ -92,7 +91,7 @@ export class ReactionService {
private userEntityService: UserEntityService, private userEntityService: UserEntityService,
private noteEntityService: NoteEntityService, private noteEntityService: NoteEntityService,
private userBlockingService: UserBlockingService, private userBlockingService: UserBlockingService,
private blockingReactionUserService: BlockingReactionUserService, private userReactionBlockingService: UserBlockingService,
private reactionsBufferingService: ReactionsBufferingService, private reactionsBufferingService: ReactionsBufferingService,
private idService: IdService, private idService: IdService,
private featuredService: FeaturedService, private featuredService: FeaturedService,
@ -109,7 +108,7 @@ export class ReactionService {
// Check blocking // Check blocking
if (note.userId !== user.id) { if (note.userId !== user.id) {
const blocked = await this.userBlockingService.checkBlocked(note.userId, user.id); const blocked = await this.userBlockingService.checkBlocked(note.userId, user.id);
const reactionBlocked = await this.blockingReactionUserService.checkBlocked(note.userId, user.id); const reactionBlocked = await this.userReactionBlockingService.checkBlocked(note.userId, user.id);
if (blocked || reactionBlocked) { if (blocked || reactionBlocked) {
throw new IdentifiableError('e70412a4-7197-4726-8e74-f3e0deb92aa7'); throw new IdentifiableError('e70412a4-7197-4726-8e74-f3e0deb92aa7');
} }

View File

@ -26,7 +26,6 @@ import { UserWebhookService } from '@/core/UserWebhookService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { CacheService } from '@/core/CacheService.js'; import { CacheService } from '@/core/CacheService.js';
import { UserFollowingService } from '@/core/UserFollowingService.js'; import { UserFollowingService } from '@/core/UserFollowingService.js';
import { UserReactionBlockingService } from '@/core/UserReactionBlockingService.js';
@Injectable() @Injectable()
export class UserBlockingService implements OnModuleInit { export class UserBlockingService implements OnModuleInit {
@ -50,7 +49,6 @@ export class UserBlockingService implements OnModuleInit {
private cacheService: CacheService, private cacheService: CacheService,
private userEntityService: UserEntityService, private userEntityService: UserEntityService,
private userReactionBlockingService: UserReactionBlockingService,
private idService: IdService, private idService: IdService,
private queueService: QueueService, private queueService: QueueService,
private globalEventService: GlobalEventService, private globalEventService: GlobalEventService,
@ -93,7 +91,7 @@ export class UserBlockingService implements OnModuleInit {
}); });
if (blocking.blockType === MiBlockingType.Reaction) { if (blocking.blockType === MiBlockingType.Reaction) {
await this.userReactionBlockingService.unblock(blocker, blockee); await this.reactionUnblock(blocker, blockee);
} }
blocking.blockType = MiBlockingType.User; blocking.blockType = MiBlockingType.User;
await this.blockingsRepository.insert(blocking); await this.blockingsRepository.insert(blocking);
@ -216,4 +214,74 @@ export class UserBlockingService implements OnModuleInit {
public async checkBlocked(blockerId: MiUser['id'], blockeeId: MiUser['id']): Promise<boolean> { public async checkBlocked(blockerId: MiUser['id'], blockeeId: MiUser['id']): Promise<boolean> {
return (await this.cacheService.userBlockingCache.fetch(blockerId)).has(blockeeId); return (await this.cacheService.userBlockingCache.fetch(blockerId)).has(blockeeId);
} }
@bindThis
public async reactionBlock(blocker: MiUser, blockee: MiUser, silent = false) {
const blocking = await this.blockingsRepository.findOneBy({
blockerId: blocker.id,
blockeeId: blockee.id,
}).then(blocking => {
if (blocking) {
return blocking;
}
return {
id: this.idService.gen(),
blocker,
blockerId: blocker.id,
blockee,
blockeeId: blockee.id,
blockType: MiBlockingType.Reaction,
} as MiBlocking;
});
if (blocking.blockType === MiBlockingType.User) {
await this.unblock(blocker, blockee);
}
blocking.blockType = MiBlockingType.Reaction;
await this.blockingsRepository.insert(blocking);
this.cacheService.userReactionBlockingCache.refresh(blocker.id);
this.cacheService.userReactionBlockedCache.refresh(blockee.id);
this.globalEventService.publishInternalEvent('blockingReactionCreated', {
blockerId: blocker.id,
blockeeId: blockee.id,
});
}
@bindThis
public async reactionUnblock(blocker: MiUser, blockee: MiUser) {
const blocking = await this.blockingsRepository.findOneBy({
blockerId: blocker.id,
blockeeId: blockee.id,
blockType: MiBlockingType.Reaction,
});
if (blocking == null) {
this.logger.warn('Unblock requested, but the target was not blocked.');
return;
}
// Since we already have the blocker and blockee, we do not need to fetch
// them in the query above and can just manually insert them here.
blocking.blocker = blocker;
blocking.blockee = blockee;
await this.blockingsRepository.delete(blocking.id);
this.cacheService.userReactionBlockingCache.refresh(blocker.id);
this.cacheService.userReactionBlockedCache.refresh(blockee.id);
this.globalEventService.publishInternalEvent('blockingReactionDeleted', {
blockerId: blocker.id,
blockeeId: blockee.id,
});
}
@bindThis
public async checkReactionBlocked(blockerId: MiUser['id'], blockeeId: MiUser['id']): Promise<boolean> {
return (await this.cacheService.userReactionBlockingCache.fetch(blockerId)).has(blockeeId);
}
} }

View File

@ -1,120 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import { IdService } from '@/core/IdService.js';
import type { MiUser } from '@/models/User.js';
import type { MiBlocking } from '@/models/Blocking.js';
import { QueueService } from '@/core/QueueService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { DI } from '@/di-symbols.js';
import type { BlockingsRepository, UserListsRepository } from '@/models/_.js';
import Logger from '@/logger.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { LoggerService } from '@/core/LoggerService.js';
import { UserWebhookService } from '@/core/UserWebhookService.js';
import { bindThis } from '@/decorators.js';
import { CacheService } from '@/core/CacheService.js';
import { UserFollowingService } from '@/core/UserFollowingService.js';
import { MiBlockingType } from '@/models/Blocking.js';
import { UserBlockingService } from '@/core/UserBlockingService.js';
@Injectable()
export class UserReactionBlockingService {
private logger: Logger;
private userFollowingService: UserFollowingService;
constructor(
private moduleRef: ModuleRef,
@Inject(DI.blockingsRepository)
private blockingsRepository: BlockingsRepository,
@Inject(DI.userListsRepository)
private userListsRepository: UserListsRepository,
private cacheService: CacheService,
private userEntityService: UserEntityService,
private userBlockingService: UserBlockingService,
private idService: IdService,
private queueService: QueueService,
private globalEventService: GlobalEventService,
private webhookService: UserWebhookService,
private apRendererService: ApRendererService,
private loggerService: LoggerService,
) {
this.logger = this.loggerService.getLogger('user-block');
}
@bindThis
public async block(blocker: MiUser, blockee: MiUser, silent = false) {
const blocking = await this.blockingsRepository.findOneBy({
blockerId: blocker.id,
blockeeId: blockee.id,
}).then(blocking => {
if (blocking) {
return blocking;
}
return {
id: this.idService.gen(),
blocker,
blockerId: blocker.id,
blockee,
blockeeId: blockee.id,
blockType: MiBlockingType.Reaction,
} as MiBlocking;
});
if (blocking.blockType === MiBlockingType.User) {
await this.userBlockingService.unblock(blocker, blockee);
}
blocking.blockType = MiBlockingType.Reaction;
await this.blockingsRepository.insert(blocking);
this.cacheService.userReactionBlockingCache.refresh(blocker.id);
this.cacheService.userReactionBlockedCache.refresh(blockee.id);
this.globalEventService.publishInternalEvent('blockingReactionCreated', {
blockerId: blocker.id,
blockeeId: blockee.id,
});
}
@bindThis
public async unblock(blocker: MiUser, blockee: MiUser) {
const blocking = await this.blockingsRepository.findOneBy({
blockerId: blocker.id,
blockeeId: blockee.id,
blockType: MiBlockingType.Reaction,
});
if (blocking == null) {
this.logger.warn('Unblock requested, but the target was not blocked.');
return;
}
// Since we already have the blocker and blockee, we do not need to fetch
// them in the query above and can just manually insert them here.
blocking.blocker = blocker;
blocking.blockee = blockee;
await this.blockingsRepository.delete(blocking.id);
this.cacheService.userReactionBlockingCache.refresh(blocker.id);
this.cacheService.userReactionBlockedCache.refresh(blockee.id);
this.globalEventService.publishInternalEvent('blockingReactionDeleted', {
blockerId: blocker.id,
blockeeId: blockee.id,
});
}
@bindThis
public async checkBlocked(blockerId: MiUser['id'], blockeeId: MiUser['id']): Promise<boolean> {
return (await this.cacheService.userReactionBlockingCache.fetch(blockerId)).has(blockeeId);
}
}

View File

@ -11,7 +11,7 @@ import { MiBlockingType } from '@/models/_.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { GetterService } from '@/server/api/GetterService.js'; import { GetterService } from '@/server/api/GetterService.js';
import { UserReactionBlockingService } from '@/core/UserReactionBlockingService.js'; import { UserBlockingService } from '@/core/UserBlockingService.js';
import { ApiError } from '../../error.js'; import { ApiError } from '../../error.js';
export const meta = { export const meta = {
@ -72,7 +72,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private userEntityService: UserEntityService, private userEntityService: UserEntityService,
private getterService: GetterService, private getterService: GetterService,
private userReactionBlockingService: UserReactionBlockingService, private userBlockingService: UserBlockingService,
) { ) {
super(meta, paramDef, async (ps, me) => { super(meta, paramDef, async (ps, me) => {
const blocker = await this.usersRepository.findOneByOrFail({ id: me.id }); const blocker = await this.usersRepository.findOneByOrFail({ id: me.id });
@ -101,7 +101,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw new ApiError(meta.errors.alreadyBlocking); throw new ApiError(meta.errors.alreadyBlocking);
} }
await this.userReactionBlockingService.block(blocker, blockee); await this.userBlockingService.reactionBlock(blocker, blockee);
return await this.userEntityService.pack(blockee.id, blocker, { return await this.userEntityService.pack(blockee.id, blocker, {
schema: 'UserDetailedNotMe', schema: 'UserDetailedNotMe',

View File

@ -8,9 +8,9 @@ import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js'; import { Endpoint } from '@/server/api/endpoint-base.js';
import type { UsersRepository, BlockingsRepository, MiBlockingType } from '@/models/_.js'; import type { UsersRepository, BlockingsRepository, MiBlockingType } from '@/models/_.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { UserReactionBlockingService } from '@/core/UserReactionBlockingService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { GetterService } from '@/server/api/GetterService.js'; import { GetterService } from '@/server/api/GetterService.js';
import { UserBlockingService } from '@/core/UserBlockingService.js';
import { ApiError } from '../../error.js'; import { ApiError } from '../../error.js';
export const meta = { export const meta = {
@ -71,7 +71,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private userEntityService: UserEntityService, private userEntityService: UserEntityService,
private getterService: GetterService, private getterService: GetterService,
private userReactionBlockingService: UserReactionBlockingService, private userBlockingService: UserBlockingService,
) { ) {
super(meta, paramDef, async (ps, me) => { super(meta, paramDef, async (ps, me) => {
const blocker = await this.usersRepository.findOneByOrFail({ id: me.id }); const blocker = await this.usersRepository.findOneByOrFail({ id: me.id });
@ -101,7 +101,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
} }
// Delete blocking // Delete blocking
await this.userReactionBlockingService.unblock(blocker, blockee); await this.userBlockingService.reactionUnblock(blocker, blockee);
return await this.userEntityService.pack(blockee.id, blocker, { return await this.userEntityService.pack(blockee.id, blocker, {
schema: 'UserDetailedNotMe', schema: 'UserDetailedNotMe',

View File

@ -4515,7 +4515,8 @@ export type components = {
/** Format: id */ /** Format: id */
blockeeId: string; blockeeId: string;
blockee: components['schemas']['UserDetailedNotMe']; blockee: components['schemas']['UserDetailedNotMe'];
isReactionBlock: boolean; /** @enum {string} */
blockType: 'user' | 'reaction';
}; };
Hashtag: { Hashtag: {
/** @example misskey */ /** @example misskey */