wip: clips

This commit is contained in:
Namekuji 2023-08-22 23:55:55 -04:00
parent e6df07afb0
commit ec3ad96d81
No known key found for this signature in database
GPG key ID: 1D62332C07FBA532

View file

@ -1,10 +1,30 @@
import define from "../../define.js"; import define from "../../define.js";
import { ClipNotes, Clips, Notes } from "@/models/index.js"; import { ClipNotes, Clips, Notes, UserProfiles } 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";
import {
type ScyllaNote,
scyllaClient,
filterVisibility,
filterMutedUser,
filterMutedNote,
filterBlockUser,
prepared,
parseScyllaNote,
} from "@/db/scylla.js";
import {
InstanceMutingsCache,
LocalFollowingsCache,
UserBlockedCache,
UserBlockingCache,
UserMutingsCache,
userWordMuteCache,
} from "@/misc/cache.js";
import { Between, MoreThan, LessThan, FindOptionsWhere } from "typeorm";
import type { ClipNote } from "@/models/entities/clip-note.js";
export const meta = { export const meta = {
tags: ["account", "notes", "clips"], tags: ["account", "notes", "clips"],
@ -51,7 +71,7 @@ export default define(meta, paramDef, async (ps, user) => {
id: ps.clipId, id: ps.clipId,
}); });
if (clip == null) { if (!clip) {
throw new ApiError(meta.errors.noSuchClip); throw new ApiError(meta.errors.noSuchClip);
} }
@ -59,6 +79,86 @@ export default define(meta, paramDef, async (ps, user) => {
throw new ApiError(meta.errors.noSuchClip); throw new ApiError(meta.errors.noSuchClip);
} }
if (scyllaClient) {
let whereOpt: FindOptionsWhere<ClipNote> = { clipId: clip.id };
if (ps.sinceId && ps.untilId) {
whereOpt = { ...whereOpt, noteId: Between(ps.sinceId, ps.untilId) };
} else if (ps.sinceId) {
whereOpt = { ...whereOpt, noteId: MoreThan(ps.sinceId) };
} else if (ps.untilId) {
whereOpt = { ...whereOpt, noteId: LessThan(ps.untilId) };
}
const noteIds = await ClipNotes.find({
select: ["noteId"],
where: whereOpt,
order: { noteId: "DESC" },
take: ps.limit,
});
if (noteIds.length === 0) {
throw new ApiError(meta.errors.noSuchClip);
}
let [
followingUserIds,
mutedUserIds,
mutedInstances,
blockerIds,
blockingIds,
]: string[][] = [];
let mutedWords: string[][];
if (user) {
[
followingUserIds,
mutedUserIds,
mutedInstances,
mutedWords,
blockerIds,
blockingIds,
] = await Promise.all([
LocalFollowingsCache.init(user.id).then((cache) => cache.getAll()),
UserMutingsCache.init(user.id).then((cache) => cache.getAll()),
InstanceMutingsCache.init(user.id).then((cache) => cache.getAll()),
userWordMuteCache
.fetchMaybe(user.id, () =>
UserProfiles.findOne({
select: ["mutedWords"],
where: { userId: user.id },
}).then((profile) => profile?.mutedWords),
)
.then((words) => words ?? []),
UserBlockedCache.init(user.id).then((cache) => cache.getAll()),
UserBlockingCache.init(user.id).then((cache) => cache.getAll()),
]);
}
const filter = async (notes: ScyllaNote[]) => {
let filtered = notes;
if (user) {
filtered = await filterVisibility(filtered, user, followingUserIds);
filtered = await filterMutedUser(
filtered,
user,
mutedUserIds,
mutedInstances,
);
filtered = await filterMutedNote(filtered, user, mutedWords);
filtered = await filterBlockUser(filtered, user, [
...blockerIds,
...blockingIds,
]);
}
return filtered;
};
const foundNotes = await scyllaClient
.execute(prepared.note.select.byIds, [noteIds], { prepare: true })
.then((result) => result.rows.map(parseScyllaNote));
return Notes.packMany(await filter(foundNotes), user);
}
const query = makePaginationQuery( const query = makePaginationQuery(
Notes.createQueryBuilder("note"), Notes.createQueryBuilder("note"),
ps.sinceId, ps.sinceId,
@ -69,17 +169,8 @@ 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.reply", "reply")
.leftJoinAndSelect("note.renote", "renote") .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) { if (user) {