From d64d133d7f9d741a16d374c200710787f6b04b8e Mon Sep 17 00:00:00 2001 From: Lhcfl Date: Tue, 26 Mar 2024 01:33:42 +0800 Subject: [PATCH] backend: added /note/history endpoint --- packages/backend/src/models/index.ts | 4 +- .../src/models/repositories/note-edit.ts | 37 +++++++++++ .../backend/src/models/schema/note-edit.ts | 2 +- packages/backend/src/server/api/endpoints.ts | 2 + .../src/server/api/endpoints/notes/history.ts | 64 +++++++++++++++++++ 5 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 packages/backend/src/models/repositories/note-edit.ts create mode 100644 packages/backend/src/server/api/endpoints/notes/history.ts diff --git a/packages/backend/src/models/index.ts b/packages/backend/src/models/index.ts index 5d4ff52198..c578d9d409 100644 --- a/packages/backend/src/models/index.ts +++ b/packages/backend/src/models/index.ts @@ -65,14 +65,14 @@ import { UserPending } from "./entities/user-pending.js"; import { InstanceRepository } from "./repositories/instance.js"; import { Webhook } from "./entities/webhook.js"; import { UserIp } from "./entities/user-ip.js"; -import { NoteEdit } from "./entities/note-edit.js"; import { NoteFileRepository } from "./repositories/note-file.js"; +import { NoteEditRepository } from "./repositories/note-edit.js"; export const Announcements = db.getRepository(Announcement); export const AnnouncementReads = db.getRepository(AnnouncementRead); export const Apps = AppRepository; export const Notes = NoteRepository; -export const NoteEdits = db.getRepository(NoteEdit); +export const NoteEdits = NoteEditRepository; export const NoteFiles = NoteFileRepository; export const NoteFavorites = NoteFavoriteRepository; export const NoteWatchings = db.getRepository(NoteWatching); diff --git a/packages/backend/src/models/repositories/note-edit.ts b/packages/backend/src/models/repositories/note-edit.ts new file mode 100644 index 0000000000..31a63af5b1 --- /dev/null +++ b/packages/backend/src/models/repositories/note-edit.ts @@ -0,0 +1,37 @@ +import { db } from "@/db/postgre.js"; +import { NoteEdit } from "@/models/entities/note-edit.js"; +import { awaitAll } from "@/prelude/await-all.js"; +import type { Packed } from "@/misc/schema.js"; + +export const NoteEditRepository = db.getRepository(NoteEdit).extend({ + async pack( + noteEdit: NoteEdit, + ) { + const packed: Packed<"NoteEdit"> = await awaitAll({ + id: noteEdit.id, + noteId: noteEdit.noteId, + updatedAt: noteEdit.updatedAt.toISOString(), + text: noteEdit.text, + cw: noteEdit.cw, + fileIds: noteEdit.fileIds, + }) + + return packed; + }, + async packMany( + noteEdits: NoteEdit[], + ) { + if (noteEdits.length === 0) return []; + + const promises = await Promise.allSettled( + noteEdits.map((n) => + this.pack(n) + ), + ); + + // filter out rejected promises, only keep fulfilled values + return promises.flatMap((result) => + result.status === "fulfilled" ? [result.value] : [], + ); + } +}); diff --git a/packages/backend/src/models/schema/note-edit.ts b/packages/backend/src/models/schema/note-edit.ts index e877f3f946..e02b866abd 100644 --- a/packages/backend/src/models/schema/note-edit.ts +++ b/packages/backend/src/models/schema/note-edit.ts @@ -16,7 +16,7 @@ export const packedNoteEdit = { }, note: { type: "object", - optional: false, + optional: true, nullable: false, ref: "Note", }, diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 52dd3382f7..9a0de00b8b 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -240,6 +240,7 @@ import * as ep___notes_conversation from "./endpoints/notes/conversation.js"; import * as ep___notes_create from "./endpoints/notes/create.js"; import * as ep___notes_delete from "./endpoints/notes/delete.js"; import * as ep___notes_edit from "./endpoints/notes/edit.js"; +import * as ep___notes_history from "./endpoints/notes/history.js"; import * as ep___notes_favorites_create from "./endpoints/notes/favorites/create.js"; import * as ep___notes_favorites_delete from "./endpoints/notes/favorites/delete.js"; import * as ep___notes_featured from "./endpoints/notes/featured.js"; @@ -583,6 +584,7 @@ const eps = [ ["notes/create", ep___notes_create], ["notes/delete", ep___notes_delete], ["notes/edit", ep___notes_edit], + ["notes/history", ep___notes_history], ["notes/favorites/create", ep___notes_favorites_create], ["notes/favorites/delete", ep___notes_favorites_delete], ["notes/featured", ep___notes_featured], diff --git a/packages/backend/src/server/api/endpoints/notes/history.ts b/packages/backend/src/server/api/endpoints/notes/history.ts new file mode 100644 index 0000000000..e0c7be3df5 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/notes/history.ts @@ -0,0 +1,64 @@ +import { NoteEdits } from "@/models/index.js"; +import define from "@/server/api/define.js"; +import { ApiError } from "@/server/api/error.js"; +import { getNote } from "@/server/api/common/getters.js"; +import type { NoteEdit } from "@/models/entities/note-edit.js"; + +export const meta = { + tags: ["notes"], + + requireCredential: false, + requireCredentialPrivateMode: true, + description: "Get edit history of a note", + + res: { + type: "array", + optional: false, + nullable: true, + items: { + type: "object", + optional: false, + nullable: false, + ref: "NoteEdit", + }, + }, + + errors: { + noSuchNote: { + message: "No such note.", + code: "NO_SUCH_NOTE", + id: "e1035875-9551-45ec-afa8-1ded1fcb53c8", + }, + }, +} as const; + +export const paramDef = { + type: "object", + properties: { + noteId: { + type: "string", + format: "misskey:id", + }, + limit: { type: "integer", minimum: 1, maximum: 100, default: 10 }, + offset: { type: "integer", default: 0 }, + }, + 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; + }); + + const history: NoteEdit[] = await NoteEdits.find({ + where: { + noteId: note.id, + }, + take: ps.limit, + skip: ps.offset, + }); + + return await NoteEdits.packMany(history); +});