diff --git a/packages/backend/migration/1665091090561-add-renote-muting.js b/packages/backend/migration/1665091090561-add-renote-muting.js index d2ed2bd2e..2c76aaff5 100644 --- a/packages/backend/migration/1665091090561-add-renote-muting.js +++ b/packages/backend/migration/1665091090561-add-renote-muting.js @@ -1,16 +1,22 @@ - export class addRenoteMuting1665091090561 { constructor() { - this.name = 'addRenoteMuting1665091090561'; + this.name = "addRenoteMuting1665091090561"; } async up(queryRunner) { - await queryRunner.query(`CREATE TABLE "renote_muting" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "muteeId" character varying(32) NOT NULL, "muterId" character varying(32) NOT NULL, CONSTRAINT "PK_renoteMuting_id" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE INDEX "IDX_renote_muting_createdAt" ON "muting" ("createdAt") `); - await queryRunner.query(`CREATE INDEX "IDX_renote_muting_muteeId" ON "muting" ("muteeId") `); - await queryRunner.query(`CREATE INDEX "IDX_renote_muting_muterId" ON "muting" ("muterId") `); + await queryRunner.query( + `CREATE TABLE "renote_muting" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "muteeId" character varying(32) NOT NULL, "muterId" character varying(32) NOT NULL, CONSTRAINT "PK_renoteMuting_id" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_renote_muting_createdAt" ON "muting" ("createdAt") `, + ); + await queryRunner.query( + `CREATE INDEX "IDX_renote_muting_muteeId" ON "muting" ("muteeId") `, + ); + await queryRunner.query( + `CREATE INDEX "IDX_renote_muting_muterId" ON "muting" ("muterId") `, + ); } - async down(queryRunner) { - } + async down(queryRunner) {} } diff --git a/packages/backend/src/models/entities/renote-muting.ts b/packages/backend/src/models/entities/renote-muting.ts index 423a94c55..64ec7f583 100644 --- a/packages/backend/src/models/entities/renote-muting.ts +++ b/packages/backend/src/models/entities/renote-muting.ts @@ -1,4 +1,11 @@ -import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from "typeorm"; +import { + PrimaryColumn, + Entity, + Index, + JoinColumn, + Column, + ManyToOne, +} from "typeorm"; import { id } from "../id.js"; import { User } from "./user.js"; diff --git a/packages/backend/src/models/repositories/renote-muting.ts b/packages/backend/src/models/repositories/renote-muting.ts index a39c69738..18fd343a0 100644 --- a/packages/backend/src/models/repositories/renote-muting.ts +++ b/packages/backend/src/models/repositories/renote-muting.ts @@ -10,7 +10,8 @@ export const RenoteMutingRepository = db.getRepository(RenoteMuting).extend({ src: RenoteMuting["id"] | RenoteMuting, me?: { id: User["id"] } | null | undefined, ): Promise> { - const muting = typeof src === "object" ? src : await this.findOneByOrFail({ id: src }); + const muting = + typeof src === "object" ? src : await this.findOneByOrFail({ id: src }); return await awaitAll({ id: muting.id, @@ -22,10 +23,7 @@ export const RenoteMutingRepository = db.getRepository(RenoteMuting).extend({ }); }, - packMany( - mutings: any[], - me: { id: User["id"] }, - ) { - return Promise.all(mutings.map(x => this.pack(x, me))); + packMany(mutings: any[], me: { id: User["id"] }) { + return Promise.all(mutings.map((x) => this.pack(x, me))); }, }); diff --git a/packages/backend/src/models/schema/renote-muting.ts b/packages/backend/src/models/schema/renote-muting.ts index f60b10567..2a5824e32 100644 --- a/packages/backend/src/models/schema/renote-muting.ts +++ b/packages/backend/src/models/schema/renote-muting.ts @@ -3,23 +3,27 @@ export const packedRenoteMutingSchema = { properties: { id: { type: "string", - optional: false, nullable: false, + optional: false, + nullable: false, format: "id", example: "xxxxxxxxxx", }, createdAt: { type: "string", - optional: false, nullable: false, + optional: false, + nullable: false, format: "date-time", }, muteeId: { type: "string", - optional: false, nullable: false, + optional: false, + nullable: false, format: "id", }, mutee: { type: "object", - optional: false, nullable: false, + optional: false, + nullable: false, ref: "UserDetailed", }, }, diff --git a/packages/backend/src/models/schema/user.ts b/packages/backend/src/models/schema/user.ts index 952999583..80e94fe50 100644 --- a/packages/backend/src/models/schema/user.ts +++ b/packages/backend/src/models/schema/user.ts @@ -337,7 +337,8 @@ export const packedUserDetailedNotMeOnlySchema = { }, isRenoteMuted: { type: "boolean", - nullable: false, optional: true, + nullable: false, + optional: true, }, //#endregion }, diff --git a/packages/backend/src/server/api/common/generated-muted-renote-query.ts b/packages/backend/src/server/api/common/generated-muted-renote-query.ts index e11f3edaf..3fcd9b28e 100644 --- a/packages/backend/src/server/api/common/generated-muted-renote-query.ts +++ b/packages/backend/src/server/api/common/generated-muted-renote-query.ts @@ -2,21 +2,27 @@ import { Brackets, SelectQueryBuilder } from "typeorm"; import { User } from "@/models/entities/user.js"; import { RenoteMutings } from "@/models/index.js"; -export function generateMutedUserRenotesQueryForNotes(q: SelectQueryBuilder, me: { id: User["id"] }): void { +export function generateMutedUserRenotesQueryForNotes( + q: SelectQueryBuilder, + me: { id: User["id"] }, +): void { const mutingQuery = RenoteMutings.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.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/server/api/endpoints/renote-mute/create.ts b/packages/backend/src/server/api/endpoints/renote-mute/create.ts index 8f76e618b..82db79cc6 100644 --- a/packages/backend/src/server/api/endpoints/renote-mute/create.ts +++ b/packages/backend/src/server/api/endpoints/renote-mute/create.ts @@ -51,8 +51,9 @@ export default define(meta, paramDef, async (ps, user) => { } // Get mutee - const mutee = await getUser(ps.userId).catch(e => { - if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff") throw new ApiError(meta.errors.noSuchUser); + const mutee = await getUser(ps.userId).catch((e) => { + if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff") + throw new ApiError(meta.errors.noSuchUser); throw e; }); diff --git a/packages/backend/src/server/api/endpoints/renote-mute/delete.ts b/packages/backend/src/server/api/endpoints/renote-mute/delete.ts index f5caad345..4fd500d7c 100644 --- a/packages/backend/src/server/api/endpoints/renote-mute/delete.ts +++ b/packages/backend/src/server/api/endpoints/renote-mute/delete.ts @@ -49,8 +49,9 @@ export default define(meta, paramDef, async (ps, user) => { } // Get mutee - const mutee = await getUser(ps.userId).catch(e => { - if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff") throw new ApiError(meta.errors.noSuchUser); + const mutee = await getUser(ps.userId).catch((e) => { + if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff") + throw new ApiError(meta.errors.noSuchUser); throw e; }); diff --git a/packages/backend/src/server/api/endpoints/renote-mute/list.ts b/packages/backend/src/server/api/endpoints/renote-mute/list.ts index fd6964bba..9149dd975 100644 --- a/packages/backend/src/server/api/endpoints/renote-mute/list.ts +++ b/packages/backend/src/server/api/endpoints/renote-mute/list.ts @@ -11,10 +11,12 @@ export const meta = { res: { type: "array", - optional: false, nullable: false, + optional: false, + nullable: false, items: { type: "object", - optional: false, nullable: false, + optional: false, + nullable: false, ref: "RenoteMuting", }, }, @@ -32,12 +34,13 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, me) => { - const query = makePaginationQuery(RenoteMutings.createQueryBuilder("muting"), ps.sinceId, ps.untilId) - .andWhere("muting.muterId = :meId", { meId: me.id }); + const query = makePaginationQuery( + RenoteMutings.createQueryBuilder("muting"), + ps.sinceId, + ps.untilId, + ).andWhere("muting.muterId = :meId", { meId: me.id }); - const mutings = await query - .take(ps.limit) - .getMany(); + const mutings = await query.take(ps.limit).getMany(); return await RenoteMutings.packMany(mutings, me); }); diff --git a/packages/backend/src/server/api/endpoints/users/relation.ts b/packages/backend/src/server/api/endpoints/users/relation.ts index b1803b01e..5580eaea0 100644 --- a/packages/backend/src/server/api/endpoints/users/relation.ts +++ b/packages/backend/src/server/api/endpoints/users/relation.ts @@ -59,7 +59,8 @@ export const meta = { }, isRenoteMuted: { type: "boolean", - optional: false, nullable: false, + optional: false, + nullable: false, }, }, }, @@ -113,7 +114,8 @@ export const meta = { }, isRenoteMuted: { type: "boolean", - optional: false, nullable: false, + optional: false, + nullable: false, }, }, }, diff --git a/packages/backend/src/server/api/stream/channels/antenna.ts b/packages/backend/src/server/api/stream/channels/antenna.ts index 7ad7353a6..050a8d101 100644 --- a/packages/backend/src/server/api/stream/channels/antenna.ts +++ b/packages/backend/src/server/api/stream/channels/antenna.ts @@ -34,7 +34,8 @@ export default class extends Channel { // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する if (isUserRelated(note, this.blocking)) return; - if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; + if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) + return; this.connection.cacheNote(note); diff --git a/packages/backend/src/server/api/stream/channels/channel.ts b/packages/backend/src/server/api/stream/channels/channel.ts index ad20adeaf..d046579f4 100644 --- a/packages/backend/src/server/api/stream/channels/channel.ts +++ b/packages/backend/src/server/api/stream/channels/channel.ts @@ -36,7 +36,8 @@ export default class extends Channel { // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する if (isUserRelated(note, this.blocking)) return; - if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; + if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) + return; this.connection.cacheNote(note); diff --git a/packages/backend/src/server/api/stream/channels/global-timeline.ts b/packages/backend/src/server/api/stream/channels/global-timeline.ts index 39dc599c1..aa3844c7e 100644 --- a/packages/backend/src/server/api/stream/channels/global-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/global-timeline.ts @@ -56,7 +56,8 @@ export default class extends Channel { // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する if (isUserRelated(note, this.blocking)) return; - if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; + if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) + return; // 流れてきたNoteがミュートすべきNoteだったら無視する // TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある) diff --git a/packages/backend/src/server/api/stream/channels/hashtag.ts b/packages/backend/src/server/api/stream/channels/hashtag.ts index 66265fe4e..a2e5481ab 100644 --- a/packages/backend/src/server/api/stream/channels/hashtag.ts +++ b/packages/backend/src/server/api/stream/channels/hashtag.ts @@ -36,8 +36,9 @@ export default class extends Channel { if (isUserRelated(note, this.muting)) return; // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する if (isUserRelated(note, this.blocking)) return; - - if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; + + if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) + return; this.connection.cacheNote(note); diff --git a/packages/backend/src/server/api/stream/channels/home-timeline.ts b/packages/backend/src/server/api/stream/channels/home-timeline.ts index 1e6f91ee4..fa4a8a390 100644 --- a/packages/backend/src/server/api/stream/channels/home-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/home-timeline.ts @@ -54,7 +54,8 @@ export default class extends Channel { // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する if (isUserRelated(note, this.blocking)) return; - if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; + if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) + return; // 流れてきたNoteがミュートすべきNoteだったら無視する // TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある) diff --git a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts index 3038374ec..557bb9682 100644 --- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts @@ -71,7 +71,8 @@ export default class extends Channel { // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する if (isUserRelated(note, this.blocking)) return; - if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; + if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) + return; // 流れてきたNoteがミュートすべきNoteだったら無視する // TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある) diff --git a/packages/backend/src/server/api/stream/channels/local-timeline.ts b/packages/backend/src/server/api/stream/channels/local-timeline.ts index 9cea11b22..dc3aab8d7 100644 --- a/packages/backend/src/server/api/stream/channels/local-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts @@ -48,7 +48,8 @@ export default class extends Channel { // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する if (isUserRelated(note, this.blocking)) return; - if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; + if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) + return; // 流れてきたNoteがミュートすべきNoteだったら無視する // TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある) diff --git a/packages/backend/src/server/api/stream/channels/user-list.ts b/packages/backend/src/server/api/stream/channels/user-list.ts index 234505fa0..105c45955 100644 --- a/packages/backend/src/server/api/stream/channels/user-list.ts +++ b/packages/backend/src/server/api/stream/channels/user-list.ts @@ -56,7 +56,8 @@ export default class extends Channel { // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する if (isUserRelated(note, this.blocking)) return; - if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; + if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) + return; this.send("note", note); } diff --git a/packages/calckey-js/src/api.types.ts b/packages/calckey-js/src/api.types.ts index e406b865a..bef00da4e 100644 --- a/packages/calckey-js/src/api.types.ts +++ b/packages/calckey-js/src/api.types.ts @@ -765,9 +765,9 @@ export type Endpoints = { "mute/create": { req: TODO; res: TODO }; "mute/delete": { req: { userId: User["id"] }; res: null }; "mute/list": { req: TODO; res: TODO }; - "renote-mute/create": { req: TODO; res: TODO; }; - "renote-mute/delete": { req: { userId: User['id'] }; res: null; }; - "renote-mute/list": { req: TODO; res: TODO; }; + "renote-mute/create": { req: TODO; res: TODO }; + "renote-mute/delete": { req: { userId: User["id"] }; res: null }; + "renote-mute/list": { req: TODO; res: TODO }; // my "my/apps": { req: TODO; res: TODO }; diff --git a/packages/client/src/pages/admin/hashtags.vue b/packages/client/src/pages/admin/hashtags.vue index c2ecbcf3a..38cd0be5e 100644 --- a/packages/client/src/pages/admin/hashtags.vue +++ b/packages/client/src/pages/admin/hashtags.vue @@ -7,36 +7,39 @@ {{ i18n.ts.hiddenTags }} - + - - {{ i18n.ts.save }} + + {{ i18n.ts.save }} diff --git a/packages/client/src/scripts/get-user-menu.ts b/packages/client/src/scripts/get-user-menu.ts index b128419f1..fd1ce0820 100644 --- a/packages/client/src/scripts/get-user-menu.ts +++ b/packages/client/src/scripts/get-user-menu.ts @@ -118,9 +118,12 @@ export function getUserMenu(user, router: Router = mainRouter) { } async function toggleRenoteMute(): Promise { - os.apiWithDialog(user.isRenoteMuted ? "renote-mute/delete" : "renote-mute/create", { - userId: user.id, - }).then(() => { + os.apiWithDialog( + user.isRenoteMuted ? "renote-mute/delete" : "renote-mute/create", + { + userId: user.id, + }, + ).then(() => { user.isRenoteMuted = !user.isRenoteMuted; }); }