diff options
| author | Mar0xy <marie@kaifa.ch> | 2023-10-22 03:00:35 +0200 |
|---|---|---|
| committer | Mar0xy <marie@kaifa.ch> | 2023-10-22 03:00:35 +0200 |
| commit | ce83c483c6053c2e49d7567392f85c70b4bf9392 (patch) | |
| tree | 4cf40466038ec7008b9cffe68c44453482bcd669 /packages/backend/src/server/api | |
| parent | upd: search filters (diff) | |
| download | sharkey-ce83c483c6053c2e49d7567392f85c70b4bf9392.tar.gz sharkey-ce83c483c6053c2e49d7567392f85c70b4bf9392.tar.bz2 sharkey-ce83c483c6053c2e49d7567392f85c70b4bf9392.zip | |
add: view previous versions of notes
Closes transfem-org/Sharkey#103
Diffstat (limited to 'packages/backend/src/server/api')
8 files changed, 101 insertions, 12 deletions
diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index fcd67f39ff..19e05e5c17 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -278,6 +278,7 @@ import * as ep___notes_reactions_delete from './endpoints/notes/reactions/delete import * as ep___notes_renotes from './endpoints/notes/renotes.js'; import * as ep___notes_replies from './endpoints/notes/replies.js'; import * as ep___notes_edit from './endpoints/notes/edit.js'; +import * as ep___notes_versions from './endpoints/notes/versions.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_show from './endpoints/notes/show.js'; @@ -646,6 +647,7 @@ const $notes_translate: Provider = { provide: 'ep:notes/translate', useClass: ep const $notes_unrenote: Provider = { provide: 'ep:notes/unrenote', useClass: ep___notes_unrenote.default }; const $notes_userListTimeline: Provider = { provide: 'ep:notes/user-list-timeline', useClass: ep___notes_userListTimeline.default }; const $notes_edit: Provider = { provide: 'ep:notes/edit', useClass: ep___notes_edit.default }; +const $notes_versions: Provider = { provide: 'ep:notes/versions', useClass: ep___notes_versions.default }; const $notifications_create: Provider = { provide: 'ep:notifications/create', useClass: ep___notifications_create.default }; const $notifications_markAllAsRead: Provider = { provide: 'ep:notifications/mark-all-as-read', useClass: ep___notifications_markAllAsRead.default }; const $notifications_testNotification: Provider = { provide: 'ep:notifications/test-notification', useClass: ep___notifications_testNotification.default }; @@ -1008,6 +1010,7 @@ const $sponsors: Provider = { provide: 'ep:sponsors', useClass: ep___sponsors.de $notes_unrenote, $notes_userListTimeline, $notes_edit, + $notes_versions, $notifications_create, $notifications_markAllAsRead, $notifications_testNotification, @@ -1364,6 +1367,7 @@ const $sponsors: Provider = { provide: 'ep:sponsors', useClass: ep___sponsors.de $notes_unrenote, $notes_userListTimeline, $notes_edit, + $notes_versions, $notifications_create, $notifications_markAllAsRead, $pagePush, diff --git a/packages/backend/src/server/api/GetterService.ts b/packages/backend/src/server/api/GetterService.ts index e2b98c34e7..2616cbb761 100644 --- a/packages/backend/src/server/api/GetterService.ts +++ b/packages/backend/src/server/api/GetterService.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { NotesRepository, UsersRepository } from '@/models/_.js'; +import type { NotesRepository, UsersRepository, NoteEditRepository } from '@/models/_.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; import type { MiLocalUser, MiRemoteUser, MiUser } from '@/models/User.js'; import type { MiNote } from '@/models/Note.js'; @@ -21,6 +21,9 @@ export class GetterService { @Inject(DI.notesRepository) private notesRepository: NotesRepository, + @Inject(DI.noteEditRepository) + private noteEditRepository: NoteEditRepository, + private userEntityService: UserEntityService, ) { } @@ -40,6 +43,18 @@ export class GetterService { } /** + * Get note for API processing + */ + @bindThis + public async getEdits(noteId: MiNote['id']) { + const edits = await this.noteEditRepository.findBy({ noteId: noteId }).catch(() => { + throw new IdentifiableError('9725d0ce-ba28-4dde-95a7-2cbb2c15de24', 'No such note.'); + }); + + return edits; + } + + /** * Get user for API processing */ @bindThis diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index be5e66cab0..7d82d116db 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -288,6 +288,7 @@ import * as ep___notes_translate from './endpoints/notes/translate.js'; import * as ep___notes_unrenote from './endpoints/notes/unrenote.js'; import * as ep___notes_userListTimeline from './endpoints/notes/user-list-timeline.js'; import * as ep___notes_edit from './endpoints/notes/edit.js'; +import * as ep___notes_versions from './endpoints/notes/versions.js'; import * as ep___notifications_create from './endpoints/notifications/create.js'; import * as ep___notifications_markAllAsRead from './endpoints/notifications/mark-all-as-read.js'; import * as ep___notifications_testNotification from './endpoints/notifications/test-notification.js'; @@ -644,6 +645,7 @@ const eps = [ ['notes/unrenote', ep___notes_unrenote], ['notes/user-list-timeline', ep___notes_userListTimeline], ['notes/edit', ep___notes_edit], + ['notes/versions', ep___notes_versions], ['notifications/create', ep___notifications_create], ['notifications/mark-all-as-read', ep___notifications_markAllAsRead], ['notifications/test-notification', ep___notifications_testNotification], diff --git a/packages/backend/src/server/api/endpoints/notes/versions.ts b/packages/backend/src/server/api/endpoints/notes/versions.ts new file mode 100644 index 0000000000..9733d781a4 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/notes/versions.ts @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { GetterService } from '@/server/api/GetterService.js'; +import { ApiError } from '../../error.js'; + +export const meta = { + tags: ['notes'], + + requireCredential: false, + + res: { + type: 'object', + optional: false, nullable: false, + }, + + 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; + +@Injectable() +export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export + constructor( + private getterService: GetterService, + ) { + super(meta, paramDef, async (ps, me) => { + const edits = await this.getterService.getEdits(ps.noteId).catch(err => { + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + throw err; + }); + + let editArray = []; + + for (const edit of edits) { + editArray.push({ + updatedAt: new Date(edit.updatedAt).toLocaleString('UTC', { hour: 'numeric', minute: 'numeric', second: 'numeric', year: 'numeric', month: 'short', day: 'numeric' }), + text: edit.text, + }); + } + + editArray = editArray.sort((a, b) => { return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(); }); + + return editArray; + }); + } +} diff --git a/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts b/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts index b0b5147a48..a8c45b98f7 100644 --- a/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts +++ b/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts @@ -3,7 +3,7 @@ import megalodon, { Entity, MegalodonInterface } from 'megalodon'; import querystring from 'querystring'; import { IsNull } from 'typeorm'; import multer from 'fastify-multer'; -import type { NotesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; +import type { NoteEditRepository, NotesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import type { Config } from '@/config.js'; @@ -31,6 +31,8 @@ export class MastodonApiServerService { private notesRepository: NotesRepository, @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, + @Inject(DI.noteEditRepository) + private noteEditRepository: NoteEditRepository, @Inject(DI.config) private config: Config, private metaService: MetaService, @@ -754,7 +756,7 @@ export class MastodonApiServerService { //#endregion //#region Timelines - const TLEndpoint = new ApiTimelineMastodon(fastify, this.config, this.usersRepository, this.notesRepository, this.userEntityService); + const TLEndpoint = new ApiTimelineMastodon(fastify, this.config, this.usersRepository, this.notesRepository, this.noteEditRepository, this.userEntityService); // GET Endpoints TLEndpoint.getTL(); @@ -779,7 +781,7 @@ export class MastodonApiServerService { //#endregion //#region Status - const NoteEndpoint = new ApiStatusMastodon(fastify, this.config, this.usersRepository, this.notesRepository, this.userEntityService); + const NoteEndpoint = new ApiStatusMastodon(fastify, this.config, this.usersRepository, this.notesRepository, this.noteEditRepository, this.userEntityService); // GET Endpoints NoteEndpoint.getStatus(); diff --git a/packages/backend/src/server/api/mastodon/converters.ts b/packages/backend/src/server/api/mastodon/converters.ts index 69b0ad93ff..cbd2550f92 100644 --- a/packages/backend/src/server/api/mastodon/converters.ts +++ b/packages/backend/src/server/api/mastodon/converters.ts @@ -7,7 +7,7 @@ import { parse } from 'mfm-js'; import { GetterService } from '../GetterService.js'; import type { IMentionedRemoteUsers } from '@/models/Note.js'; import type { MiUser } from '@/models/User.js'; -import type { NotesRepository, UsersRepository } from '@/models/_.js'; +import type { NoteEditRepository, NotesRepository, UsersRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; const CHAR_COLLECTION = '0123456789abcdefghijklmnopqrstuvwxyz'; @@ -39,11 +39,14 @@ export class MastoConverters { @Inject(DI.notesRepository) private notesRepository: NotesRepository, + + @Inject(DI.noteEditRepository) + private noteEditRepository: NoteEditRepository, private userEntityService: UserEntityService ) { this.MfmService = new MfmService(this.config); - this.GetterService = new GetterService(this.usersRepository, this.notesRepository, this.userEntityService); + this.GetterService = new GetterService(this.usersRepository, this.notesRepository, this.noteEditRepository, this.userEntityService); } private encode(u: MiUser, m: IMentionedRemoteUsers): MastodonEntity.Mention { diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts index 46dce65081..2690a1036f 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/status.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts @@ -6,7 +6,7 @@ import { convertTimelinesArgsId, limitToInt } from './timeline.js'; import type { Entity } from 'megalodon'; import type { FastifyInstance } from 'fastify'; import type { Config } from '@/config.js'; -import { NotesRepository, UsersRepository } from '@/models/_.js'; +import { NoteEditRepository, NotesRepository, UsersRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; function normalizeQuery(data: any) { @@ -18,9 +18,9 @@ export class ApiStatusMastodon { private fastify: FastifyInstance; private mastoconverter: MastoConverters; - constructor(fastify: FastifyInstance, config: Config, usersrepo: UsersRepository, notesrepo: NotesRepository, userentity: UserEntityService) { + constructor(fastify: FastifyInstance, config: Config, usersrepo: UsersRepository, notesrepo: NotesRepository, noteeditrepo: NoteEditRepository, userentity: UserEntityService) { this.fastify = fastify; - this.mastoconverter = new MastoConverters(config, usersrepo, notesrepo, userentity); + this.mastoconverter = new MastoConverters(config, usersrepo, notesrepo, noteeditrepo, userentity); } public async getStatus() { diff --git a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts index bb66a7707c..e4f510ea2b 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts @@ -4,7 +4,7 @@ import { getClient } from '../MastodonApiServerService.js'; import type { Entity } from 'megalodon'; import type { FastifyInstance } from 'fastify'; import type { Config } from '@/config.js'; -import { NotesRepository, UsersRepository } from '@/models/_.js'; +import { NoteEditRepository, NotesRepository, UsersRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; export function limitToInt(q: ParsedUrlQuery) { @@ -43,9 +43,9 @@ export class ApiTimelineMastodon { private fastify: FastifyInstance; private mastoconverter: MastoConverters; - constructor(fastify: FastifyInstance, config: Config, usersRepository: UsersRepository, notesRepository: NotesRepository, userEntityService: UserEntityService) { + constructor(fastify: FastifyInstance, config: Config, usersRepository: UsersRepository, notesRepository: NotesRepository, noteEditRepository: NoteEditRepository, userEntityService: UserEntityService) { this.fastify = fastify; - this.mastoconverter = new MastoConverters(config, usersRepository, notesRepository, userEntityService); + this.mastoconverter = new MastoConverters(config, usersRepository, notesRepository, noteEditRepository, userEntityService); } public async getTL() { |