From 3ea69b6203ba4062c929c30b0d306358c1e381fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B4=87=E5=B3=B0=20=E6=9C=94=E8=8F=AF?= Date: Mon, 18 Nov 2024 21:03:33 +0900 Subject: [PATCH] =?UTF-8?q?Mod:=20isReactionBlock=E3=81=8B=E3=82=89enum?= =?UTF-8?q?=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/core/QueryService.ts | 6 +- .../backend/src/core/UserBlockingService.ts | 66 +++++++++++++------ .../src/core/UserReactionBlockingService.ts | 43 +++++++----- .../src/core/entities/UserEntityService.ts | 17 ++--- packages/backend/src/models/Blocking.ts | 11 +++- packages/backend/src/models/_.ts | 3 +- .../src/models/json-schema/blocking.ts | 5 +- .../blocking-reaction-user/create.ts | 19 +++--- .../blocking-reaction-user/delete.ts | 3 +- .../endpoints/blocking-reaction-user/list.ts | 2 +- .../server/api/endpoints/blocking/create.ts | 18 ++--- .../server/api/endpoints/blocking/delete.ts | 18 ++--- .../src/server/api/endpoints/blocking/list.ts | 2 +- 13 files changed, 132 insertions(+), 81 deletions(-) diff --git a/packages/backend/src/core/QueryService.ts b/packages/backend/src/core/QueryService.ts index c4feeaf971..65b6bc2ef4 100644 --- a/packages/backend/src/core/QueryService.ts +++ b/packages/backend/src/core/QueryService.ts @@ -72,7 +72,8 @@ export class QueryService { public generateBlockedUserQuery(q: SelectQueryBuilder, me: { id: MiUser['id'] }): void { const blockingQuery = this.blockingsRepository.createQueryBuilder('blocking') .select('blocking.blockerId') - .where('blocking.blockeeId = :blockeeId', { blockeeId: me.id }); + .where('blocking.blockeeId = :blockeeId', { blockeeId: me.id }) + .andWhere('blocking.blockType = "user"'); // 投稿の作者にブロックされていない かつ // 投稿の返信先の作者にブロックされていない かつ @@ -97,7 +98,8 @@ export class QueryService { public generateBlockQueryForUsers(q: SelectQueryBuilder, me: { id: MiUser['id'] }): void { const blockingQuery = this.blockingsRepository.createQueryBuilder('blocking') .select('blocking.blockeeId') - .where('blocking.blockerId = :blockerId', { blockerId: me.id }); + .where('blocking.blockerId = :blockerId', { blockerId: me.id }) + .andWhere('blocking.blockType = "user"'); const blockedQuery = this.blockingsRepository.createQueryBuilder('blocking') .select('blocking.blockerId') diff --git a/packages/backend/src/core/UserBlockingService.ts b/packages/backend/src/core/UserBlockingService.ts index 0234042903..9b5c40f267 100644 --- a/packages/backend/src/core/UserBlockingService.ts +++ b/packages/backend/src/core/UserBlockingService.ts @@ -3,15 +3,21 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { Inject, Injectable, OnModuleInit } 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 { FollowRequestsRepository, BlockingsRepository, UserListsRepository, UserListMembershipsRepository } from '@/models/_.js'; +import {Inject, Injectable, OnModuleInit} 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 {MiBlockingType} 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, + FollowRequestsRepository, + UserListMembershipsRepository, + UserListsRepository, +} from '@/models/_.js'; import Logger from '@/logger.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; @@ -20,6 +26,7 @@ import { UserWebhookService } from '@/core/UserWebhookService.js'; import { bindThis } from '@/decorators.js'; import { CacheService } from '@/core/CacheService.js'; import { UserFollowingService } from '@/core/UserFollowingService.js'; +import { UserReactionBlockingService } from '@/core/UserReactionBlockingService.js'; @Injectable() export class UserBlockingService implements OnModuleInit { @@ -43,6 +50,7 @@ export class UserBlockingService implements OnModuleInit { private cacheService: CacheService, private userEntityService: UserEntityService, + private userReactionBlockingService: UserReactionBlockingService, private idService: IdService, private queueService: QueueService, private globalEventService: GlobalEventService, @@ -67,15 +75,27 @@ export class UserBlockingService implements OnModuleInit { this.removeFromList(blockee, blocker), ]); - const blocking = { - id: this.idService.gen(), - blocker, + const blocking = await this.blockingsRepository.findOneBy({ blockerId: blocker.id, - blockee, blockeeId: blockee.id, - isReactionBlock: false, - } as MiBlocking; + }).then(blocking => { + if (blocking) { + return blocking; + } + return { + id: this.idService.gen(), + blocker, + blockerId: blocker.id, + blockee, + blockeeId: blockee.id, + blockType: MiBlockingType.User, + } as MiBlocking; + }); + if (blocking.blockType === MiBlockingType.Reaction) { + await this.userReactionBlockingService.unblock(blocker, blockee); + } + blocking.blockType = MiBlockingType.User; await this.blockingsRepository.insert(blocking); this.cacheService.userBlockingCache.refresh(blocker.id); @@ -161,7 +181,7 @@ export class UserBlockingService implements OnModuleInit { const blocking = await this.blockingsRepository.findOneBy({ blockerId: blocker.id, blockeeId: blockee.id, - isReactionBlock: false, + blockType: MiBlockingType.User, }); if (blocking == null) { @@ -177,17 +197,23 @@ export class UserBlockingService implements OnModuleInit { await this.blockingsRepository.delete(blocking.id); - this.cacheService.userReactionBlockedCache.refresh(blocker.id); - this.cacheService.userReactionBlockedCache.refresh(blockee.id); + this.cacheService.userBlockingCache.refresh(blocker.id); + this.cacheService.userBlockedCache.refresh(blockee.id); - this.globalEventService.publishInternalEvent('blockingReactionDeleted', { + this.globalEventService.publishInternalEvent('blockingDeleted', { blockerId: blocker.id, blockeeId: blockee.id, }); + + // deliver if remote bloking + if (this.userEntityService.isLocalUser(blocker) && this.userEntityService.isRemoteUser(blockee)) { + const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderBlock(blocking), blocker)); + this.queueService.deliver(blocker, content, blockee.inbox, false); + } } @bindThis public async checkBlocked(blockerId: MiUser['id'], blockeeId: MiUser['id']): Promise { - return (await this.cacheService.userReactionBlockingCache.fetch(blockerId)).has(blockeeId); + return (await this.cacheService.userBlockingCache.fetch(blockerId)).has(blockeeId); } } diff --git a/packages/backend/src/core/UserReactionBlockingService.ts b/packages/backend/src/core/UserReactionBlockingService.ts index 1b17f82fe3..cf3de8f331 100644 --- a/packages/backend/src/core/UserReactionBlockingService.ts +++ b/packages/backend/src/core/UserReactionBlockingService.ts @@ -20,6 +20,8 @@ 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 { @@ -37,6 +39,7 @@ export class UserReactionBlockingService { private cacheService: CacheService, private userEntityService: UserEntityService, + private userBlockingService: UserBlockingService, private idService: IdService, private queueService: QueueService, private globalEventService: GlobalEventService, @@ -49,15 +52,27 @@ export class UserReactionBlockingService { @bindThis public async block(blocker: MiUser, blockee: MiUser, silent = false) { - const blocking = { - id: this.idService.gen(), - blocker, + const blocking = await this.blockingsRepository.findOneBy({ blockerId: blocker.id, - blockee, blockeeId: blockee.id, - isReactionBlock: true, - } satisfies MiBlocking; + }).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); @@ -74,7 +89,7 @@ export class UserReactionBlockingService { const blocking = await this.blockingsRepository.findOneBy({ blockerId: blocker.id, blockeeId: blockee.id, - isReactionBlock: true, + blockType: MiBlockingType.Reaction, }); if (blocking == null) { @@ -89,23 +104,17 @@ export class UserReactionBlockingService { await this.blockingsRepository.delete(blocking.id); - this.cacheService.userBlockingCache.refresh(blocker.id); - this.cacheService.userBlockedCache.refresh(blockee.id); + this.cacheService.userReactionBlockingCache.refresh(blocker.id); + this.cacheService.userReactionBlockedCache.refresh(blockee.id); - this.globalEventService.publishInternalEvent('blockingDeleted', { + this.globalEventService.publishInternalEvent('blockingReactionDeleted', { blockerId: blocker.id, blockeeId: blockee.id, }); - - // deliver if remote bloking - if (this.userEntityService.isLocalUser(blocker) && this.userEntityService.isRemoteUser(blockee)) { - const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderBlock(blocking), blocker)); - this.queueService.deliver(blocker, content, blockee.inbox, false); - } } @bindThis public async checkBlocked(blockerId: MiUser['id'], blockeeId: MiUser['id']): Promise { - return (await this.cacheService.userBlockingCache.fetch(blockerId)).has(blockeeId); + return (await this.cacheService.userReactionBlockingCache.fetch(blockerId)).has(blockeeId); } } diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index a9dc7fb65b..22d178dd74 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -27,6 +27,7 @@ import type { BlockingsRepository, FollowingsRepository, FollowRequestsRepository, + MiBlockingType, MiFollowing, MiUserNotePining, MiUserProfile, @@ -202,28 +203,28 @@ export class UserEntityService implements OnModuleInit { where: { blockerId: me, blockeeId: target, - isReactionBlock: false, + blockType: MiBlockingType.User, }, }), this.blockingsRepository.exists({ where: { blockerId: target, blockeeId: me, - isReactionBlock: false, + blockType: MiBlockingType.User, }, }), this.blockingsRepository.exists({ where: { blockerId: me, blockeeId: target, - isReactionBlock: true, + blockType: MiBlockingType.Reaction, }, }), this.blockingsRepository.exists({ where: { blockerId: target, blockeeId: me, - isReactionBlock: true, + blockType: MiBlockingType.Reaction, }, }), this.mutingsRepository.exists({ @@ -290,25 +291,25 @@ export class UserEntityService implements OnModuleInit { this.blockingsRepository.createQueryBuilder('b') .select('b.blockeeId') .where('b.blockerId = :me', { me }) - .andWhere('b.isReactionBlock = false') + .andWhere('b.blockType = "user"') .getRawMany<{ b_blockeeId: string }>() .then(it => it.map(it => it.b_blockeeId)), this.blockingsRepository.createQueryBuilder('b') .select('b.blockerId') .where('b.blockeeId = :me', { me }) - .andWhere('b.isReactionBlock = false') + .andWhere('b.blockType = "user"') .getRawMany<{ b_blockerId: string }>() .then(it => it.map(it => it.b_blockerId)), this.blockingsRepository.createQueryBuilder('b') .select('b.blockeeId') .where('b.blockerId = :me', { me }) - .andWhere('b.isReactionBlock = true') + .andWhere('b.blockType = "reaction"') .getRawMany<{ b_blockeeId: string }>() .then(it => it.map(it => it.b_blockeeId)), this.blockingsRepository.createQueryBuilder('b') .select('b.blockerId') .where('b.blockeeId = :me', { me }) - .andWhere('b.isReactionBlock = true') + .andWhere('b.blockType = "reaction"') .getRawMany<{ b_blockerId: string }>() .then(it => it.map(it => it.b_blockerId)), this.mutingsRepository.createQueryBuilder('m') diff --git a/packages/backend/src/models/Blocking.ts b/packages/backend/src/models/Blocking.ts index 8989154e7e..e19edd7935 100644 --- a/packages/backend/src/models/Blocking.ts +++ b/packages/backend/src/models/Blocking.ts @@ -7,6 +7,11 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typ import { id } from './util/id.js'; import { MiUser } from './User.js'; +export enum MiBlockingType { + User = 'user', + Reaction = 'reaction', +} + @Entity('blocking') @Index(['blockerId', 'blockeeId'], { unique: true }) export class MiBlocking { @@ -41,8 +46,8 @@ export class MiBlocking { @Index() @Column({ - comment: 'Whether the blockee is a reaction block.', - default: false, + comment: 'Block type.', + default: MiBlockingType.User, }) - public isReactionBlock: boolean; + public blockType: MiBlockingType; } diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index c72bdaa727..5a9769760f 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -20,7 +20,7 @@ import { MiAntenna } from '@/models/Antenna.js'; import { MiApp } from '@/models/App.js'; import { MiAvatarDecoration } from '@/models/AvatarDecoration.js'; import { MiAuthSession } from '@/models/AuthSession.js'; -import { MiBlocking } from '@/models/Blocking.js'; +import { MiBlocking, MiBlockingType } from '@/models/Blocking.js'; import { MiChannelFollowing } from '@/models/ChannelFollowing.js'; import { MiChannelFavorite } from '@/models/ChannelFavorite.js'; import { MiClip } from '@/models/Clip.js'; @@ -136,6 +136,7 @@ export { MiAvatarDecoration, MiAuthSession, MiBlocking, + MiBlockingType, MiChannelFollowing, MiChannelFavorite, MiClip, diff --git a/packages/backend/src/models/json-schema/blocking.ts b/packages/backend/src/models/json-schema/blocking.ts index ccaf18cd8a..431832b28b 100644 --- a/packages/backend/src/models/json-schema/blocking.ts +++ b/packages/backend/src/models/json-schema/blocking.ts @@ -27,9 +27,10 @@ export const packedBlockingSchema = { optional: false, nullable: false, ref: 'UserDetailedNotMe', }, - isReactionBlock: { - type: 'boolean', + blockType: { + type: 'string', optional: false, nullable: false, + enum: ['user', 'reaction'], }, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/blocking-reaction-user/create.ts b/packages/backend/src/server/api/endpoints/blocking-reaction-user/create.ts index 1c75de0796..0df2acd69c 100644 --- a/packages/backend/src/server/api/endpoints/blocking-reaction-user/create.ts +++ b/packages/backend/src/server/api/endpoints/blocking-reaction-user/create.ts @@ -4,14 +4,15 @@ */ import ms from 'ms'; -import { Inject, Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository, BlockingsRepository } from '@/models/_.js'; -import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import { DI } from '@/di-symbols.js'; -import { GetterService } from '@/server/api/GetterService.js'; -import { ApiError } from '../../error.js'; -import { UserReactionBlockingService } from '@/core/UserReactionBlockingService.js'; +import {Inject, Injectable} from '@nestjs/common'; +import {Endpoint} from '@/server/api/endpoint-base.js'; +import type {BlockingsRepository, UsersRepository} from '@/models/_.js'; +import {MiBlockingType} from "@/models/_.js"; +import {UserEntityService} from '@/core/entities/UserEntityService.js'; +import {DI} from '@/di-symbols.js'; +import {GetterService} from '@/server/api/GetterService.js'; +import {ApiError} from '../../error.js'; +import {UserReactionBlockingService} from '@/core/UserReactionBlockingService.js'; export const meta = { tags: ['account'], @@ -92,7 +93,7 @@ export default class extends Endpoint { // eslint- where: { blockerId: blocker.id, blockeeId: blockee.id, - isReactionBlock: true, + blockType: MiBlockingType.Reaction, }, }); diff --git a/packages/backend/src/server/api/endpoints/blocking-reaction-user/delete.ts b/packages/backend/src/server/api/endpoints/blocking-reaction-user/delete.ts index f35fc9ab9e..393d05f900 100644 --- a/packages/backend/src/server/api/endpoints/blocking-reaction-user/delete.ts +++ b/packages/backend/src/server/api/endpoints/blocking-reaction-user/delete.ts @@ -12,6 +12,7 @@ import { UserReactionBlockingService } from '@/core/UserReactionBlockingService. import { DI } from '@/di-symbols.js'; import { GetterService } from '@/server/api/GetterService.js'; import { ApiError } from '../../error.js'; +import {MiBlockingType} from "@/models/_.js"; export const meta = { tags: ['account'], @@ -92,7 +93,7 @@ export default class extends Endpoint { // eslint- where: { blockerId: blocker.id, blockeeId: blockee.id, - isReactionBlock: true, + blockType: MiBlockingType.Reaction, }, }); diff --git a/packages/backend/src/server/api/endpoints/blocking-reaction-user/list.ts b/packages/backend/src/server/api/endpoints/blocking-reaction-user/list.ts index 385266b1e4..5055bd596b 100644 --- a/packages/backend/src/server/api/endpoints/blocking-reaction-user/list.ts +++ b/packages/backend/src/server/api/endpoints/blocking-reaction-user/list.ts @@ -50,7 +50,7 @@ export default class extends Endpoint { // eslint- super(meta, paramDef, async (ps, me) => { const query = this.queryService.makePaginationQuery(this.blockingsRepository.createQueryBuilder('blocking'), ps.sinceId, ps.untilId) .andWhere('blocking.blockerId = :meId', { meId: me.id }) - .andWhere('blocking.isReactionBlock = true'); + .andWhere('blocking.blockType = "reaction"'); const blockings = await query .limit(ps.limit) diff --git a/packages/backend/src/server/api/endpoints/blocking/create.ts b/packages/backend/src/server/api/endpoints/blocking/create.ts index 5066215749..b9adbb2deb 100644 --- a/packages/backend/src/server/api/endpoints/blocking/create.ts +++ b/packages/backend/src/server/api/endpoints/blocking/create.ts @@ -4,14 +4,15 @@ */ import ms from 'ms'; -import { Inject, Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository, BlockingsRepository } from '@/models/_.js'; -import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import { UserBlockingService } from '@/core/UserBlockingService.js'; -import { DI } from '@/di-symbols.js'; -import { GetterService } from '@/server/api/GetterService.js'; -import { ApiError } from '../../error.js'; +import {Inject, Injectable} from '@nestjs/common'; +import {Endpoint} from '@/server/api/endpoint-base.js'; +import type {BlockingsRepository, UsersRepository} from '@/models/_.js'; +import {MiBlockingType} from "@/models/_.js"; +import {UserEntityService} from '@/core/entities/UserEntityService.js'; +import {UserBlockingService} from '@/core/UserBlockingService.js'; +import {DI} from '@/di-symbols.js'; +import {GetterService} from '@/server/api/GetterService.js'; +import {ApiError} from '../../error.js'; export const meta = { tags: ['account'], @@ -92,6 +93,7 @@ export default class extends Endpoint { // eslint- where: { blockerId: blocker.id, blockeeId: blockee.id, + blockType: MiBlockingType.User, }, }); diff --git a/packages/backend/src/server/api/endpoints/blocking/delete.ts b/packages/backend/src/server/api/endpoints/blocking/delete.ts index cebb307338..e035cb9823 100644 --- a/packages/backend/src/server/api/endpoints/blocking/delete.ts +++ b/packages/backend/src/server/api/endpoints/blocking/delete.ts @@ -4,14 +4,15 @@ */ import ms from 'ms'; -import { Inject, Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository, BlockingsRepository } from '@/models/_.js'; -import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import { UserBlockingService } from '@/core/UserBlockingService.js'; -import { DI } from '@/di-symbols.js'; -import { GetterService } from '@/server/api/GetterService.js'; -import { ApiError } from '../../error.js'; +import {Inject, Injectable} from '@nestjs/common'; +import {Endpoint} from '@/server/api/endpoint-base.js'; +import type {BlockingsRepository, UsersRepository} from '@/models/_.js'; +import {MiBlockingType} from "@/models/_.js"; +import {UserEntityService} from '@/core/entities/UserEntityService.js'; +import {UserBlockingService} from '@/core/UserBlockingService.js'; +import {DI} from '@/di-symbols.js'; +import {GetterService} from '@/server/api/GetterService.js'; +import {ApiError} from '../../error.js'; export const meta = { tags: ['account'], @@ -92,6 +93,7 @@ export default class extends Endpoint { // eslint- where: { blockerId: blocker.id, blockeeId: blockee.id, + blockType: MiBlockingType.User, }, }); diff --git a/packages/backend/src/server/api/endpoints/blocking/list.ts b/packages/backend/src/server/api/endpoints/blocking/list.ts index 21f8b4815b..f7a5fa1412 100644 --- a/packages/backend/src/server/api/endpoints/blocking/list.ts +++ b/packages/backend/src/server/api/endpoints/blocking/list.ts @@ -50,7 +50,7 @@ export default class extends Endpoint { // eslint- super(meta, paramDef, async (ps, me) => { const query = this.queryService.makePaginationQuery(this.blockingsRepository.createQueryBuilder('blocking'), ps.sinceId, ps.untilId) .andWhere('blocking.blockerId = :meId', { meId: me.id }) - .andWhere('blocking.isReactionBlock = false'); + .andWhere('blocking.blockType = "user"'); const blockings = await query .limit(ps.limit)