further cleanup

This commit is contained in:
Namekuji 2023-09-05 10:58:20 -04:00
parent 2570f8a9eb
commit efda68bc64
No known key found for this signature in database
GPG key ID: 1D62332C07FBA532
8 changed files with 178 additions and 40 deletions

View file

@ -1,4 +1,14 @@
user-agent: * User-agent: *
allow: / Allow: /
# todo: sitemap # Uncomment the following to block CommonCrawl
#
# User-agent: CCBot
# User-agent: CCBot/2.0
# User-agent: CCBot/3.1
# Disallow: /
# Uncomment the following to block ChatGPT
#
# User-agent: GPTBot
# Disallow: /

View file

@ -33,6 +33,8 @@ import Following from "./activitypub/following.js";
import Followers from "./activitypub/followers.js"; import Followers from "./activitypub/followers.js";
import Outbox, { packActivity } from "./activitypub/outbox.js"; import Outbox, { packActivity } from "./activitypub/outbox.js";
import { serverLogger } from "./index.js"; import { serverLogger } from "./index.js";
import { parseScyllaNote, prepared, scyllaClient } from "@/db/scylla.js";
import type { Note } from "@/models/entities/note.js";
// Init router // Init router
const router = new Router(); const router = new Router();
@ -87,13 +89,32 @@ router.get("/notes/:note", async (ctx, next) => {
return; return;
} }
const note = await Notes.findOneBy({ let note: Note | null = null;
id: ctx.params.note, const validVisibilities = ["public", "home", "followers"];
visibility: In(["public" as const, "home" as const, "followers" as const]), if (scyllaClient) {
localOnly: false, const result = await scyllaClient.execute(
}); prepared.note.select.byId,
[ctx.params.note],
{ prepare: true },
);
if (result.rowLength > 0) {
const candidate = parseScyllaNote(result.first());
if (
!candidate.localOnly &&
validVisibilities.includes(candidate.visibility)
) {
note = candidate;
}
}
} else {
note = await Notes.findOneBy({
id: ctx.params.note,
visibility: In(validVisibilities),
localOnly: false,
});
}
if (note == null) { if (!note) {
ctx.status = 404; ctx.status = 404;
return; return;
} }
@ -158,14 +179,34 @@ router.get("/notes/:note/activity", async (ctx) => {
return; return;
} }
const note = await Notes.findOneBy({ let note: Note | null = null;
id: ctx.params.note, const validVisibilities = ["public", "home"];
userHost: IsNull(), if (scyllaClient) {
visibility: In(["public" as const, "home" as const]), const result = await scyllaClient.execute(
localOnly: false, prepared.note.select.byId,
}); [ctx.params.note],
{ prepare: true },
);
if (result.rowLength > 0) {
const candidate = parseScyllaNote(result.first());
if (
!candidate.userHost &&
!candidate.localOnly &&
validVisibilities.includes(candidate.visibility)
) {
note = candidate;
}
}
} else {
note = await Notes.findOneBy({
id: ctx.params.note,
userHost: IsNull(),
visibility: In(validVisibilities),
localOnly: false,
});
}
if (note == null) { if (!note) {
ctx.status = 404; ctx.status = 404;
return; return;
} }

View file

