From c443079db0e27f4d35d493f28f1d2e79506de46b Mon Sep 17 00:00:00 2001 From: Natty Date: Thu, 28 Dec 2023 00:31:05 +0100 Subject: [PATCH] Removed out all note packing --- packages/backend/package.json | 2 +- .../backend/src/misc/check-hit-antenna.ts | 19 +- packages/backend/src/misc/gen-id.ts | 2 +- packages/backend/src/misc/get-note-summary.ts | 14 +- .../backend/src/misc/is-instance-muted.ts | 5 +- packages/backend/src/misc/is-user-related.ts | 4 +- packages/backend/src/misc/schema.ts | 2 - .../src/models/repositories/note-favorite.ts | 10 +- .../src/models/repositories/note-reaction.ts | 17 +- .../backend/src/models/repositories/note.ts | 186 +------------- .../src/models/repositories/notification.ts | 94 ++------ .../backend/src/models/repositories/user.ts | 42 +--- packages/backend/src/models/schema/user.ts | 45 ---- packages/backend/src/server/api/endpoints.ts | 6 - .../server/api/endpoints/antennas/notes.ts | 25 +- .../src/server/api/endpoints/ap/show.ts | 33 +-- .../src/server/api/endpoints/clips/notes.ts | 35 +-- .../endpoints/drive/files/attached-notes.ts | 16 +- .../server/api/endpoints/i/notifications.ts | 26 +- .../backend/src/server/api/endpoints/notes.ts | 91 ------- .../server/api/endpoints/notes/children.ts | 19 +- .../api/endpoints/notes/conversation.ts | 9 +- .../src/server/api/endpoints/notes/create.ts | 4 +- .../src/server/api/endpoints/notes/edit.ts | 4 +- .../server/api/endpoints/notes/featured.ts | 21 +- .../api/endpoints/notes/global-timeline.ts | 35 +-- .../api/endpoints/notes/hybrid-timeline.ts | 33 +-- .../api/endpoints/notes/local-timeline.ts | 35 +-- .../server/api/endpoints/notes/mentions.ts | 48 +--- .../endpoints/notes/polls/recommendation.ts | 85 ------- .../server/api/endpoints/notes/reactions.ts | 13 +- .../endpoints/notes/recommended-timeline.ts | 35 +-- .../src/server/api/endpoints/notes/renotes.ts | 44 +--- .../src/server/api/endpoints/notes/replies.ts | 41 +--- .../api/endpoints/notes/search-by-tag.ts | 47 +--- .../src/server/api/endpoints/notes/search.ts | 42 ++-- .../src/server/api/endpoints/notes/show.ts | 51 ---- .../server/api/endpoints/notes/timeline.ts | 13 +- .../api/endpoints/notes/user-list-timeline.ts | 44 +--- .../src/server/api/endpoints/users/notes.ts | 32 +-- .../backend/src/server/api/stream/channel.ts | 34 --- .../src/server/api/stream/channels/antenna.ts | 27 +-- .../api/stream/channels/global-timeline.ts | 10 +- .../src/server/api/stream/channels/hashtag.ts | 10 +- .../api/stream/channels/home-timeline.ts | 10 +- .../api/stream/channels/hybrid-timeline.ts | 12 +- .../api/stream/channels/local-timeline.ts | 12 +- .../stream/channels/recommended-timeline.ts | 14 +- .../server/api/stream/channels/user-list.ts | 8 +- .../backend/src/server/api/stream/index.ts | 21 -- .../backend/src/server/api/stream/types.ts | 6 +- packages/backend/src/services/note/create.ts | 80 ++++--- packages/backend/src/services/note/read.ts | 9 +- .../backend/src/services/push-notification.ts | 10 +- pnpm-lock.yaml | 226 ++++++++++-------- 55 files changed, 427 insertions(+), 1391 deletions(-) delete mode 100644 packages/backend/src/server/api/endpoints/notes.ts delete mode 100644 packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts delete mode 100644 packages/backend/src/server/api/endpoints/notes/show.ts diff --git a/packages/backend/package.json b/packages/backend/package.json index af9fc1501c..face9d5e1b 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -92,7 +92,7 @@ "qs": "6.11.2", "random-seed": "0.3.0", "ratelimiter": "3.4.1", - "re2": "1.19.0", + "re2": "1.20.9", "redis-lock": "0.1.4", "reflect-metadata": "0.1.13", "rename": "1.0.4", diff --git a/packages/backend/src/misc/check-hit-antenna.ts b/packages/backend/src/misc/check-hit-antenna.ts index 358fba0f37..e57ba32ffb 100644 --- a/packages/backend/src/misc/check-hit-antenna.ts +++ b/packages/backend/src/misc/check-hit-antenna.ts @@ -1,15 +1,10 @@ -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 { getFullApAccount } from "./convert-host.js"; +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 {Blockings, UserGroupJoinings, UserListJoinings,} 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 {Cache} from "./cache.js"; const blockingCache = new Cache(1000 * 60 * 5); @@ -20,7 +15,7 @@ const blockingCache = new Cache(1000 * 60 * 5); */ export async function checkHitAntenna( antenna: Antenna, - note: Note | Packed<"Note">, + note: Note, noteUser: { id: User["id"]; username: string; host: string | null }, noteUserFollowers?: User["id"][], antennaUserFollowing?: User["id"][], diff --git a/packages/backend/src/misc/gen-id.ts b/packages/backend/src/misc/gen-id.ts index 86bae2b2f6..6ba6e1fc98 100644 --- a/packages/backend/src/misc/gen-id.ts +++ b/packages/backend/src/misc/gen-id.ts @@ -29,4 +29,4 @@ export function genId(date?: Date): string { const cuid = createId(); return `${time36}${cuid}`; -} \ No newline at end of file +} diff --git a/packages/backend/src/misc/get-note-summary.ts b/packages/backend/src/misc/get-note-summary.ts index 0a662e434e..4285f29231 100644 --- a/packages/backend/src/misc/get-note-summary.ts +++ b/packages/backend/src/misc/get-note-summary.ts @@ -1,14 +1,10 @@ -import type { Packed } from "./schema.js"; +import {Note} from "@/models/entities/note"; /** * 投稿を表す文字列を取得します。 * @param {*} note (packされた)投稿 */ -export const getNoteSummary = (note: Packed<"Note">): string => { - if (note.deletedAt) { - return "❌"; - } - +export const getNoteSummary = (note: Note): string => { let summary = ""; // 本文 @@ -19,13 +15,13 @@ export const getNoteSummary = (note: Packed<"Note">): string => { } // ファイルが添付されているとき - if ((note.files || []).length !== 0) { - const len = note.files?.length; + if ((note.fileIds || []).length !== 0) { + const len = note.fileIds?.length; summary += ` 📎${len !== 1 ? ` (${len})` : ""}`; } // 投票が添付されているとき - if (note.poll) { + if (note.fileIds) { summary += " 📊"; } diff --git a/packages/backend/src/misc/is-instance-muted.ts b/packages/backend/src/misc/is-instance-muted.ts index 1547d4555c..2d24e92d14 100644 --- a/packages/backend/src/misc/is-instance-muted.ts +++ b/packages/backend/src/misc/is-instance-muted.ts @@ -1,7 +1,8 @@ -import type { Packed } from "./schema.js"; +import type {Packed} from "./schema.js"; +import {Note} from "@/models/entities/note"; export function isInstanceMuted( - note: Packed<"Note">, + note: Note, mutedInstances: Set, ): boolean { if (mutedInstances.has(note?.user?.host ?? "")) return true; diff --git a/packages/backend/src/misc/is-user-related.ts b/packages/backend/src/misc/is-user-related.ts index 64591cfef3..1572c7e684 100644 --- a/packages/backend/src/misc/is-user-related.ts +++ b/packages/backend/src/misc/is-user-related.ts @@ -1,4 +1,6 @@ -export function isUserRelated(note: any, ids: Set): boolean { +import {Note} from "@/models/entities/note"; + +export function isUserRelated(note: Note, ids: Set): boolean { if (ids.has(note.userId)) return true; // note author is muted if (note.mentions?.some((user: string) => ids.has(user))) return true; // any of mentioned users are muted if (note.reply && isUserRelated(note.reply, ids)) return true; // also check reply target diff --git a/packages/backend/src/misc/schema.ts b/packages/backend/src/misc/schema.ts index 5c45802b8a..31fb237304 100644 --- a/packages/backend/src/misc/schema.ts +++ b/packages/backend/src/misc/schema.ts @@ -7,7 +7,6 @@ import { packedUserLiteSchema, packedUserSchema, } from "@/models/schema/user.js"; -import {packedNoteSchema} from "@/models/schema/note.js"; import {packedUserListSchema} from "@/models/schema/user-list.js"; import {packedAppSchema} from "@/models/schema/app.js"; import {packedNotificationSchema} from "@/models/schema/notification.js"; @@ -42,7 +41,6 @@ export const refs = { UserList: packedUserListSchema, UserGroup: packedUserGroupSchema, App: packedAppSchema, - Note: packedNoteSchema, NoteEdit: packedNoteEdit, NoteReaction: packedNoteReactionSchema, NoteFavorite: packedNoteFavoriteSchema, diff --git a/packages/backend/src/models/repositories/note-favorite.ts b/packages/backend/src/models/repositories/note-favorite.ts index ba43e3c3b4..d98631bc35 100644 --- a/packages/backend/src/models/repositories/note-favorite.ts +++ b/packages/backend/src/models/repositories/note-favorite.ts @@ -1,7 +1,7 @@ -import { db } from "@/db/postgre.js"; -import { NoteFavorite } from "@/models/entities/note-favorite.js"; -import { Notes } from "../index.js"; -import type { User } from "@/models/entities/user.js"; +import {db} from "@/db/postgre.js"; +import {NoteFavorite} from "@/models/entities/note-favorite.js"; +import type {User} from "@/models/entities/user.js"; +import {getNote} from "@/server/api/common/getters.js"; export const NoteFavoriteRepository = db.getRepository(NoteFavorite).extend({ async pack( @@ -16,7 +16,7 @@ export const NoteFavoriteRepository = db.getRepository(NoteFavorite).extend({ createdAt: favorite.createdAt.toISOString(), noteId: favorite.noteId, // may throw error - note: await Notes.pack(favorite.note || favorite.noteId, me), + note: await getNote(favorite.noteId, me ?? null), }; }, diff --git a/packages/backend/src/models/repositories/note-reaction.ts b/packages/backend/src/models/repositories/note-reaction.ts index 6d1dfbd6fd..9b536aae07 100644 --- a/packages/backend/src/models/repositories/note-reaction.ts +++ b/packages/backend/src/models/repositories/note-reaction.ts @@ -1,9 +1,10 @@ -import { db } from "@/db/postgre.js"; -import { NoteReaction } from "@/models/entities/note-reaction.js"; -import { Notes, Users } from "../index.js"; -import type { Packed } from "@/misc/schema.js"; -import { convertLegacyReaction } from "@/misc/reaction-lib.js"; -import type { User } from "@/models/entities/user.js"; +import {db} from "@/db/postgre.js"; +import {NoteReaction} from "@/models/entities/note-reaction.js"; +import {Users} from "../index.js"; +import type {Packed} from "@/misc/schema.js"; +import {convertLegacyReaction} from "@/misc/reaction-lib.js"; +import type {User} from "@/models/entities/user.js"; +import {getNote} from "@/server/api/common/getters.js"; export const NoteReactionRepository = db.getRepository(NoteReaction).extend({ async pack( @@ -31,7 +32,7 @@ export const NoteReactionRepository = db.getRepository(NoteReaction).extend({ ...(opts.withNote ? { // may throw error - note: await Notes.pack(reaction.note ?? reaction.noteId, me), + note: getNote(reaction.noteId, me), } : {}), }; @@ -41,7 +42,7 @@ export const NoteReactionRepository = db.getRepository(NoteReaction).extend({ src: NoteReaction[], me?: { id: User["id"] } | null | undefined, options?: { - withNote: booleam; + withNote: boolean; }, ): Promise[]> { const reactions = await Promise.allSettled( diff --git a/packages/backend/src/models/repositories/note.ts b/packages/backend/src/models/repositories/note.ts index cbc15814d5..b97d068f34 100644 --- a/packages/backend/src/models/repositories/note.ts +++ b/packages/backend/src/models/repositories/note.ts @@ -1,16 +1,9 @@ -import {In} from "typeorm"; -import * as mfm from "mfm-js"; import {Note} from "@/models/entities/note.js"; import type {User} from "@/models/entities/user.js"; -import {DriveFiles, Followings, NoteReactions, Notes, Polls, PollVotes, Users,} from "../index.js"; -import type {Packed} from "@/misc/schema.js"; -import {nyaize} from "@/misc/nyaize.js"; -import {awaitAll} from "@/prelude/await-all.js"; -import {convertLegacyReaction, convertLegacyReactions, decodeReaction,} from "@/misc/reaction-lib.js"; +import {Followings, NoteReactions, Polls, PollVotes, Users,} from "../index.js"; +import {convertLegacyReaction,} from "@/misc/reaction-lib.js"; import type {NoteReaction} from "@/models/entities/note-reaction.js"; -import {aggregateNoteEmojis, populateEmojis, prefetchEmojis,} from "@/misc/populate-emojis.js"; import {db} from "@/db/postgre.js"; -import {IdentifiableError} from "@/misc/identifiable-error.js"; export async function populatePoll(note: Note, meId: User["id"] | null) { const poll = await Polls.findOneByOrFail({ noteId: note.id }); @@ -132,179 +125,4 @@ export const NoteRepository = db.getRepository(Note).extend({ return true; }, - - async pack( - src: Note["id"] | Note, - me?: { id: User["id"] } | null | undefined, - options?: { - detail?: boolean; - _hint_?: { - myReactions: Map; - }; - }, - ): Promise> { - const opts = Object.assign( - { - detail: true, - }, - options, - ); - - const meId = me ? me.id : null; - const note = - typeof src === "object" ? src : await this.findOneByOrFail({ id: src }); - const host = note.userHost; - - if (!(await this.isVisibleForMe(note, meId))) { - throw new IdentifiableError( - "9725d0ce-ba28-4dde-95a7-2cbb2c15de24", - "No such note.", - ); - } - - let text = note.text; - - if (note.name && (note.url ?? note.uri)) { - text = `【${note.name}】\n${(note.text || "").trim()}\n\n${ - note.url ?? note.uri - }`; - } - - const reactionEmojiNames = Object.keys(note.reactions) - .filter((x) => x?.startsWith(":")) - .map((x) => decodeReaction(x).reaction) - .map((x) => x.replace(/:/g, "")); - - const userRenoteExists = meId ? (Notes.createQueryBuilder("note") - .andWhere("note.renoteId = :renoteId", { renoteId: note.id }) - .andWhere("note.userId = :userId", { userId: meId }) - .getExists()) : (async () => false)(); - - const noteEmoji = await populateEmojis( - note.emojis.concat(reactionEmojiNames), - host, - ); - const reactionEmoji = await populateEmojis(reactionEmojiNames, host); - const packed: Packed<"Note"> = await awaitAll({ - id: note.id, - createdAt: note.createdAt.toISOString(), - userId: note.userId, - user: Users.pack(note.user ?? note.userId, me, { - detail: false, - }), - text: text, - cw: note.cw, - visibility: note.visibility, - localOnly: note.localOnly || undefined, - visibleUserIds: - note.visibility === "specified" ? note.visibleUserIds : undefined, - renoteCount: note.renoteCount, - repliesCount: note.repliesCount, - reactions: convertLegacyReactions(note.reactions), - reactionEmojis: reactionEmoji, - emojis: noteEmoji, - tags: note.tags.length > 0 ? note.tags : undefined, - fileIds: note.fileIds, - files: DriveFiles.packMany(note.fileIds), - replyId: note.replyId, - renoteId: note.renoteId, - mentions: note.mentions.length > 0 ? note.mentions : undefined, - uri: note.uri || undefined, - url: note.url || undefined, - updatedAt: note.updatedAt?.toISOString() || undefined, - hasRenotedBefore: userRenoteExists, - poll: note.hasPoll ? populatePoll(note, meId) : undefined, - ...(meId - ? { - myReaction: populateMyReaction(note, meId, options?._hint_), - } - : {}), - - ...(opts.detail - ? { - reply: note.replyId - ? this.pack(note.reply || note.replyId, me, { - detail: false, - _hint_: options?._hint_, - }) - : undefined, - - renote: note.renoteId - ? this.pack(note.renote || note.renoteId, me, { - detail: true, - _hint_: options?._hint_, - }) - : undefined, - } - : {}), - }); - - if (packed.user.isCat && packed.user.speakAsCat && packed.text) { - const tokens = packed.text ? mfm.parse(packed.text) : []; - function nyaizeNode(node: mfm.MfmNode) { - if (node.type === "quote") return; - if (node.type === "text") node.props.text = nyaize(node.props.text); - - if (node.children) { - for (const child of node.children) { - nyaizeNode(child); - } - } - } - - for (const node of tokens) nyaizeNode(node); - - packed.text = mfm.toString(tokens); - } - - return packed; - }, - - async packMany( - notes: Note[], - me?: { id: User["id"] } | null | undefined, - options?: { - detail?: boolean; - }, - ) { - if (notes.length === 0) return []; - - const meId = me ? me.id : null; - const myReactionsMap = new Map(); - if (meId) { - const renoteIds = notes - .filter((n) => n.renoteId != null) - .map((n) => n.renoteId!); - const targets = [...notes.map((n) => n.id), ...renoteIds]; - const myReactions = await NoteReactions.findBy({ - userId: meId, - noteId: In(targets), - }); - - for (const target of targets) { - myReactionsMap.set( - target, - myReactions.find((reaction) => reaction.noteId === target) || null, - ); - } - } - - await prefetchEmojis(aggregateNoteEmojis(notes)); - - const promises = await Promise.allSettled( - notes.map((n) => - this.pack(n, me, { - ...options, - _hint_: { - myReactions: myReactionsMap, - }, - }), - ), - ); - - // filter out rejected promises, only keep fulfilled values - return promises.flatMap((result) => - result.status === "fulfilled" ? [result.value] : [], - ); - }, }); diff --git a/packages/backend/src/models/repositories/notification.ts b/packages/backend/src/models/repositories/notification.ts index 1538e67d86..b3273b5776 100644 --- a/packages/backend/src/models/repositories/notification.ts +++ b/packages/backend/src/models/repositories/notification.ts @@ -1,20 +1,14 @@ -import { In, Repository } from "typeorm"; -import { Notification } from "@/models/entities/notification.js"; -import { awaitAll } from "@/prelude/await-all.js"; -import type { Packed } from "@/misc/schema.js"; -import type { Note } from "@/models/entities/note.js"; -import type { NoteReaction } from "@/models/entities/note-reaction.js"; -import type { User } from "@/models/entities/user.js"; -import { aggregateNoteEmojis, prefetchEmojis } from "@/misc/populate-emojis.js"; -import { notificationTypes } from "@/types.js"; -import { db } from "@/db/postgre.js"; -import { - Users, - Notes, - UserGroupInvitations, - AccessTokens, - NoteReactions, -} from "../index.js"; +import {In} from "typeorm"; +import {Notification} from "@/models/entities/notification.js"; +import {awaitAll} from "@/prelude/await-all.js"; +import type {Packed} from "@/misc/schema.js"; +import type {Note} from "@/models/entities/note.js"; +import type {NoteReaction} from "@/models/entities/note-reaction.js"; +import type {User} from "@/models/entities/user.js"; +import {aggregateNoteEmojis, prefetchEmojis} from "@/misc/populate-emojis.js"; +import {db} from "@/db/postgre.js"; +import {AccessTokens, NoteReactions, UserGroupInvitations, Users,} from "../index.js"; +import {getNote} from "@/server/api/common/getters.js"; export const NotificationRepository = db.getRepository(Notification).extend({ async pack( @@ -44,88 +38,42 @@ export const NotificationRepository = db.getRepository(Notification).extend({ : null, ...(notification.type === "mention" ? { - note: Notes.pack( - notification.note || notification.noteId!, - { id: notification.notifieeId }, - { - detail: true, - _hint_: options._hintForEachNotes_, - }, - ), + note: getNote(notification.noteId!, { id: notification.notifieeId }), } : {}), ...(notification.type === "reply" ? { - note: Notes.pack( - notification.note || notification.noteId!, - { id: notification.notifieeId }, - { - detail: true, - _hint_: options._hintForEachNotes_, - }, - ), + note: getNote(notification.noteId!, { id: notification.notifieeId }), } : {}), ...(notification.type === "renote" ? { - note: Notes.pack( - notification.note || notification.noteId!, - { id: notification.notifieeId }, - { - detail: true, - _hint_: options._hintForEachNotes_, - }, - ), + note: getNote(notification.noteId!, { id: notification.notifierId }).then(async (n) => { + n.renote = await getNote(n.renoteId!, { id: notification.notifieeId }); + return n; + }), } : {}), ...(notification.type === "quote" ? { - note: Notes.pack( - notification.note || notification.noteId!, - { id: notification.notifieeId }, - { - detail: true, - _hint_: options._hintForEachNotes_, - }, - ), + note: getNote(notification.noteId!, { id: notification.notifieeId }), } : {}), ...(notification.type === "reaction" ? { - note: Notes.pack( - notification.note || notification.noteId!, - { id: notification.notifieeId }, - { - detail: true, - _hint_: options._hintForEachNotes_, - }, - ), + note: getNote(notification.noteId!, { id: notification.notifieeId }), reaction: notification.reaction, } : {}), ...(notification.type === "pollVote" ? { - note: Notes.pack( - notification.note || notification.noteId!, - { id: notification.notifieeId }, - { - detail: true, - _hint_: options._hintForEachNotes_, - }, - ), + note: getNote(notification.noteId!, { id: notification.notifieeId }), choice: notification.choice, } : {}), ...(notification.type === "pollEnded" ? { - note: Notes.pack( - notification.note || notification.noteId!, - { id: notification.notifieeId }, - { - detail: true, - _hint_: options._hintForEachNotes_, - }, - ), + note: getNote(notification.noteId!, { id: notification.notifieeId }), } : {}), ...(notification.type === "groupInvited" diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts index d00b6b8c8f..f4dc1411c1 100644 --- a/packages/backend/src/models/repositories/user.ts +++ b/packages/backend/src/models/repositories/user.ts @@ -25,7 +25,6 @@ import { FollowRequests, Instances, Mutings, - Notes, NoteUnreads, Notifications, Pages, @@ -276,22 +275,6 @@ export const UserRepository = db.getRepository(User).extend({ : "offline"; }, - async getAvatarUrl(user: User): Promise { - if (user.avatar) { - return ( - DriveFiles.getPublicUrl(user.avatar, true) || - this.getIdenticonUrl(user.id) - ); - } else if (user.avatarId) { - const avatar = await DriveFiles.findOneByOrFail({ id: user.avatarId }); - return ( - DriveFiles.getPublicUrl(avatar, true) || this.getIdenticonUrl(user.id) - ); - } else { - return this.getIdenticonUrl(user.id); - } - }, - getAvatarUrlSync(user: User): string { if (user.avatar) { return ( @@ -330,17 +313,9 @@ export const UserRepository = db.getRepository(User).extend({ if (typeof src === "object") { user = src; - if (src.avatar === undefined && src.avatarId) - src.avatar = (await DriveFiles.findOneBy({ id: src.avatarId })) ?? null; - if (src.banner === undefined && src.bannerId) - src.banner = (await DriveFiles.findOneBy({ id: src.bannerId })) ?? null; } else { user = await this.findOneOrFail({ - where: { id: src }, - relations: { - avatar: true, - banner: true, - }, + where: { id: src } }); } @@ -391,9 +366,6 @@ export const UserRepository = db.getRepository(User).extend({ name: user.name, username: user.username, host: user.host, - avatarUrl: this.getAvatarUrlSync(user), - avatarBlurhash: user.avatar?.blurhash || null, - avatarColor: null, // 後方互換性のため isAdmin: user.isAdmin || falsy, isModerator: user.isModerator || falsy, isBot: user.isBot || falsy, @@ -436,11 +408,6 @@ export const UserRepository = db.getRepository(User).extend({ lastFetchedAt: user.lastFetchedAt ? user.lastFetchedAt.toISOString() : null, - bannerUrl: user.banner - ? DriveFiles.getPublicUrl(user.banner, false) - : null, - bannerBlurhash: user.banner?.blurhash || null, - bannerColor: null, // 後方互換性のため isLocked: user.isLocked, isSilenced: user.isSilenced || falsy, isSuspended: user.isSuspended || falsy, @@ -453,13 +420,6 @@ export const UserRepository = db.getRepository(User).extend({ followingCount: followingCount || 0, notesCount: user.notesCount, pinnedNoteIds: pins.map((pin) => pin.noteId), - pinnedNotes: Notes.packMany( - pins.map((pin) => pin.note!), - me, - { - detail: true, - }, - ), pinnedPageId: profile!.pinnedPageId, pinnedPage: profile!.pinnedPageId ? Pages.pack(profile!.pinnedPageId, me) diff --git a/packages/backend/src/models/schema/user.ts b/packages/backend/src/models/schema/user.ts index 037f894b6a..1b680d1234 100644 --- a/packages/backend/src/models/schema/user.ts +++ b/packages/backend/src/models/schema/user.ts @@ -27,23 +27,6 @@ export const packedUserLiteSchema = { example: "misskey.example.com", description: "The local host is represented with `null`.", }, - avatarUrl: { - type: "string", - format: "url", - nullable: true, - optional: false, - }, - avatarBlurhash: { - type: "any", - nullable: true, - optional: false, - }, - avatarColor: { - type: "any", - nullable: true, - optional: false, - default: null, - }, isAdmin: { type: "boolean", nullable: false, @@ -149,23 +132,6 @@ export const packedUserDetailedNotMeOnlySchema = { optional: false, format: "date-time", }, - bannerUrl: { - type: "string", - format: "url", - nullable: true, - optional: false, - }, - bannerBlurhash: { - type: "any", - nullable: true, - optional: false, - }, - bannerColor: { - type: "any", - nullable: true, - optional: false, - default: null, - }, isLocked: { type: "boolean", nullable: false, @@ -254,17 +220,6 @@ export const packedUserDetailedNotMeOnlySchema = { format: "id", }, }, - pinnedNotes: { - type: "array", - nullable: false, - optional: false, - items: { - type: "object", - nullable: false, - optional: false, - ref: "Note", - }, - }, pinnedPageId: { type: "string", nullable: true, diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 75d8801958..ab7efe100e 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -222,7 +222,6 @@ import * as ep___renote_mute_create from "./endpoints/renote-mute/create.js"; import * as ep___renote_mute_delete from "./endpoints/renote-mute/delete.js"; import * as ep___renote_mute_list from "./endpoints/renote-mute/list.js"; import * as ep___my_apps from "./endpoints/my/apps.js"; -import * as ep___notes from "./endpoints/notes.js"; import * as ep___notes_children from "./endpoints/notes/children.js"; import * as ep___notes_clips from "./endpoints/notes/clips.js"; import * as ep___notes_conversation from "./endpoints/notes/conversation.js"; @@ -237,7 +236,6 @@ import * as ep___notes_hybridTimeline from "./endpoints/notes/hybrid-timeline.js import * as ep___notes_localTimeline from "./endpoints/notes/local-timeline.js"; import * as ep___notes_recommendedTimeline from "./endpoints/notes/recommended-timeline.js"; import * as ep___notes_mentions from "./endpoints/notes/mentions.js"; -import * as ep___notes_polls_recommendation from "./endpoints/notes/polls/recommendation.js"; import * as ep___notes_polls_vote from "./endpoints/notes/polls/vote.js"; import * as ep___notes_reactions from "./endpoints/notes/reactions.js"; import * as ep___notes_reactions_create from "./endpoints/notes/reactions/create.js"; @@ -246,7 +244,6 @@ import * as ep___notes_renotes from "./endpoints/notes/renotes.js"; import * as ep___notes_replies from "./endpoints/notes/replies.js"; import * as ep___notes_searchByTag from "./endpoints/notes/search-by-tag.js"; import * as ep___notes_search from "./endpoints/notes/search.js"; -import * as ep___notes_show from "./endpoints/notes/show.js"; import * as ep___notes_state from "./endpoints/notes/state.js"; import * as ep___notes_threadMuting_create from "./endpoints/notes/thread-muting/create.js"; import * as ep___notes_threadMuting_delete from "./endpoints/notes/thread-muting/delete.js"; @@ -555,7 +552,6 @@ const eps = [ ["mute/delete", ep___mute_delete], ["mute/list", ep___mute_list], ["my/apps", ep___my_apps], - ["notes", ep___notes], ["notes/children", ep___notes_children], ["notes/clips", ep___notes_clips], ["notes/conversation", ep___notes_conversation], @@ -570,7 +566,6 @@ const eps = [ ["notes/local-timeline", ep___notes_localTimeline], ["notes/recommended-timeline", ep___notes_recommendedTimeline], ["notes/mentions", ep___notes_mentions], - ["notes/polls/recommendation", ep___notes_polls_recommendation], ["notes/polls/vote", ep___notes_polls_vote], ["notes/reactions", ep___notes_reactions], ["notes/reactions/create", ep___notes_reactions_create], @@ -579,7 +574,6 @@ const eps = [ ["notes/replies", ep___notes_replies], ["notes/search-by-tag", ep___notes_searchByTag], ["notes/search", ep___notes_search], - ["notes/show", ep___notes_show], ["notes/state", ep___notes_state], ["notes/thread-muting/create", ep___notes_threadMuting_create], ["notes/thread-muting/delete", ep___notes_threadMuting_delete], diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts index 29e2e085ad..e9cbebcee5 100644 --- a/packages/backend/src/server/api/endpoints/antennas/notes.ts +++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts @@ -1,11 +1,11 @@ import define from "../../define.js"; import readNote from "@/services/note/read.js"; -import { Antennas, Notes, AntennaNotes } from "@/models/index.js"; -import { makePaginationQuery } from "../../common/make-pagination-query.js"; -import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; -import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; -import { ApiError } from "../../error.js"; -import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; +import {AntennaNotes, Antennas, Notes} from "@/models/index.js"; +import {makePaginationQuery} from "../../common/make-pagination-query.js"; +import {generateVisibilityQuery} from "../../common/generate-visibility-query.js"; +import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js"; +import {ApiError} from "../../error.js"; +import {generateBlockedUserQuery} from "../../common/generate-block-query.js"; export const meta = { tags: ["antennas", "account", "notes"], @@ -70,17 +70,6 @@ export default define(meta, paramDef, async (ps, user) => { "antennaNote", "antennaNote.noteId = note.id", ) - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner") .andWhere("antennaNote.antennaId = :antennaId", { antennaId: antenna.id }) .andWhere("note.visibility != 'home'"); @@ -94,5 +83,5 @@ export default define(meta, paramDef, async (ps, user) => { readNote(user.id, notes); } - return await Notes.packMany(notes, user); + return notes; }); diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts index 0bd3414ee3..fde94844a8 100644 --- a/packages/backend/src/server/api/endpoints/ap/show.ts +++ b/packages/backend/src/server/api/endpoints/ap/show.ts @@ -1,20 +1,20 @@ import define from "../../define.js"; -import { createPerson } from "@/remote/activitypub/models/person.js"; -import { createNote } from "@/remote/activitypub/models/note.js"; +import {createPerson} from "@/remote/activitypub/models/person.js"; +import {createNote} from "@/remote/activitypub/models/note.js"; import DbResolver from "@/remote/activitypub/db-resolver.js"; import Resolver from "@/remote/activitypub/resolver.js"; -import { ApiError } from "../../error.js"; -import { extractDbHost } from "@/misc/convert-host.js"; -import { Users, Notes } from "@/models/index.js"; -import type { Note } from "@/models/entities/note.js"; -import type { CacheableLocalUser, User } from "@/models/entities/user.js"; -import { isActor, isPost, getApId } from "@/remote/activitypub/type.js"; -import type { SchemaType } from "@/misc/schema.js"; -import { HOUR } from "@/const.js"; -import { shouldBlockInstance } from "@/misc/should-block-instance.js"; -import { updateQuestion } from "@/remote/activitypub/models/question.js"; -import { populatePoll } from "@/models/repositories/note.js"; -import { redisClient } from "@/db/redis.js"; +import {ApiError} from "../../error.js"; +import {extractDbHost} from "@/misc/convert-host.js"; +import {Notes, Users} from "@/models/index.js"; +import type {Note} from "@/models/entities/note.js"; +import type {CacheableLocalUser, User} from "@/models/entities/user.js"; +import {getApId, isActor, isPost} from "@/remote/activitypub/type.js"; +import type {SchemaType} from "@/misc/schema.js"; +import {HOUR} from "@/const.js"; +import {shouldBlockInstance} from "@/misc/should-block-instance.js"; +import {updateQuestion} from "@/remote/activitypub/models/question.js"; +import {populatePoll} from "@/models/repositories/note.js"; +import {redisClient} from "@/db/redis.js"; export const meta = { tags: ["federation"], @@ -161,11 +161,12 @@ async function mergePack( }; } else if (note != null) { try { - const object = await Notes.pack(note, me, { detail: true }); + if (!await Notes.isVisibleForMe(note, me?.id ?? null)) + return null; return { type: "Note", - object, + note, }; } catch (e) { return null; diff --git a/packages/backend/src/server/api/endpoints/clips/notes.ts b/packages/backend/src/server/api/endpoints/clips/notes.ts index c641d9ba9f..162087e2ff 100644 --- a/packages/backend/src/server/api/endpoints/clips/notes.ts +++ b/packages/backend/src/server/api/endpoints/clips/notes.ts @@ -1,10 +1,10 @@ import define from "../../define.js"; -import { ClipNotes, Clips, Notes } from "@/models/index.js"; -import { makePaginationQuery } from "../../common/make-pagination-query.js"; -import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; -import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; -import { ApiError } from "../../error.js"; -import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; +import {ClipNotes, Clips, Notes} from "@/models/index.js"; +import {makePaginationQuery} from "../../common/make-pagination-query.js"; +import {generateVisibilityQuery} from "../../common/generate-visibility-query.js"; +import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js"; +import {ApiError} from "../../error.js"; +import {generateBlockedUserQuery} from "../../common/generate-block-query.js"; export const meta = { tags: ["account", "notes", "clips"], @@ -69,26 +69,11 @@ export default define(meta, paramDef, async (ps, user) => { "clipNote", "clipNote.noteId = note.id", ) - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner") .andWhere("clipNote.clipId = :clipId", { clipId: clip.id }); - if (user) { - generateVisibilityQuery(query, user); - generateMutedUserQuery(query, user); - generateBlockedUserQuery(query, user); - } + generateVisibilityQuery(query, user); + generateMutedUserQuery(query, user); + generateBlockedUserQuery(query, user); - const notes = await query.take(ps.limit).getMany(); - - return await Notes.packMany(notes, user); + return await query.take(ps.limit).getMany(); }); diff --git a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts index 9267da5856..e70e4e297f 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts @@ -1,6 +1,7 @@ import define from "../../../define.js"; -import { ApiError } from "../../../error.js"; -import { DriveFiles, Notes } from "@/models/index.js"; +import {ApiError} from "../../../error.js"; +import {DriveFiles, Notes} from "@/models/index.js"; +import {generateVisibilityQuery} from "@/server/api/common/generate-visibility-query.js"; export const meta = { tags: ["drive", "notes"], @@ -51,11 +52,10 @@ export default define(meta, paramDef, async (ps, user) => { throw new ApiError(meta.errors.noSuchFile); } - const notes = await Notes.createQueryBuilder("note") - .where(":file = ANY(note.fileIds)", { file: file.id }) - .getMany(); + const notes = Notes.createQueryBuilder("note") + .where(":file = ANY(note.fileIds)", { file: file.id }); - return await Notes.packMany(notes, user, { - detail: true, - }); + generateVisibilityQuery(notes, user); + + return await notes.getMany(); }); diff --git a/packages/backend/src/server/api/endpoints/i/notifications.ts b/packages/backend/src/server/api/endpoints/i/notifications.ts index 6e1aabef7d..845e4a0fe4 100644 --- a/packages/backend/src/server/api/endpoints/i/notifications.ts +++ b/packages/backend/src/server/api/endpoints/i/notifications.ts @@ -1,16 +1,10 @@ -import { Brackets } from "typeorm"; -import { - Notifications, - Followings, - Mutings, - Users, - UserProfiles, -} from "@/models/index.js"; -import { notificationTypes } from "@/types.js"; +import {Brackets} from "typeorm"; +import {Followings, Mutings, Notifications, UserProfiles, Users,} from "@/models/index.js"; +import {notificationTypes} from "@/types.js"; import read from "@/services/note/read.js"; -import { readNotification } from "../../common/read-notification.js"; +import {readNotification} from "../../common/read-notification.js"; import define from "../../define.js"; -import { makePaginationQuery } from "../../common/make-pagination-query.js"; +import {makePaginationQuery} from "../../common/make-pagination-query.js"; export const meta = { tags: ["account", "notifications"], @@ -97,19 +91,11 @@ export default define(meta, paramDef, async (ps, user) => { .andWhere("notification.notifieeId = :meId", { meId: user.id }) .leftJoinAndSelect("notification.notifier", "notifier") .leftJoinAndSelect("notification.note", "note") - .leftJoinAndSelect("notifier.avatar", "notifierAvatar") - .leftJoinAndSelect("notifier.banner", "notifierBanner") .leftJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") .leftJoinAndSelect("note.reply", "reply") .leftJoinAndSelect("note.renote", "renote") .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); + .leftJoinAndSelect("renote.user", "renoteUser"); // muted users query.andWhere( diff --git a/packages/backend/src/server/api/endpoints/notes.ts b/packages/backend/src/server/api/endpoints/notes.ts deleted file mode 100644 index 9787740ab0..0000000000 --- a/packages/backend/src/server/api/endpoints/notes.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Notes } from "@/models/index.js"; -import define from "../define.js"; -import { makePaginationQuery } from "../common/make-pagination-query.js"; - -export const meta = { - tags: ["notes"], - - requireCredentialPrivateMode: true, - res: { - type: "array", - optional: false, - nullable: false, - items: { - type: "object", - optional: false, - nullable: false, - ref: "Note", - }, - }, -} as const; - -export const paramDef = { - type: "object", - properties: { - local: { type: "boolean", default: false }, - reply: { type: "boolean" }, - renote: { type: "boolean" }, - withFiles: { type: "boolean" }, - poll: { type: "boolean" }, - limit: { type: "integer", minimum: 1, maximum: 100, default: 10 }, - sinceId: { type: "string", format: "misskey:id" }, - untilId: { type: "string", format: "misskey:id" }, - }, - required: [], -} as const; - -export default define(meta, paramDef, async (ps) => { - const query = makePaginationQuery( - Notes.createQueryBuilder("note"), - ps.sinceId, - ps.untilId, - ) - .andWhere("note.visibility = 'public'") - .andWhere("note.localOnly = FALSE") - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); - - if (ps.local) { - query.andWhere("note.userHost IS NULL"); - } - - if (ps.reply !== undefined) { - query.andWhere( - ps.reply ? "note.replyId IS NOT NULL" : "note.replyId IS NULL", - ); - } - - if (ps.renote !== undefined) { - query.andWhere( - ps.renote ? "note.renoteId IS NOT NULL" : "note.renoteId IS NULL", - ); - } - - if (ps.withFiles !== undefined) { - query.andWhere( - ps.withFiles ? "note.fileIds != '{}'" : "note.fileIds = '{}'", - ); - } - - if (ps.poll !== undefined) { - query.andWhere(ps.poll ? "note.hasPoll = TRUE" : "note.hasPoll = FALSE"); - } - - // TODO - //if (bot != undefined) { - // query.isBot = bot; - //} - - const notes = await query.take(ps.limit).getMany(); - - return await Notes.packMany(notes); -}); diff --git a/packages/backend/src/server/api/endpoints/notes/children.ts b/packages/backend/src/server/api/endpoints/notes/children.ts index 9047fcce1d..c67f92c602 100644 --- a/packages/backend/src/server/api/endpoints/notes/children.ts +++ b/packages/backend/src/server/api/endpoints/notes/children.ts @@ -1,10 +1,9 @@ -import { Brackets } from "typeorm"; -import { Notes } from "@/models/index.js"; +import {Notes} from "@/models/index.js"; import define from "../../define.js"; -import { makePaginationQuery } from "../../common/make-pagination-query.js"; -import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; -import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; -import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; +import {makePaginationQuery} from "../../common/make-pagination-query.js"; +import {generateVisibilityQuery} from "../../common/generate-visibility-query.js"; +import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js"; +import {generateBlockedUserQuery} from "../../common/generate-block-query.js"; export const meta = { tags: ["notes"], @@ -46,9 +45,7 @@ export default define(meta, paramDef, async (ps, user) => { "note.id IN (SELECT id FROM note_replies(:noteId, :depth, :limit))", { noteId: ps.noteId, depth: ps.depth, limit: ps.limit }, ) - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner"); + .innerJoinAndSelect("note.user", "user"); generateVisibilityQuery(query, user); if (user) { @@ -56,7 +53,5 @@ export default define(meta, paramDef, async (ps, user) => { generateBlockedUserQuery(query, user); } - const notes = await query.getMany(); - - return await Notes.packMany(notes, user, { detail: false }); + return await query.getMany(); }); diff --git a/packages/backend/src/server/api/endpoints/notes/conversation.ts b/packages/backend/src/server/api/endpoints/notes/conversation.ts index 2e8f5ef73b..7bb2c8b110 100644 --- a/packages/backend/src/server/api/endpoints/notes/conversation.ts +++ b/packages/backend/src/server/api/endpoints/notes/conversation.ts @@ -1,8 +1,7 @@ -import type { Note } from "@/models/entities/note.js"; -import { Notes } from "@/models/index.js"; +import type {Note} from "@/models/entities/note.js"; import define from "../../define.js"; -import { ApiError } from "../../error.js"; -import { getNote } from "../../common/getters.js"; +import {ApiError} from "../../error.js"; +import {getNote} from "../../common/getters.js"; export const meta = { tags: ["notes"], @@ -77,5 +76,5 @@ export default define(meta, paramDef, async (ps, user) => { await get(note.replyId); } - return await Notes.packMany(conversation, user); + return conversation; }); diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index c16e2f3dcc..2810027c3a 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -1,7 +1,7 @@ import {In} from "typeorm"; import create from "@/services/note/create.js"; import type {User} from "@/models/entities/user.js"; -import {Blockings, DriveFiles, Notes, Users,} from "@/models/index.js"; +import {Blockings, DriveFiles, Users,} from "@/models/index.js"; import type {DriveFile} from "@/models/entities/drive-file.js"; import type {Note} from "@/models/entities/note.js"; import {HOUR, MAX_NOTE_TEXT_LENGTH} from "@/const.js"; @@ -284,6 +284,6 @@ export default define(meta, paramDef, async (ps, user) => { }); return { - createdNote: await Notes.pack(note, user), + createdNote: note, }; }); diff --git a/packages/backend/src/server/api/endpoints/notes/edit.ts b/packages/backend/src/server/api/endpoints/notes/edit.ts index 53c42951a4..067019bea3 100644 --- a/packages/backend/src/server/api/endpoints/notes/edit.ts +++ b/packages/backend/src/server/api/endpoints/notes/edit.ts @@ -624,11 +624,11 @@ export default define(meta, paramDef, async (ps, user) => { // GO! dm.execute(); - })(); + })().then(); } return { - createdNote: await Notes.pack(note, user), + createdNote: note, }; }); diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index 47c1e13812..44b9f4f705 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -1,7 +1,7 @@ -import { Notes } from "@/models/index.js"; +import {Notes} from "@/models/index.js"; import define from "../../define.js"; -import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; -import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; +import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js"; +import {generateBlockedUserQuery} from "../../common/generate-block-query.js"; export const meta = { tags: ["notes"], @@ -45,18 +45,7 @@ export default define(meta, paramDef, async (ps, user) => { .addSelect("note.score") .andWhere("note.score > 0") .andWhere("note.createdAt > :date", { date: new Date(Date.now() - day) }) - .andWhere("note.visibility = 'public'") - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); + .andWhere("note.visibility = 'public'"); switch (ps.origin) { case "local": @@ -78,5 +67,5 @@ export default define(meta, paramDef, async (ps, user) => { notes = notes.slice(ps.offset, ps.offset + ps.limit); - return await Notes.packMany(notes, user); + return notes; }); diff --git a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts index 7394af4bdb..ee4b48d4a7 100644 --- a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts @@ -78,18 +78,7 @@ export default define(meta, paramDef, async (ps, user) => { ps.sinceDate, ps.untilDate, ) - .andWhere("note.visibility = 'public'") - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); + .andWhere("note.visibility = 'public'"); generateRepliesQuery(query, ps.withReplies, user); if (user) { @@ -111,25 +100,5 @@ export default define(meta, paramDef, async (ps, user) => { } }); - // We fetch more than requested because some may be filtered out, and if there's less than - // requested, the pagination stops. - const found = []; - const take = Math.floor(ps.limit * 1.5); - let skip = 0; - try { - while (found.length < ps.limit) { - const notes = await query.take(take).skip(skip).getMany(); - found.push(...(await Notes.packMany(notes, user))); - skip += take; - if (notes.length < take) break; - } - } catch (error) { - throw new ApiError(meta.errors.queryError); - } - - if (found.length > ps.limit) { - found.length = ps.limit; - } - - return found; + return await query.take(ps.limit).getMany(); }); diff --git a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts index 1637de2f0d..4f0b9fa416 100644 --- a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -94,17 +94,6 @@ export default define(meta, paramDef, async (ps, user) => { ).orWhere("(note.visibility = 'public') AND (note.userHost IS NULL)"); }), ) - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner") .setParameters(followingQuery.getParameters()); generateRepliesQuery(query, ps.withReplies, user); @@ -167,25 +156,5 @@ export default define(meta, paramDef, async (ps, user) => { activeUsersChart.read(user); }); - // We fetch more than requested because some may be filtered out, and if there's less than - // requested, the pagination stops. - const found = []; - const take = Math.floor(ps.limit * 1.5); - let skip = 0; - try { - while (found.length < ps.limit) { - const notes = await query.take(take).skip(skip).getMany(); - found.push(...(await Notes.packMany(notes, user))); - skip += take; - if (notes.length < take) break; - } - } catch (error) { - throw new ApiError(meta.errors.queryError); - } - - if (found.length > ps.limit) { - found.length = ps.limit; - } - - return found; + return await query.take(ps.limit).getMany(); }); diff --git a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts index 0ac175cc1b..a8e5612033 100644 --- a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts @@ -87,18 +87,7 @@ export default define(meta, paramDef, async (ps, user) => { ps.sinceDate, ps.untilDate, ) - .andWhere("(note.visibility = 'public') AND (note.userHost IS NULL)") - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); + .andWhere("(note.visibility = 'public') AND (note.userHost IS NULL)"); generateRepliesQuery(query, ps.withReplies, user); generateVisibilityQuery(query, user); @@ -140,25 +129,5 @@ export default define(meta, paramDef, async (ps, user) => { } }); - // We fetch more than requested because some may be filtered out, and if there's less than - // requested, the pagination stops. - const found = []; - const take = Math.floor(ps.limit * 1.5); - let skip = 0; - try { - while (found.length < ps.limit) { - const notes = await query.take(take).skip(skip).getMany(); - found.push(...(await Notes.packMany(notes, user))); - skip += take; - if (notes.length < take) break; - } - } catch (error) { - throw new ApiError(meta.errors.queryError); - } - - if (found.length > ps.limit) { - found.length = ps.limit; - } - - return found; + return await query.take(ps.limit).getMany(); }); diff --git a/packages/backend/src/server/api/endpoints/notes/mentions.ts b/packages/backend/src/server/api/endpoints/notes/mentions.ts index 68688b504c..6c0cd239e0 100644 --- a/packages/backend/src/server/api/endpoints/notes/mentions.ts +++ b/packages/backend/src/server/api/endpoints/notes/mentions.ts @@ -1,12 +1,11 @@ -import { Brackets } from "typeorm"; -import read from "@/services/note/read.js"; -import { Notes, Followings } from "@/models/index.js"; +import {Brackets} from "typeorm"; +import {Followings, Notes} from "@/models/index.js"; import define from "../../define.js"; -import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; -import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; -import { makePaginationQuery } from "../../common/make-pagination-query.js"; -import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; -import { generateMutedNoteThreadQuery } from "../../common/generate-muted-note-thread-query.js"; +import {generateVisibilityQuery} from "../../common/generate-visibility-query.js"; +import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js"; +import {makePaginationQuery} from "../../common/make-pagination-query.js"; +import {generateBlockedUserQuery} from "../../common/generate-block-query.js"; +import {generateMutedNoteThreadQuery} from "../../common/generate-muted-note-thread-query.js"; export const meta = { tags: ["notes"], @@ -54,18 +53,7 @@ export default define(meta, paramDef, async (ps, user) => { `'{"${user.id}"}' <@ note.visibleUserIds`, ); }), - ) - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); + ); generateVisibilityQuery(query, user); generateMutedUserQuery(query, user); @@ -86,23 +74,5 @@ export default define(meta, paramDef, async (ps, user) => { query.setParameters(followingQuery.getParameters()); } - // We fetch more than requested because some may be filtered out, and if there's less than - // requested, the pagination stops. - const found = []; - const take = Math.floor(ps.limit * 1.5); - let skip = 0; - while (found.length < ps.limit) { - const notes = await query.take(take).skip(skip).getMany(); - found.push(...(await Notes.packMany(notes, user))); - skip += take; - if (notes.length < take) break; - } - - if (found.length > ps.limit) { - found.length = ps.limit; - } - - read(user.id, found); - - return found; + return await query.take(ps.limit).getMany(); }); diff --git a/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts b/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts deleted file mode 100644 index fcd24db992..0000000000 --- a/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Brackets, In } from "typeorm"; -import { Polls, Mutings, Notes, PollVotes } from "@/models/index.js"; -import define from "../../../define.js"; - -export const meta = { - tags: ["notes"], - - requireCredential: true, - - res: { - type: "array", - optional: false, - nullable: false, - items: { - type: "object", - optional: false, - nullable: false, - ref: "Note", - }, - }, -} as const; - -export const paramDef = { - type: "object", - properties: { - limit: { type: "integer", minimum: 1, maximum: 100, default: 10 }, - offset: { type: "integer", default: 0 }, - }, - required: [], -} as const; - -export default define(meta, paramDef, async (ps, user) => { - const query = Polls.createQueryBuilder("poll") - .where("poll.userHost IS NULL") - .andWhere("poll.userId != :meId", { meId: user.id }) - .andWhere("poll.noteVisibility = 'public'") - .andWhere( - new Brackets((qb) => { - qb.where("poll.expiresAt IS NULL").orWhere("poll.expiresAt > :now", { - now: new Date(), - }); - }), - ); - - //#region exclude arleady voted polls - const votedQuery = PollVotes.createQueryBuilder("vote") - .select("vote.noteId") - .where("vote.userId = :meId", { meId: user.id }); - - query.andWhere(`poll.noteId NOT IN (${votedQuery.getQuery()})`); - - query.setParameters(votedQuery.getParameters()); - //#endregion - - //#region mute - const mutingQuery = Mutings.createQueryBuilder("muting") - .select("muting.muteeId") - .where("muting.muterId = :muterId", { muterId: user.id }); - - query.andWhere(`poll.userId NOT IN (${mutingQuery.getQuery()})`); - - query.setParameters(mutingQuery.getParameters()); - //#endregion - - const polls = await query - .orderBy("poll.noteId", "DESC") - .take(ps.limit) - .skip(ps.offset) - .getMany(); - - if (polls.length === 0) return []; - - const notes = await Notes.find({ - where: { - id: In(polls.map((poll) => poll.noteId)), - }, - order: { - createdAt: "DESC", - }, - }); - - return await Notes.packMany(notes, user, { - detail: true, - }); -}); diff --git a/packages/backend/src/server/api/endpoints/notes/reactions.ts b/packages/backend/src/server/api/endpoints/notes/reactions.ts index 3c8af119ab..e683c9d10c 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions.ts @@ -1,10 +1,9 @@ -import type { FindOptionsWhere } from "typeorm"; -import { DeepPartial } from "typeorm"; -import { NoteReactions } from "@/models/index.js"; -import type { NoteReaction } from "@/models/entities/note-reaction.js"; +import type {FindOptionsWhere} from "typeorm"; +import {NoteReactions} from "@/models/index.js"; +import type {NoteReaction} from "@/models/entities/note-reaction.js"; import define from "../../define.js"; -import { ApiError } from "../../error.js"; -import { getNote } from "../../common/getters.js"; +import {ApiError} from "../../error.js"; +import {getNote} from "../../common/getters.js"; export const meta = { tags: ["notes", "reactions"], @@ -78,7 +77,7 @@ export default define(meta, paramDef, async (ps, user) => { order: { id: -1, }, - relations: ["user", "user.avatar", "user.banner", "note"], + relations: ["user", "note"], }); return await NoteReactions.packMany(reactions, user); diff --git a/packages/backend/src/server/api/endpoints/notes/recommended-timeline.ts b/packages/backend/src/server/api/endpoints/notes/recommended-timeline.ts index 44763b67e8..3dd28a0173 100644 --- a/packages/backend/src/server/api/endpoints/notes/recommended-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/recommended-timeline.ts @@ -90,18 +90,7 @@ export default define(meta, paramDef, async (ps, user) => { .andWhere( `(note.userHost = ANY ('{"${m.recommendedInstances.join('","')}"}'))`, ) - .andWhere("(note.visibility = 'public')") - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); + .andWhere("(note.visibility = 'public')"); generateRepliesQuery(query, ps.withReplies, user); generateVisibilityQuery(query, user); @@ -143,25 +132,5 @@ export default define(meta, paramDef, async (ps, user) => { } }); - // We fetch more than requested because some may be filtered out, and if there's less than - // requested, the pagination stops. - const found = []; - const take = Math.floor(ps.limit * 1.5); - let skip = 0; - try { - while (found.length < ps.limit) { - const notes = await query.take(take).skip(skip).getMany(); - found.push(...(await Notes.packMany(notes, user))); - skip += take; - if (notes.length < take) break; - } - } catch (error) { - throw new ApiError(meta.errors.queryError); - } - - if (found.length > ps.limit) { - found.length = ps.limit; - } - - return found; + return await query.take(ps.limit).getMany(); }); diff --git a/packages/backend/src/server/api/endpoints/notes/renotes.ts b/packages/backend/src/server/api/endpoints/notes/renotes.ts index df801c7fc4..f9cae91968 100644 --- a/packages/backend/src/server/api/endpoints/notes/renotes.ts +++ b/packages/backend/src/server/api/endpoints/notes/renotes.ts @@ -1,11 +1,11 @@ -import { Notes } from "@/models/index.js"; +import {Notes} from "@/models/index.js"; import define from "../../define.js"; -import { getNote } from "../../common/getters.js"; -import { ApiError } from "../../error.js"; -import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; -import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; -import { makePaginationQuery } from "../../common/make-pagination-query.js"; -import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; +import {getNote} from "../../common/getters.js"; +import {ApiError} from "../../error.js"; +import {generateVisibilityQuery} from "../../common/generate-visibility-query.js"; +import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js"; +import {makePaginationQuery} from "../../common/make-pagination-query.js"; +import {generateBlockedUserQuery} from "../../common/generate-block-query.js"; export const meta = { tags: ["notes"], @@ -65,37 +65,9 @@ export default define(meta, paramDef, async (ps, user) => { query.andWhere("user.id = :userId", { userId: ps.userId }); } - query - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); - generateVisibilityQuery(query, user); if (user) generateMutedUserQuery(query, user); if (user) generateBlockedUserQuery(query, user); - // We fetch more than requested because some may be filtered out, and if there's less than - // requested, the pagination stops. - const found = []; - const take = Math.floor(ps.limit * 1.5); - let skip = 0; - while (found.length < ps.limit) { - const notes = await query.take(take).skip(skip).getMany(); - found.push(...(await Notes.packMany(notes, user))); - skip += take; - if (notes.length < take) break; - } - - if (found.length > ps.limit) { - found.length = ps.limit; - } - - return found; + return await query.take(ps.limit).getMany(); }); diff --git a/packages/backend/src/server/api/endpoints/notes/replies.ts b/packages/backend/src/server/api/endpoints/notes/replies.ts index 5ea4d479c5..978ccee23d 100644 --- a/packages/backend/src/server/api/endpoints/notes/replies.ts +++ b/packages/backend/src/server/api/endpoints/notes/replies.ts @@ -1,9 +1,9 @@ -import { Notes } from "@/models/index.js"; +import {Notes} from "@/models/index.js"; import define from "../../define.js"; -import { makePaginationQuery } from "../../common/make-pagination-query.js"; -import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; -import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; -import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; +import {makePaginationQuery} from "../../common/make-pagination-query.js"; +import {generateVisibilityQuery} from "../../common/generate-visibility-query.js"; +import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js"; +import {generateBlockedUserQuery} from "../../common/generate-block-query.js"; export const meta = { tags: ["notes"], @@ -41,38 +41,11 @@ export default define(meta, paramDef, async (ps, user) => { ps.sinceId, ps.untilId, ) - .andWhere("note.replyId = :replyId", { replyId: ps.noteId }) - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); + .andWhere("note.replyId = :replyId", { replyId: ps.noteId }); generateVisibilityQuery(query, user); if (user) generateMutedUserQuery(query, user); if (user) generateBlockedUserQuery(query, user); - // We fetch more than requested because some may be filtered out, and if there's less than - // requested, the pagination stops. - const found = []; - const take = Math.floor(ps.limit * 1.5); - let skip = 0; - while (found.length < ps.limit) { - const notes = await query.take(take).skip(skip).getMany(); - found.push(...(await Notes.packMany(notes, user))); - skip += take; - if (notes.length < take) break; - } - - if (found.length > ps.limit) { - found.length = ps.limit; - } - - return found; + return await query.take(ps.limit).getMany(); }); diff --git a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts index f988acaa51..226838a371 100644 --- a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts +++ b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts @@ -1,12 +1,12 @@ -import { Brackets } from "typeorm"; -import { Notes } from "@/models/index.js"; -import { safeForSql } from "@/misc/safe-for-sql.js"; -import { normalizeForSearch } from "@/misc/normalize-for-search.js"; +import {Brackets} from "typeorm"; +import {Notes} from "@/models/index.js"; +import {safeForSql} from "@/misc/safe-for-sql.js"; +import {normalizeForSearch} from "@/misc/normalize-for-search.js"; import define from "../../define.js"; -import { makePaginationQuery } from "../../common/make-pagination-query.js"; -import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; -import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; -import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; +import {makePaginationQuery} from "../../common/make-pagination-query.js"; +import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js"; +import {generateVisibilityQuery} from "../../common/generate-visibility-query.js"; +import {generateBlockedUserQuery} from "../../common/generate-block-query.js"; export const meta = { tags: ["notes", "hashtags"], @@ -74,18 +74,7 @@ export default define(meta, paramDef, async (ps, me) => { Notes.createQueryBuilder("note"), ps.sinceId, ps.untilId, - ) - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); + ); generateVisibilityQuery(query, me); if (me) generateMutedUserQuery(query, me); @@ -145,21 +134,5 @@ export default define(meta, paramDef, async (ps, me) => { } } - // We fetch more than requested because some may be filtered out, and if there's less than - // requested, the pagination stops. - const found = []; - const take = Math.floor(ps.limit * 1.5); - let skip = 0; - while (found.length < ps.limit) { - const notes = await query.take(take).skip(skip).getMany(); - found.push(...(await Notes.packMany(notes, me))); - skip += take; - if (notes.length < take) break; - } - - if (found.length > ps.limit) { - found.length = ps.limit; - } - - return found; + return await query.take(ps.limit).getMany(); }); diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts index b4d83aa0bc..5a4c709b31 100644 --- a/packages/backend/src/server/api/endpoints/notes/search.ts +++ b/packages/backend/src/server/api/endpoints/notes/search.ts @@ -1,16 +1,16 @@ -import { In } from "typeorm"; -import { Notes } from "@/models/index.js"; -import { Note } from "@/models/entities/note.js"; +import {In} from "typeorm"; +import {Notes} from "@/models/index.js"; +import {Note} from "@/models/entities/note.js"; import config from "@/config/index.js"; import es from "@/db/elasticsearch.js"; import sonic from "@/db/sonic.js"; -import meilisearch, { MeilisearchNote } from "@/db/meilisearch.js"; +import meilisearch, {MeilisearchNote} from "@/db/meilisearch.js"; import define from "../../define.js"; -import { makePaginationQuery } from "../../common/make-pagination-query.js"; -import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; -import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; -import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; +import {makePaginationQuery} from "../../common/make-pagination-query.js"; +import {generateVisibilityQuery} from "../../common/generate-visibility-query.js"; +import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js"; +import {generateBlockedUserQuery} from "../../common/generate-block-query.js"; +import {sqlLikeEscape} from "@/misc/sql-like-escape.js"; export const meta = { tags: ["notes"], @@ -79,18 +79,7 @@ export default define(meta, paramDef, async (ps, me) => { } query - .andWhere("note.text ILIKE :q", { q: `%${sqlLikeEscape(ps.query)}%` }) - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); + .andWhere("note.text ILIKE :q", { q: `%${sqlLikeEscape(ps.query)}%` }); generateVisibilityQuery(query, me); if (me) generateMutedUserQuery(query, me); @@ -98,7 +87,7 @@ export default define(meta, paramDef, async (ps, me) => { const notes: Note[] = await query.take(ps.limit).getMany(); - return await Notes.packMany(notes, me); + return notes; } else if (sonic) { let start = 0; const chunkSize = 100; @@ -162,7 +151,7 @@ export default define(meta, paramDef, async (ps, me) => { }); // The notes are checked for visibility and muted/blocked users when packed - found.push(...(await Notes.packMany(notes, me))); + found.push(...notes); start += chunkSize; } @@ -192,9 +181,6 @@ export default define(meta, paramDef, async (ps, me) => { if (ps.userId && key.userId !== ps.userId) { return false; } - if (ps.channelId && key.channelId !== ps.channelId) { - return false; - } if (ps.sinceId && key.id <= ps.sinceId) { return false; } @@ -226,7 +212,7 @@ export default define(meta, paramDef, async (ps, me) => { }); // The notes are checked for visibility and muted/blocked users when packed - found.push(...(await Notes.packMany(notes, me))); + found.push(...notes); start += chunkSize; } @@ -315,6 +301,6 @@ export default define(meta, paramDef, async (ps, me) => { }, }); - return await Notes.packMany(notes, me); + return notes; } }); diff --git a/packages/backend/src/server/api/endpoints/notes/show.ts b/packages/backend/src/server/api/endpoints/notes/show.ts deleted file mode 100644 index 39d128134f..0000000000 --- a/packages/backend/src/server/api/endpoints/notes/show.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Notes } from "@/models/index.js"; -import define from "../../define.js"; -import { getNote } from "../../common/getters.js"; -import { ApiError } from "../../error.js"; - -export const meta = { - tags: ["notes"], - - requireCredential: false, - requireCredentialPrivateMode: true, - - res: { - type: "object", - optional: false, - nullable: false, - ref: "Note", - }, - - errors: { - noSuchNote: { - message: "No such note.", - code: "NO_SUCH_NOTE", - id: "24fcbfc6-2e37-42b6-8388-c29b3861a08d", - }, - }, -} as const; - -export const paramDef = { - type: "object", - properties: { - noteId: { type: "string", format: "misskey:id" }, - }, - required: ["noteId"], -} as const; - -export default define(meta, paramDef, async (ps, user) => { - const note = await getNote(ps.noteId, user).catch((err) => { - if (err.id === "9725d0ce-ba28-4dde-95a7-2cbb2c15de24") - throw new ApiError(meta.errors.noSuchNote); - throw err; - }); - - return await Notes.pack(note, user, { - // FIXME: packing with detail may throw an error if the reply or renote is not visible (#8774) - detail: true, - }).catch((err) => { - if (err.id === "9725d0ce-ba28-4dde-95a7-2cbb2c15de24") - throw new ApiError(meta.errors.noSuchNote); - throw err; - }); -}); diff --git a/packages/backend/src/server/api/endpoints/notes/timeline.ts b/packages/backend/src/server/api/endpoints/notes/timeline.ts index 6cd50da174..6e7e6fc174 100644 --- a/packages/backend/src/server/api/endpoints/notes/timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/timeline.ts @@ -90,17 +90,6 @@ export default define(meta, paramDef, async (ps, user) => { qb.orWhere(`note.userId IN (${followingQuery.getQuery()})`); }), ) - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner") .setParameters(followingQuery.getParameters()); generateRepliesQuery(query, ps.withReplies, user); @@ -171,7 +160,7 @@ export default define(meta, paramDef, async (ps, user) => { try { while (found.length < ps.limit) { const notes = await query.take(take).skip(skip).getMany(); - found.push(...(await Notes.packMany(notes, user))); + found.push(...notes); skip += take; if (notes.length < take) break; } diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts index 5c3fc55bef..7901d33271 100644 --- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts @@ -1,10 +1,10 @@ -import { Brackets } from "typeorm"; -import { UserLists, UserListJoinings, Notes } from "@/models/index.js"; -import { activeUsersChart } from "@/services/chart/index.js"; +import {Brackets} from "typeorm"; +import {Notes, UserListJoinings, UserLists} from "@/models/index.js"; +import {activeUsersChart} from "@/services/chart/index.js"; import define from "../../define.js"; -import { ApiError } from "../../error.js"; -import { makePaginationQuery } from "../../common/make-pagination-query.js"; -import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; +import {ApiError} from "../../error.js"; +import {makePaginationQuery} from "../../common/make-pagination-query.js"; +import {generateVisibilityQuery} from "../../common/generate-visibility-query.js"; export const meta = { tags: ["notes", "lists"], @@ -80,16 +80,6 @@ export default define(meta, paramDef, async (ps, user) => { "userListJoining.userId = note.userId", ) .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner") .andWhere("userListJoining.userListId = :userListId", { userListId: list.id, }); @@ -149,25 +139,5 @@ export default define(meta, paramDef, async (ps, user) => { } }); - // We fetch more than requested because some may be filtered out, and if there's less than - // requested, the pagination stops. - const found = []; - const take = Math.floor(ps.limit * 1.5); - let skip = 0; - try { - while (found.length < ps.limit) { - const notes = await query.take(take).skip(skip).getMany(); - found.push(...(await Notes.packMany(notes, user))); - skip += take; - if (notes.length < take) break; - } - } catch (error) { - throw new ApiError(meta.errors.queryError); - } - - if (found.length > ps.limit) { - found.length = ps.limit; - } - - return found; + return await query.take(ps.limit).getMany(); }); diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts index 724cfc9af1..b86b955eb3 100644 --- a/packages/backend/src/server/api/endpoints/users/notes.ts +++ b/packages/backend/src/server/api/endpoints/users/notes.ts @@ -1,12 +1,12 @@ -import { Brackets } from "typeorm"; -import { Notes } from "@/models/index.js"; +import {Brackets} from "typeorm"; +import {Notes} from "@/models/index.js"; import define from "../../define.js"; -import { ApiError } from "../../error.js"; -import { getUser } from "../../common/getters.js"; -import { makePaginationQuery } from "../../common/make-pagination-query.js"; -import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; -import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; -import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; +import {ApiError} from "../../error.js"; +import {getUser} from "../../common/getters.js"; +import {makePaginationQuery} from "../../common/make-pagination-query.js"; +import {generateVisibilityQuery} from "../../common/generate-visibility-query.js"; +import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js"; +import {generateBlockedUserQuery} from "../../common/generate-block-query.js"; export const meta = { tags: ["users", "notes"], @@ -75,17 +75,7 @@ export default define(meta, paramDef, async (ps, me) => { ps.untilDate, ) .andWhere("note.userId = :userId", { userId: user.id }) - .innerJoinAndSelect("note.user", "user") - .leftJoinAndSelect("user.avatar", "avatar") - .leftJoinAndSelect("user.banner", "banner") - .leftJoinAndSelect("note.reply", "reply") - .leftJoinAndSelect("note.renote", "renote") - .leftJoinAndSelect("reply.user", "replyUser") - .leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") - .leftJoinAndSelect("replyUser.banner", "replyUserBanner") - .leftJoinAndSelect("renote.user", "renoteUser") - .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); + .innerJoinAndSelect("note.user", "user"); generateVisibilityQuery(query, me); if (me) { @@ -138,7 +128,5 @@ export default define(meta, paramDef, async (ps, me) => { //#endregion - const timeline = await query.take(ps.limit).getMany(); - - return await Notes.packMany(timeline, me); + return await query.take(ps.limit).getMany(); }); diff --git a/packages/backend/src/server/api/stream/channel.ts b/packages/backend/src/server/api/stream/channel.ts index f6533c9af2..d6d2299c9e 100644 --- a/packages/backend/src/server/api/stream/channel.ts +++ b/packages/backend/src/server/api/stream/channel.ts @@ -1,8 +1,4 @@ import type Connection from "."; -import type {Note} from "@/models/entities/note.js"; -import {Notes} from "@/models/index.js"; -import type {Packed} from "@/misc/schema.js"; -import {IdentifiableError} from "@/misc/identifiable-error.js"; /** * Stream channel @@ -63,34 +59,4 @@ export default abstract class Channel { public dispose?(): void; public onMessage?(type: string, body: any): void; - - protected withPackedNote( - callback: (noteMessage: { type: "note", body: Packed<"Note"> }) => void, - ): (noteMessage: { type: "note", body: Note }) => void { - return async ({body: note}) => { - try { - // because `note` was previously JSON.stringify'ed, the fields that - // were objects before are now strings and have to be restored or - // removed from the object - note.createdAt = new Date(note.createdAt); - note.reply = undefined; - note.renote = undefined; - note.user = undefined; - - const packed = await Notes.pack(note, this.user, { detail: true }); - - callback({ type: "note", body: packed }); - } catch (err) { - if ( - err instanceof IdentifiableError && - err.id === "9725d0ce-ba28-4dde-95a7-2cbb2c15de24" - ) { - // skip: note not visible to user - return; - } else { - throw err; - } - } - }; - } } diff --git a/packages/backend/src/server/api/stream/channels/antenna.ts b/packages/backend/src/server/api/stream/channels/antenna.ts index ec5a8b175f..a5d380c980 100644 --- a/packages/backend/src/server/api/stream/channels/antenna.ts +++ b/packages/backend/src/server/api/stream/channels/antenna.ts @@ -1,13 +1,12 @@ import Channel from "../channel.js"; -import { Notes } from "@/models/index.js"; -import { isUserRelated } from "@/misc/is-user-related.js"; -import type { StreamMessages } from "../types.js"; -import { IdentifiableError } from "@/misc/identifiable-error.js"; +import {isUserRelated} from "@/misc/is-user-related.js"; +import type {StreamMessages} from "../types.js"; +import {IdentifiableError} from "@/misc/identifiable-error.js"; export default class extends Channel { - public readonly chName = "antenna"; public static shouldShare = false; public static requireCredential = false; + public readonly chName = "antenna"; private antennaId: string; constructor(id: string, connection: Channel["connection"]) { @@ -22,12 +21,15 @@ export default class extends Channel { this.subscriber.on(`antennaStream:${this.antennaId}`, this.onEvent); } + public dispose() { + // Unsubscribe events + this.subscriber.off(`antennaStream:${this.antennaId}`, this.onEvent); + } + private async onEvent(data: StreamMessages["antenna"]["payload"]) { if (data.type === "note") { try { - const note = await Notes.pack(data.body.id, this.user, { - detail: true, - }); + const note = data.body; // 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する if (isUserRelated(note, this.muting)) return; @@ -37,9 +39,7 @@ export default class extends Channel { if (note.renote && !note.text && this.renoteMuting.has(note.userId)) return; - this.connection.cacheNote(note); - - this.send("note", note); + this.send("note", note.id); } catch (e) { if ( e instanceof IdentifiableError && @@ -55,9 +55,4 @@ export default class extends Channel { this.send(data.type, data.body); } } - - public dispose() { - // Unsubscribe events - this.subscriber.off(`antennaStream:${this.antennaId}`, this.onEvent); - } } 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 baca4cda16..b6b7c8d984 100644 --- a/packages/backend/src/server/api/stream/channels/global-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/global-timeline.ts @@ -3,7 +3,7 @@ import {fetchMeta} from "@/misc/fetch-meta.js"; import {getWordHardMute} from "@/misc/check-word-mute.js"; import {isInstanceMuted} from "@/misc/is-instance-muted.js"; import {isUserRelated} from "@/misc/is-user-related.js"; -import type {Packed} from "@/misc/schema.js"; +import {Note} from "@/models/entities/note"; export default class extends Channel { public static shouldShare = true; @@ -13,7 +13,7 @@ export default class extends Channel { constructor(id: string, connection: Channel["connection"]) { super(id, connection); - this.onNote = this.withPackedNote(this.onNote.bind(this)); + this.onNote = this.onNote.bind(this); } public async init(params: any) { @@ -34,7 +34,7 @@ export default class extends Channel { this.subscriber.off("notesStream", this.onNote); } - private async onNote({body: note}: { type: "note", body: Packed<"Note"> }) { + private async onNote({body: note}: { type: "note", body: Note }) { if (note.visibility !== "public") return; // 関係ない返信は除外 @@ -76,8 +76,6 @@ export default class extends Channel { ) return; - this.connection.cacheNote(note); - - this.send("note", note); + this.send("note", note.id); } } diff --git a/packages/backend/src/server/api/stream/channels/hashtag.ts b/packages/backend/src/server/api/stream/channels/hashtag.ts index 2a5e9f1b3d..2015d2df8c 100644 --- a/packages/backend/src/server/api/stream/channels/hashtag.ts +++ b/packages/backend/src/server/api/stream/channels/hashtag.ts @@ -1,7 +1,7 @@ import Channel from "../channel.js"; import {normalizeForSearch} from "@/misc/normalize-for-search.js"; import {isUserRelated} from "@/misc/is-user-related.js"; -import type {Packed} from "@/misc/schema.js"; +import {Note} from "@/models/entities/note"; export default class extends Channel { public static shouldShare = false; @@ -11,7 +11,7 @@ export default class extends Channel { constructor(id: string, connection: Channel["connection"]) { super(id, connection); - this.onNote = this.withPackedNote(this.onNote.bind(this)); + this.onNote = this.onNote.bind(this); } public async init(params: any) { @@ -28,7 +28,7 @@ export default class extends Channel { this.subscriber.off("notesStream", this.onNote); } - private async onNote({body: note}: {type: "note", body: Packed<"Note">}) { + private async onNote({body: note}: {type: "note", body: Note}) { if (note.visibility === "hidden") return; const noteTags = note.tags ? note.tags.map((t: string) => t.toLowerCase()) @@ -45,8 +45,6 @@ export default class extends Channel { if (note.renote && !note.text && this.renoteMuting.has(note.userId)) return; - this.connection.cacheNote(note); - - this.send("note", note); + this.send("note", note.id); } } 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 fe8ff8274c..e6c38971fc 100644 --- a/packages/backend/src/server/api/stream/channels/home-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/home-timeline.ts @@ -2,7 +2,7 @@ import Channel from "../channel.js"; import {getWordHardMute} from "@/misc/check-word-mute.js"; import {isUserRelated} from "@/misc/is-user-related.js"; import {isInstanceMuted} from "@/misc/is-instance-muted.js"; -import type {Packed} from "@/misc/schema.js"; +import {Note} from "@/models/entities/note"; export default class extends Channel { public static shouldShare = true; @@ -12,7 +12,7 @@ export default class extends Channel { constructor(id: string, connection: Channel["connection"]) { super(id, connection); - this.onNote = this.withPackedNote(this.onNote.bind(this)); + this.onNote = this.onNote.bind(this); } public async init(params: any) { @@ -27,7 +27,7 @@ export default class extends Channel { this.subscriber.off("notesStream", this.onNote); } - private async onNote({ body: note }: { type: "note", body: Packed<"Note"> }) { + private async onNote({ body: note }: { type: "note", body: Note }) { if (note.visibility === "hidden") return; // Filter away notes that are not authored by the user or any of the followed users @@ -73,8 +73,6 @@ export default class extends Channel { ) return; - this.connection.cacheNote(note); - - this.send("note", note); + this.send("note", note.id); } } 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 1aeb5f71fe..d3ba279ec7 100644 --- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts @@ -3,7 +3,7 @@ import {fetchMeta} from "@/misc/fetch-meta.js"; import {getWordHardMute} from "@/misc/check-word-mute.js"; import {isUserRelated} from "@/misc/is-user-related.js"; import {isInstanceMuted} from "@/misc/is-instance-muted.js"; -import type {Packed} from "@/misc/schema.js"; +import {Note} from "@/models/entities/note"; export default class extends Channel { public static shouldShare = true; @@ -13,7 +13,7 @@ export default class extends Channel { constructor(id: string, connection: Channel["connection"]) { super(id, connection); - this.onNote = this.withPackedNote(this.onNote.bind(this)); + this.onNote = this.onNote.bind(this); } public async init(params: any) { @@ -36,7 +36,7 @@ export default class extends Channel { this.subscriber.off("notesStream", this.onNote); } - private async onNote({ body: note }: { type: "note", "body": Packed<"Note"> }) { + private async onNote({ body: note }: { type: "note", "body": Note }) { if (note.visibility === "hidden") return; @@ -48,7 +48,7 @@ export default class extends Channel { !( this.user!.id === note.userId || this.following.has(note.userId) || - (note.user.host == null && note.visibility === "public") + (note.userHost == null && note.visibility === "public") ) ) return; @@ -92,8 +92,6 @@ export default class extends Channel { ) return; - this.connection.cacheNote(note); - - this.send("note", note); + this.send("note", note.id); } } 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 91472a6679..7653c3b2cc 100644 --- a/packages/backend/src/server/api/stream/channels/local-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts @@ -2,7 +2,7 @@ import Channel from "../channel.js"; import {fetchMeta} from "@/misc/fetch-meta.js"; import {getWordHardMute} from "@/misc/check-word-mute.js"; import {isUserRelated} from "@/misc/is-user-related.js"; -import type {Packed} from "@/misc/schema.js"; +import {Note} from "@/models/entities/note"; export default class extends Channel { public static shouldShare = true; @@ -12,7 +12,7 @@ export default class extends Channel { constructor(id: string, connection: Channel["connection"]) { super(id, connection); - this.onNote = this.withPackedNote(this.onNote.bind(this)); + this.onNote = this.onNote.bind(this); } public async init(params: any) { @@ -33,8 +33,8 @@ export default class extends Channel { this.subscriber.off("notesStream", this.onNote); } - private async onNote({ body: note }: { type: "note", body: Packed<"Note"> }) { - if (note.user.host !== null) return; + private async onNote({ body: note }: { type: "note", body: Note }) { + if (note.userHost !== null) return; if (note.visibility !== "public") return; // 関係ない返信は除外 @@ -67,8 +67,6 @@ export default class extends Channel { ) return; - this.connection.cacheNote(note); - - this.send("note", note); + this.send("note", note.id); } } 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 6b4e589ad4..95848bb629 100644 --- a/packages/backend/src/server/api/stream/channels/recommended-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/recommended-timeline.ts @@ -3,7 +3,7 @@ import {fetchMeta} from "@/misc/fetch-meta.js"; import {getWordHardMute} from "@/misc/check-word-mute.js"; import {isUserRelated} from "@/misc/is-user-related.js"; import {isInstanceMuted} from "@/misc/is-instance-muted.js"; -import type {Packed} from "@/misc/schema.js"; +import {Note} from "@/models/entities/note"; export default class extends Channel { public static shouldShare = true; @@ -13,7 +13,7 @@ export default class extends Channel { constructor(id: string, connection: Channel["connection"]) { super(id, connection); - this.onNote = this.withPackedNote(this.onNote.bind(this)); + this.onNote = this.onNote.bind(this); } public async init(params: any) { @@ -36,7 +36,7 @@ export default class extends Channel { this.subscriber.off("notesStream", this.onNote); } - private async onNote({ body: note }: { type: "note", body: Packed<"Note"> }) { + private async onNote({ body: note }: { type: "note", body: Note }) { if (note.visibility === "hidden") return; // チャンネルの投稿ではなく、自分自身の投稿 または // チャンネルの投稿ではなく、その投稿のユーザーをフォローしている または @@ -45,8 +45,8 @@ export default class extends Channel { const meta = await fetchMeta(); if ( !( - note.user.host != null && - meta.recommendedInstances.includes(note.user.host) && + note.userHost != null && + meta.recommendedInstances.includes(note.userHost) && note.visibility === "public" ) ) @@ -91,8 +91,6 @@ export default class extends Channel { ) return; - this.connection.cacheNote(note); - - this.send("note", note); + this.send("note", note.id); } } 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 3acfa53d94..1e92d0dd69 100644 --- a/packages/backend/src/server/api/stream/channels/user-list.ts +++ b/packages/backend/src/server/api/stream/channels/user-list.ts @@ -2,7 +2,7 @@ import Channel from "../channel.js"; import {UserListJoinings, UserLists} from "@/models/index.js"; import type {User} from "@/models/entities/user.js"; import {isUserRelated} from "@/misc/is-user-related.js"; -import type {Packed} from "@/misc/schema.js"; +import {Note} from "@/models/entities/note"; export default class extends Channel { public static shouldShare = false; @@ -15,7 +15,7 @@ export default class extends Channel { constructor(id: string, connection: Channel["connection"]) { super(id, connection); this.updateListUsers = this.updateListUsers.bind(this); - this.onNote = this.withPackedNote(this.onNote.bind(this)); + this.onNote = this.onNote.bind(this); } public async init(params: any) { @@ -56,7 +56,7 @@ export default class extends Channel { this.listUsers = users.map((x) => x.userId); } - private async onNote({ body: note }: { type: "note", body: Packed<"Note"> }) { + private async onNote({ body: note }: { type: "note", body: Note }) { if (note.visibility === "hidden") return; if (!this.listUsers.includes(note.userId)) return; @@ -67,6 +67,6 @@ export default class extends Channel { if (note.renote && !note.text && this.renoteMuting.has(note.userId)) return; - this.send("note", note); + this.send("note", note.id); } } diff --git a/packages/backend/src/server/api/stream/index.ts b/packages/backend/src/server/api/stream/index.ts index e7b0236dd3..87fa101f7a 100644 --- a/packages/backend/src/server/api/stream/index.ts +++ b/packages/backend/src/server/api/stream/index.ts @@ -4,7 +4,6 @@ import type {User} from "@/models/entities/user.js"; import {Blockings, Followings, Mutings, RenoteMutings, UserProfiles,} from "@/models/index.js"; import type {AccessToken} from "@/models/entities/access-token.js"; import type {UserProfile} from "@/models/entities/user-profile.js"; -import type {Packed} from "@/misc/schema.js"; import {readNotification} from "../common/read-notification.js"; import channels from "./channels/index.js"; import type Channel from "./channel.js"; @@ -25,7 +24,6 @@ export default class Connection { private wsConnection: websocket.connection; private channels: Channel[] = []; private subscribingNotes: Map = new Map(); - private cachedNotes: Packed<"Note">[] = []; private host: string; private accessToken: string; private currentSubscribe: string[][] = []; @@ -76,25 +74,6 @@ export default class Connection { } } - public cacheNote(note: Packed<"Note">) { - const add = (note: Packed<"Note">) => { - const existIndex = this.cachedNotes.findIndex((n) => n.id === note.id); - if (existIndex > -1) { - this.cachedNotes[existIndex] = note; - return; - } - - this.cachedNotes.unshift(note); - if (this.cachedNotes.length > 32) { - this.cachedNotes.splice(32); - } - }; - - add(note); - if (note.reply) add(note.reply); - if (note.renote) add(note.renote); - } - /** * クライアントにメッセージ送信 */ diff --git a/packages/backend/src/server/api/stream/types.ts b/packages/backend/src/server/api/stream/types.ts index b6f06a1b61..725693fca0 100644 --- a/packages/backend/src/server/api/stream/types.ts +++ b/packages/backend/src/server/api/stream/types.ts @@ -64,9 +64,9 @@ export interface UserStreamTypes { export interface MainStreamTypes { notification: Packed<"Notification">; - mention: Packed<"Note">; - reply: Packed<"Note">; - renote: Packed<"Note">; + mention: Note; + reply: Note; + renote: Note; follow: Packed<"UserDetailedNotMe">; followed: Packed<"User">; unfollow: Packed<"User">; diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 2e128295a5..92b2e5a800 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -54,6 +54,7 @@ import {getActiveWebhooks} from "@/misc/webhook-cache.js"; import {shouldSilenceInstance} from "@/misc/should-block-instance.js"; import meilisearch from "../../db/meilisearch.js"; import {redisClient} from "@/db/redis.js"; +import {getNote} from "@/server/api/common/getters.js"; const mutedWordsCache = new Cache< { userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[] @@ -466,10 +467,12 @@ export default async ( webhooks.filter((x) => x.userId === user.id && x.on.includes("note")), ); - for (const webhook of webhooks) { - webhookDeliver(webhook, "note", { - note: await Notes.pack(note, user), - }); + if (await Notes.isVisibleForMe(note, user.id)) { + for (const webhook of webhooks) { + webhookDeliver(webhook, "note", { + note, + }); + } } const nm = new NotificationManager(user, note); @@ -492,19 +495,21 @@ export default async ( if (!threadMuted) { nm.push(data.reply.userId, "reply"); - const packedReply = await Notes.pack(note, { - id: data.reply.userId, - }); - publishMainStream(data.reply.userId, "reply", packedReply); + if (data.reply.userId) { + getNote(note.id, { id: data.reply.userId }).then(async (reply) => { + publishMainStream(data.reply!.userId, "reply", reply); - const webhooks = (await getActiveWebhooks()).filter( - (x) => x.userId === data.reply!.userId && x.on.includes("reply"), - ); - for (const webhook of webhooks) { - webhookDeliver(webhook, "reply", { - note: packedReply, + const webhooks = (await getActiveWebhooks()).filter( + (x) => x.userId === data.reply!.userId && x.on.includes("reply"), + ); + for (const webhook of webhooks) { + webhookDeliver(webhook, "reply", { + note: reply, + }); + } }); } + } } } @@ -531,18 +536,18 @@ export default async ( // Publish event if (user.id !== data.renote.userId && data.renote.userHost === null) { - const packedRenote = await Notes.pack(note, { - id: data.renote.userId, - }); - publishMainStream(data.renote.userId, "renote", packedRenote); + if (data.renote.userId) { + getNote(note.id, { id: data.renote.userId }).then(async (renote) => { + publishMainStream(data.renote!.userId, "renote", renote); - const renote = data.renote; - const webhooks = (await getActiveWebhooks()).filter( - (x) => x.userId === renote.userId && x.on.includes("renote"), - ); - for (const webhook of webhooks) { - webhookDeliver(webhook, "renote", { - note: packedRenote, + const webhooks = (await getActiveWebhooks()).filter( + (x) => x.userId === renote.renoteUserId && x.on.includes("renote"), + ); + for (const webhook of webhooks) { + webhookDeliver(webhook, "renote", { + note: renote, + }); + } }); } } @@ -585,7 +590,7 @@ export default async ( } dm.execute(); - })(); + })().then(); } //#endregion } @@ -823,20 +828,19 @@ async function createMentionedEvents( // note with "specified" visibility might not be visible to mentioned users try { - const detailPackedNote = await Notes.pack(note, u, { - detail: true, - }); + await getNote(note.id, { id: u.id }).then(async (note) => { + publishMainStream(u.id, "mention", note); - publishMainStream(u.id, "mention", detailPackedNote); + const webhooks = (await getActiveWebhooks()).filter( + (x) => x.userId === u.id && x.on.includes("mention"), + ); + for (const webhook of webhooks) { + webhookDeliver(webhook, "mention", { + note, + }); + } + }) - const webhooks = (await getActiveWebhooks()).filter( - (x) => x.userId === u.id && x.on.includes("mention"), - ); - for (const webhook of webhooks) { - webhookDeliver(webhook, "mention", { - note: detailPackedNote, - }); - } } catch (err) { if (err.id === "9725d0ce-ba28-4dde-95a7-2cbb2c15de24") continue; throw err; diff --git a/packages/backend/src/services/note/read.ts b/packages/backend/src/services/note/read.ts index 0081d622c2..e516313645 100644 --- a/packages/backend/src/services/note/read.ts +++ b/packages/backend/src/services/note/read.ts @@ -6,14 +6,13 @@ import {In} from "typeorm"; 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"; /** * Mark notes as read */ export default async function ( userId: User["id"], - notes: (Note | Packed<"Note">)[], + notes: Note[], info?: { following: Set; }, @@ -32,9 +31,9 @@ export default async function ( ); const myAntennas = (await getAntennas()).filter((a) => a.userId === userId); - const readMentions: (Note | Packed<"Note">)[] = []; - const readSpecifiedNotes: (Note | Packed<"Note">)[] = []; - const readAntennaNotes: (Note | Packed<"Note">)[] = []; + const readMentions: Note[] = []; + const readSpecifiedNotes: Note[] = []; + const readAntennaNotes: Note[] = []; for (const note of notes) { if (note.mentions?.includes(userId)) { diff --git a/packages/backend/src/services/push-notification.ts b/packages/backend/src/services/push-notification.ts index 13834b8f7c..47ab2f3496 100644 --- a/packages/backend/src/services/push-notification.ts +++ b/packages/backend/src/services/push-notification.ts @@ -1,9 +1,9 @@ import push from "web-push"; import config from "@/config/index.js"; -import { SwSubscriptions } from "@/models/index.js"; -import { fetchMeta } from "@/misc/fetch-meta.js"; -import type { Packed } from "@/misc/schema.js"; -import { getNoteSummary } from "@/misc/get-note-summary.js"; +import {SwSubscriptions} from "@/models/index.js"; +import {fetchMeta} from "@/misc/fetch-meta.js"; +import type {Packed} from "@/misc/schema.js"; +import {getNoteSummary} from "@/misc/get-note-summary.js"; // Defined also packages/sw/types.ts#L14-L21 type pushNotificationsTypes = { @@ -22,7 +22,7 @@ function truncateNotification(notification: Packed<"Notification">): any { // textをgetNoteSummaryしたものに置き換える text: getNoteSummary( notification.type === "renote" - ? (notification.note.renote as Packed<"Note">) + ? (notification.note.renote) : notification.note, ), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f2dd837ced..d80832b61b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -280,8 +280,8 @@ importers: specifier: 3.4.1 version: 3.4.1 re2: - specifier: 1.19.0 - version: 1.19.0 + specifier: 1.20.9 + version: 1.20.9 redis-lock: specifier: 0.1.4 version: 0.1.4 @@ -1146,6 +1146,19 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 + /@npmcli/agent@2.2.0: + resolution: {integrity: sha512-2yThA1Es98orMkpSLVqlDZAMPK3jHJhifP2gnNUdk1754uZ8yI5c+ulCoVG+WlntQA6MzhrURMXjSd9Z7dJ2/Q==} + engines: {node: ^16.14.0 || >=18.0.0} + dependencies: + agent-base: 7.1.0 + http-proxy-agent: 7.0.0 + https-proxy-agent: 7.0.2 + lru-cache: 10.1.0 + socks-proxy-agent: 8.0.2 + transitivePeerDependencies: + - supports-color + dev: false + /@npmcli/fs@3.1.0: resolution: {integrity: sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -2069,6 +2082,11 @@ packages: /abbrev@1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + /abbrev@2.0.0: + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: false + /abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -2129,13 +2147,11 @@ packages: - supports-color dev: false - /agentkeepalive@4.3.0: - resolution: {integrity: sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==} - engines: {node: '>= 8.0.0'} + /agent-base@7.1.0: + resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} + engines: {node: '>= 14'} dependencies: debug: 4.3.4 - depd: 2.0.0 - humanize-ms: 1.2.1 transitivePeerDependencies: - supports-color dev: false @@ -2264,14 +2280,6 @@ packages: readable-stream: 3.6.2 dev: false - /are-we-there-yet@3.0.1: - resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - dev: false - /arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} @@ -2582,16 +2590,16 @@ packages: engines: {node: '>= 0.8'} dev: false - /cacache@17.1.3: - resolution: {integrity: sha512-jAdjGxmPxZh0IipMdR7fK/4sDSrHMLUV0+GvVUsjwyGNKHsh79kW/otg+GkbXwl6Uzvy9wsvHOX4nUoWldeZMg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + /cacache@18.0.1: + resolution: {integrity: sha512-g4Uf2CFZPaxtJKre6qr4zqLDOOPU7bNVhWjlNhvzc51xaTOx2noMOLhfFkTAqwtrAZAKQUuDfyjitzilpA8WsQ==} + engines: {node: ^16.14.0 || >=18.0.0} dependencies: '@npmcli/fs': 3.1.0 fs-minipass: 3.0.2 - glob: 10.2.7 - lru-cache: 7.18.3 - minipass: 5.0.0 - minipass-collect: 1.0.2 + glob: 10.3.10 + lru-cache: 10.1.0 + minipass: 7.0.4 + minipass-collect: 2.0.1 minipass-flush: 1.0.5 minipass-pipeline: 1.2.4 p-map: 4.0.0 @@ -4089,20 +4097,6 @@ packages: wide-align: 1.1.5 dev: false - /gauge@4.0.4: - resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - dev: false - /generic-pool@3.9.0: resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} engines: {node: '>= 4'} @@ -4180,16 +4174,16 @@ packages: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} dev: true - /glob@10.2.7: - resolution: {integrity: sha512-jTKehsravOJo8IJxUGfZILnkvVJM/MOfHRs8QcXolVef2zNI9Tqyy5+SeuOAZd3upViEZQLyFpQhYiHLrMUNmA==} + /glob@10.3.10: + resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} engines: {node: '>=16 || 14 >=14.17'} hasBin: true dependencies: foreground-child: 3.1.1 - jackspeak: 2.2.1 + jackspeak: 2.3.6 minimatch: 9.0.1 minipass: 5.0.0 - path-scurry: 1.9.2 + path-scurry: 1.10.1 dev: false /glob@7.2.3: @@ -4386,6 +4380,16 @@ packages: - supports-color dev: false + /http-proxy-agent@7.0.0: + resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /http2-wrapper@1.0.3: resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} engines: {node: '>=10.19.0'} @@ -4419,6 +4423,16 @@ packages: - supports-color dev: false + /https-proxy-agent@7.0.2: + resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -4429,12 +4443,6 @@ packages: engines: {node: '>=12.20.0'} dev: true - /humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - dependencies: - ms: 2.1.3 - dev: false - /humanize-number@0.0.2: resolution: {integrity: sha512-un3ZAcNQGI7RzaWGZzQDH47HETM4Wrj6z6E4TId8Yeq9w5ZKUVB1nrT2jwFheTUjEmqcgTjXDc959jum+ai1kQ==} dev: false @@ -4504,8 +4512,8 @@ packages: /ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - /install-artifact-from-github@1.3.3: - resolution: {integrity: sha512-x79SL0d8WOi1ZjXSTUqqs0GPQZ92YArJAN9O46wgU9wdH2U9ecyyhB9YGDbPe2OLV4ptmt6AZYRQZ2GydQZosQ==} + /install-artifact-from-github@1.3.5: + resolution: {integrity: sha512-gZHC7f/cJgXz7MXlHFBxPVMsvIbev1OQN1uKQYKVJDydGNm9oYf9JstbU4Atnh/eSvk41WtEovoRm+8IF686xg==} hasBin: true dev: false @@ -4709,8 +4717,13 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - /jackspeak@2.2.1: - resolution: {integrity: sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==} + /isexe@3.1.1: + resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} + engines: {node: '>=16'} + dev: false + + /jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} dependencies: '@isaacs/cliui': 8.0.2 @@ -5274,6 +5287,11 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: false + /lru-cache@10.1.0: + resolution: {integrity: sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==} + engines: {node: 14 || >=16.14} + dev: false + /lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} dependencies: @@ -5292,11 +5310,6 @@ packages: dependencies: yallist: 4.0.0 - /lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - dev: false - /lru-cache@9.1.2: resolution: {integrity: sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==} engines: {node: 14 || >=16.14} @@ -5321,24 +5334,20 @@ packages: /make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - /make-fetch-happen@11.1.1: - resolution: {integrity: sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + /make-fetch-happen@13.0.0: + resolution: {integrity: sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==} + engines: {node: ^16.14.0 || >=18.0.0} dependencies: - agentkeepalive: 4.3.0 - cacache: 17.1.3 + '@npmcli/agent': 2.2.0 + cacache: 18.0.1 http-cache-semantics: 4.1.1 - http-proxy-agent: 5.0.0 - https-proxy-agent: 5.0.1 is-lambda: 1.0.1 - lru-cache: 7.18.3 - minipass: 5.0.0 + minipass: 7.0.4 minipass-fetch: 3.0.3 minipass-flush: 1.0.5 minipass-pipeline: 1.2.4 negotiator: 0.6.3 promise-retry: 2.0.1 - socks-proxy-agent: 7.0.0 ssri: 10.0.4 transitivePeerDependencies: - supports-color @@ -5448,11 +5457,11 @@ packages: /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - /minipass-collect@1.0.2: - resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} - engines: {node: '>= 8'} + /minipass-collect@2.0.1: + resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} + engines: {node: '>=16 || 14 >=14.17'} dependencies: - minipass: 3.3.6 + minipass: 7.0.4 dev: false /minipass-fetch@3.0.3: @@ -5499,6 +5508,11 @@ packages: engines: {node: '>=8'} dev: false + /minipass@7.0.4: + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + engines: {node: '>=16 || 14 >=14.17'} + dev: false + /minizlib@2.1.2: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} @@ -5588,8 +5602,8 @@ packages: object-assign: 4.1.1 thenify-all: 1.6.0 - /nan@2.17.0: - resolution: {integrity: sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==} + /nan@2.18.0: + resolution: {integrity: sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==} dev: false /nanoid@3.3.6: @@ -5689,22 +5703,21 @@ packages: hasBin: true dev: false - /node-gyp@9.4.0: - resolution: {integrity: sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==} - engines: {node: ^12.13 || ^14.13 || >=16} + /node-gyp@10.0.1: + resolution: {integrity: sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==} + engines: {node: ^16.14.0 || >=18.0.0} hasBin: true dependencies: env-paths: 2.2.1 exponential-backoff: 3.1.1 - glob: 7.2.3 + glob: 10.3.10 graceful-fs: 4.2.11 - make-fetch-happen: 11.1.1 - nopt: 6.0.0 - npmlog: 6.0.2 - rimraf: 3.0.2 + make-fetch-happen: 13.0.0 + nopt: 7.2.0 + proc-log: 3.0.0 semver: 7.5.1 tar: 6.1.15 - which: 2.0.2 + which: 4.0.0 transitivePeerDependencies: - supports-color dev: false @@ -5736,6 +5749,14 @@ packages: dependencies: abbrev: 1.1.1 + /nopt@7.2.0: + resolution: {integrity: sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + abbrev: 2.0.0 + dev: false + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -5780,16 +5801,6 @@ packages: set-blocking: 2.0.0 dev: false - /npmlog@6.0.2: - resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dependencies: - are-we-there-yet: 3.0.1 - console-control-strings: 1.1.0 - gauge: 4.0.4 - set-blocking: 2.0.0 - dev: false - /nwsapi@2.2.5: resolution: {integrity: sha512-6xpotnECFy/og7tKSBVmUNft7J3jyXAka4XvG6AUhFWRz+Q/Ljus7znJAA3bxColfQLdS+XsjoodtJfCgeTEFQ==} dev: false @@ -6011,8 +6022,8 @@ packages: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: false - /path-scurry@1.9.2: - resolution: {integrity: sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==} + /path-scurry@1.10.1: + resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} engines: {node: '>=16 || 14 >=14.17'} dependencies: lru-cache: 9.1.2 @@ -6214,6 +6225,11 @@ packages: - supports-color dev: false + /proc-log@3.0.0: + resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: false + /process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: false @@ -6363,13 +6379,13 @@ packages: setimmediate: 1.0.5 dev: false - /re2@1.19.0: - resolution: {integrity: sha512-y0LcLZgBF3L7mDtNfbghb7dCmChYQO2QsUGklNueAJUH+HAZO8UZUubgNsf6OxRTAQpeE4KMPR7vcpK3+Q+GiA==} + /re2@1.20.9: + resolution: {integrity: sha512-ZYcPTFr5ha2xq3WQjBDTF9CWPSDK1z28MLh5UFRxc//7X8BNQ3A7yR7ITnP0jO346661ertdKVFqw1qoL3FMEQ==} requiresBuild: true dependencies: - install-artifact-from-github: 1.3.3 - nan: 2.17.0 - node-gyp: 9.4.0 + install-artifact-from-github: 1.3.5 + nan: 2.18.0 + node-gyp: 10.0.1 transitivePeerDependencies: - supports-color dev: false @@ -6764,11 +6780,11 @@ packages: engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} dev: false - /socks-proxy-agent@7.0.0: - resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} - engines: {node: '>= 10'} + /socks-proxy-agent@8.0.2: + resolution: {integrity: sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==} + engines: {node: '>= 14'} dependencies: - agent-base: 6.0.2 + agent-base: 7.1.0 debug: 4.3.4 socks: 2.7.1 transitivePeerDependencies: @@ -7787,6 +7803,14 @@ packages: dependencies: isexe: 2.0.0 + /which@4.0.0: + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + isexe: 3.1.1 + dev: false + /wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} dependencies: