From 41250d997bf620084303df7fa0abba88544a9ea8 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 3 Jul 2023 08:57:13 +0000 Subject: [PATCH] wip gallery --- .../server/api/endpoints/gallery/featured.ts | 27 +- .../server/api/endpoints/gallery/popular.ts | 27 +- .../src/server/api/endpoints/gallery/posts.ts | 29 +-- .../api/endpoints/gallery/posts/create.ts | 43 +-- .../api/endpoints/gallery/posts/delete.ts | 31 +-- .../api/endpoints/gallery/posts/like.ts | 49 +--- .../api/endpoints/gallery/posts/show.ts | 35 +-- .../api/endpoints/gallery/posts/unlike.ts | 41 +-- .../api/endpoints/gallery/posts/update.ts | 44 +--- packages/misskey-js/src/endpoints.ts | 245 ++++++++++++++++++ 10 files changed, 279 insertions(+), 292 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/gallery/featured.ts b/packages/backend/src/server/api/endpoints/gallery/featured.ts index 9994ce90d7..2bc312dd03 100644 --- a/packages/backend/src/server/api/endpoints/gallery/featured.ts +++ b/packages/backend/src/server/api/endpoints/gallery/featured.ts @@ -4,38 +4,17 @@ import type { GalleryPostsRepository } from '@/models/index.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { DI } from '@/di-symbols.js'; -export const meta = { - tags: ['gallery'], - - requireCredential: false, - - res: { - type: 'array', - optional: false, nullable: false, - items: { - type: 'object', - optional: false, nullable: false, - ref: 'GalleryPost', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: {}, - required: [], -} as const; - // eslint-disable-next-line import/no-default-export @Injectable() -export default class extends Endpoint { +export default class extends Endpoint<'gallery/featured'> { + name = 'gallery/featured' as const; constructor( @Inject(DI.galleryPostsRepository) private galleryPostsRepository: GalleryPostsRepository, private galleryPostEntityService: GalleryPostEntityService, ) { - super(meta, paramDef, async (ps, me) => { + super(async (ps, me) => { const query = this.galleryPostsRepository.createQueryBuilder('post') .andWhere('post.createdAt > :date', { date: new Date(Date.now() - (1000 * 60 * 60 * 24 * 3)) }) .andWhere('post.likedCount > 0') diff --git a/packages/backend/src/server/api/endpoints/gallery/popular.ts b/packages/backend/src/server/api/endpoints/gallery/popular.ts index 55d3dabfb0..c2e6c37668 100644 --- a/packages/backend/src/server/api/endpoints/gallery/popular.ts +++ b/packages/backend/src/server/api/endpoints/gallery/popular.ts @@ -4,38 +4,17 @@ import type { GalleryPostsRepository } from '@/models/index.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { DI } from '@/di-symbols.js'; -export const meta = { - tags: ['gallery'], - - requireCredential: false, - - res: { - type: 'array', - optional: false, nullable: false, - items: { - type: 'object', - optional: false, nullable: false, - ref: 'GalleryPost', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: {}, - required: [], -} as const; - // eslint-disable-next-line import/no-default-export @Injectable() -export default class extends Endpoint { +export default class extends Endpoint<'gallery/popular'> { + name = 'gallery/popular' as const; constructor( @Inject(DI.galleryPostsRepository) private galleryPostsRepository: GalleryPostsRepository, private galleryPostEntityService: GalleryPostEntityService, ) { - super(meta, paramDef, async (ps, me) => { + super(async (ps, me) => { const query = this.galleryPostsRepository.createQueryBuilder('post') .andWhere('post.likedCount > 0') .orderBy('post.likedCount', 'DESC'); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts.ts b/packages/backend/src/server/api/endpoints/gallery/posts.ts index e94003eb79..0c050ef61d 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts.ts @@ -5,33 +5,10 @@ import { QueryService } from '@/core/QueryService.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { DI } from '@/di-symbols.js'; -export const meta = { - tags: ['gallery'], - - res: { - type: 'array', - optional: false, nullable: false, - items: { - type: 'object', - optional: false, nullable: false, - ref: 'GalleryPost', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, - sinceId: { type: 'string', format: 'misskey:id' }, - untilId: { type: 'string', format: 'misskey:id' }, - }, - required: [], -} as const; - // eslint-disable-next-line import/no-default-export @Injectable() -export default class extends Endpoint { +export default class extends Endpoint<'gallery/posts'> { + name = 'gallery/posts' as const; constructor( @Inject(DI.galleryPostsRepository) private galleryPostsRepository: GalleryPostsRepository, @@ -39,7 +16,7 @@ export default class extends Endpoint { private galleryPostEntityService: GalleryPostEntityService, private queryService: QueryService, ) { - super(meta, paramDef, async (ps, me) => { + super(async (ps, me) => { const query = this.queryService.makePaginationQuery(this.galleryPostsRepository.createQueryBuilder('post'), ps.sinceId, ps.untilId) .innerJoinAndSelect('post.user', 'user'); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts index ca6bfa7e0f..7f8561b659 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts @@ -8,47 +8,10 @@ import { IdService } from '@/core/IdService.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { DI } from '@/di-symbols.js'; -export const meta = { - tags: ['gallery'], - - requireCredential: true, - - prohibitMoved: true, - - kind: 'write:gallery', - - limit: { - duration: ms('1hour'), - max: 20, - }, - - res: { - type: 'object', - optional: false, nullable: false, - ref: 'GalleryPost', - }, - - errors: { - - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - title: { type: 'string', minLength: 1 }, - description: { type: 'string', nullable: true }, - fileIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 32, items: { - type: 'string', format: 'misskey:id', - } }, - isSensitive: { type: 'boolean', default: false }, - }, - required: ['title', 'fileIds'], -} as const; - // eslint-disable-next-line import/no-default-export @Injectable() -export default class extends Endpoint { +export default class extends Endpoint<'gallery/posts/create'> { + name = 'gallery/posts/create' as const; constructor( @Inject(DI.galleryPostsRepository) private galleryPostsRepository: GalleryPostsRepository, @@ -59,7 +22,7 @@ export default class extends Endpoint { private galleryPostEntityService: GalleryPostEntityService, private idService: IdService, ) { - super(meta, paramDef, async (ps, me) => { + super(async (ps, me) => { const files = (await Promise.all(ps.fileIds.map(fileId => this.driveFilesRepository.findOneBy({ id: fileId, diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts b/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts index 6cdcc17b39..deb1936e89 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts @@ -4,45 +4,22 @@ import type { GalleryPostsRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; -export const meta = { - tags: ['gallery'], - - requireCredential: true, - - kind: 'write:gallery', - - errors: { - noSuchPost: { - message: 'No such post.', - code: 'NO_SUCH_POST', - id: 'ae52f367-4bd7-4ecd-afc6-5672fff427f5', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - postId: { type: 'string', format: 'misskey:id' }, - }, - required: ['postId'], -} as const; - // eslint-disable-next-line import/no-default-export @Injectable() -export default class extends Endpoint { +export default class extends Endpoint<'gallery/posts/delete'> { + name = 'gallery/posts/delete' as const; constructor( @Inject(DI.galleryPostsRepository) private galleryPostsRepository: GalleryPostsRepository, ) { - super(meta, paramDef, async (ps, me) => { + super(async (ps, me) => { const post = await this.galleryPostsRepository.findOneBy({ id: ps.postId, userId: me.id, }); if (post == null) { - throw new ApiError(meta.errors.noSuchPost); + throw new ApiError(this.meta.errors.noSuchPost); } await this.galleryPostsRepository.delete(post.id); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts index 6ac5fa8606..9539656d45 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts @@ -5,47 +5,10 @@ import { IdService } from '@/core/IdService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; -export const meta = { - tags: ['gallery'], - - requireCredential: true, - - prohibitMoved: true, - - kind: 'write:gallery-likes', - - errors: { - noSuchPost: { - message: 'No such post.', - code: 'NO_SUCH_POST', - id: '56c06af3-1287-442f-9701-c93f7c4a62ff', - }, - - yourPost: { - message: 'You cannot like your post.', - code: 'YOUR_POST', - id: 'f78f1511-5ebc-4478-a888-1198d752da68', - }, - - alreadyLiked: { - message: 'The post has already been liked.', - code: 'ALREADY_LIKED', - id: '40e9ed56-a59c-473a-bf3f-f289c54fb5a7', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - postId: { type: 'string', format: 'misskey:id' }, - }, - required: ['postId'], -} as const; - // eslint-disable-next-line import/no-default-export @Injectable() -export default class extends Endpoint { +export default class extends Endpoint<'gallery/posts/like'> { + name = 'gallery/posts/like' as const; constructor( @Inject(DI.galleryPostsRepository) private galleryPostsRepository: GalleryPostsRepository, @@ -55,14 +18,14 @@ export default class extends Endpoint { private idService: IdService, ) { - super(meta, paramDef, async (ps, me) => { + super(async (ps, me) => { const post = await this.galleryPostsRepository.findOneBy({ id: ps.postId }); if (post == null) { - throw new ApiError(meta.errors.noSuchPost); + throw new ApiError(this.meta.errors.noSuchPost); } if (post.userId === me.id) { - throw new ApiError(meta.errors.yourPost); + throw new ApiError(this.meta.errors.yourPost); } // if already liked @@ -72,7 +35,7 @@ export default class extends Endpoint { }); if (exist != null) { - throw new ApiError(meta.errors.alreadyLiked); + throw new ApiError(this.meta.errors.alreadyLiked); } // Create like diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/show.ts b/packages/backend/src/server/api/endpoints/gallery/posts/show.ts index f7e828142b..489107aa0b 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/show.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/show.ts @@ -5,50 +5,23 @@ import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityServi import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; -export const meta = { - tags: ['gallery'], - - requireCredential: false, - - errors: { - noSuchPost: { - message: 'No such post.', - code: 'NO_SUCH_POST', - id: '1137bf14-c5b0-4604-85bb-5b5371b1cd45', - }, - }, - - res: { - type: 'object', - optional: false, nullable: false, - ref: 'GalleryPost', - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - postId: { type: 'string', format: 'misskey:id' }, - }, - required: ['postId'], -} as const; - // eslint-disable-next-line import/no-default-export @Injectable() -export default class extends Endpoint { +export default class extends Endpoint<'gallery/posts/show'> { + name = 'gallery/posts/show' as const; constructor( @Inject(DI.galleryPostsRepository) private galleryPostsRepository: GalleryPostsRepository, private galleryPostEntityService: GalleryPostEntityService, ) { - super(meta, paramDef, async (ps, me) => { + super(async (ps, me) => { const post = await this.galleryPostsRepository.findOneBy({ id: ps.postId, }); if (post == null) { - throw new ApiError(meta.errors.noSuchPost); + throw new ApiError(this.meta.errors.noSuchPost); } return await this.galleryPostEntityService.pack(post, me); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts b/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts index 513089217d..02fd8a512d 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts @@ -4,41 +4,10 @@ import type { GalleryPostsRepository, GalleryLikesRepository } from '@/models/in import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; -export const meta = { - tags: ['gallery'], - - requireCredential: true, - - prohibitMoved: true, - - kind: 'write:gallery-likes', - - errors: { - noSuchPost: { - message: 'No such post.', - code: 'NO_SUCH_POST', - id: 'c32e6dd0-b555-4413-925e-b3757d19ed84', - }, - - notLiked: { - message: 'You have not liked that post.', - code: 'NOT_LIKED', - id: 'e3e8e06e-be37-41f7-a5b4-87a8250288f0', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - postId: { type: 'string', format: 'misskey:id' }, - }, - required: ['postId'], -} as const; - // eslint-disable-next-line import/no-default-export @Injectable() -export default class extends Endpoint { +export default class extends Endpoint<'gallery/posts/unlike'> { + name = 'gallery/posts/unlike' as const; constructor( @Inject(DI.galleryPostsRepository) private galleryPostsRepository: GalleryPostsRepository, @@ -46,10 +15,10 @@ export default class extends Endpoint { @Inject(DI.galleryLikesRepository) private galleryLikesRepository: GalleryLikesRepository, ) { - super(meta, paramDef, async (ps, me) => { + super(async (ps, me) => { const post = await this.galleryPostsRepository.findOneBy({ id: ps.postId }); if (post == null) { - throw new ApiError(meta.errors.noSuchPost); + throw new ApiError(this.meta.errors.noSuchPost); } const exist = await this.galleryLikesRepository.findOneBy({ @@ -58,7 +27,7 @@ export default class extends Endpoint { }); if (exist == null) { - throw new ApiError(meta.errors.notLiked); + throw new ApiError(this.meta.errors.notLiked); } // Delete like diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts index a2a10d8400..555d25f10a 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts @@ -6,48 +6,10 @@ import type { DriveFile } from '@/models/entities/DriveFile.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { DI } from '@/di-symbols.js'; -export const meta = { - tags: ['gallery'], - - requireCredential: true, - - prohibitMoved: true, - - kind: 'write:gallery', - - limit: { - duration: ms('1hour'), - max: 300, - }, - - res: { - type: 'object', - optional: false, nullable: false, - ref: 'GalleryPost', - }, - - errors: { - - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - postId: { type: 'string', format: 'misskey:id' }, - title: { type: 'string', minLength: 1 }, - description: { type: 'string', nullable: true }, - fileIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 32, items: { - type: 'string', format: 'misskey:id', - } }, - isSensitive: { type: 'boolean', default: false }, - }, - required: ['postId', 'title', 'fileIds'], -} as const; - // eslint-disable-next-line import/no-default-export @Injectable() -export default class extends Endpoint { +export default class extends Endpoint<'gallery/posts/update'> { + name = 'gallery/posts/update' as const; constructor( @Inject(DI.galleryPostsRepository) private galleryPostsRepository: GalleryPostsRepository, @@ -57,7 +19,7 @@ export default class extends Endpoint { private galleryPostEntityService: GalleryPostEntityService, ) { - super(meta, paramDef, async (ps, me) => { + super(async (ps, me) => { const files = (await Promise.all(ps.fileIds.map(fileId => this.driveFilesRepository.findOneBy({ id: fileId, diff --git a/packages/misskey-js/src/endpoints.ts b/packages/misskey-js/src/endpoints.ts index ecc996b0b7..983575c00b 100644 --- a/packages/misskey-js/src/endpoints.ts +++ b/packages/misskey-js/src/endpoints.ts @@ -4972,6 +4972,251 @@ export const endpoints = { }], }, //#endregion + + //#region gallery + 'gallery/posts/create': { + tags: ['gallery'], + + requireCredential: true, + + prohibitMoved: true, + + kind: 'write:gallery', + + limit: { + duration: ms('1hour'), + max: 20, + }, + + defines: [{ + req: { + type: 'object', + properties: { + title: { type: 'string', minLength: 1 }, + description: { type: ['string', 'null'] }, + fileIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 32, items: { + type: 'string', format: 'misskey:id', + } }, + isSensitive: { type: 'boolean', default: false }, + }, + required: ['title', 'fileIds'], + }, + res: { + $ref: 'https://misskey-hub.net/api/schemas/GalleryPost', + }, + }], + }, + 'gallery/posts/delete': { + tags: ['gallery'], + + requireCredential: true, + + kind: 'write:gallery', + + errors: { + noSuchPost: { + message: 'No such post.', + code: 'NO_SUCH_POST', + id: 'ae52f367-4bd7-4ecd-afc6-5672fff427f5', + }, + }, + + defines: [{ + req: { + type: 'object', + properties: { + postId: { type: 'string', format: 'misskey:id' }, + }, + required: ['postId'], + }, + res: undefined, + }], + }, + 'gallery/posts/like': { + tags: ['gallery'], + + requireCredential: true, + + prohibitMoved: true, + + kind: 'write:gallery-likes', + + errors: { + noSuchPost: { + message: 'No such post.', + code: 'NO_SUCH_POST', + id: '56c06af3-1287-442f-9701-c93f7c4a62ff', + }, + + yourPost: { + message: 'You cannot like your post.', + code: 'YOUR_POST', + id: 'f78f1511-5ebc-4478-a888-1198d752da68', + }, + + alreadyLiked: { + message: 'The post has already been liked.', + code: 'ALREADY_LIKED', + id: '40e9ed56-a59c-473a-bf3f-f289c54fb5a7', + }, + }, + + defines: [{ + req: { + type: 'object', + properties: { + postId: { type: 'string', format: 'misskey:id' }, + }, + required: ['postId'], + }, + res: undefined, + }], + }, + 'gallery/posts/show': { + tags: ['gallery'], + + requireCredential: false, + + errors: { + noSuchPost: { + message: 'No such post.', + code: 'NO_SUCH_POST', + id: '1137bf14-c5b0-4604-85bb-5b5371b1cd45', + }, + }, + + defines: [{ + req: { + type: 'object', + properties: { + postId: { type: 'string', format: 'misskey:id' }, + }, + required: ['postId'], + }, + res: { + $ref: 'https://misskey-hub.net/api/schemas/GalleryPost', + }, + }], + }, + 'gallery/posts/unlike': { + tags: ['gallery'], + + requireCredential: true, + + prohibitMoved: true, + + kind: 'write:gallery-likes', + + errors: { + noSuchPost: { + message: 'No such post.', + code: 'NO_SUCH_POST', + id: 'c32e6dd0-b555-4413-925e-b3757d19ed84', + }, + + notLiked: { + message: 'You have not liked that post.', + code: 'NOT_LIKED', + id: 'e3e8e06e-be37-41f7-a5b4-87a8250288f0', + }, + }, + + defines: [{ + req: { + type: 'object', + properties: { + postId: { type: 'string', format: 'misskey:id' }, + }, + required: ['postId'], + }, + res: undefined, + }] + }, + 'gallery/posts/update': { + tags: ['gallery'], + + requireCredential: true, + + prohibitMoved: true, + + kind: 'write:gallery', + + limit: { + duration: ms('1hour'), + max: 300, + }, + + defines: [{ + req: { + type: 'object', + properties: { + postId: { type: 'string', format: 'misskey:id' }, + title: { type: 'string', minLength: 1 }, + description: { type: ['string', 'null'] }, + fileIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 32, items: { + type: 'string', format: 'misskey:id', + } }, + isSensitive: { type: 'boolean', default: false }, + }, + required: ['postId', 'title', 'fileIds'], + }, + res: { + $ref: 'https://misskey-hub.net/api/schemas/GalleryPost', + }, + }], + }, + 'gallery/featured': { + tags: ['gallery'], + + requireCredential: false, + + defines: [{ + req: undefined, + res: { + type: 'array', + items: { + $ref: 'https://misskey-hub.net/api/schemas/GalleryPost', + }, + }, + }], + }, + 'gallery/popular': { + tags: ['gallery'], + + requireCredential: false, + + defines: [{ + req: undefined, + res: { + type: 'array', + items: { + $ref: 'https://misskey-hub.net/api/schemas/GalleryPost', + }, + }, + }], + }, + 'gallery/posts': { + tags: ['gallery'], + + defines: [{ + req: { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], + }, + res: { + type: 'array', + items: { + $ref: 'https://misskey-hub.net/api/schemas/GalleryPost', + }, + }, + }], + }, + //#endregion } as const satisfies { [x: string]: IEndpointMeta; }; /**