@ -8,6 +8,8 @@ import { checkFetch } from "@/remote/activitypub/check-fetch.js";
import { fetchMeta } from "@/misc/fetch-meta.js"; import { fetchMeta } from "@/misc/fetch-meta.js";
import { setResponseType } from "../activitypub.js"; import { setResponseType } from "../activitypub.js";
import type Router from "@koa/router"; import type Router from "@koa/router";
import { parseScyllaNote, prepared, scyllaClient } from "@/db/scylla.js";
import { Note } from "@/models/entities/note.js";
export default async (ctx: Router.RouterContext) => { export default async (ctx: Router.RouterContext) => {
const verify = await checkFetch(ctx.req); const verify = await checkFetch(ctx.req);
@ -33,9 +35,17 @@ export default async (ctx: Router.RouterContext) => {
order: { id: "DESC" }, order: { id: "DESC" },
}); });
const pinnedNotes = await Promise.all( let pinnedNotes: Note[] = [];
pinings.map((pining) => Notes.findOneByOrFail({ id: pining.noteId })), if (scyllaClient) {
); const noteIds = pinings.map(({ noteId }) => noteId);
pinnedNotes = await scyllaClient
.execute(prepared.note.select.byIds, [noteIds], { prepare: true })
.then((result) => result.rows.map(parseScyllaNote));
} else {
pinnedNotes = await Promise.all(
pinings.map((pining) => Notes.findOneByOrFail({ id: pining.noteId })),
);
}
const renderedNotes = await Promise.all( const renderedNotes = await Promise.all(
pinnedNotes.map((note) => renderNote(note)), pinnedNotes.map((note) => renderNote(note)),

View file

@ -15,6 +15,7 @@ import { fetchMeta } from "@/misc/fetch-meta.js";
import { makePaginationQuery } from "../api/common/make-pagination-query.js"; import { makePaginationQuery } from "../api/common/make-pagination-query.js";
import { setResponseType } from "../activitypub.js"; import { setResponseType } from "../activitypub.js";
import type Router from "@koa/router"; import type Router from "@koa/router";
import { parseScyllaNote, prepared, scyllaClient } from "@/db/scylla.js";
export default async (ctx: Router.RouterContext) => { export default async (ctx: Router.RouterContext) => {
const verify = await checkFetch(ctx.req); const verify = await checkFetch(ctx.req);
@ -136,7 +137,25 @@ export async function packActivity(note: Note): Promise<any> {
!note.hasPoll && !note.hasPoll &&
(note.fileIds == null || note.fileIds.length === 0) (note.fileIds == null || note.fileIds.length === 0)
) { ) {
const renote = await Notes.findOneByOrFail({ id: note.renoteId }); let renote: Note | null = null;
if (scyllaClient) {
const result = await scyllaClient.execute(
prepared.note.select.byId,
[note.renoteId],
{ prepare: true },
);
if (result.rowLength > 0) {
renote = parseScyllaNote(result.first());
}
} else {
renote = await Notes.findOneBy({ id: note.renoteId });
}
if (!renote) {
throw new Error("Renote not found");
}
return renderAnnounce( return renderAnnounce(
renote.uri ? renote.uri : `${config.url}/notes/${renote.id}`, renote.uri ? renote.uri : `${config.url}/notes/${renote.id}`,
note, note,

View file

@ -4,6 +4,7 @@ import { Notes, Users } 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 { scyllaClient } from "@/db/scylla.js";
export const meta = { export const meta = {
tags: ["users"], tags: ["users"],
@ -64,6 +65,10 @@ export default define(meta, paramDef, async (ps, me) => {
throw e; throw e;
}); });
if (scyllaClient) {
return [];
}
// Fetch recent notes // Fetch recent notes
const recentNotes = await Notes.find({ const recentNotes = await Notes.find({
where: { where: {

View file

@ -3,6 +3,8 @@ import { In, IsNull } from "typeorm";
import config from "@/config/index.js"; import config from "@/config/index.js";
import type { User } from "@/models/entities/user.js"; import type { User } from "@/models/entities/user.js";
import { Notes, DriveFiles, UserProfiles, Users } from "@/models/index.js"; import { Notes, DriveFiles, UserProfiles, Users } from "@/models/index.js";
import { parseScyllaNote, prepared, scyllaClient } from "@/db/scylla.js";
import type { Note } from "@/models/entities/note.js";
export default async function ( export default async function (
user: User, user: User,
@ -146,17 +148,35 @@ export default async function (
return outstr; return outstr;
} }
async function findById(id) { async function findById(id: string) {
let text = ""; let text = "";
let next = null; let next: string | null = null;
const findings = await Notes.findOneBy({ let note: Note | null = null;
id: id, const validVisibilities = ["public", "home"];
visibility: In(["public", "home"]),
}); if (scyllaClient) {
if (findings) { const result = await scyllaClient.execute(
text += `<hr>`; prepared.note.select.byId,
text += await noteToString(findings); [id],
next = findings.renoteId ? findings.renoteId : findings.replyId; { prepare: true },
);
if (result.rowLength > 0) {
const candidate = parseScyllaNote(result.first());
if (validVisibilities.includes(candidate.visibility)) {
note = candidate;
}
}
} else {
note = await Notes.findOneBy({
id: id,
visibility: In(validVisibilities),
});
}
if (note) {
text += "<hr>";
text += await noteToString(note);
next = note.renoteId ? note.renoteId : note.replyId;
} }
return { text, next }; return { text, next };
} }

View file

@ -78,7 +78,7 @@ export async function addPinned(
} }
/** /**
* 稿 * Remove pinned note
* @param user * @param user
* @param noteId * @param noteId
*/ */
@ -87,12 +87,27 @@ export async function removePinned(
noteId: Note["id"], noteId: Note["id"],
) { ) {
// Fetch unpinee // Fetch unpinee
const note = await Notes.findOneBy({ let note: Note | null = null;
id: noteId, if (scyllaClient) {
userId: user.id, const result = await scyllaClient.execute(
}); prepared.note.select.byId,
[noteId],
{ prepare: true },
);
if (result.rowLength > 0) {
const candidate = parseScyllaNote(result.first());
if (candidate.userId === user.id) {
note = candidate;
}
}
} else {
note = await Notes.findOneBy({
id: noteId,
userId: user.id,
});
}
if (note == null) { if (!note) {
throw new IdentifiableError( throw new IdentifiableError(
"b302d4cf-c050-400a-bbb3-be208681f40c", "b302d4cf-c050-400a-bbb3-be208681f40c",
"No such note.", "No such note.",

View file

@ -5,13 +5,31 @@ import { Users, Notes } from "@/models/index.js";
import type { Note } from "@/models/entities/note.js"; import type { Note } from "@/models/entities/note.js";
import { deliverToFollowers } from "@/remote/activitypub/deliver-manager.js"; import { deliverToFollowers } from "@/remote/activitypub/deliver-manager.js";
import { deliverToRelays } from "../../relay.js"; import { deliverToRelays } from "../../relay.js";
import { parseScyllaNote, prepared, scyllaClient } from "@/db/scylla.js";
import { userByIdCache } from "@/services/user-cache.js";
export async function deliverQuestionUpdate(noteId: Note["id"]) { export async function deliverQuestionUpdate(noteId: Note["id"]) {
const note = await Notes.findOneBy({ id: noteId }); let note: Note | null = null;
if (note == null) throw new Error("note not found"); if (scyllaClient) {
const result = await scyllaClient.execute(
prepared.note.select.byId,
[noteId],
{ prepare: true },
);
if (result.rowLength > 0) {
note = parseScyllaNote(result.first());
}
} else {
note = await Notes.findOneBy({ id: noteId });
}
if (!note) throw new Error("note not found");
const user = await Users.findOneBy({ id: note.userId }); const user = await userByIdCache.fetchMaybe(note.userId, () =>
if (user == null) throw new Error("note not found"); Users.findOneBy({ id: (note as Note).userId }).then(
(user) => user ?? undefined,
),
);
if (!user) throw new Error("note not found");
if (Users.isLocalUser(user)) { if (Users.isLocalUser(user)) {
const content = renderActivity( const content = renderActivity(