Removed out all note packing
ci/woodpecker/tag/ociImageTag Pipeline was successful Details

This commit is contained in:
Natty 2023-12-28 00:31:05 +01:00
parent f4d03a4f48
commit c443079db0
Signed by: natty
GPG Key ID: BF6CB659ADEE60EC
55 changed files with 427 additions and 1391 deletions

View File

@ -92,7 +92,7 @@
"qs": "6.11.2", "qs": "6.11.2",
"random-seed": "0.3.0", "random-seed": "0.3.0",
"ratelimiter": "3.4.1", "ratelimiter": "3.4.1",
"re2": "1.19.0", "re2": "1.20.9",
"redis-lock": "0.1.4", "redis-lock": "0.1.4",
"reflect-metadata": "0.1.13", "reflect-metadata": "0.1.13",
"rename": "1.0.4", "rename": "1.0.4",

View File

@ -1,15 +1,10 @@
import type { Antenna } from "@/models/entities/antenna.js"; import type {Antenna} from "@/models/entities/antenna.js";
import type { Note } from "@/models/entities/note.js"; import type {Note} from "@/models/entities/note.js";
import type { User } from "@/models/entities/user.js"; import type {User} from "@/models/entities/user.js";
import { import {Blockings, UserGroupJoinings, UserListJoinings,} from "@/models/index.js";
UserListJoinings, import {getFullApAccount} from "./convert-host.js";
UserGroupJoinings,
Blockings,
} from "@/models/index.js";
import { getFullApAccount } from "./convert-host.js";
import * as Acct from "@/misc/acct.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<User["id"][]>(1000 * 60 * 5); const blockingCache = new Cache<User["id"][]>(1000 * 60 * 5);
@ -20,7 +15,7 @@ const blockingCache = new Cache<User["id"][]>(1000 * 60 * 5);
*/ */
export async function checkHitAntenna( export async function checkHitAntenna(
antenna: Antenna, antenna: Antenna,
note: Note | Packed<"Note">, note: Note,
noteUser: { id: User["id"]; username: string; host: string | null }, noteUser: { id: User["id"]; username: string; host: string | null },
noteUserFollowers?: User["id"][], noteUserFollowers?: User["id"][],
antennaUserFollowing?: User["id"][], antennaUserFollowing?: User["id"][],

View File

@ -29,4 +29,4 @@ export function genId(date?: Date): string {
const cuid = createId(); const cuid = createId();
return `${time36}${cuid}`; return `${time36}${cuid}`;
} }

View File

@ -1,14 +1,10 @@
import type { Packed } from "./schema.js"; import {Note} from "@/models/entities/note";
/** /**
* 稿 * 稿
* @param {*} note (packされた)稿 * @param {*} note (packされた)稿
*/ */
export const getNoteSummary = (note: Packed<"Note">): string => { export const getNoteSummary = (note: Note): string => {
if (note.deletedAt) {
return "❌";
}
let summary = ""; let summary = "";
// 本文 // 本文
@ -19,13 +15,13 @@ export const getNoteSummary = (note: Packed<"Note">): string => {
} }
// ファイルが添付されているとき // ファイルが添付されているとき
if ((note.files || []).length !== 0) { if ((note.fileIds || []).length !== 0) {
const len = note.files?.length; const len = note.fileIds?.length;
summary += ` 📎${len !== 1 ? ` (${len})` : ""}`; summary += ` 📎${len !== 1 ? ` (${len})` : ""}`;
} }
// 投票が添付されているとき // 投票が添付されているとき
if (note.poll) { if (note.fileIds) {
summary += " 📊"; summary += " 📊";
} }

View File

@ -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( export function isInstanceMuted(
note: Packed<"Note">, note: Note,
mutedInstances: Set<string>, mutedInstances: Set<string>,
): boolean { ): boolean {
if (mutedInstances.has(note?.user?.host ?? "")) return true; if (mutedInstances.has(note?.user?.host ?? "")) return true;

View File

@ -1,4 +1,6 @@
export function isUserRelated(note: any, ids: Set<string>): boolean { import {Note} from "@/models/entities/note";
export function isUserRelated(note: Note, ids: Set<string>): boolean {
if (ids.has(note.userId)) return true; // note author is muted 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.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 if (note.reply && isUserRelated(note.reply, ids)) return true; // also check reply target

View File

@ -7,7 +7,6 @@ import {
packedUserLiteSchema, packedUserLiteSchema,
packedUserSchema, packedUserSchema,
} from "@/models/schema/user.js"; } from "@/models/schema/user.js";
import {packedNoteSchema} from "@/models/schema/note.js";
import {packedUserListSchema} from "@/models/schema/user-list.js"; import {packedUserListSchema} from "@/models/schema/user-list.js";
import {packedAppSchema} from "@/models/schema/app.js"; import {packedAppSchema} from "@/models/schema/app.js";
import {packedNotificationSchema} from "@/models/schema/notification.js"; import {packedNotificationSchema} from "@/models/schema/notification.js";
@ -42,7 +41,6 @@ export const refs = {
UserList: packedUserListSchema, UserList: packedUserListSchema,
UserGroup: packedUserGroupSchema, UserGroup: packedUserGroupSchema,
App: packedAppSchema, App: packedAppSchema,
Note: packedNoteSchema,
NoteEdit: packedNoteEdit, NoteEdit: packedNoteEdit,
NoteReaction: packedNoteReactionSchema, NoteReaction: packedNoteReactionSchema,
NoteFavorite: packedNoteFavoriteSchema, NoteFavorite: packedNoteFavoriteSchema,

View File

@ -1,7 +1,7 @@
import { db } from "@/db/postgre.js"; import {db} from "@/db/postgre.js";
import { NoteFavorite } from "@/models/entities/note-favorite.js"; import {NoteFavorite} from "@/models/entities/note-favorite.js";
import { Notes } from "../index.js"; import type {User} from "@/models/entities/user.js";
import type { User } from "@/models/entities/user.js"; import {getNote} from "@/server/api/common/getters.js";
export const NoteFavoriteRepository = db.getRepository(NoteFavorite).extend({ export const NoteFavoriteRepository = db.getRepository(NoteFavorite).extend({
async pack( async pack(
@ -16,7 +16,7 @@ export const NoteFavoriteRepository = db.getRepository(NoteFavorite).extend({
createdAt: favorite.createdAt.toISOString(), createdAt: favorite.createdAt.toISOString(),
noteId: favorite.noteId, noteId: favorite.noteId,
// may throw error // may throw error
note: await Notes.pack(favorite.note || favorite.noteId, me), note: await getNote(favorite.noteId, me ?? null),
}; };
}, },

View File

@ -1,9 +1,10 @@
import { db } from "@/db/postgre.js"; import {db} from "@/db/postgre.js";
import { NoteReaction } from "@/models/entities/note-reaction.js"; import {NoteReaction} from "@/models/entities/note-reaction.js";
import { Notes, Users } from "../index.js"; import {Users} from "../index.js";
import type { Packed } from "@/misc/schema.js"; import type {Packed} from "@/misc/schema.js";
import { convertLegacyReaction } from "@/misc/reaction-lib.js"; import {convertLegacyReaction} from "@/misc/reaction-lib.js";
import type { User } from "@/models/entities/user.js"; import type {User} from "@/models/entities/user.js";
import {getNote} from "@/server/api/common/getters.js";
export const NoteReactionRepository = db.getRepository(NoteReaction).extend({ export const NoteReactionRepository = db.getRepository(NoteReaction).extend({
async pack( async pack(
@ -31,7 +32,7 @@ export const NoteReactionRepository = db.getRepository(NoteReaction).extend({
...(opts.withNote ...(opts.withNote
? { ? {
// may throw error // 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[], src: NoteReaction[],
me?: { id: User["id"] } | null | undefined, me?: { id: User["id"] } | null | undefined,
options?: { options?: {
withNote: booleam; withNote: boolean;
}, },
): Promise<Packed<"NoteReaction">[]> { ): Promise<Packed<"NoteReaction">[]> {
const reactions = await Promise.allSettled( const reactions = await Promise.allSettled(

View File

@ -1,16 +1,9 @@
import {In} from "typeorm";
import * as mfm from "mfm-js";
import {Note} from "@/models/entities/note.js"; import {Note} from "@/models/entities/note.js";
import type {User} from "@/models/entities/user.js"; import type {User} from "@/models/entities/user.js";
import {DriveFiles, Followings, NoteReactions, Notes, Polls, PollVotes, Users,} from "../index.js"; import {Followings, NoteReactions, Polls, PollVotes, Users,} from "../index.js";
import type {Packed} from "@/misc/schema.js"; import {convertLegacyReaction,} from "@/misc/reaction-lib.js";
import {nyaize} from "@/misc/nyaize.js";
import {awaitAll} from "@/prelude/await-all.js";
import {convertLegacyReaction, convertLegacyReactions, decodeReaction,} from "@/misc/reaction-lib.js";
import type {NoteReaction} from "@/models/entities/note-reaction.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 {db} from "@/db/postgre.js";
import {IdentifiableError} from "@/misc/identifiable-error.js";
export async function populatePoll(note: Note, meId: User["id"] | null) { export async function populatePoll(note: Note, meId: User["id"] | null) {
const poll = await Polls.findOneByOrFail({ noteId: note.id }); const poll = await Polls.findOneByOrFail({ noteId: note.id });
@ -132,179 +125,4 @@ export const NoteRepository = db.getRepository(Note).extend({
return true; return true;
}, },
async pack(
src: Note["id"] | Note,
me?: { id: User["id"] } | null | undefined,
options?: {
detail?: boolean;
_hint_?: {
myReactions: Map<Note["id"], NoteReaction | null>;
};
},
): Promise<Packed<"Note">> {
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<Note["id"], NoteReaction | null>();
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] : [],
);
},
}); });

View File

@ -1,20 +1,14 @@
import { In, Repository } from "typeorm"; import {In} from "typeorm";
import { Notification } from "@/models/entities/notification.js"; import {Notification} from "@/models/entities/notification.js";
import { awaitAll } from "@/prelude/await-all.js"; import {awaitAll} from "@/prelude/await-all.js";
import type { Packed } from "@/misc/schema.js"; import type {Packed} from "@/misc/schema.js";
import type { Note } from "@/models/entities/note.js"; import type {Note} from "@/models/entities/note.js";
import type { NoteReaction } from "@/models/entities/note-reaction.js"; import type {NoteReaction} from "@/models/entities/note-reaction.js";
import type { User } from "@/models/entities/user.js"; import type {User} from "@/models/entities/user.js";
import { aggregateNoteEmojis, prefetchEmojis } from "@/misc/populate-emojis.js"; import {aggregateNoteEmojis, prefetchEmojis} from "@/misc/populate-emojis.js";
import { notificationTypes } from "@/types.js"; import {db} from "@/db/postgre.js";
import { db } from "@/db/postgre.js"; import {AccessTokens, NoteReactions, UserGroupInvitations, Users,} from "../index.js";
import { import {getNote} from "@/server/api/common/getters.js";
Users,
Notes,
UserGroupInvitations,
AccessTokens,
NoteReactions,
} from "../index.js";
export const NotificationRepository = db.getRepository(Notification).extend({ export const NotificationRepository = db.getRepository(Notification).extend({
async pack( async pack(
@ -44,88 +38,42 @@ export const NotificationRepository = db.getRepository(Notification).extend({
: null, : null,
...(notification.type === "mention" ...(notification.type === "mention"
? { ? {
note: Notes.pack( note: getNote(notification.noteId!, { id: notification.notifieeId }),
notification.note || notification.noteId!,
{ id: notification.notifieeId },
{
detail: true,
_hint_: options._hintForEachNotes_,
},
),
} }
: {}), : {}),
...(notification.type === "reply" ...(notification.type === "reply"
? { ? {
note: Notes.pack( note: getNote(notification.noteId!, { id: notification.notifieeId }),
notification.note || notification.noteId!,
{ id: notification.notifieeId },
{
detail: true,
_hint_: options._hintForEachNotes_,
},
),
} }
: {}), : {}),
...(notification.type === "renote" ...(notification.type === "renote"
? { ? {
note: Notes.pack( note: getNote(notification.noteId!, { id: notification.notifierId }).then(async (n) => {
notification.note || notification.noteId!, n.renote = await getNote(n.renoteId!, { id: notification.notifieeId });
{ id: notification.notifieeId }, return n;
{ }),
detail: true,
_hint_: options._hintForEachNotes_,
},
),
} }
: {}), : {}),
...(notification.type === "quote" ...(notification.type === "quote"
? { ? {
note: Notes.pack( note: getNote(notification.noteId!, { id: notification.notifieeId }),
notification.note || notification.noteId!,
{ id: notification.notifieeId },
{
detail: true,
_hint_: options._hintForEachNotes_,
},
),
} }
: {}), : {}),
...(notification.type === "reaction" ...(notification.type === "reaction"
? { ? {
note: Notes.pack( note: getNote(notification.noteId!, { id: notification.notifieeId }),
notification.note || notification.noteId!,
{ id: notification.notifieeId },
{
detail: true,
_hint_: options._hintForEachNotes_,
},
),
reaction: notification.reaction, reaction: notification.reaction,
} }
: {}), : {}),
...(notification.type === "pollVote" ...(notification.type === "pollVote"
? { ? {
note: Notes.pack( note: getNote(notification.noteId!, { id: notification.notifieeId }),
notification.note || notification.noteId!,
{ id: notification.notifieeId },
{
detail: true,
_hint_: options._hintForEachNotes_,
},
),
choice: notification.choice, choice: notification.choice,
} }
: {}), : {}),
...(notification.type === "pollEnded" ...(notification.type === "pollEnded"
? { ? {
note: Notes.pack( note: getNote(notification.noteId!, { id: notification.notifieeId }),
notification.note || notification.noteId!,
{ id: notification.notifieeId },
{
detail: true,
_hint_: options._hintForEachNotes_,
},
),
} }
: {}), : {}),
...(notification.type === "groupInvited" ...(notification.type === "groupInvited"

View File

@ -25,7 +25,6 @@ import {
FollowRequests, FollowRequests,
Instances, Instances,
Mutings, Mutings,
Notes,
NoteUnreads, NoteUnreads,
Notifications, Notifications,
Pages, Pages,
@ -276,22 +275,6 @@ export const UserRepository = db.getRepository(User).extend({
: "offline"; : "offline";
}, },
async getAvatarUrl(user: User): Promise<string> {
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 { getAvatarUrlSync(user: User): string {
if (user.avatar) { if (user.avatar) {
return ( return (
@ -330,17 +313,9 @@ export const UserRepository = db.getRepository(User).extend({
if (typeof src === "object") { if (typeof src === "object") {
user = src; 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 { } else {
user = await this.findOneOrFail({ user = await this.findOneOrFail({
where: { id: src }, where: { id: src }
relations: {
avatar: true,
banner: true,
},
}); });
} }
@ -391,9 +366,6 @@ export const UserRepository = db.getRepository(User).extend({
name: user.name, name: user.name,
username: user.username, username: user.username,
host: user.host, host: user.host,
avatarUrl: this.getAvatarUrlSync(user),
avatarBlurhash: user.avatar?.blurhash || null,
avatarColor: null, // 後方互換性のため
isAdmin: user.isAdmin || falsy, isAdmin: user.isAdmin || falsy,
isModerator: user.isModerator || falsy, isModerator: user.isModerator || falsy,
isBot: user.isBot || falsy, isBot: user.isBot || falsy,
@ -436,11 +408,6 @@ export const UserRepository = db.getRepository(User).extend({
lastFetchedAt: user.lastFetchedAt lastFetchedAt: user.lastFetchedAt
? user.lastFetchedAt.toISOString() ? user.lastFetchedAt.toISOString()
: null, : null,
bannerUrl: user.banner
? DriveFiles.getPublicUrl(user.banner, false)
: null,
bannerBlurhash: user.banner?.blurhash || null,
bannerColor: null, // 後方互換性のため
isLocked: user.isLocked, isLocked: user.isLocked,
isSilenced: user.isSilenced || falsy, isSilenced: user.isSilenced || falsy,
isSuspended: user.isSuspended || falsy, isSuspended: user.isSuspended || falsy,
@ -453,13 +420,6 @@ export const UserRepository = db.getRepository(User).extend({
followingCount: followingCount || 0, followingCount: followingCount || 0,
notesCount: user.notesCount, notesCount: user.notesCount,
pinnedNoteIds: pins.map((pin) => pin.noteId), pinnedNoteIds: pins.map((pin) => pin.noteId),
pinnedNotes: Notes.packMany(
pins.map((pin) => pin.note!),
me,
{
detail: true,
},
),
pinnedPageId: profile!.pinnedPageId, pinnedPageId: profile!.pinnedPageId,
pinnedPage: profile!.pinnedPageId pinnedPage: profile!.pinnedPageId
? Pages.pack(profile!.pinnedPageId, me) ? Pages.pack(profile!.pinnedPageId, me)

View File

@ -27,23 +27,6 @@ export const packedUserLiteSchema = {
example: "misskey.example.com", example: "misskey.example.com",
description: "The local host is represented with `null`.", 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: { isAdmin: {
type: "boolean", type: "boolean",
nullable: false, nullable: false,
@ -149,23 +132,6 @@ export const packedUserDetailedNotMeOnlySchema = {
optional: false, optional: false,
format: "date-time", 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: { isLocked: {
type: "boolean", type: "boolean",
nullable: false, nullable: false,
@ -254,17 +220,6 @@ export const packedUserDetailedNotMeOnlySchema = {
format: "id", format: "id",
}, },
}, },
pinnedNotes: {
type: "array",
nullable: false,
optional: false,
items: {
type: "object",
nullable: false,
optional: false,
ref: "Note",
},
},
pinnedPageId: { pinnedPageId: {
type: "string", type: "string",
nullable: true, nullable: true,

View File

@ -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_delete from "./endpoints/renote-mute/delete.js";
import * as ep___renote_mute_list from "./endpoints/renote-mute/list.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___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_children from "./endpoints/notes/children.js";
import * as ep___notes_clips from "./endpoints/notes/clips.js"; import * as ep___notes_clips from "./endpoints/notes/clips.js";
import * as ep___notes_conversation from "./endpoints/notes/conversation.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_localTimeline from "./endpoints/notes/local-timeline.js";
import * as ep___notes_recommendedTimeline from "./endpoints/notes/recommended-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_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_polls_vote from "./endpoints/notes/polls/vote.js";
import * as ep___notes_reactions from "./endpoints/notes/reactions.js"; import * as ep___notes_reactions from "./endpoints/notes/reactions.js";
import * as ep___notes_reactions_create from "./endpoints/notes/reactions/create.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_replies from "./endpoints/notes/replies.js";
import * as ep___notes_searchByTag from "./endpoints/notes/search-by-tag.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_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_state from "./endpoints/notes/state.js";
import * as ep___notes_threadMuting_create from "./endpoints/notes/thread-muting/create.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"; 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/delete", ep___mute_delete],
["mute/list", ep___mute_list], ["mute/list", ep___mute_list],
["my/apps", ep___my_apps], ["my/apps", ep___my_apps],
["notes", ep___notes],
["notes/children", ep___notes_children], ["notes/children", ep___notes_children],
["notes/clips", ep___notes_clips], ["notes/clips", ep___notes_clips],
["notes/conversation", ep___notes_conversation], ["notes/conversation", ep___notes_conversation],
@ -570,7 +566,6 @@ const eps = [
["notes/local-timeline", ep___notes_localTimeline], ["notes/local-timeline", ep___notes_localTimeline],
["notes/recommended-timeline", ep___notes_recommendedTimeline], ["notes/recommended-timeline", ep___notes_recommendedTimeline],
["notes/mentions", ep___notes_mentions], ["notes/mentions", ep___notes_mentions],
["notes/polls/recommendation", ep___notes_polls_recommendation],
["notes/polls/vote", ep___notes_polls_vote], ["notes/polls/vote", ep___notes_polls_vote],
["notes/reactions", ep___notes_reactions], ["notes/reactions", ep___notes_reactions],
["notes/reactions/create", ep___notes_reactions_create], ["notes/reactions/create", ep___notes_reactions_create],
@ -579,7 +574,6 @@ const eps = [
["notes/replies", ep___notes_replies], ["notes/replies", ep___notes_replies],
["notes/search-by-tag", ep___notes_searchByTag], ["notes/search-by-tag", ep___notes_searchByTag],
["notes/search", ep___notes_search], ["notes/search", ep___notes_search],
["notes/show", ep___notes_show],
["notes/state", ep___notes_state], ["notes/state", ep___notes_state],
["notes/thread-muting/create", ep___notes_threadMuting_create], ["notes/thread-muting/create", ep___notes_threadMuting_create],
["notes/thread-muting/delete", ep___notes_threadMuting_delete], ["notes/thread-muting/delete", ep___notes_threadMuting_delete],

View File

@ -1,11 +1,11 @@
import define from "../../define.js"; import define from "../../define.js";
import readNote from "@/services/note/read.js"; import readNote from "@/services/note/read.js";
import { Antennas, Notes, AntennaNotes } from "@/models/index.js"; import {AntennaNotes, Antennas, Notes} from "@/models/index.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js"; import {makePaginationQuery} from "../../common/make-pagination-query.js";
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
import { ApiError } from "../../error.js"; import {ApiError} from "../../error.js";
import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
export const meta = { export const meta = {
tags: ["antennas", "account", "notes"], tags: ["antennas", "account", "notes"],
@ -70,17 +70,6 @@ export default define(meta, paramDef, async (ps, user) => {
"antennaNote", "antennaNote",
"antennaNote.noteId = note.id", "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("antennaNote.antennaId = :antennaId", { antennaId: antenna.id })
.andWhere("note.visibility != 'home'"); .andWhere("note.visibility != 'home'");
@ -94,5 +83,5 @@ export default define(meta, paramDef, async (ps, user) => {
readNote(user.id, notes); readNote(user.id, notes);
} }
return await Notes.packMany(notes, user); return notes;
}); });

View File

@ -1,20 +1,20 @@
import define from "../../define.js"; import define from "../../define.js";
import { createPerson } from "@/remote/activitypub/models/person.js"; import {createPerson} from "@/remote/activitypub/models/person.js";
import { createNote } from "@/remote/activitypub/models/note.js"; import {createNote} from "@/remote/activitypub/models/note.js";
import DbResolver from "@/remote/activitypub/db-resolver.js"; import DbResolver from "@/remote/activitypub/db-resolver.js";
import Resolver from "@/remote/activitypub/resolver.js"; import Resolver from "@/remote/activitypub/resolver.js";
import { ApiError } from "../../error.js"; import {ApiError} from "../../error.js";
import { extractDbHost } from "@/misc/convert-host.js"; import {extractDbHost} from "@/misc/convert-host.js";
import { Users, Notes } from "@/models/index.js"; import {Notes, Users} from "@/models/index.js";
import type { Note } from "@/models/entities/note.js"; import type {Note} from "@/models/entities/note.js";
import type { CacheableLocalUser, User } from "@/models/entities/user.js"; import type {CacheableLocalUser, User} from "@/models/entities/user.js";
import { isActor, isPost, getApId } from "@/remote/activitypub/type.js"; import {getApId, isActor, isPost} from "@/remote/activitypub/type.js";
import type { SchemaType } from "@/misc/schema.js"; import type {SchemaType} from "@/misc/schema.js";
import { HOUR } from "@/const.js"; import {HOUR} from "@/const.js";
import { shouldBlockInstance } from "@/misc/should-block-instance.js"; import {shouldBlockInstance} from "@/misc/should-block-instance.js";
import { updateQuestion } from "@/remote/activitypub/models/question.js"; import {updateQuestion} from "@/remote/activitypub/models/question.js";
import { populatePoll } from "@/models/repositories/note.js"; import {populatePoll} from "@/models/repositories/note.js";
import { redisClient } from "@/db/redis.js"; import {redisClient} from "@/db/redis.js";
export const meta = { export const meta = {
tags: ["federation"], tags: ["federation"],
@ -161,11 +161,12 @@ async function mergePack(
}; };
} else if (note != null) { } else if (note != null) {
try { try {
const object = await Notes.pack(note, me, { detail: true }); if (!await Notes.isVisibleForMe(note, me?.id ?? null))
return null;
return { return {
type: "Note", type: "Note",
object, note,
}; };
} catch (e) { } catch (e) {
return null; return null;

View File

@ -1,10 +1,10 @@
import define from "../../define.js"; import define from "../../define.js";
import { ClipNotes, Clips, Notes } from "@/models/index.js"; import {ClipNotes, Clips, Notes} from "@/models/index.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js"; import {makePaginationQuery} from "../../common/make-pagination-query.js";
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
import { ApiError } from "../../error.js"; import {ApiError} from "../../error.js";
import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
export const meta = { export const meta = {
tags: ["account", "notes", "clips"], tags: ["account", "notes", "clips"],
@ -69,26 +69,11 @@ export default define(meta, paramDef, async (ps, user) => {
"clipNote", "clipNote",
"clipNote.noteId = note.id", "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 }); .andWhere("clipNote.clipId = :clipId", { clipId: clip.id });
if (user) { generateVisibilityQuery(query, user);
generateVisibilityQuery(query, user); generateMutedUserQuery(query, user);
generateMutedUserQuery(query, user); generateBlockedUserQuery(query, user);
generateBlockedUserQuery(query, user);
}
const notes = await query.take(ps.limit).getMany(); return await query.take(ps.limit).getMany();
return await Notes.packMany(notes, user);
}); });

View File

@ -1,6 +1,7 @@
import define from "../../../define.js"; import define from "../../../define.js";
import { ApiError } from "../../../error.js"; import {ApiError} from "../../../error.js";
import { DriveFiles, Notes } from "@/models/index.js"; import {DriveFiles, Notes} from "@/models/index.js";
import {generateVisibilityQuery} from "@/server/api/common/generate-visibility-query.js";
export const meta = { export const meta = {
tags: ["drive", "notes"], tags: ["drive", "notes"],
@ -51,11 +52,10 @@ export default define(meta, paramDef, async (ps, user) => {
throw new ApiError(meta.errors.noSuchFile); throw new ApiError(meta.errors.noSuchFile);
} }
const notes = await Notes.createQueryBuilder("note") const notes = Notes.createQueryBuilder("note")
.where(":file = ANY(note.fileIds)", { file: file.id }) .where(":file = ANY(note.fileIds)", { file: file.id });
.getMany();
return await Notes.packMany(notes, user, { generateVisibilityQuery(notes, user);
detail: true,
}); return await notes.getMany();
}); });

View File

@ -1,16 +1,10 @@
import { Brackets } from "typeorm"; import {Brackets} from "typeorm";
import { import {Followings, Mutings, Notifications, UserProfiles, Users,} from "@/models/index.js";
Notifications, import {notificationTypes} from "@/types.js";
Followings,
Mutings,
Users,
UserProfiles,
} from "@/models/index.js";
import { notificationTypes } from "@/types.js";
import read from "@/services/note/read.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 define from "../../define.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js"; import {makePaginationQuery} from "../../common/make-pagination-query.js";
export const meta = { export const meta = {
tags: ["account", "notifications"], tags: ["account", "notifications"],
@ -97,19 +91,11 @@ export default define(meta, paramDef, async (ps, user) => {
.andWhere("notification.notifieeId = :meId", { meId: user.id }) .andWhere("notification.notifieeId = :meId", { meId: user.id })
.leftJoinAndSelect("notification.notifier", "notifier") .leftJoinAndSelect("notification.notifier", "notifier")
.leftJoinAndSelect("notification.note", "note") .leftJoinAndSelect("notification.note", "note")
.leftJoinAndSelect("notifier.avatar", "notifierAvatar")
.leftJoinAndSelect("notifier.banner", "notifierBanner")
.leftJoinAndSelect("note.user", "user") .leftJoinAndSelect("note.user", "user")
.leftJoinAndSelect("user.avatar", "avatar")
.leftJoinAndSelect("user.banner", "banner")
.leftJoinAndSelect("note.reply", "reply") .leftJoinAndSelect("note.reply", "reply")
.leftJoinAndSelect("note.renote", "renote") .leftJoinAndSelect("note.renote", "renote")
.leftJoinAndSelect("reply.user", "replyUser") .leftJoinAndSelect("reply.user", "replyUser")
.leftJoinAndSelect("replyUser.avatar", "replyUserAvatar") .leftJoinAndSelect("renote.user", "renoteUser");
.leftJoinAndSelect("replyUser.banner", "replyUserBanner")
.leftJoinAndSelect("renote.user", "renoteUser")
.leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar")
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner");
// muted users // muted users
query.andWhere( query.andWhere(

View File

@ -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);
});

View File

@ -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 define from "../../define.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js"; import {makePaginationQuery} from "../../common/make-pagination-query.js";
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
export const meta = { export const meta = {
tags: ["notes"], 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))", "note.id IN (SELECT id FROM note_replies(:noteId, :depth, :limit))",
{ noteId: ps.noteId, depth: ps.depth, limit: ps.limit }, { noteId: ps.noteId, depth: ps.depth, limit: ps.limit },
) )
.innerJoinAndSelect("note.user", "user") .innerJoinAndSelect("note.user", "user");
.leftJoinAndSelect("user.avatar", "avatar")
.leftJoinAndSelect("user.banner", "banner");
generateVisibilityQuery(query, user); generateVisibilityQuery(query, user);
if (user) { if (user) {
@ -56,7 +53,5 @@ export default define(meta, paramDef, async (ps, user) => {
generateBlockedUserQuery(query, user); generateBlockedUserQuery(query, user);
} }
const notes = await query.getMany(); return await query.getMany();
return await Notes.packMany(notes, user, { detail: false });
}); });

View File

@ -1,8 +1,7 @@
import type { Note } from "@/models/entities/note.js"; import type {Note} from "@/models/entities/note.js";
import { Notes } from "@/models/index.js";
import define from "../../define.js"; import define from "../../define.js";
import { ApiError } from "../../error.js"; import {ApiError} from "../../error.js";
import { getNote } from "../../common/getters.js"; import {getNote} from "../../common/getters.js";
export const meta = { export const meta = {
tags: ["notes"], tags: ["notes"],
@ -77,5 +76,5 @@ export default define(meta, paramDef, async (ps, user) => {
await get(note.replyId); await get(note.replyId);
} }
return await Notes.packMany(conversation, user); return conversation;
}); });

View File

@ -1,7 +1,7 @@
import {In} from "typeorm"; import {In} from "typeorm";
import create from "@/services/note/create.js"; import create from "@/services/note/create.js";
import type {User} from "@/models/entities/user.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 {DriveFile} from "@/models/entities/drive-file.js";
import type {Note} from "@/models/entities/note.js"; import type {Note} from "@/models/entities/note.js";
import {HOUR, MAX_NOTE_TEXT_LENGTH} from "@/const.js"; import {HOUR, MAX_NOTE_TEXT_LENGTH} from "@/const.js";
@ -284,6 +284,6 @@ export default define(meta, paramDef, async (ps, user) => {
}); });
return { return {
createdNote: await Notes.pack(note, user), createdNote: note,
}; };
}); });

View File

@ -624,11 +624,11 @@ export default define(meta, paramDef, async (ps, user) => {
// GO! // GO!
dm.execute(); dm.execute();
})(); })().then();
} }
return { return {
createdNote: await Notes.pack(note, user), createdNote: note,
}; };
}); });

View File

@ -1,7 +1,7 @@
import { Notes } from "@/models/index.js"; import {Notes} from "@/models/index.js";
import define from "../../define.js"; import define from "../../define.js";
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
export const meta = { export const meta = {
tags: ["notes"], tags: ["notes"],
@ -45,18 +45,7 @@ export default define(meta, paramDef, async (ps, user) => {
.addSelect("note.score") .addSelect("note.score")
.andWhere("note.score > 0") .andWhere("note.score > 0")
.andWhere("note.createdAt > :date", { date: new Date(Date.now() - day) }) .andWhere("note.createdAt > :date", { date: new Date(Date.now() - day) })
.andWhere("note.visibility = 'public'") .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");
switch (ps.origin) { switch (ps.origin) {
case "local": case "local":
@ -78,5 +67,5 @@ export default define(meta, paramDef, async (ps, user) => {
notes = notes.slice(ps.offset, ps.offset + ps.limit); notes = notes.slice(ps.offset, ps.offset + ps.limit);
return await Notes.packMany(notes, user); return notes;
}); });

View File

@ -78,18 +78,7 @@ export default define(meta, paramDef, async (ps, user) => {
ps.sinceDate, ps.sinceDate,
ps.untilDate, ps.untilDate,
) )
.andWhere("note.visibility = 'public'") .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");
generateRepliesQuery(query, ps.withReplies, user); generateRepliesQuery(query, ps.withReplies, user);
if (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 return await query.take(ps.limit).getMany();
// 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;
}); });

View File

@ -94,17 +94,6 @@ export default define(meta, paramDef, async (ps, user) => {
).orWhere("(note.visibility = 'public') AND (note.userHost IS NULL)"); ).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()); .setParameters(followingQuery.getParameters());
generateRepliesQuery(query, ps.withReplies, user); generateRepliesQuery(query, ps.withReplies, user);
@ -167,25 +156,5 @@ export default define(meta, paramDef, async (ps, user) => {
activeUsersChart.read(user); activeUsersChart.read(user);
}); });
// We fetch more than requested because some may be filtered out, and if there's less than return await query.take(ps.limit).getMany();
// 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;
}); });

View File

@ -87,18 +87,7 @@ export default define(meta, paramDef, async (ps, user) => {
ps.sinceDate, ps.sinceDate,
ps.untilDate, ps.untilDate,
) )
.andWhere("(note.visibility = 'public') AND (note.userHost IS NULL)") .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");
generateRepliesQuery(query, ps.withReplies, user); generateRepliesQuery(query, ps.withReplies, user);
generateVisibilityQuery(query, 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 return await query.take(ps.limit).getMany();
// 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;
}); });

View File

@ -1,12 +1,11 @@
import { Brackets } from "typeorm"; import {Brackets} from "typeorm";
import read from "@/services/note/read.js"; import {Followings, Notes} from "@/models/index.js";
import { Notes, Followings } from "@/models/index.js";
import define from "../../define.js"; import define from "../../define.js";
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js"; import {makePaginationQuery} from "../../common/make-pagination-query.js";
import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
import { generateMutedNoteThreadQuery } from "../../common/generate-muted-note-thread-query.js"; import {generateMutedNoteThreadQuery} from "../../common/generate-muted-note-thread-query.js";
export const meta = { export const meta = {
tags: ["notes"], tags: ["notes"],
@ -54,18 +53,7 @@ export default define(meta, paramDef, async (ps, user) => {
`'{"${user.id}"}' <@ note.visibleUserIds`, `'{"${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); generateVisibilityQuery(query, user);
generateMutedUserQuery(query, user); generateMutedUserQuery(query, user);
@ -86,23 +74,5 @@ export default define(meta, paramDef, async (ps, user) => {
query.setParameters(followingQuery.getParameters()); query.setParameters(followingQuery.getParameters());
} }
// We fetch more than requested because some may be filtered out, and if there's less than return await query.take(ps.limit).getMany();
// 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;
}); });

View File

@ -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,
});
});

View File

@ -1,10 +1,9 @@
import type { FindOptionsWhere } from "typeorm"; import type {FindOptionsWhere} from "typeorm";
import { DeepPartial } from "typeorm"; import {NoteReactions} from "@/models/index.js";
import { NoteReactions } from "@/models/index.js"; import type {NoteReaction} from "@/models/entities/note-reaction.js";
import type { NoteReaction } from "@/models/entities/note-reaction.js";
import define from "../../define.js"; import define from "../../define.js";
import { ApiError } from "../../error.js"; import {ApiError} from "../../error.js";
import { getNote } from "../../common/getters.js"; import {getNote} from "../../common/getters.js";
export const meta = { export const meta = {
tags: ["notes", "reactions"], tags: ["notes", "reactions"],
@ -78,7 +77,7 @@ export default define(meta, paramDef, async (ps, user) => {
order: { order: {
id: -1, id: -1,
}, },
relations: ["user", "user.avatar", "user.banner", "note"], relations: ["user", "note"],
}); });
return await NoteReactions.packMany(reactions, user); return await NoteReactions.packMany(reactions, user);

View File

@ -90,18 +90,7 @@ export default define(meta, paramDef, async (ps, user) => {
.andWhere( .andWhere(
`(note.userHost = ANY ('{"${m.recommendedInstances.join('","')}"}'))`, `(note.userHost = ANY ('{"${m.recommendedInstances.join('","')}"}'))`,
) )
.andWhere("(note.visibility = 'public')") .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");
generateRepliesQuery(query, ps.withReplies, user); generateRepliesQuery(query, ps.withReplies, user);
generateVisibilityQuery(query, 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 return await query.take(ps.limit).getMany();
// 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;
}); });

View File

@ -1,11 +1,11 @@
import { Notes } from "@/models/index.js"; import {Notes} from "@/models/index.js";
import define from "../../define.js"; import define from "../../define.js";
import { getNote } from "../../common/getters.js"; import {getNote} from "../../common/getters.js";
import { ApiError } from "../../error.js"; import {ApiError} from "../../error.js";
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js"; import {makePaginationQuery} from "../../common/make-pagination-query.js";
import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
export const meta = { export const meta = {
tags: ["notes"], tags: ["notes"],
@ -65,37 +65,9 @@ export default define(meta, paramDef, async (ps, user) => {
query.andWhere("user.id = :userId", { userId: ps.userId }); 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); generateVisibilityQuery(query, user);
if (user) generateMutedUserQuery(query, user); if (user) generateMutedUserQuery(query, user);
if (user) generateBlockedUserQuery(query, user); if (user) generateBlockedUserQuery(query, user);
// We fetch more than requested because some may be filtered out, and if there's less than return await query.take(ps.limit).getMany();
// 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;
}); });

View File

@ -1,9 +1,9 @@
import { Notes } from "@/models/index.js"; import {Notes} from "@/models/index.js";
import define from "../../define.js"; import define from "../../define.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js"; import {makePaginationQuery} from "../../common/make-pagination-query.js";
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
export const meta = { export const meta = {
tags: ["notes"], tags: ["notes"],
@ -41,38 +41,11 @@ export default define(meta, paramDef, async (ps, user) => {
ps.sinceId, ps.sinceId,
ps.untilId, ps.untilId,
) )
.andWhere("note.replyId = :replyId", { replyId: ps.noteId }) .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");
generateVisibilityQuery(query, user); generateVisibilityQuery(query, user);
if (user) generateMutedUserQuery(query, user); if (user) generateMutedUserQuery(query, user);
if (user) generateBlockedUserQuery(query, user); if (user) generateBlockedUserQuery(query, user);
// We fetch more than requested because some may be filtered out, and if there's less than return await query.take(ps.limit).getMany();
// 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;
}); });

View File

@ -1,12 +1,12 @@
import { Brackets } from "typeorm"; import {Brackets} from "typeorm";
import { Notes } from "@/models/index.js"; import {Notes} from "@/models/index.js";
import { safeForSql } from "@/misc/safe-for-sql.js"; import {safeForSql} from "@/misc/safe-for-sql.js";
import { normalizeForSearch } from "@/misc/normalize-for-search.js"; import {normalizeForSearch} from "@/misc/normalize-for-search.js";
import define from "../../define.js"; import define from "../../define.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js"; import {makePaginationQuery} from "../../common/make-pagination-query.js";
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
export const meta = { export const meta = {
tags: ["notes", "hashtags"], tags: ["notes", "hashtags"],
@ -74,18 +74,7 @@ export default define(meta, paramDef, async (ps, me) => {
Notes.createQueryBuilder("note"), Notes.createQueryBuilder("note"),
ps.sinceId, ps.sinceId,
ps.untilId, 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); generateVisibilityQuery(query, me);
if (me) generateMutedUserQuery(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 return await query.take(ps.limit).getMany();
// 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;
}); });

View File

@ -1,16 +1,16 @@
import { In } from "typeorm"; import {In} from "typeorm";
import { Notes } from "@/models/index.js"; import {Notes} from "@/models/index.js";
import { Note } from "@/models/entities/note.js"; import {Note} from "@/models/entities/note.js";
import config from "@/config/index.js"; import config from "@/config/index.js";
import es from "@/db/elasticsearch.js"; import es from "@/db/elasticsearch.js";
import sonic from "@/db/sonic.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 define from "../../define.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js"; import {makePaginationQuery} from "../../common/make-pagination-query.js";
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; import {sqlLikeEscape} from "@/misc/sql-like-escape.js";
export const meta = { export const meta = {
tags: ["notes"], tags: ["notes"],
@ -79,18 +79,7 @@ export default define(meta, paramDef, async (ps, me) => {
} }
query query
.andWhere("note.text ILIKE :q", { q: `%${sqlLikeEscape(ps.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");
generateVisibilityQuery(query, me); generateVisibilityQuery(query, me);
if (me) generateMutedUserQuery(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(); const notes: Note[] = await query.take(ps.limit).getMany();
return await Notes.packMany(notes, me); return notes;
} else if (sonic) { } else if (sonic) {
let start = 0; let start = 0;
const chunkSize = 100; 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 // The notes are checked for visibility and muted/blocked users when packed
found.push(...(await Notes.packMany(notes, me))); found.push(...notes);
start += chunkSize; start += chunkSize;
} }
@ -192,9 +181,6 @@ export default define(meta, paramDef, async (ps, me) => {
if (ps.userId && key.userId !== ps.userId) { if (ps.userId && key.userId !== ps.userId) {
return false; return false;
} }
if (ps.channelId && key.channelId !== ps.channelId) {
return false;
}
if (ps.sinceId && key.id <= ps.sinceId) { if (ps.sinceId && key.id <= ps.sinceId) {
return false; 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 // The notes are checked for visibility and muted/blocked users when packed
found.push(...(await Notes.packMany(notes, me))); found.push(...notes);
start += chunkSize; start += chunkSize;
} }
@ -315,6 +301,6 @@ export default define(meta, paramDef, async (ps, me) => {
}, },
}); });
return await Notes.packMany(notes, me); return notes;
} }
}); });

View File

@ -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;
});
});

View File

@ -90,17 +90,6 @@ export default define(meta, paramDef, async (ps, user) => {
qb.orWhere(`note.userId IN (${followingQuery.getQuery()})`); 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()); .setParameters(followingQuery.getParameters());
generateRepliesQuery(query, ps.withReplies, user); generateRepliesQuery(query, ps.withReplies, user);
@ -171,7 +160,7 @@ export default define(meta, paramDef, async (ps, user) => {
try { try {
while (found.length < ps.limit) { while (found.length < ps.limit) {
const notes = await query.take(take).skip(skip).getMany(); const notes = await query.take(take).skip(skip).getMany();
found.push(...(await Notes.packMany(notes, user))); found.push(...notes);
skip += take; skip += take;
if (notes.length < take) break; if (notes.length < take) break;
} }

View File

@ -1,10 +1,10 @@
import { Brackets } from "typeorm"; import {Brackets} from "typeorm";
import { UserLists, UserListJoinings, Notes } from "@/models/index.js"; import {Notes, UserListJoinings, UserLists} from "@/models/index.js";
import { activeUsersChart } from "@/services/chart/index.js"; import {activeUsersChart} from "@/services/chart/index.js";
import define from "../../define.js"; import define from "../../define.js";
import { ApiError } from "../../error.js"; import {ApiError} from "../../error.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js"; import {makePaginationQuery} from "../../common/make-pagination-query.js";
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
export const meta = { export const meta = {
tags: ["notes", "lists"], tags: ["notes", "lists"],
@ -80,16 +80,6 @@ export default define(meta, paramDef, async (ps, user) => {
"userListJoining.userId = note.userId", "userListJoining.userId = note.userId",
) )
.innerJoinAndSelect("note.user", "user") .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", { .andWhere("userListJoining.userListId = :userListId", {
userListId: list.id, 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 return await query.take(ps.limit).getMany();
// 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;
}); });

View File

@ -1,12 +1,12 @@
import { Brackets } from "typeorm"; import {Brackets} from "typeorm";
import { Notes } from "@/models/index.js"; import {Notes} from "@/models/index.js";
import define from "../../define.js"; import define from "../../define.js";
import { ApiError } from "../../error.js"; import {ApiError} from "../../error.js";
import { getUser } from "../../common/getters.js"; import {getUser} from "../../common/getters.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js"; import {makePaginationQuery} from "../../common/make-pagination-query.js";
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
export const meta = { export const meta = {
tags: ["users", "notes"], tags: ["users", "notes"],
@ -75,17 +75,7 @@ export default define(meta, paramDef, async (ps, me) => {
ps.untilDate, ps.untilDate,
) )
.andWhere("note.userId = :userId", { userId: user.id }) .andWhere("note.userId = :userId", { userId: user.id })
.innerJoinAndSelect("note.user", "user") .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); generateVisibilityQuery(query, me);
if (me) { if (me) {
@ -138,7 +128,5 @@ export default define(meta, paramDef, async (ps, me) => {
//#endregion //#endregion
const timeline = await query.take(ps.limit).getMany(); return await query.take(ps.limit).getMany();
return await Notes.packMany(timeline, me);
}); });

View File

@ -1,8 +1,4 @@
import type Connection from "."; 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 * Stream channel
@ -63,34 +59,4 @@ export default abstract class Channel {
public dispose?(): void; public dispose?(): void;
public onMessage?(type: string, body: any): 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;
}
}
};
}
} }

View File

@ -1,13 +1,12 @@
import Channel from "../channel.js"; import Channel from "../channel.js";
import { Notes } from "@/models/index.js"; import {isUserRelated} from "@/misc/is-user-related.js";
import { isUserRelated } from "@/misc/is-user-related.js"; import type {StreamMessages} from "../types.js";
import type { StreamMessages } from "../types.js"; import {IdentifiableError} from "@/misc/identifiable-error.js";
import { IdentifiableError } from "@/misc/identifiable-error.js";
export default class extends Channel { export default class extends Channel {
public readonly chName = "antenna";
public static shouldShare = false; public static shouldShare = false;
public static requireCredential = false; public static requireCredential = false;
public readonly chName = "antenna";
private antennaId: string; private antennaId: string;
constructor(id: string, connection: Channel["connection"]) { constructor(id: string, connection: Channel["connection"]) {
@ -22,12 +21,15 @@ export default class extends Channel {
this.subscriber.on(`antennaStream:${this.antennaId}`, this.onEvent); 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"]) { private async onEvent(data: StreamMessages["antenna"]["payload"]) {
if (data.type === "note") { if (data.type === "note") {
try { try {
const note = await Notes.pack(data.body.id, this.user, { const note = data.body;
detail: true,
});
// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する // 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する
if (isUserRelated(note, this.muting)) return; 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)) if (note.renote && !note.text && this.renoteMuting.has(note.userId))
return; return;
this.connection.cacheNote(note); this.send("note", note.id);
this.send("note", note);
} catch (e) { } catch (e) {
if ( if (
e instanceof IdentifiableError && e instanceof IdentifiableError &&
@ -55,9 +55,4 @@ export default class extends Channel {
this.send(data.type, data.body); this.send(data.type, data.body);
} }
} }
public dispose() {
// Unsubscribe events
this.subscriber.off(`antennaStream:${this.antennaId}`, this.onEvent);
}
} }

View File

@ -3,7 +3,7 @@ import {fetchMeta} from "@/misc/fetch-meta.js";
import {getWordHardMute} from "@/misc/check-word-mute.js"; import {getWordHardMute} from "@/misc/check-word-mute.js";
import {isInstanceMuted} from "@/misc/is-instance-muted.js"; import {isInstanceMuted} from "@/misc/is-instance-muted.js";
import {isUserRelated} from "@/misc/is-user-related.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 { export default class extends Channel {
public static shouldShare = true; public static shouldShare = true;
@ -13,7 +13,7 @@ export default class extends Channel {
constructor(id: string, connection: Channel["connection"]) { constructor(id: string, connection: Channel["connection"]) {
super(id, connection); super(id, connection);
this.onNote = this.withPackedNote(this.onNote.bind(this)); this.onNote = this.onNote.bind(this);
} }
public async init(params: any) { public async init(params: any) {
@ -34,7 +34,7 @@ export default class extends Channel {
this.subscriber.off("notesStream", this.onNote); 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; if (note.visibility !== "public") return;
// 関係ない返信は除外 // 関係ない返信は除外
@ -76,8 +76,6 @@ export default class extends Channel {
) )
return; return;
this.connection.cacheNote(note); this.send("note", note.id);
this.send("note", note);
} }
} }

View File

@ -1,7 +1,7 @@
import Channel from "../channel.js"; import Channel from "../channel.js";
import {normalizeForSearch} from "@/misc/normalize-for-search.js"; import {normalizeForSearch} from "@/misc/normalize-for-search.js";
import {isUserRelated} from "@/misc/is-user-related.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 { export default class extends Channel {
public static shouldShare = false; public static shouldShare = false;
@ -11,7 +11,7 @@ export default class extends Channel {
constructor(id: string, connection: Channel["connection"]) { constructor(id: string, connection: Channel["connection"]) {
super(id, connection); super(id, connection);
this.onNote = this.withPackedNote(this.onNote.bind(this)); this.onNote = this.onNote.bind(this);
} }
public async init(params: any) { public async init(params: any) {
@ -28,7 +28,7 @@ export default class extends Channel {
this.subscriber.off("notesStream", this.onNote); 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; if (note.visibility === "hidden") return;
const noteTags = note.tags const noteTags = note.tags
? note.tags.map((t: string) => t.toLowerCase()) ? 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; if (note.renote && !note.text && this.renoteMuting.has(note.userId)) return;
this.connection.cacheNote(note); this.send("note", note.id);
this.send("note", note);
} }
} }

View File

@ -2,7 +2,7 @@ import Channel from "../channel.js";
import {getWordHardMute} from "@/misc/check-word-mute.js"; import {getWordHardMute} from "@/misc/check-word-mute.js";
import {isUserRelated} from "@/misc/is-user-related.js"; import {isUserRelated} from "@/misc/is-user-related.js";
import {isInstanceMuted} from "@/misc/is-instance-muted.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 { export default class extends Channel {
public static shouldShare = true; public static shouldShare = true;
@ -12,7 +12,7 @@ export default class extends Channel {
constructor(id: string, connection: Channel["connection"]) { constructor(id: string, connection: Channel["connection"]) {
super(id, connection); super(id, connection);
this.onNote = this.withPackedNote(this.onNote.bind(this)); this.onNote = this.onNote.bind(this);
} }
public async init(params: any) { public async init(params: any) {
@ -27,7 +27,7 @@ export default class extends Channel {
this.subscriber.off("notesStream", this.onNote); 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; if (note.visibility === "hidden") return;
// Filter away notes that are not authored by the user or any of the followed users // 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; return;
this.connection.cacheNote(note); this.send("note", note.id);
this.send("note", note);
} }
} }

View File

@ -3,7 +3,7 @@ import {fetchMeta} from "@/misc/fetch-meta.js";
import {getWordHardMute} from "@/misc/check-word-mute.js"; import {getWordHardMute} from "@/misc/check-word-mute.js";
import {isUserRelated} from "@/misc/is-user-related.js"; import {isUserRelated} from "@/misc/is-user-related.js";
import {isInstanceMuted} from "@/misc/is-instance-muted.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 { export default class extends Channel {
public static shouldShare = true; public static shouldShare = true;
@ -13,7 +13,7 @@ export default class extends Channel {
constructor(id: string, connection: Channel["connection"]) { constructor(id: string, connection: Channel["connection"]) {
super(id, connection); super(id, connection);
this.onNote = this.withPackedNote(this.onNote.bind(this)); this.onNote = this.onNote.bind(this);
} }
public async init(params: any) { public async init(params: any) {
@ -36,7 +36,7 @@ export default class extends Channel {
this.subscriber.off("notesStream", this.onNote); 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") if (note.visibility === "hidden")
return; return;
@ -48,7 +48,7 @@ export default class extends Channel {
!( !(
this.user!.id === note.userId || this.user!.id === note.userId ||
this.following.has(note.userId) || this.following.has(note.userId) ||
(note.user.host == null && note.visibility === "public") (note.userHost == null && note.visibility === "public")
) )
) )
return; return;
@ -92,8 +92,6 @@ export default class extends Channel {
) )
return; return;
this.connection.cacheNote(note); this.send("note", note.id);
this.send("note", note);
} }
} }

View File

@ -2,7 +2,7 @@ import Channel from "../channel.js";
import {fetchMeta} from "@/misc/fetch-meta.js"; import {fetchMeta} from "@/misc/fetch-meta.js";
import {getWordHardMute} from "@/misc/check-word-mute.js"; import {getWordHardMute} from "@/misc/check-word-mute.js";
import {isUserRelated} from "@/misc/is-user-related.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 { export default class extends Channel {
public static shouldShare = true; public static shouldShare = true;
@ -12,7 +12,7 @@ export default class extends Channel {
constructor(id: string, connection: Channel["connection"]) { constructor(id: string, connection: Channel["connection"]) {
super(id, connection); super(id, connection);
this.onNote = this.withPackedNote(this.onNote.bind(this)); this.onNote = this.onNote.bind(this);
} }
public async init(params: any) { public async init(params: any) {
@ -33,8 +33,8 @@ export default class extends Channel {
this.subscriber.off("notesStream", this.onNote); 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.user.host !== null) return; if (note.userHost !== null) return;
if (note.visibility !== "public") return; if (note.visibility !== "public") return;
// 関係ない返信は除外 // 関係ない返信は除外
@ -67,8 +67,6 @@ export default class extends Channel {
) )
return; return;
this.connection.cacheNote(note); this.send("note", note.id);
this.send("note", note);
} }
} }

View File

@ -3,7 +3,7 @@ import {fetchMeta} from "@/misc/fetch-meta.js";
import {getWordHardMute} from "@/misc/check-word-mute.js"; import {getWordHardMute} from "@/misc/check-word-mute.js";
import {isUserRelated} from "@/misc/is-user-related.js"; import {isUserRelated} from "@/misc/is-user-related.js";
import {isInstanceMuted} from "@/misc/is-instance-muted.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 { export default class extends Channel {
public static shouldShare = true; public static shouldShare = true;
@ -13,7 +13,7 @@ export default class extends Channel {
constructor(id: string, connection: Channel["connection"]) { constructor(id: string, connection: Channel["connection"]) {
super(id, connection); super(id, connection);
this.onNote = this.withPackedNote(this.onNote.bind(this)); this.onNote = this.onNote.bind(this);
} }
public async init(params: any) { public async init(params: any) {
@ -36,7 +36,7 @@ export default class extends Channel {
this.subscriber.off("notesStream", this.onNote); 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; if (note.visibility === "hidden") return;
// チャンネルの投稿ではなく、自分自身の投稿 または // チャンネルの投稿ではなく、自分自身の投稿 または
// チャンネルの投稿ではなく、その投稿のユーザーをフォローしている または // チャンネルの投稿ではなく、その投稿のユーザーをフォローしている または
@ -45,8 +45,8 @@ export default class extends Channel {
const meta = await fetchMeta(); const meta = await fetchMeta();
if ( if (
!( !(
note.user.host != null && note.userHost != null &&
meta.recommendedInstances.includes(note.user.host) && meta.recommendedInstances.includes(note.userHost) &&
note.visibility === "public" note.visibility === "public"
) )
) )
@ -91,8 +91,6 @@ export default class extends Channel {
) )
return; return;
this.connection.cacheNote(note); this.send("note", note.id);
this.send("note", note);
} }
} }

View File

@ -2,7 +2,7 @@ import Channel from "../channel.js";
import {UserListJoinings, UserLists} from "@/models/index.js"; import {UserListJoinings, UserLists} from "@/models/index.js";
import type {User} from "@/models/entities/user.js"; import type {User} from "@/models/entities/user.js";
import {isUserRelated} from "@/misc/is-user-related.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 { export default class extends Channel {
public static shouldShare = false; public static shouldShare = false;
@ -15,7 +15,7 @@ export default class extends Channel {
constructor(id: string, connection: Channel["connection"]) { constructor(id: string, connection: Channel["connection"]) {
super(id, connection); super(id, connection);
this.updateListUsers = this.updateListUsers.bind(this); 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) { public async init(params: any) {
@ -56,7 +56,7 @@ export default class extends Channel {
this.listUsers = users.map((x) => x.userId); 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 (note.visibility === "hidden") return;
if (!this.listUsers.includes(note.userId)) 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; if (note.renote && !note.text && this.renoteMuting.has(note.userId)) return;
this.send("note", note); this.send("note", note.id);
} }
} }

View File

@ -4,7 +4,6 @@ import type {User} from "@/models/entities/user.js";
import {Blockings, Followings, Mutings, RenoteMutings, UserProfiles,} from "@/models/index.js"; import {Blockings, Followings, Mutings, RenoteMutings, UserProfiles,} from "@/models/index.js";
import type {AccessToken} from "@/models/entities/access-token.js"; import type {AccessToken} from "@/models/entities/access-token.js";
import type {UserProfile} from "@/models/entities/user-profile.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 {readNotification} from "../common/read-notification.js";
import channels from "./channels/index.js"; import channels from "./channels/index.js";
import type Channel from "./channel.js"; import type Channel from "./channel.js";
@ -25,7 +24,6 @@ export default class Connection {
private wsConnection: websocket.connection; private wsConnection: websocket.connection;
private channels: Channel[] = []; private channels: Channel[] = [];
private subscribingNotes: Map<string, number> = new Map(); private subscribingNotes: Map<string, number> = new Map();
private cachedNotes: Packed<"Note">[] = [];
private host: string; private host: string;
private accessToken: string; private accessToken: string;
private currentSubscribe: 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);
}
/** /**
* *
*/ */

View File

@ -64,9 +64,9 @@ export interface UserStreamTypes {
export interface MainStreamTypes { export interface MainStreamTypes {
notification: Packed<"Notification">; notification: Packed<"Notification">;
mention: Packed<"Note">; mention: Note;
reply: Packed<"Note">; reply: Note;
renote: Packed<"Note">; renote: Note;
follow: Packed<"UserDetailedNotMe">; follow: Packed<"UserDetailedNotMe">;
followed: Packed<"User">; followed: Packed<"User">;
unfollow: Packed<"User">; unfollow: Packed<"User">;

View File

@ -54,6 +54,7 @@ import {getActiveWebhooks} from "@/misc/webhook-cache.js";
import {shouldSilenceInstance} from "@/misc/should-block-instance.js"; import {shouldSilenceInstance} from "@/misc/should-block-instance.js";
import meilisearch from "../../db/meilisearch.js"; import meilisearch from "../../db/meilisearch.js";
import {redisClient} from "@/db/redis.js"; import {redisClient} from "@/db/redis.js";
import {getNote} from "@/server/api/common/getters.js";
const mutedWordsCache = new Cache< const mutedWordsCache = new Cache<
{ userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[] { userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[]
@ -466,10 +467,12 @@ export default async (
webhooks.filter((x) => x.userId === user.id && x.on.includes("note")), webhooks.filter((x) => x.userId === user.id && x.on.includes("note")),
); );
for (const webhook of webhooks) { if (await Notes.isVisibleForMe(note, user.id)) {
webhookDeliver(webhook, "note", { for (const webhook of webhooks) {
note: await Notes.pack(note, user), webhookDeliver(webhook, "note", {
}); note,
});
}
} }
const nm = new NotificationManager(user, note); const nm = new NotificationManager(user, note);
@ -492,19 +495,21 @@ export default async (
if (!threadMuted) { if (!threadMuted) {
nm.push(data.reply.userId, "reply"); nm.push(data.reply.userId, "reply");
const packedReply = await Notes.pack(note, { if (data.reply.userId) {
id: data.reply.userId, getNote(note.id, { id: data.reply.userId }).then(async (reply) => {
}); publishMainStream(data.reply!.userId, "reply", reply);
publishMainStream(data.reply.userId, "reply", packedReply);
const webhooks = (await getActiveWebhooks()).filter( const webhooks = (await getActiveWebhooks()).filter(
(x) => x.userId === data.reply!.userId && x.on.includes("reply"), (x) => x.userId === data.reply!.userId && x.on.includes("reply"),
); );
for (const webhook of webhooks) { for (const webhook of webhooks) {
webhookDeliver(webhook, "reply", { webhookDeliver(webhook, "reply", {
note: packedReply, note: reply,
});
}
}); });
} }
} }
} }
} }
@ -531,18 +536,18 @@ export default async (
// Publish event // Publish event
if (user.id !== data.renote.userId && data.renote.userHost === null) { if (user.id !== data.renote.userId && data.renote.userHost === null) {
const packedRenote = await Notes.pack(note, { if (data.renote.userId) {
id: data.renote.userId, getNote(note.id, { id: data.renote.userId }).then(async (renote) => {
}); publishMainStream(data.renote!.userId, "renote", renote);
publishMainStream(data.renote.userId, "renote", packedRenote);
const renote = data.renote; const webhooks = (await getActiveWebhooks()).filter(
const webhooks = (await getActiveWebhooks()).filter( (x) => x.userId === renote.renoteUserId && x.on.includes("renote"),
(x) => x.userId === renote.userId && x.on.includes("renote"), );
); for (const webhook of webhooks) {
for (const webhook of webhooks) { webhookDeliver(webhook, "renote", {
webhookDeliver(webhook, "renote", { note: renote,
note: packedRenote, });
}
}); });
} }
} }
@ -585,7 +590,7 @@ export default async (
} }
dm.execute(); dm.execute();
})(); })().then();
} }
//#endregion //#endregion
} }
@ -823,20 +828,19 @@ async function createMentionedEvents(
// note with "specified" visibility might not be visible to mentioned users // note with "specified" visibility might not be visible to mentioned users
try { try {
const detailPackedNote = await Notes.pack(note, u, { await getNote(note.id, { id: u.id }).then(async (note) => {
detail: true, 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) { } catch (err) {
if (err.id === "9725d0ce-ba28-4dde-95a7-2cbb2c15de24") continue; if (err.id === "9725d0ce-ba28-4dde-95a7-2cbb2c15de24") continue;
throw err; throw err;

View File

@ -6,14 +6,13 @@ import {In} from "typeorm";
import {checkHitAntenna} from "@/misc/check-hit-antenna.js"; import {checkHitAntenna} from "@/misc/check-hit-antenna.js";
import {getAntennas} from "@/misc/antenna-cache.js"; import {getAntennas} from "@/misc/antenna-cache.js";
import {readNotificationByQuery} from "@/server/api/common/read-notification.js"; import {readNotificationByQuery} from "@/server/api/common/read-notification.js";
import type {Packed} from "@/misc/schema.js";
/** /**
* Mark notes as read * Mark notes as read
*/ */
export default async function ( export default async function (
userId: User["id"], userId: User["id"],
notes: (Note | Packed<"Note">)[], notes: Note[],
info?: { info?: {
following: Set<User["id"]>; following: Set<User["id"]>;
}, },
@ -32,9 +31,9 @@ export default async function (
); );
const myAntennas = (await getAntennas()).filter((a) => a.userId === userId); const myAntennas = (await getAntennas()).filter((a) => a.userId === userId);
const readMentions: (Note | Packed<"Note">)[] = []; const readMentions: Note[] = [];
const readSpecifiedNotes: (Note | Packed<"Note">)[] = []; const readSpecifiedNotes: Note[] = [];
const readAntennaNotes: (Note | Packed<"Note">)[] = []; const readAntennaNotes: Note[] = [];
for (const note of notes) { for (const note of notes) {
if (note.mentions?.includes(userId)) { if (note.mentions?.includes(userId)) {

View File

@ -1,9 +1,9 @@
import push from "web-push"; import push from "web-push";
import config from "@/config/index.js"; import config from "@/config/index.js";
import { SwSubscriptions } from "@/models/index.js"; import {SwSubscriptions} from "@/models/index.js";
import { fetchMeta } from "@/misc/fetch-meta.js"; import {fetchMeta} from "@/misc/fetch-meta.js";
import type { Packed } from "@/misc/schema.js"; import type {Packed} from "@/misc/schema.js";
import { getNoteSummary } from "@/misc/get-note-summary.js"; import {getNoteSummary} from "@/misc/get-note-summary.js";
// Defined also packages/sw/types.ts#L14-L21 // Defined also packages/sw/types.ts#L14-L21
type pushNotificationsTypes = { type pushNotificationsTypes = {
@ -22,7 +22,7 @@ function truncateNotification(notification: Packed<"Notification">): any {
// textをgetNoteSummaryしたものに置き換える // textをgetNoteSummaryしたものに置き換える
text: getNoteSummary( text: getNoteSummary(
notification.type === "renote" notification.type === "renote"
? (notification.note.renote as Packed<"Note">) ? (notification.note.renote)
: notification.note, : notification.note,
), ),

View File

@ -280,8 +280,8 @@ importers:
specifier: 3.4.1 specifier: 3.4.1
version: 3.4.1 version: 3.4.1
re2: re2:
specifier: 1.19.0 specifier: 1.20.9
version: 1.19.0 version: 1.20.9
redis-lock: redis-lock:
specifier: 0.1.4 specifier: 0.1.4
version: 0.1.4 version: 0.1.4
@ -1146,6 +1146,19 @@ packages:
'@nodelib/fs.scandir': 2.1.5 '@nodelib/fs.scandir': 2.1.5
fastq: 1.15.0 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: /@npmcli/fs@3.1.0:
resolution: {integrity: sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==} resolution: {integrity: sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
@ -2069,6 +2082,11 @@ packages:
/abbrev@1.1.1: /abbrev@1.1.1:
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} 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: /abort-controller@3.0.0:
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
engines: {node: '>=6.5'} engines: {node: '>=6.5'}
@ -2129,13 +2147,11 @@ packages:
- supports-color - supports-color
dev: false dev: false
/agentkeepalive@4.3.0: /agent-base@7.1.0:
resolution: {integrity: sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==} resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==}
engines: {node: '>= 8.0.0'} engines: {node: '>= 14'}
dependencies: dependencies:
debug: 4.3.4 debug: 4.3.4
depd: 2.0.0
humanize-ms: 1.2.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: false dev: false
@ -2264,14 +2280,6 @@ packages:
readable-stream: 3.6.2 readable-stream: 3.6.2
dev: false 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: /arg@4.1.3:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
@ -2582,16 +2590,16 @@ packages:
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
dev: false dev: false
/cacache@17.1.3: /cacache@18.0.1:
resolution: {integrity: sha512-jAdjGxmPxZh0IipMdR7fK/4sDSrHMLUV0+GvVUsjwyGNKHsh79kW/otg+GkbXwl6Uzvy9wsvHOX4nUoWldeZMg==} resolution: {integrity: sha512-g4Uf2CFZPaxtJKre6qr4zqLDOOPU7bNVhWjlNhvzc51xaTOx2noMOLhfFkTAqwtrAZAKQUuDfyjitzilpA8WsQ==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} engines: {node: ^16.14.0 || >=18.0.0}
dependencies: dependencies:
'@npmcli/fs': 3.1.0 '@npmcli/fs': 3.1.0
fs-minipass: 3.0.2 fs-minipass: 3.0.2
glob: 10.2.7 glob: 10.3.10
lru-cache: 7.18.3 lru-cache: 10.1.0
minipass: 5.0.0 minipass: 7.0.4
minipass-collect: 1.0.2 minipass-collect: 2.0.1
minipass-flush: 1.0.5 minipass-flush: 1.0.5
minipass-pipeline: 1.2.4 minipass-pipeline: 1.2.4
p-map: 4.0.0 p-map: 4.0.0
@ -4089,20 +4097,6 @@ packages:
wide-align: 1.1.5 wide-align: 1.1.5
dev: false 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: /generic-pool@3.9.0:
resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==}
engines: {node: '>= 4'} engines: {node: '>= 4'}
@ -4180,16 +4174,16 @@ packages:
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
dev: true dev: true
/glob@10.2.7: /glob@10.3.10:
resolution: {integrity: sha512-jTKehsravOJo8IJxUGfZILnkvVJM/MOfHRs8QcXolVef2zNI9Tqyy5+SeuOAZd3upViEZQLyFpQhYiHLrMUNmA==} resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==}
engines: {node: '>=16 || 14 >=14.17'} engines: {node: '>=16 || 14 >=14.17'}
hasBin: true hasBin: true
dependencies: dependencies:
foreground-child: 3.1.1 foreground-child: 3.1.1
jackspeak: 2.2.1 jackspeak: 2.3.6
minimatch: 9.0.1 minimatch: 9.0.1
minipass: 5.0.0 minipass: 5.0.0
path-scurry: 1.9.2 path-scurry: 1.10.1
dev: false dev: false
/glob@7.2.3: /glob@7.2.3:
@ -4386,6 +4380,16 @@ packages:
- supports-color - supports-color
dev: false 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: /http2-wrapper@1.0.3:
resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==}
engines: {node: '>=10.19.0'} engines: {node: '>=10.19.0'}
@ -4419,6 +4423,16 @@ packages:
- supports-color - supports-color
dev: false 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: /human-signals@2.1.0:
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
engines: {node: '>=10.17.0'} engines: {node: '>=10.17.0'}
@ -4429,12 +4443,6 @@ packages:
engines: {node: '>=12.20.0'} engines: {node: '>=12.20.0'}
dev: true 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: /humanize-number@0.0.2:
resolution: {integrity: sha512-un3ZAcNQGI7RzaWGZzQDH47HETM4Wrj6z6E4TId8Yeq9w5ZKUVB1nrT2jwFheTUjEmqcgTjXDc959jum+ai1kQ==} resolution: {integrity: sha512-un3ZAcNQGI7RzaWGZzQDH47HETM4Wrj6z6E4TId8Yeq9w5ZKUVB1nrT2jwFheTUjEmqcgTjXDc959jum+ai1kQ==}
dev: false dev: false
@ -4504,8 +4512,8 @@ packages:
/ini@1.3.8: /ini@1.3.8:
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
/install-artifact-from-github@1.3.3: /install-artifact-from-github@1.3.5:
resolution: {integrity: sha512-x79SL0d8WOi1ZjXSTUqqs0GPQZ92YArJAN9O46wgU9wdH2U9ecyyhB9YGDbPe2OLV4ptmt6AZYRQZ2GydQZosQ==} resolution: {integrity: sha512-gZHC7f/cJgXz7MXlHFBxPVMsvIbev1OQN1uKQYKVJDydGNm9oYf9JstbU4Atnh/eSvk41WtEovoRm+8IF686xg==}
hasBin: true hasBin: true
dev: false dev: false
@ -4709,8 +4717,13 @@ packages:
/isexe@2.0.0: /isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
/jackspeak@2.2.1: /isexe@3.1.1:
resolution: {integrity: sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==} 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'} engines: {node: '>=14'}
dependencies: dependencies:
'@isaacs/cliui': 8.0.2 '@isaacs/cliui': 8.0.2
@ -5274,6 +5287,11 @@ packages:
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dev: false 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: /lru-cache@4.1.5:
resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==}
dependencies: dependencies:
@ -5292,11 +5310,6 @@ packages:
dependencies: dependencies:
yallist: 4.0.0 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: /lru-cache@9.1.2:
resolution: {integrity: sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==} resolution: {integrity: sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==}
engines: {node: 14 || >=16.14} engines: {node: 14 || >=16.14}
@ -5321,24 +5334,20 @@ packages:
/make-error@1.3.6: /make-error@1.3.6:
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
/make-fetch-happen@11.1.1: /make-fetch-happen@13.0.0:
resolution: {integrity: sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==} resolution: {integrity: sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} engines: {node: ^16.14.0 || >=18.0.0}
dependencies: dependencies:
agentkeepalive: 4.3.0 '@npmcli/agent': 2.2.0
cacache: 17.1.3 cacache: 18.0.1
http-cache-semantics: 4.1.1 http-cache-semantics: 4.1.1
http-proxy-agent: 5.0.0
https-proxy-agent: 5.0.1
is-lambda: 1.0.1 is-lambda: 1.0.1
lru-cache: 7.18.3 minipass: 7.0.4
minipass: 5.0.0
minipass-fetch: 3.0.3 minipass-fetch: 3.0.3
minipass-flush: 1.0.5 minipass-flush: 1.0.5
minipass-pipeline: 1.2.4 minipass-pipeline: 1.2.4
negotiator: 0.6.3 negotiator: 0.6.3
promise-retry: 2.0.1 promise-retry: 2.0.1
socks-proxy-agent: 7.0.0
ssri: 10.0.4 ssri: 10.0.4
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -5448,11 +5457,11 @@ packages:
/minimist@1.2.8: /minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
/minipass-collect@1.0.2: /minipass-collect@2.0.1:
resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==}
engines: {node: '>= 8'} engines: {node: '>=16 || 14 >=14.17'}
dependencies: dependencies:
minipass: 3.3.6 minipass: 7.0.4
dev: false dev: false
/minipass-fetch@3.0.3: /minipass-fetch@3.0.3:
@ -5499,6 +5508,11 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dev: false dev: false
/minipass@7.0.4:
resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==}
engines: {node: '>=16 || 14 >=14.17'}
dev: false
/minizlib@2.1.2: /minizlib@2.1.2:
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -5588,8 +5602,8 @@ packages:
object-assign: 4.1.1 object-assign: 4.1.1
thenify-all: 1.6.0 thenify-all: 1.6.0
/nan@2.17.0: /nan@2.18.0:
resolution: {integrity: sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==} resolution: {integrity: sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==}
dev: false dev: false
/nanoid@3.3.6: /nanoid@3.3.6:
@ -5689,22 +5703,21 @@ packages:
hasBin: true hasBin: true
dev: false dev: false
/node-gyp@9.4.0: /node-gyp@10.0.1:
resolution: {integrity: sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==} resolution: {integrity: sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==}
engines: {node: ^12.13 || ^14.13 || >=16} engines: {node: ^16.14.0 || >=18.0.0}
hasBin: true hasBin: true
dependencies: dependencies:
env-paths: 2.2.1 env-paths: 2.2.1
exponential-backoff: 3.1.1 exponential-backoff: 3.1.1
glob: 7.2.3 glob: 10.3.10
graceful-fs: 4.2.11 graceful-fs: 4.2.11
make-fetch-happen: 11.1.1 make-fetch-happen: 13.0.0
nopt: 6.0.0 nopt: 7.2.0
npmlog: 6.0.2 proc-log: 3.0.0
rimraf: 3.0.2
semver: 7.5.1 semver: 7.5.1
tar: 6.1.15 tar: 6.1.15
which: 2.0.2 which: 4.0.0
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: false dev: false
@ -5736,6 +5749,14 @@ packages:
dependencies: dependencies:
abbrev: 1.1.1 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: /normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -5780,16 +5801,6 @@ packages:
set-blocking: 2.0.0 set-blocking: 2.0.0
dev: false 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: /nwsapi@2.2.5:
resolution: {integrity: sha512-6xpotnECFy/og7tKSBVmUNft7J3jyXAka4XvG6AUhFWRz+Q/Ljus7znJAA3bxColfQLdS+XsjoodtJfCgeTEFQ==} resolution: {integrity: sha512-6xpotnECFy/og7tKSBVmUNft7J3jyXAka4XvG6AUhFWRz+Q/Ljus7znJAA3bxColfQLdS+XsjoodtJfCgeTEFQ==}
dev: false dev: false
@ -6011,8 +6022,8 @@ packages:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: false dev: false
/path-scurry@1.9.2: /path-scurry@1.10.1:
resolution: {integrity: sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==} resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==}
engines: {node: '>=16 || 14 >=14.17'} engines: {node: '>=16 || 14 >=14.17'}
dependencies: dependencies:
lru-cache: 9.1.2 lru-cache: 9.1.2
@ -6214,6 +6225,11 @@ packages:
- supports-color - supports-color
dev: false 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: /process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
dev: false dev: false
@ -6363,13 +6379,13 @@ packages:
setimmediate: 1.0.5 setimmediate: 1.0.5
dev: false dev: false
/re2@1.19.0: /re2@1.20.9:
resolution: {integrity: sha512-y0LcLZgBF3L7mDtNfbghb7dCmChYQO2QsUGklNueAJUH+HAZO8UZUubgNsf6OxRTAQpeE4KMPR7vcpK3+Q+GiA==} resolution: {integrity: sha512-ZYcPTFr5ha2xq3WQjBDTF9CWPSDK1z28MLh5UFRxc//7X8BNQ3A7yR7ITnP0jO346661ertdKVFqw1qoL3FMEQ==}
requiresBuild: true requiresBuild: true
dependencies: dependencies:
install-artifact-from-github: 1.3.3 install-artifact-from-github: 1.3.5
nan: 2.17.0 nan: 2.18.0
node-gyp: 9.4.0 node-gyp: 10.0.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: false dev: false
@ -6764,11 +6780,11 @@ packages:
engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
dev: false dev: false
/socks-proxy-agent@7.0.0: /socks-proxy-agent@8.0.2:
resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} resolution: {integrity: sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==}
engines: {node: '>= 10'} engines: {node: '>= 14'}
dependencies: dependencies:
agent-base: 6.0.2 agent-base: 7.1.0
debug: 4.3.4 debug: 4.3.4
socks: 2.7.1 socks: 2.7.1
transitivePeerDependencies: transitivePeerDependencies:
@ -7787,6 +7803,14 @@ packages:
dependencies: dependencies:
isexe: 2.0.0 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: /wide-align@1.1.5:
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
dependencies: dependencies: