diff --git a/packages/backend/src/misc/check-hit-antenna.ts b/packages/backend/src/misc/check-hit-antenna.ts index e7abba23d..bff919eea 100644 --- a/packages/backend/src/misc/check-hit-antenna.ts +++ b/packages/backend/src/misc/check-hit-antenna.ts @@ -1,29 +1,20 @@ import type { Antenna } from "@/models/entities/antenna.js"; import type { Note } from "@/models/entities/note.js"; import type { User } from "@/models/entities/user.js"; -import { - UserListJoinings, - UserGroupJoinings, - Blockings, -} from "@/models/index.js"; +import { Blockings, UserProfiles } from "@/models/index.js"; import { getFullApAccount } from "./convert-host.js"; import * as Acct from "@/misc/acct.js"; import type { Packed } from "./schema.js"; import { Cache } from "./cache.js"; +import { getWordHardMute } from "./check-word-mute.js"; const blockingCache = new Cache("blocking", 60 * 5); -// NOTE: フォローしているユーザーのノート、リストのユーザーのノート、グループのユーザーのノート指定はパフォーマンス上の理由で無効になっている - -/** - * noteUserFollowers / antennaUserFollowing はどちらか一方が指定されていればよい - */ export async function checkHitAntenna( antenna: Antenna, note: Note | Packed<"Note">, noteUser: { id: User["id"]; username: string; host: string | null }, - noteUserFollowers?: User["id"][], - antennaUserFollowing?: User["id"][], + antennaUserFollowing: User["id"][], ): Promise { if (note.visibility === "specified") return false; @@ -35,41 +26,25 @@ export async function checkHitAntenna( ); if (blockings.some((blocking) => blocking === antenna.userId)) return false; + if ( + await getWordHardMute( + note, + antenna.userId, + ( + await UserProfiles.findOneBy({ userId: antenna.userId }) + )?.mutedWords, + ) + ) + return false; + if (note.visibility === "followers" || note.visibility === "home") { - if (noteUserFollowers && !noteUserFollowers.includes(antenna.userId)) - return false; if (antennaUserFollowing && !antennaUserFollowing.includes(note.userId)) return false; } if (!antenna.withReplies && note.replyId != null) return false; - if (antenna.src === "home") { - if (noteUserFollowers && !noteUserFollowers.includes(antenna.userId)) - return false; - if (antennaUserFollowing && !antennaUserFollowing.includes(note.userId)) - return false; - } else if (antenna.src === "list") { - const listUsers = ( - await UserListJoinings.findBy({ - userListId: antenna.userListId!, - }) - ).map((x) => x.userId); - - if (!listUsers.includes(note.userId)) return false; - } else if (antenna.src === "group") { - const joining = await UserGroupJoinings.findOneByOrFail({ - id: antenna.userGroupJoiningId!, - }); - - const groupUsers = ( - await UserGroupJoinings.findBy({ - userGroupId: joining.userGroupId, - }) - ).map((x) => x.userId); - - if (!groupUsers.includes(note.userId)) return false; - } else if (antenna.src === "users") { + if (antenna.src === "users") { const accts = antenna.users.map((x) => { const { username, host } = Acct.parse(x); return getFullApAccount(username, host).toLowerCase(); diff --git a/packages/backend/src/misc/check-word-mute.ts b/packages/backend/src/misc/check-word-mute.ts index a75beed9d..fe02fb0f1 100644 --- a/packages/backend/src/misc/check-word-mute.ts +++ b/packages/backend/src/misc/check-word-mute.ts @@ -1,6 +1,5 @@ import RE2 from "re2"; import type { Note } from "@/models/entities/note.js"; -import type { User } from "@/models/entities/user.js"; type NoteLike = { userId: Note["userId"]; @@ -9,10 +8,6 @@ type NoteLike = { cw?: Note["cw"]; }; -type UserLike = { - id: User["id"]; -}; - function checkWordMute( note: NoteLike, mutedWords: Array, @@ -61,11 +56,11 @@ function checkWordMute( export async function getWordHardMute( note: NoteLike, - me: UserLike | null | undefined, - mutedWords: Array, + meId: string | null | undefined, + mutedWords?: Array, ): Promise { // 自分自身 - if (me && note.userId === me.id) { + if (note.userId === meId || mutedWords == null) { return false; } 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 f2aca7e3c..2f117087c 100644 --- a/packages/backend/src/server/api/stream/channels/global-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/global-timeline.ts @@ -67,8 +67,9 @@ export default class extends Channel { // レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。 // そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる if ( + this.user && this.userProfile && - (await getWordHardMute(note, this.user, this.userProfile.mutedWords)) + (await getWordHardMute(note, this.user.id, this.userProfile.mutedWords)) ) return; 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 52e2dc2a9..031d7bab0 100644 --- a/packages/backend/src/server/api/stream/channels/home-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/home-timeline.ts @@ -66,8 +66,9 @@ export default class extends Channel { // レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。 // そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる if ( + this.user && this.userProfile && - (await getWordHardMute(note, this.user, this.userProfile.mutedWords)) + (await getWordHardMute(note, this.user.id, this.userProfile.mutedWords)) ) return; 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 6e2da514f..06aef92ae 100644 --- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts @@ -83,8 +83,9 @@ export default class extends Channel { // レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。 // そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる if ( + this.user && this.userProfile && - (await getWordHardMute(note, this.user, this.userProfile.mutedWords)) + (await getWordHardMute(note, this.user.id, this.userProfile.mutedWords)) ) return; 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 2cc286b17..e64ba215f 100644 --- a/packages/backend/src/server/api/stream/channels/local-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts @@ -59,8 +59,9 @@ export default class extends Channel { // レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。 // そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる if ( + this.user && this.userProfile && - (await getWordHardMute(note, this.user, this.userProfile.mutedWords)) + (await getWordHardMute(note, this.user.id, this.userProfile.mutedWords)) ) return; diff --git a/packages/backend/src/server/api/stream/channels/recommended-timeline.ts b/packages/backend/src/server/api/stream/channels/recommended-timeline.ts index 186b12032..358a43ddd 100644 --- a/packages/backend/src/server/api/stream/channels/recommended-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/recommended-timeline.ts @@ -81,8 +81,9 @@ export default class extends Channel { // レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。 // そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる if ( + this.user && this.userProfile && - (await getWordHardMute(note, this.user, this.userProfile.mutedWords)) + (await getWordHardMute(note, this.user.id, this.userProfile.mutedWords)) ) return; diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index f19962d23..dd21dc762 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -23,6 +23,7 @@ import { extractHashtags } from "@/misc/extract-hashtags.js"; import type { IMentionedRemoteUsers } from "@/models/entities/note.js"; import { Note } from "@/models/entities/note.js"; import { + Followings, Mutings, Users, NoteWatchings, @@ -370,7 +371,7 @@ export default async ( ) .then((us) => { for (const u of us) { - getWordHardMute(data, { id: u.userId }, u.mutedWords).then( + getWordHardMute(data, u.userId, u.mutedWords).then( (shouldMute) => { if (shouldMute) { MutedNotes.insert({ @@ -387,7 +388,17 @@ export default async ( // Antenna for (const antenna of await getAntennas()) { - checkHitAntenna(antenna, note, user).then((hit) => { + checkHitAntenna( + antenna, + note, + user, + ( + await Followings.find({ + where: { followerId: user.id }, + select: ["followeeId"], + }) + ).map((x) => x.followeeId), + ).then((hit) => { if (hit) { addNoteToAntenna(antenna, note, user); } diff --git a/packages/backend/src/services/note/read.ts b/packages/backend/src/services/note/read.ts index 5e61fe95d..73c586401 100644 --- a/packages/backend/src/services/note/read.ts +++ b/packages/backend/src/services/note/read.ts @@ -9,8 +9,6 @@ import { } from "@/models/index.js"; import { Not, IsNull, In } from "typeorm"; import type { Channel } from "@/models/entities/channel.js"; -import { checkHitAntenna } from "@/misc/check-hit-antenna.js"; -import { getAntennas } from "@/misc/antenna-cache.js"; import { readNotificationByQuery } from "@/server/api/common/read-notification.js"; import type { Packed } from "@/misc/schema.js"; @@ -50,11 +48,9 @@ export default async function ( ).map((x) => x.followeeId), ); - // const myAntennas = (await getAntennas()).filter((a) => a.userId === userId); const readMentions: (Note | Packed<"Note">)[] = []; const readSpecifiedNotes: (Note | Packed<"Note">)[] = []; const readChannelNotes: (Note | Packed<"Note">)[] = []; - // const readAntennaNotes: (Note | Packed<"Note">)[] = []; for (const note of notes) { if (note.mentions?.includes(userId)) { @@ -66,23 +62,6 @@ export default async function ( if (note.channelId && followingChannels.has(note.channelId)) { readChannelNotes.push(note); } - - // if (note.user != null) { - // // たぶんnullになることは無いはずだけど一応 - // for (const antenna of myAntennas) { - // if ( - // await checkHitAntenna( - // antenna, - // note, - // note.user, - // undefined, - // Array.from(following), - // ) - // ) { - // readAntennaNotes.push(note); - // } - // } - // } } if ( @@ -139,34 +118,4 @@ export default async function ( ]), }); } - - // if (readAntennaNotes.length > 0) { - // await AntennaNotes.update( - // { - // antennaId: In(myAntennas.map((a) => a.id)), - // noteId: In(readAntennaNotes.map((n) => n.id)), - // }, - // { - // read: true, - // }, - // ); - - // // TODO: まとめてクエリしたい - // for (const antenna of myAntennas) { - // const count = await AntennaNotes.countBy({ - // antennaId: antenna.id, - // read: false, - // }); - - // if (count === 0) { - // publishMainStream(userId, "readAntenna", antenna); - // } - // } - - // Users.getHasUnreadAntenna(userId).then((unread) => { - // if (!unread) { - // publishMainStream(userId, "readAllAntennas"); - // } - // }); - // } }