summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api
diff options
context:
space:
mode:
authorMar0xy <marie@kaifa.ch>2023-10-22 03:00:35 +0200
committerMar0xy <marie@kaifa.ch>2023-10-22 03:00:35 +0200
commitce83c483c6053c2e49d7567392f85c70b4bf9392 (patch)
tree4cf40466038ec7008b9cffe68c44453482bcd669 /packages/backend/src/server/api
parentupd: search filters (diff)
downloadsharkey-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')
-rw-r--r--packages/backend/src/server/api/EndpointsModule.ts4
-rw-r--r--packages/backend/src/server/api/GetterService.ts17
-rw-r--r--packages/backend/src/server/api/endpoints.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/notes/versions.ts63
-rw-r--r--packages/backend/src/server/api/mastodon/MastodonApiServerService.ts8
-rw-r--r--packages/backend/src/server/api/mastodon/converters.ts7
-rw-r--r--packages/backend/src/server/api/mastodon/endpoints/status.ts6
-rw-r--r--packages/backend/src/server/api/mastodon/endpoints/timeline.ts6
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() {