refactor: cache suspended users
This commit is contained in:
parent
19d7dc8b84
commit
8e0b0c7cb9
21 changed files with 234 additions and 225 deletions
|
@ -404,7 +404,7 @@ export async function execPaginationQuery(
|
||||||
userIds?: string[];
|
userIds?: string[];
|
||||||
},
|
},
|
||||||
filter?: {
|
filter?: {
|
||||||
note?: (_: ScyllaNote[]) => Promise<ScyllaNote[]>;
|
note?: (_: ScyllaNote[]) => ScyllaNote[];
|
||||||
reaction?: (_: ScyllaNoteReaction[]) => Promise<ScyllaNoteReaction[]>;
|
reaction?: (_: ScyllaNoteReaction[]) => Promise<ScyllaNoteReaction[]>;
|
||||||
notification?: (_: ScyllaNotification[]) => Promise<ScyllaNotification[]>;
|
notification?: (_: ScyllaNotification[]) => Promise<ScyllaNotification[]>;
|
||||||
},
|
},
|
||||||
|
@ -492,7 +492,7 @@ export async function execPaginationQuery(
|
||||||
} else {
|
} else {
|
||||||
const notes = result.rows.map(parseScyllaNote);
|
const notes = result.rows.map(parseScyllaNote);
|
||||||
(found as ScyllaNote[]).push(
|
(found as ScyllaNote[]).push(
|
||||||
...(filter?.note ? await filter.note(notes) : notes),
|
...(filter?.note ? filter.note(notes) : notes),
|
||||||
);
|
);
|
||||||
untilDate = notes[notes.length - 1].createdAt;
|
untilDate = notes[notes.length - 1].createdAt;
|
||||||
}
|
}
|
||||||
|
@ -517,11 +517,11 @@ export async function execPaginationQuery(
|
||||||
return found as ScyllaNote[];
|
return found as ScyllaNote[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function filterVisibility(
|
export function filterVisibility(
|
||||||
notes: ScyllaNote[],
|
notes: ScyllaNote[],
|
||||||
user: { id: User["id"] } | null,
|
user: { id: User["id"] } | null,
|
||||||
followingIds?: User["id"][],
|
followingIds: User["id"][],
|
||||||
): Promise<ScyllaNote[]> {
|
): ScyllaNote[] {
|
||||||
let filtered = notes;
|
let filtered = notes;
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
@ -529,15 +529,6 @@ export async function filterVisibility(
|
||||||
["public", "home"].includes(note.visibility),
|
["public", "home"].includes(note.visibility),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let ids: User["id"][];
|
|
||||||
if (followingIds) {
|
|
||||||
ids = followingIds;
|
|
||||||
} else {
|
|
||||||
ids = await LocalFollowingsCache.init(user.id).then((cache) =>
|
|
||||||
cache.getAll(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
filtered = filtered.filter(
|
filtered = filtered.filter(
|
||||||
(note) =>
|
(note) =>
|
||||||
["public", "home"].includes(note.visibility) ||
|
["public", "home"].includes(note.visibility) ||
|
||||||
|
@ -545,18 +536,18 @@ export async function filterVisibility(
|
||||||
note.visibleUserIds.includes(user.id) ||
|
note.visibleUserIds.includes(user.id) ||
|
||||||
note.mentions.includes(user.id) ||
|
note.mentions.includes(user.id) ||
|
||||||
(note.visibility === "followers" &&
|
(note.visibility === "followers" &&
|
||||||
(ids.includes(note.userId) || note.replyUserId === user.id)),
|
(followingIds.includes(note.userId) || note.replyUserId === user.id)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function filterChannel(
|
export function filterChannel(
|
||||||
notes: ScyllaNote[],
|
notes: ScyllaNote[],
|
||||||
user: { id: User["id"] } | null,
|
user: { id: User["id"] } | null,
|
||||||
followingIds?: Channel["id"][],
|
followingIds: Channel["id"][],
|
||||||
): Promise<ScyllaNote[]> {
|
): ScyllaNote[] {
|
||||||
let filtered = notes;
|
let filtered = notes;
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
@ -564,16 +555,8 @@ export async function filterChannel(
|
||||||
} else {
|
} else {
|
||||||
const channelNotes = filtered.filter((note) => !!note.channelId);
|
const channelNotes = filtered.filter((note) => !!note.channelId);
|
||||||
if (channelNotes.length > 0) {
|
if (channelNotes.length > 0) {
|
||||||
let followings: Channel["id"][];
|
|
||||||
if (followingIds) {
|
|
||||||
followings = followingIds;
|
|
||||||
} else {
|
|
||||||
followings = await ChannelFollowingsCache.init(user.id).then((cache) =>
|
|
||||||
cache.getAll(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
filtered = filtered.filter(
|
filtered = filtered.filter(
|
||||||
(note) => !note.channelId || followings.includes(note.channelId),
|
(note) => !note.channelId || followingIds.includes(note.channelId),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -581,11 +564,11 @@ export async function filterChannel(
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function filterReply(
|
export function filterReply(
|
||||||
notes: ScyllaNote[],
|
notes: ScyllaNote[],
|
||||||
withReplies: boolean,
|
withReplies: boolean,
|
||||||
user: { id: User["id"] } | null,
|
user: { id: User["id"] } | null,
|
||||||
): Promise<ScyllaNote[]> {
|
): ScyllaNote[] {
|
||||||
let filtered = notes;
|
let filtered = notes;
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
@ -605,113 +588,60 @@ export async function filterReply(
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function filterMutedUser(
|
export function filterMutedUser(
|
||||||
notes: ScyllaNote[],
|
notes: ScyllaNote[],
|
||||||
user: { id: User["id"] },
|
mutedIds: User["id"][],
|
||||||
mutedIds?: User["id"][],
|
mutedInstances: UserProfile["mutedInstances"],
|
||||||
mutedInstances?: UserProfile["mutedInstances"],
|
|
||||||
exclude?: User,
|
exclude?: User,
|
||||||
): Promise<ScyllaNote[]> {
|
): ScyllaNote[] {
|
||||||
let ids: User["id"][];
|
let userIds: User["id"][] = mutedIds;
|
||||||
let instances: UserProfile["mutedInstances"];
|
|
||||||
|
|
||||||
if (mutedIds) {
|
|
||||||
ids = mutedIds;
|
|
||||||
} else {
|
|
||||||
ids = await UserMutingsCache.init(user.id).then((cache) => cache.getAll());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mutedInstances) {
|
|
||||||
instances = mutedInstances;
|
|
||||||
} else {
|
|
||||||
instances = await InstanceMutingsCache.init(user.id).then((cache) =>
|
|
||||||
cache.getAll(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exclude) {
|
if (exclude) {
|
||||||
ids = ids.filter((id) => id !== exclude.id);
|
userIds = mutedIds.filter((id) => id !== exclude.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return notes.filter(
|
return notes.filter(
|
||||||
(note) =>
|
(note) =>
|
||||||
!ids.includes(note.userId) &&
|
!userIds.includes(note.userId) &&
|
||||||
!(note.replyUserId && ids.includes(note.replyUserId)) &&
|
!(note.replyUserId && userIds.includes(note.replyUserId)) &&
|
||||||
!(note.renoteUserId && ids.includes(note.renoteUserId)) &&
|
!(note.renoteUserId && userIds.includes(note.renoteUserId)) &&
|
||||||
!(note.userHost && instances.includes(note.userHost)) &&
|
!(note.userHost && mutedInstances.includes(note.userHost)) &&
|
||||||
!(note.replyUserHost && instances.includes(note.replyUserHost)) &&
|
!(note.replyUserHost && mutedInstances.includes(note.replyUserHost)) &&
|
||||||
!(note.renoteUserHost && instances.includes(note.renoteUserHost)),
|
!(note.renoteUserHost && mutedInstances.includes(note.renoteUserHost)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function filterMutedNote(
|
export function filterMutedNote(
|
||||||
notes: ScyllaNote[],
|
notes: ScyllaNote[],
|
||||||
user: { id: User["id"] },
|
user: { id: User["id"] },
|
||||||
mutedWords?: string[][],
|
mutedWords: string[][],
|
||||||
): Promise<ScyllaNote[]> {
|
): ScyllaNote[] {
|
||||||
let words = mutedWords;
|
if (mutedWords.length > 0) {
|
||||||
|
|
||||||
if (!words) {
|
|
||||||
words = await userWordMuteCache.fetchMaybe(user.id, () =>
|
|
||||||
UserProfiles.findOne({
|
|
||||||
select: ["mutedWords"],
|
|
||||||
where: { userId: user.id },
|
|
||||||
}).then((profile) => profile?.mutedWords),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (words && words.length > 0) {
|
|
||||||
return notes.filter(
|
return notes.filter(
|
||||||
(note) => !getWordHardMute(note, user, words as string[][]),
|
(note) => !getWordHardMute(note, user, mutedWords),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return notes;
|
return notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function filterBlockUser(
|
export function filterBlockUser(
|
||||||
notes: ScyllaNote[],
|
notes: ScyllaNote[],
|
||||||
user: { id: User["id"] },
|
blockIds: User["id"][],
|
||||||
blockIds?: User["id"][],
|
): ScyllaNote[] {
|
||||||
): Promise<ScyllaNote[]> {
|
|
||||||
let ids: User["id"][];
|
|
||||||
|
|
||||||
if (blockIds) {
|
|
||||||
ids = blockIds;
|
|
||||||
} else {
|
|
||||||
const blocked = await UserBlockedCache.init(user.id).then((cache) =>
|
|
||||||
cache.getAll(),
|
|
||||||
);
|
|
||||||
const blocking = await UserBlockingCache.init(user.id).then((cache) =>
|
|
||||||
cache.getAll(),
|
|
||||||
);
|
|
||||||
ids = [...blocked, ...blocking];
|
|
||||||
}
|
|
||||||
|
|
||||||
return notes.filter(
|
return notes.filter(
|
||||||
(note) =>
|
(note) =>
|
||||||
!ids.includes(note.userId) &&
|
!blockIds.includes(note.userId) &&
|
||||||
!(note.replyUserId && ids.includes(note.replyUserId)) &&
|
!(note.replyUserId && blockIds.includes(note.replyUserId)) &&
|
||||||
!(note.renoteUserId && ids.includes(note.renoteUserId)),
|
!(note.renoteUserId && blockIds.includes(note.renoteUserId)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function filterMutedRenotes(
|
export function filterMutedRenotes(
|
||||||
notes: ScyllaNote[],
|
notes: ScyllaNote[],
|
||||||
user: { id: User["id"] },
|
muteeIds: User["id"][],
|
||||||
muteeIds?: User["id"][],
|
): ScyllaNote[] {
|
||||||
): Promise<ScyllaNote[]> {
|
|
||||||
let ids: User["id"][];
|
|
||||||
|
|
||||||
if (muteeIds) {
|
|
||||||
ids = muteeIds;
|
|
||||||
} else {
|
|
||||||
ids = await RenoteMutingsCache.init(user.id).then((cache) =>
|
|
||||||
cache.getAll(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return notes.filter(
|
return notes.filter(
|
||||||
(note) => note.text || !note.renoteId || !ids.includes(note.userId),
|
(note) => note.text || !note.renoteId || !muteeIds.includes(note.userId),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
Mutings,
|
Mutings,
|
||||||
RenoteMutings,
|
RenoteMutings,
|
||||||
UserProfiles,
|
UserProfiles,
|
||||||
|
Users,
|
||||||
} from "@/models/index.js";
|
} from "@/models/index.js";
|
||||||
import { IsNull } from "typeorm";
|
import { IsNull } from "typeorm";
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
|
@ -479,3 +480,21 @@ export class RenoteMutingsCache extends SetCache {
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class SuspendedUsersCache extends SetCache {
|
||||||
|
private constructor() {
|
||||||
|
const fetcher = () => Users.find({
|
||||||
|
select: ["id"],
|
||||||
|
where: { isSuspended: true }
|
||||||
|
}).then((users) => users.map(({ id }) => id));
|
||||||
|
|
||||||
|
super("suspendedUsers", "system", fetcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async init(): Promise<SuspendedUsersCache> {
|
||||||
|
const cache = new SuspendedUsersCache();
|
||||||
|
await cache.fetch();
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
scyllaClient,
|
scyllaClient,
|
||||||
} from "@/db/scylla.js";
|
} from "@/db/scylla.js";
|
||||||
import { userByIdCache } from "@/services/user-cache.js";
|
import { userByIdCache } from "@/services/user-cache.js";
|
||||||
|
import { LocalFollowingsCache } from "@/misc/cache.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get note for API processing, taking into account visibility.
|
* Get note for API processing, taking into account visibility.
|
||||||
|
@ -28,7 +29,13 @@ export async function getNote(
|
||||||
);
|
);
|
||||||
if (result.rowLength > 0) {
|
if (result.rowLength > 0) {
|
||||||
const candidate = parseScyllaNote(result.first());
|
const candidate = parseScyllaNote(result.first());
|
||||||
const filtered = await filterVisibility([candidate], me, followingIds);
|
let ids: string[] = [];
|
||||||
|
if (followingIds) {
|
||||||
|
ids = followingIds
|
||||||
|
} else if (me) {
|
||||||
|
ids = await LocalFollowingsCache.init(me.id).then((cache) => cache.getAll());
|
||||||
|
}
|
||||||
|
const filtered = filterVisibility([candidate], me, ids);
|
||||||
if (filtered.length > 0) {
|
if (filtered.length > 0) {
|
||||||
note = filtered[0];
|
note = filtered[0];
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { insertModerationLog } from "@/services/insert-moderation-log.js";
|
||||||
import { doPostSuspend } from "@/services/suspend-user.js";
|
import { doPostSuspend } from "@/services/suspend-user.js";
|
||||||
import { publishUserEvent } from "@/services/stream.js";
|
import { publishUserEvent } from "@/services/stream.js";
|
||||||
import { scyllaClient } from "@/db/scylla.js";
|
import { scyllaClient } from "@/db/scylla.js";
|
||||||
|
import { SuspendedUsersCache } from "@/misc/cache.js";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["admin"],
|
tags: ["admin"],
|
||||||
|
@ -37,6 +38,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
throw new Error("cannot suspend moderator");
|
throw new Error("cannot suspend moderator");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await SuspendedUsersCache.init().then((cache) => cache.add(user.id));
|
||||||
await Users.update(user.id, {
|
await Users.update(user.id, {
|
||||||
isSuspended: true,
|
isSuspended: true,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { SuspendedUsersCache } from "@/misc/cache.js";
|
||||||
import define from "../../define.js";
|
import define from "../../define.js";
|
||||||
import { Users } from "@/models/index.js";
|
import { Users } from "@/models/index.js";
|
||||||
import { insertModerationLog } from "@/services/insert-moderation-log.js";
|
import { insertModerationLog } from "@/services/insert-moderation-log.js";
|
||||||
|
@ -25,6 +26,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
throw new Error("user not found");
|
throw new Error("user not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await SuspendedUsersCache.init().then((cache) => cache.delete(user.id));
|
||||||
await Users.update(user.id, {
|
await Users.update(user.id, {
|
||||||
isSuspended: false,
|
isSuspended: false,
|
||||||
});
|
});
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
InstanceMutingsCache,
|
InstanceMutingsCache,
|
||||||
LocalFollowingsCache,
|
LocalFollowingsCache,
|
||||||
RenoteMutingsCache,
|
RenoteMutingsCache,
|
||||||
|
SuspendedUsersCache,
|
||||||
UserBlockedCache,
|
UserBlockedCache,
|
||||||
UserBlockingCache,
|
UserBlockingCache,
|
||||||
UserMutingsCache,
|
UserMutingsCache,
|
||||||
|
@ -93,6 +94,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
blockerIds,
|
blockerIds,
|
||||||
blockingIds,
|
blockingIds,
|
||||||
renoteMutedIds,
|
renoteMutedIds,
|
||||||
|
suspendedUsers,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
LocalFollowingsCache.init(user.id).then((cache) => cache.getAll()),
|
LocalFollowingsCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
UserMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
UserMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
|
@ -108,6 +110,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
UserBlockedCache.init(user.id).then((cache) => cache.getAll()),
|
UserBlockedCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
RenoteMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
RenoteMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
|
SuspendedUsersCache.init().then((cache) => cache.getAll()),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const userIds: string[] = [];
|
const userIds: string[] = [];
|
||||||
|
@ -139,21 +142,21 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
.map((xs) => xs.filter((x) => x !== ""))
|
.map((xs) => xs.filter((x) => x !== ""))
|
||||||
.filter((xs) => xs.length > 0);
|
.filter((xs) => xs.length > 0);
|
||||||
|
|
||||||
const filter = async (notes: ScyllaNote[]) => {
|
const filter = (notes: ScyllaNote[]) => {
|
||||||
let filtered = await filterVisibility(notes, user, followingUserIds);
|
let filtered = filterVisibility(notes, user, followingUserIds);
|
||||||
filtered = await filterReply(filtered, antenna.withReplies, user);
|
filtered = filterReply(filtered, antenna.withReplies, user);
|
||||||
filtered = await filterMutedUser(
|
filtered = filterMutedUser(
|
||||||
filtered,
|
filtered,
|
||||||
user,
|
|
||||||
mutedUserIds,
|
mutedUserIds,
|
||||||
mutedInstances,
|
mutedInstances,
|
||||||
);
|
);
|
||||||
filtered = await filterMutedNote(filtered, user, mutedWords);
|
filtered = filterMutedNote(filtered, user, mutedWords);
|
||||||
filtered = await filterBlockUser(filtered, user, [
|
filtered = filterBlockUser(filtered, [
|
||||||
...blockerIds,
|
...blockerIds,
|
||||||
...blockingIds,
|
...blockingIds,
|
||||||
|
...suspendedUsers,
|
||||||
]);
|
]);
|
||||||
filtered = await filterMutedRenotes(filtered, user, renoteMutedIds);
|
filtered = filterMutedRenotes(filtered, renoteMutedIds);
|
||||||
if (antenna.withFile) {
|
if (antenna.withFile) {
|
||||||
filtered = filtered.filter((n) => n.files.length > 0);
|
filtered = filtered.filter((n) => n.files.length > 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
scyllaClient,
|
scyllaClient,
|
||||||
} from "@/db/scylla.js";
|
} from "@/db/scylla.js";
|
||||||
import {
|
import {
|
||||||
|
SuspendedUsersCache,
|
||||||
UserBlockedCache,
|
UserBlockedCache,
|
||||||
UserBlockingCache,
|
UserBlockingCache,
|
||||||
UserMutingsCache,
|
UserMutingsCache,
|
||||||
|
@ -87,15 +88,17 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
const suspendedUsers = await SuspendedUsersCache.init().then((cache) => cache.getAll());
|
||||||
|
|
||||||
const filter = async (notes: ScyllaNote[]) => {
|
const filter = (notes: ScyllaNote[]) => {
|
||||||
if (!user) return notes;
|
let filtered = filterBlockUser(notes, [
|
||||||
let filtered = await filterMutedUser(notes, user, mutedUserIds, []);
|
|
||||||
filtered = await filterMutedNote(filtered, user, mutedWords);
|
|
||||||
filtered = await filterBlockUser(filtered, user, [
|
|
||||||
...blockerIds,
|
...blockerIds,
|
||||||
...blockingIds,
|
...blockingIds,
|
||||||
|
...suspendedUsers
|
||||||
]);
|
]);
|
||||||
|
if (!user) return filtered;
|
||||||
|
filtered = filterMutedUser(notes, mutedUserIds, []);
|
||||||
|
filtered = filterMutedNote(filtered, user, mutedWords);
|
||||||
return filtered;
|
return filtered;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
import {
|
import {
|
||||||
InstanceMutingsCache,
|
InstanceMutingsCache,
|
||||||
LocalFollowingsCache,
|
LocalFollowingsCache,
|
||||||
|
SuspendedUsersCache,
|
||||||
UserBlockedCache,
|
UserBlockedCache,
|
||||||
UserBlockingCache,
|
UserBlockingCache,
|
||||||
UserMutingsCache,
|
UserMutingsCache,
|
||||||
|
@ -91,6 +92,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const noteIds = await ClipNotes.find({
|
const noteIds = await ClipNotes.find({
|
||||||
|
select: ["noteId"],
|
||||||
where: whereOpt,
|
where: whereOpt,
|
||||||
order: { noteId: "DESC" },
|
order: { noteId: "DESC" },
|
||||||
take: Math.min(ps.limit * 2, config.scylla?.queryLimit ?? 100),
|
take: Math.min(ps.limit * 2, config.scylla?.queryLimit ?? 100),
|
||||||
|
@ -108,6 +110,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
blockingIds,
|
blockingIds,
|
||||||
]: string[][] = [];
|
]: string[][] = [];
|
||||||
let mutedWords: string[][];
|
let mutedWords: string[][];
|
||||||
|
blockerIds = [];
|
||||||
|
blockingIds = [];
|
||||||
if (user) {
|
if (user) {
|
||||||
[
|
[
|
||||||
followingUserIds,
|
followingUserIds,
|
||||||
|
@ -132,22 +136,22 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
const suspendedUserIds = await SuspendedUsersCache.init().then((cache) => cache.getAll());
|
||||||
|
|
||||||
const filter = async (notes: ScyllaNote[]) => {
|
const filter = (notes: ScyllaNote[]) => {
|
||||||
let filtered = notes;
|
let filtered = filterBlockUser(notes, [
|
||||||
|
...blockerIds,
|
||||||
|
...blockingIds,
|
||||||
|
...suspendedUserIds,
|
||||||
|
]);
|
||||||
if (user) {
|
if (user) {
|
||||||
filtered = await filterVisibility(filtered, user, followingUserIds);
|
filtered = filterVisibility(filtered, user, followingUserIds);
|
||||||
filtered = await filterMutedUser(
|
filtered = filterMutedUser(
|
||||||
filtered,
|
filtered,
|
||||||
user,
|
|
||||||
mutedUserIds,
|
mutedUserIds,
|
||||||
mutedInstances,
|
mutedInstances,
|
||||||
);
|
);
|
||||||
filtered = await filterMutedNote(filtered, user, mutedWords);
|
filtered = filterMutedNote(filtered, user, mutedWords);
|
||||||
filtered = await filterBlockUser(filtered, user, [
|
|
||||||
...blockerIds,
|
|
||||||
...blockingIds,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
return filtered;
|
return filtered;
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
import {
|
import {
|
||||||
InstanceMutingsCache,
|
InstanceMutingsCache,
|
||||||
LocalFollowingsCache,
|
LocalFollowingsCache,
|
||||||
|
SuspendedUsersCache,
|
||||||
UserBlockedCache,
|
UserBlockedCache,
|
||||||
UserBlockingCache,
|
UserBlockingCache,
|
||||||
UserMutingsCache,
|
UserMutingsCache,
|
||||||
|
@ -98,12 +99,14 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
mutedInstances,
|
mutedInstances,
|
||||||
blockerIds,
|
blockerIds,
|
||||||
blockingIds,
|
blockingIds,
|
||||||
|
suspendedUsers,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
LocalFollowingsCache.init(user.id).then((cache) => cache.getAll()),
|
LocalFollowingsCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
UserMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
UserMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
InstanceMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
InstanceMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
UserBlockedCache.init(user.id).then((cache) => cache.getAll()),
|
UserBlockedCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
|
SuspendedUsersCache.init().then((cache) => cache.getAll()),
|
||||||
]);
|
]);
|
||||||
const validUserIds = [user.id, ...followingUserIds];
|
const validUserIds = [user.id, ...followingUserIds];
|
||||||
|
|
||||||
|
@ -130,7 +133,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
n.notifierId &&
|
n.notifierId &&
|
||||||
(mutedUserIds.includes(n.notifierId) ||
|
(mutedUserIds.includes(n.notifierId) ||
|
||||||
blockingIds.includes(n.notifierId) ||
|
blockingIds.includes(n.notifierId) ||
|
||||||
blockerIds.includes(n.notifierId))
|
blockerIds.includes(n.notifierId) ||
|
||||||
|
suspendedUsers.includes(n.notifierId))
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (ps.directOnly) {
|
if (ps.directOnly) {
|
||||||
|
|
|
@ -42,7 +42,7 @@ export const paramDef = {
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps) => {
|
export default define(meta, paramDef, async (ps) => {
|
||||||
if (scyllaClient) {
|
if (scyllaClient) {
|
||||||
const filter = async (notes: ScyllaNote[]) => {
|
const filter = (notes: ScyllaNote[]) => {
|
||||||
let filtered = notes.filter((note) => !note.localOnly);
|
let filtered = notes.filter((note) => !note.localOnly);
|
||||||
if (ps.reply === undefined) {
|
if (ps.reply === undefined) {
|
||||||
filtered = filtered.filter(
|
filtered = filtered.filter(
|
||||||
|
|
|
@ -19,6 +19,7 @@ import type { Note } from "@/models/entities/note.js";
|
||||||
import {
|
import {
|
||||||
InstanceMutingsCache,
|
InstanceMutingsCache,
|
||||||
LocalFollowingsCache,
|
LocalFollowingsCache,
|
||||||
|
SuspendedUsersCache,
|
||||||
UserBlockedCache,
|
UserBlockedCache,
|
||||||
UserBlockingCache,
|
UserBlockingCache,
|
||||||
UserMutingsCache,
|
UserMutingsCache,
|
||||||
|
@ -67,6 +68,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
blockingIds,
|
blockingIds,
|
||||||
]: string[][] = [];
|
]: string[][] = [];
|
||||||
let mutedWords: string[][] = [];
|
let mutedWords: string[][] = [];
|
||||||
|
blockerIds = [];
|
||||||
|
blockingIds = [];
|
||||||
if (user) {
|
if (user) {
|
||||||
[
|
[
|
||||||
followingUserIds,
|
followingUserIds,
|
||||||
|
@ -91,6 +94,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
const suspendedUserIds = await SuspendedUsersCache.init().then((cache) => cache.getAll());
|
||||||
|
|
||||||
const root = await getNote(ps.noteId, user, followingUserIds).catch(
|
const root = await getNote(ps.noteId, user, followingUserIds).catch(
|
||||||
() => null,
|
() => null,
|
||||||
|
@ -99,20 +103,20 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
return await Notes.packMany([]);
|
return await Notes.packMany([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const filter = async (notes: ScyllaNote[]) => {
|
const filter = (notes: ScyllaNote[]) => {
|
||||||
let filtered = await filterVisibility(notes, user, followingUserIds);
|
let filtered = filterVisibility(notes, user, followingUserIds);
|
||||||
|
filtered = filterBlockUser(filtered, [
|
||||||
|
...blockerIds,
|
||||||
|
...blockingIds,
|
||||||
|
...suspendedUserIds,
|
||||||
|
]);
|
||||||
if (user) {
|
if (user) {
|
||||||
filtered = await filterMutedUser(
|
filtered = filterMutedUser(
|
||||||
filtered,
|
filtered,
|
||||||
user,
|
|
||||||
mutedUserIds,
|
mutedUserIds,
|
||||||
mutedInstances,
|
mutedInstances,
|
||||||
);
|
);
|
||||||
filtered = await filterMutedNote(filtered, user, mutedWords);
|
filtered = filterMutedNote(filtered, user, mutedWords);
|
||||||
filtered = await filterBlockUser(filtered, user, [
|
|
||||||
...blockerIds,
|
|
||||||
...blockingIds,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
return filtered;
|
return filtered;
|
||||||
};
|
};
|
||||||
|
@ -123,7 +127,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
[root.id],
|
[root.id],
|
||||||
{ prepare: true },
|
{ prepare: true },
|
||||||
);
|
);
|
||||||
const foundNotes = await filter(
|
const foundNotes = filter(
|
||||||
renoteResult.rows.map(parseScyllaNote).filter((note) => !!note.text),
|
renoteResult.rows.map(parseScyllaNote).filter((note) => !!note.text),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -140,7 +144,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
[note.id],
|
[note.id],
|
||||||
{ prepare: true },
|
{ prepare: true },
|
||||||
);
|
);
|
||||||
const replies = await filter(replyResult.rows.map(parseScyllaNote));
|
const replies = filter(replyResult.rows.map(parseScyllaNote));
|
||||||
if (replies.length > 0) {
|
if (replies.length > 0) {
|
||||||
foundNotes.push(...replies);
|
foundNotes.push(...replies);
|
||||||
queue.push(...replies);
|
queue.push(...replies);
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
} from "@/db/scylla.js";
|
} from "@/db/scylla.js";
|
||||||
import {
|
import {
|
||||||
InstanceMutingsCache,
|
InstanceMutingsCache,
|
||||||
|
SuspendedUsersCache,
|
||||||
UserBlockedCache,
|
UserBlockedCache,
|
||||||
UserBlockingCache,
|
UserBlockingCache,
|
||||||
UserMutingsCache,
|
UserMutingsCache,
|
||||||
|
@ -63,6 +64,9 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
let [mutedUserIds, mutedInstances, blockerIds, blockingIds]: string[][] =
|
let [mutedUserIds, mutedInstances, blockerIds, blockingIds]: string[][] =
|
||||||
[];
|
[];
|
||||||
let mutedWords: string[][] = [];
|
let mutedWords: string[][] = [];
|
||||||
|
blockerIds = [];
|
||||||
|
blockingIds = [];
|
||||||
|
const suspendedUserIds = await SuspendedUsersCache.init().then((cache) => cache.getAll());
|
||||||
|
|
||||||
const foundNotes: ScyllaNote[] = [];
|
const foundNotes: ScyllaNote[] = [];
|
||||||
let searchedDays = 0;
|
let searchedDays = 0;
|
||||||
|
@ -101,18 +105,19 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notes = filterBlockUser(notes, [
|
||||||
|
...blockerIds,
|
||||||
|
...blockingIds,
|
||||||
|
...suspendedUserIds,
|
||||||
|
]);
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
notes = await filterMutedUser(
|
notes = filterMutedUser(
|
||||||
notes,
|
notes,
|
||||||
user,
|
|
||||||
mutedUserIds,
|
mutedUserIds,
|
||||||
mutedInstances,
|
mutedInstances,
|
||||||
);
|
);
|
||||||
notes = await filterMutedNote(notes, user, mutedWords);
|
notes = filterMutedNote(notes, user, mutedWords);
|
||||||
notes = await filterBlockUser(notes, user, [
|
|
||||||
...blockerIds,
|
|
||||||
...blockingIds,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foundNotes.push(...notes);
|
foundNotes.push(...notes);
|
||||||
|
|
|
@ -22,6 +22,7 @@ import {
|
||||||
import {
|
import {
|
||||||
InstanceMutingsCache,
|
InstanceMutingsCache,
|
||||||
RenoteMutingsCache,
|
RenoteMutingsCache,
|
||||||
|
SuspendedUsersCache,
|
||||||
UserBlockedCache,
|
UserBlockedCache,
|
||||||
UserBlockingCache,
|
UserBlockingCache,
|
||||||
UserMutingsCache,
|
UserMutingsCache,
|
||||||
|
@ -103,6 +104,9 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
renoteMutedIds,
|
renoteMutedIds,
|
||||||
]: string[][] = [];
|
]: string[][] = [];
|
||||||
let mutedWords: string[][];
|
let mutedWords: string[][];
|
||||||
|
blockerIds = [];
|
||||||
|
blockingIds = [];
|
||||||
|
const suspendedUsers = await SuspendedUsersCache.init().then((cache) => cache.getAll());
|
||||||
if (user) {
|
if (user) {
|
||||||
[
|
[
|
||||||
mutedUserIds,
|
mutedUserIds,
|
||||||
|
@ -128,24 +132,24 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const filter = async (notes: ScyllaNote[]) => {
|
const filter = (notes: ScyllaNote[]) => {
|
||||||
let filtered = notes.filter(
|
let filtered = notes.filter(
|
||||||
(n) => n.visibility === "public" && !n.channelId,
|
(n) => n.visibility === "public" && !n.channelId,
|
||||||
);
|
);
|
||||||
filtered = await filterReply(filtered, ps.withReplies, user);
|
filtered = filterReply(filtered, ps.withReplies, user);
|
||||||
|
filtered = filterBlockUser(filtered, [
|
||||||
|
...blockerIds,
|
||||||
|
...blockingIds,
|
||||||
|
...suspendedUsers,
|
||||||
|
]);
|
||||||
if (user) {
|
if (user) {
|
||||||
filtered = await filterMutedUser(
|
filtered = filterMutedUser(
|
||||||
filtered,
|
filtered,
|
||||||
user,
|
|
||||||
mutedUserIds,
|
mutedUserIds,
|
||||||
mutedInstances,
|
mutedInstances,
|
||||||
);
|
);
|
||||||
filtered = await filterMutedNote(filtered, user, mutedWords);
|
filtered = filterMutedNote(filtered, user, mutedWords);
|
||||||
filtered = await filterBlockUser(filtered, user, [
|
filtered = filterMutedRenotes(filtered, renoteMutedIds);
|
||||||
...blockerIds,
|
|
||||||
...blockingIds,
|
|
||||||
]);
|
|
||||||
filtered = await filterMutedRenotes(filtered, user, renoteMutedIds);
|
|
||||||
}
|
}
|
||||||
if (ps.withFiles) {
|
if (ps.withFiles) {
|
||||||
filtered = filtered.filter((n) => n.files.length > 0);
|
filtered = filtered.filter((n) => n.files.length > 0);
|
||||||
|
|
|
@ -29,6 +29,7 @@ import {
|
||||||
InstanceMutingsCache,
|
InstanceMutingsCache,
|
||||||
LocalFollowingsCache,
|
LocalFollowingsCache,
|
||||||
RenoteMutingsCache,
|
RenoteMutingsCache,
|
||||||
|
SuspendedUsersCache,
|
||||||
UserBlockedCache,
|
UserBlockedCache,
|
||||||
UserBlockingCache,
|
UserBlockingCache,
|
||||||
UserMutingsCache,
|
UserMutingsCache,
|
||||||
|
@ -111,6 +112,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
blockerIds,
|
blockerIds,
|
||||||
blockingIds,
|
blockingIds,
|
||||||
renoteMutedIds,
|
renoteMutedIds,
|
||||||
|
suspendedUserIds,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
ChannelFollowingsCache.init(user.id).then((cache) => cache.getAll()),
|
ChannelFollowingsCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
LocalFollowingsCache.init(user.id).then((cache) => cache.getAll()),
|
LocalFollowingsCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
|
@ -127,6 +129,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
UserBlockedCache.init(user.id).then((cache) => cache.getAll()),
|
UserBlockedCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
RenoteMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
RenoteMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
|
SuspendedUsersCache.init().then((cache) => cache.getAll()),
|
||||||
]);
|
]);
|
||||||
const homeUserIds = [user.id, ...followingUserIds];
|
const homeUserIds = [user.id, ...followingUserIds];
|
||||||
const optFilter = (n: ScyllaNote) =>
|
const optFilter = (n: ScyllaNote) =>
|
||||||
|
@ -137,22 +140,22 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
const localFilter = (notes: ScyllaNote[]) =>
|
const localFilter = (notes: ScyllaNote[]) =>
|
||||||
notes.filter((n) => !homeUserIds.includes(n.userId));
|
notes.filter((n) => !homeUserIds.includes(n.userId));
|
||||||
|
|
||||||
const commonFilter = async (notes: ScyllaNote[]) => {
|
const commonFilter = (notes: ScyllaNote[]) => {
|
||||||
let filtered = await filterChannel(notes, user, followingChannelIds);
|
let filtered = filterChannel(notes, user, followingChannelIds);
|
||||||
filtered = await filterReply(filtered, ps.withReplies, user);
|
filtered = filterReply(filtered, ps.withReplies, user);
|
||||||
filtered = await filterVisibility(filtered, user, followingUserIds);
|
filtered = filterVisibility(filtered, user, followingUserIds);
|
||||||
filtered = await filterMutedUser(
|
filtered = filterMutedUser(
|
||||||
filtered,
|
filtered,
|
||||||
user,
|
|
||||||
mutedUserIds,
|
mutedUserIds,
|
||||||
mutedInstances,
|
mutedInstances,
|
||||||
);
|
);
|
||||||
filtered = await filterMutedNote(filtered, user, mutedWords);
|
filtered = filterMutedNote(filtered, user, mutedWords);
|
||||||
filtered = await filterBlockUser(filtered, user, [
|
filtered = filterBlockUser(filtered, [
|
||||||
...blockerIds,
|
...blockerIds,
|
||||||
...blockingIds,
|
...blockingIds,
|
||||||
|
...suspendedUserIds,
|
||||||
]);
|
]);
|
||||||
filtered = await filterMutedRenotes(filtered, user, renoteMutedIds);
|
filtered = filterMutedRenotes(filtered, renoteMutedIds);
|
||||||
if (!ps.includeMyRenotes) {
|
if (!ps.includeMyRenotes) {
|
||||||
filtered = filtered.filter((n) => n.userId !== user.id || optFilter(n));
|
filtered = filtered.filter((n) => n.userId !== user.id || optFilter(n));
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import {
|
||||||
InstanceMutingsCache,
|
InstanceMutingsCache,
|
||||||
LocalFollowingsCache,
|
LocalFollowingsCache,
|
||||||
RenoteMutingsCache,
|
RenoteMutingsCache,
|
||||||
|
SuspendedUsersCache,
|
||||||
UserBlockedCache,
|
UserBlockedCache,
|
||||||
UserBlockingCache,
|
UserBlockingCache,
|
||||||
UserMutingsCache,
|
UserMutingsCache,
|
||||||
|
@ -120,6 +121,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
renoteMutedIds,
|
renoteMutedIds,
|
||||||
]: string[][] = [];
|
]: string[][] = [];
|
||||||
let mutedWords: string[][];
|
let mutedWords: string[][];
|
||||||
|
blockerIds = [];
|
||||||
|
blockingIds = [];
|
||||||
if (user) {
|
if (user) {
|
||||||
[
|
[
|
||||||
followingChannelIds,
|
followingChannelIds,
|
||||||
|
@ -148,24 +151,25 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
RenoteMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
RenoteMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
const suspendedUserIds = await SuspendedUsersCache.init().then((cache) => cache.getAll());
|
||||||
|
|
||||||
const filter = async (notes: ScyllaNote[]) => {
|
const filter = (notes: ScyllaNote[]) => {
|
||||||
let filtered = await filterChannel(notes, user, followingChannelIds);
|
let filtered = filterChannel(notes, user, followingChannelIds);
|
||||||
filtered = await filterReply(filtered, ps.withReplies, user);
|
filtered = filterReply(filtered, ps.withReplies, user);
|
||||||
filtered = await filterVisibility(filtered, user, followingUserIds);
|
filtered = filterVisibility(filtered, user, followingUserIds);
|
||||||
|
filtered = filterBlockUser(filtered, [
|
||||||
|
...blockerIds,
|
||||||
|
...blockingIds,
|
||||||
|
...suspendedUserIds,
|
||||||
|
]);
|
||||||
if (user) {
|
if (user) {
|
||||||
filtered = await filterMutedUser(
|
filtered = filterMutedUser(
|
||||||
filtered,
|
filtered,
|
||||||
user,
|
|
||||||
mutedUserIds,
|
mutedUserIds,
|
||||||
mutedInstances,
|
mutedInstances,
|
||||||
);
|
);
|
||||||
filtered = await filterMutedNote(filtered, user, mutedWords);
|
filtered = filterMutedNote(filtered, user, mutedWords);
|
||||||
filtered = await filterBlockUser(filtered, user, [
|
filtered = filterMutedRenotes(filtered, renoteMutedIds);
|
||||||
...blockerIds,
|
|
||||||
...blockingIds,
|
|
||||||
]);
|
|
||||||
filtered = await filterMutedRenotes(filtered, user, renoteMutedIds);
|
|
||||||
}
|
}
|
||||||
if (ps.withFiles) {
|
if (ps.withFiles) {
|
||||||
filtered = filtered.filter((n) => n.files.length > 0);
|
filtered = filtered.filter((n) => n.files.length > 0);
|
||||||
|
|
|
@ -27,6 +27,7 @@ import {
|
||||||
InstanceMutingsCache,
|
InstanceMutingsCache,
|
||||||
LocalFollowingsCache,
|
LocalFollowingsCache,
|
||||||
RenoteMutingsCache,
|
RenoteMutingsCache,
|
||||||
|
SuspendedUsersCache,
|
||||||
UserBlockedCache,
|
UserBlockedCache,
|
||||||
UserBlockingCache,
|
UserBlockingCache,
|
||||||
UserMutingsCache,
|
UserMutingsCache,
|
||||||
|
@ -116,6 +117,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
renoteMutedIds,
|
renoteMutedIds,
|
||||||
]: string[][] = [];
|
]: string[][] = [];
|
||||||
let mutedWords: string[][];
|
let mutedWords: string[][];
|
||||||
|
blockerIds = [];
|
||||||
|
blockingIds = [];
|
||||||
if (user) {
|
if (user) {
|
||||||
[
|
[
|
||||||
followingUserIds,
|
followingUserIds,
|
||||||
|
@ -142,8 +145,9 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
RenoteMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
RenoteMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
const suspendedUserIds = await SuspendedUsersCache.init().then((cache) => cache.getAll());
|
||||||
|
|
||||||
const filter = async (notes: ScyllaNote[]) => {
|
const filter = (notes: ScyllaNote[]) => {
|
||||||
let filtered = notes.filter(
|
let filtered = notes.filter(
|
||||||
(n) =>
|
(n) =>
|
||||||
n.visibility === "public" &&
|
n.visibility === "public" &&
|
||||||
|
@ -151,21 +155,21 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
m.recommendedInstances.includes(n.userHost) &&
|
m.recommendedInstances.includes(n.userHost) &&
|
||||||
!n.channelId,
|
!n.channelId,
|
||||||
);
|
);
|
||||||
filtered = await filterReply(filtered, ps.withReplies, user);
|
filtered = filterReply(filtered, ps.withReplies, user);
|
||||||
filtered = await filterVisibility(filtered, user, followingUserIds);
|
filtered = filterVisibility(filtered, user, followingUserIds);
|
||||||
|
filtered = filterBlockUser(filtered, [
|
||||||
|
...blockerIds,
|
||||||
|
...blockingIds,
|
||||||
|
...suspendedUserIds,
|
||||||
|
]);
|
||||||
if (user) {
|
if (user) {
|
||||||
filtered = await filterMutedUser(
|
filtered = filterMutedUser(
|
||||||
filtered,
|
filtered,
|
||||||
user,
|
|
||||||
mutedUserIds,
|
mutedUserIds,
|
||||||
mutedInstances,
|
mutedInstances,
|
||||||
);
|
);
|
||||||
filtered = await filterMutedNote(filtered, user, mutedWords);
|
filtered = filterMutedNote(filtered, user, mutedWords);
|
||||||
filtered = await filterBlockUser(filtered, user, [
|
filtered = filterMutedRenotes(filtered, renoteMutedIds);
|
||||||
...blockerIds,
|
|
||||||
...blockingIds,
|
|
||||||
]);
|
|
||||||
filtered = await filterMutedRenotes(filtered, user, renoteMutedIds);
|
|
||||||
}
|
}
|
||||||
if (ps.withFiles) {
|
if (ps.withFiles) {
|
||||||
filtered = filtered.filter((n) => n.files.length > 0);
|
filtered = filtered.filter((n) => n.files.length > 0);
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
import {
|
import {
|
||||||
InstanceMutingsCache,
|
InstanceMutingsCache,
|
||||||
LocalFollowingsCache,
|
LocalFollowingsCache,
|
||||||
|
SuspendedUsersCache,
|
||||||
UserBlockedCache,
|
UserBlockedCache,
|
||||||
UserBlockingCache,
|
UserBlockingCache,
|
||||||
UserMutingsCache,
|
UserMutingsCache,
|
||||||
|
@ -78,6 +79,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
if (scyllaClient) {
|
if (scyllaClient) {
|
||||||
let [mutedUserIds, mutedInstances, blockerIds, blockingIds]: string[][] =
|
let [mutedUserIds, mutedInstances, blockerIds, blockingIds]: string[][] =
|
||||||
[];
|
[];
|
||||||
|
blockerIds = [];
|
||||||
|
blockingIds = [];
|
||||||
if (user) {
|
if (user) {
|
||||||
[mutedUserIds, mutedInstances, blockerIds, blockingIds] =
|
[mutedUserIds, mutedInstances, blockerIds, blockingIds] =
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
@ -87,24 +90,25 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
const suspendedUserIds = await SuspendedUsersCache.init().then((cache) => cache.getAll());
|
||||||
|
|
||||||
const filter = async (notes: ScyllaNote[]) => {
|
const filter = (notes: ScyllaNote[]) => {
|
||||||
let filtered = notes;
|
let filtered = notes;
|
||||||
if (ps.userId) {
|
if (ps.userId) {
|
||||||
filtered = filtered.filter((n) => n.userId === ps.userId);
|
filtered = filtered.filter((n) => n.userId === ps.userId);
|
||||||
}
|
}
|
||||||
filtered = await filterVisibility(filtered, user, followingUserIds);
|
filtered = filterVisibility(filtered, user, followingUserIds);
|
||||||
|
filtered = filterBlockUser(filtered, [
|
||||||
|
...blockerIds,
|
||||||
|
...blockingIds,
|
||||||
|
...suspendedUserIds,
|
||||||
|
]);
|
||||||
if (user) {
|
if (user) {
|
||||||
filtered = await filterMutedUser(
|
filtered = filterMutedUser(
|
||||||
filtered,
|
filtered,
|
||||||
user,
|
|
||||||
mutedUserIds,
|
mutedUserIds,
|
||||||
mutedInstances,
|
mutedInstances,
|
||||||
);
|
);
|
||||||
filtered = await filterBlockUser(filtered, user, [
|
|
||||||
...blockerIds,
|
|
||||||
...blockingIds,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
return filtered;
|
return filtered;
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,6 +28,7 @@ import {
|
||||||
InstanceMutingsCache,
|
InstanceMutingsCache,
|
||||||
LocalFollowingsCache,
|
LocalFollowingsCache,
|
||||||
RenoteMutingsCache,
|
RenoteMutingsCache,
|
||||||
|
SuspendedUsersCache,
|
||||||
UserBlockedCache,
|
UserBlockedCache,
|
||||||
UserBlockingCache,
|
UserBlockingCache,
|
||||||
UserMutingsCache,
|
UserMutingsCache,
|
||||||
|
@ -102,6 +103,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
blockerIds,
|
blockerIds,
|
||||||
blockingIds,
|
blockingIds,
|
||||||
renoteMutedIds,
|
renoteMutedIds,
|
||||||
|
suspendedUserIds,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
ChannelFollowingsCache.init(user.id).then((cache) => cache.getAll()),
|
ChannelFollowingsCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
followingsCache.getAll(),
|
followingsCache.getAll(),
|
||||||
|
@ -118,28 +120,29 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
UserBlockedCache.init(user.id).then((cache) => cache.getAll()),
|
UserBlockedCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
RenoteMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
RenoteMutingsCache.init(user.id).then((cache) => cache.getAll()),
|
||||||
|
SuspendedUsersCache.init().then((cache) => cache.getAll()),
|
||||||
]);
|
]);
|
||||||
const validUserIds = [user.id, ...followingUserIds];
|
const validUserIds = [user.id, ...followingUserIds];
|
||||||
const optFilter = (n: ScyllaNote) =>
|
const optFilter = (n: ScyllaNote) =>
|
||||||
!n.renoteId || !!n.text || n.files.length > 0 || n.hasPoll;
|
!n.renoteId || !!n.text || n.files.length > 0 || n.hasPoll;
|
||||||
|
|
||||||
const filter = async (notes: ScyllaNote[]) => {
|
const filter = (notes: ScyllaNote[]) => {
|
||||||
let filtered = notes.filter((n) => validUserIds.includes(n.userId));
|
let filtered = notes.filter((n) => validUserIds.includes(n.userId));
|
||||||
filtered = await filterChannel(filtered, user, followingChannelIds);
|
filtered = filterChannel(filtered, user, followingChannelIds);
|
||||||
filtered = await filterReply(filtered, ps.withReplies, user);
|
filtered = filterReply(filtered, ps.withReplies, user);
|
||||||
filtered = await filterVisibility(filtered, user, followingUserIds);
|
filtered = filterVisibility(filtered, user, followingUserIds);
|
||||||
filtered = await filterMutedUser(
|
filtered = filterMutedUser(
|
||||||
filtered,
|
filtered,
|
||||||
user,
|
|
||||||
mutedUserIds,
|
mutedUserIds,
|
||||||
mutedInstances,
|
mutedInstances,
|
||||||
);
|
);
|
||||||
filtered = await filterMutedNote(filtered, user, mutedWords);
|
filtered = filterMutedNote(filtered, user, mutedWords);
|
||||||
filtered = await filterBlockUser(filtered, user, [
|
filtered = filterBlockUser(filtered, [
|
||||||
...blockerIds,
|
...blockerIds,
|
||||||
...blockingIds,
|
...blockingIds,
|
||||||
|
...suspendedUserIds,
|
||||||
]);
|
]);
|
||||||
filtered = await filterMutedRenotes(filtered, user, renoteMutedIds);
|
filtered = filterMutedRenotes(filtered, renoteMutedIds);
|
||||||
if (!ps.includeMyRenotes) {
|
if (!ps.includeMyRenotes) {
|
||||||
filtered = filtered.filter((n) => n.userId !== user.id || optFilter(n));
|
filtered = filtered.filter((n) => n.userId !== user.id || optFilter(n));
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,8 +91,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
);
|
);
|
||||||
const optFilter = (n: ScyllaNote) =>
|
const optFilter = (n: ScyllaNote) =>
|
||||||
!n.renoteId || !!n.text || n.files.length > 0 || n.hasPoll;
|
!n.renoteId || !!n.text || n.files.length > 0 || n.hasPoll;
|
||||||
const filter = async (notes: ScyllaNote[]) => {
|
const filter = (notes: ScyllaNote[]) => {
|
||||||
let filtered = await filterVisibility(notes, user, followingUserIds);
|
let filtered = filterVisibility(notes, user, followingUserIds);
|
||||||
if (!ps.includeMyRenotes) {
|
if (!ps.includeMyRenotes) {
|
||||||
filtered = filtered.filter((n) => n.userId !== user.id || optFilter(n));
|
filtered = filtered.filter((n) => n.userId !== user.id || optFilter(n));
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
InstanceMutingsCache,
|
InstanceMutingsCache,
|
||||||
LocalFollowingsCache,
|
LocalFollowingsCache,
|
||||||
RenoteMutingsCache,
|
RenoteMutingsCache,
|
||||||
|
SuspendedUsersCache,
|
||||||
UserBlockedCache,
|
UserBlockedCache,
|
||||||
UserBlockingCache,
|
UserBlockingCache,
|
||||||
UserMutingsCache,
|
UserMutingsCache,
|
||||||
|
@ -94,6 +95,8 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
blockingIds,
|
blockingIds,
|
||||||
]: string[][] = [];
|
]: string[][] = [];
|
||||||
let mutedWords: string[][];
|
let mutedWords: string[][];
|
||||||
|
blockerIds = [];
|
||||||
|
blockingIds = [];
|
||||||
if (me) {
|
if (me) {
|
||||||
[
|
[
|
||||||
followingUserIds,
|
followingUserIds,
|
||||||
|
@ -118,6 +121,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
UserBlockingCache.init(me.id).then((cache) => cache.getAll()),
|
UserBlockingCache.init(me.id).then((cache) => cache.getAll()),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
const suspendedUserIds = await SuspendedUsersCache.init().then((cache) => cache.getAll());
|
||||||
|
|
||||||
if (
|
if (
|
||||||
me &&
|
me &&
|
||||||
|
@ -128,21 +132,21 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
return Notes.packMany([]);
|
return Notes.packMany([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const filter = async (notes: ScyllaNote[]) => {
|
const filter = (notes: ScyllaNote[]) => {
|
||||||
let filtered = notes.filter((n) => n.userId === ps.userId);
|
let filtered = notes.filter((n) => n.userId === ps.userId);
|
||||||
filtered = await filterVisibility(filtered, me, followingUserIds);
|
filtered = filterVisibility(filtered, me, followingUserIds);
|
||||||
|
filtered = filterBlockUser(filtered, [
|
||||||
|
...blockerIds,
|
||||||
|
...blockingIds,
|
||||||
|
...suspendedUserIds,
|
||||||
|
]);
|
||||||
if (me) {
|
if (me) {
|
||||||
filtered = await filterMutedUser(
|
filtered = filterMutedUser(
|
||||||
filtered,
|
filtered,
|
||||||
me,
|
|
||||||
mutedUserIds,
|
mutedUserIds,
|
||||||
mutedInstances,
|
mutedInstances,
|
||||||
);
|
);
|
||||||
filtered = await filterMutedNote(filtered, me, mutedWords);
|
filtered = filterMutedNote(filtered, me, mutedWords);
|
||||||
filtered = await filterBlockUser(filtered, me, [
|
|
||||||
...blockerIds,
|
|
||||||
...blockingIds,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
if (ps.withFiles) {
|
if (ps.withFiles) {
|
||||||
filtered = filtered.filter((n) => n.files.length > 0);
|
filtered = filtered.filter((n) => n.files.length > 0);
|
||||||
|
|
|
@ -79,11 +79,11 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
const notes = await client
|
const notes = await client
|
||||||
.execute(prepared.note.select.byIds, [noteIds], { prepare: true })
|
.execute(prepared.note.select.byIds, [noteIds], { prepare: true })
|
||||||
.then((result) => result.rows.map(parseScyllaNote));
|
.then((result) => result.rows.map(parseScyllaNote));
|
||||||
const filteredNoteIds = await filterVisibility(
|
const filteredNoteIds = filterVisibility(
|
||||||
notes,
|
notes,
|
||||||
me,
|
me,
|
||||||
followingUserIds,
|
followingUserIds,
|
||||||
).then((notes) => notes.map(({ id }) => id));
|
).map(({ id }) => id);
|
||||||
noteIds = noteIds.filter((id) => filteredNoteIds.includes(id));
|
noteIds = noteIds.filter((id) => filteredNoteIds.includes(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue