MisskeyPlay (#9467)
* wip * wip * wip * wip * wip * Update ui.ts * wip * wip * wip * wip * wip * wip * wip * wip * Update CHANGELOG.md * wip * wip * wip * wip * 🎨 * wip * ✌️
This commit is contained in:
		| @@ -266,6 +266,15 @@ import * as ep___pages_like from './endpoints/pages/like.js'; | ||||
| import * as ep___pages_show from './endpoints/pages/show.js'; | ||||
| import * as ep___pages_unlike from './endpoints/pages/unlike.js'; | ||||
| import * as ep___pages_update from './endpoints/pages/update.js'; | ||||
| import * as ep___flash_create from './endpoints/flash/create.js'; | ||||
| import * as ep___flash_delete from './endpoints/flash/delete.js'; | ||||
| import * as ep___flash_featured from './endpoints/flash/featured.js'; | ||||
| import * as ep___flash_like from './endpoints/flash/like.js'; | ||||
| import * as ep___flash_show from './endpoints/flash/show.js'; | ||||
| import * as ep___flash_unlike from './endpoints/flash/unlike.js'; | ||||
| import * as ep___flash_update from './endpoints/flash/update.js'; | ||||
| import * as ep___flash_my from './endpoints/flash/my.js'; | ||||
| import * as ep___flash_myLikes from './endpoints/flash/my-likes.js'; | ||||
| import * as ep___ping from './endpoints/ping.js'; | ||||
| import * as ep___pinnedUsers from './endpoints/pinned-users.js'; | ||||
| import * as ep___promo_read from './endpoints/promo/read.js'; | ||||
| @@ -587,6 +596,15 @@ const $pages_like: Provider = { provide: 'ep:pages/like', useClass: ep___pages_l | ||||
| const $pages_show: Provider = { provide: 'ep:pages/show', useClass: ep___pages_show.default }; | ||||
| const $pages_unlike: Provider = { provide: 'ep:pages/unlike', useClass: ep___pages_unlike.default }; | ||||
| const $pages_update: Provider = { provide: 'ep:pages/update', useClass: ep___pages_update.default }; | ||||
| const $flash_create: Provider = { provide: 'ep:flash/create', useClass: ep___flash_create.default }; | ||||
| const $flash_delete: Provider = { provide: 'ep:flash/delete', useClass: ep___flash_delete.default }; | ||||
| const $flash_featured: Provider = { provide: 'ep:flash/featured', useClass: ep___flash_featured.default }; | ||||
| const $flash_like: Provider = { provide: 'ep:flash/like', useClass: ep___flash_like.default }; | ||||
| const $flash_show: Provider = { provide: 'ep:flash/show', useClass: ep___flash_show.default }; | ||||
| const $flash_unlike: Provider = { provide: 'ep:flash/unlike', useClass: ep___flash_unlike.default }; | ||||
| const $flash_update: Provider = { provide: 'ep:flash/update', useClass: ep___flash_update.default }; | ||||
| const $flash_my: Provider = { provide: 'ep:flash/my', useClass: ep___flash_my.default }; | ||||
| const $flash_myLikes: Provider = { provide: 'ep:flash/my-likes', useClass: ep___flash_myLikes.default }; | ||||
| const $ping: Provider = { provide: 'ep:ping', useClass: ep___ping.default }; | ||||
| const $pinnedUsers: Provider = { provide: 'ep:pinned-users', useClass: ep___pinnedUsers.default }; | ||||
| const $promo_read: Provider = { provide: 'ep:promo/read', useClass: ep___promo_read.default }; | ||||
| @@ -912,6 +930,15 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention | ||||
| 		$pages_show, | ||||
| 		$pages_unlike, | ||||
| 		$pages_update, | ||||
| 		$flash_create, | ||||
| 		$flash_delete, | ||||
| 		$flash_featured, | ||||
| 		$flash_like, | ||||
| 		$flash_show, | ||||
| 		$flash_unlike, | ||||
| 		$flash_update, | ||||
| 		$flash_my, | ||||
| 		$flash_myLikes, | ||||
| 		$ping, | ||||
| 		$pinnedUsers, | ||||
| 		$promo_read, | ||||
| @@ -1231,6 +1258,15 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention | ||||
| 		$pages_show, | ||||
| 		$pages_unlike, | ||||
| 		$pages_update, | ||||
| 		$flash_create, | ||||
| 		$flash_delete, | ||||
| 		$flash_featured, | ||||
| 		$flash_like, | ||||
| 		$flash_show, | ||||
| 		$flash_unlike, | ||||
| 		$flash_update, | ||||
| 		$flash_my, | ||||
| 		$flash_myLikes, | ||||
| 		$ping, | ||||
| 		$pinnedUsers, | ||||
| 		$promo_read, | ||||
|   | ||||
| @@ -265,6 +265,15 @@ import * as ep___pages_like from './endpoints/pages/like.js'; | ||||
| import * as ep___pages_show from './endpoints/pages/show.js'; | ||||
| import * as ep___pages_unlike from './endpoints/pages/unlike.js'; | ||||
| import * as ep___pages_update from './endpoints/pages/update.js'; | ||||
| import * as ep___flash_create from './endpoints/flash/create.js'; | ||||
| import * as ep___flash_delete from './endpoints/flash/delete.js'; | ||||
| import * as ep___flash_featured from './endpoints/flash/featured.js'; | ||||
| import * as ep___flash_like from './endpoints/flash/like.js'; | ||||
| import * as ep___flash_show from './endpoints/flash/show.js'; | ||||
| import * as ep___flash_unlike from './endpoints/flash/unlike.js'; | ||||
| import * as ep___flash_update from './endpoints/flash/update.js'; | ||||
| import * as ep___flash_my from './endpoints/flash/my.js'; | ||||
| import * as ep___flash_myLikes from './endpoints/flash/my-likes.js'; | ||||
| import * as ep___ping from './endpoints/ping.js'; | ||||
| import * as ep___pinnedUsers from './endpoints/pinned-users.js'; | ||||
| import * as ep___promo_read from './endpoints/promo/read.js'; | ||||
| @@ -584,6 +593,15 @@ const eps = [ | ||||
| 	['pages/show', ep___pages_show], | ||||
| 	['pages/unlike', ep___pages_unlike], | ||||
| 	['pages/update', ep___pages_update], | ||||
| 	['flash/create', ep___flash_create], | ||||
| 	['flash/delete', ep___flash_delete], | ||||
| 	['flash/featured', ep___flash_featured], | ||||
| 	['flash/like', ep___flash_like], | ||||
| 	['flash/show', ep___flash_show], | ||||
| 	['flash/unlike', ep___flash_unlike], | ||||
| 	['flash/update', ep___flash_update], | ||||
| 	['flash/my', ep___flash_my], | ||||
| 	['flash/my-likes', ep___flash_myLikes], | ||||
| 	['ping', ep___ping], | ||||
| 	['pinned-users', ep___pinnedUsers], | ||||
| 	['promo/read', ep___promo_read], | ||||
|   | ||||
							
								
								
									
										66
									
								
								packages/backend/src/server/api/endpoints/flash/create.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								packages/backend/src/server/api/endpoints/flash/create.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| import ms from 'ms'; | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import type { DriveFilesRepository, FlashsRepository, PagesRepository } from '@/models/index.js'; | ||||
| import { IdService } from '@/core/IdService.js'; | ||||
| import { Page } from '@/models/entities/Page.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { PageEntityService } from '@/core/entities/PageEntityService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
|  | ||||
| export const meta = { | ||||
| 	tags: ['flash'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'write:flash', | ||||
|  | ||||
| 	limit: { | ||||
| 		duration: ms('1hour'), | ||||
| 		max: 10, | ||||
| 	}, | ||||
|  | ||||
| 	errors: { | ||||
| 	}, | ||||
| } as const; | ||||
|  | ||||
| export const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		title: { type: 'string' }, | ||||
| 		summary: { type: 'string' }, | ||||
| 		script: { type: 'string' }, | ||||
| 		permissions: { type: 'array', items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 	}, | ||||
| 	required: ['title', 'summary', 'script', 'permissions'], | ||||
| } as const; | ||||
|  | ||||
| // eslint-disable-next-line import/no-default-export | ||||
| @Injectable() | ||||
| export default class extends Endpoint<typeof meta, typeof paramDef> { | ||||
| 	constructor( | ||||
| 		@Inject(DI.flashsRepository) | ||||
| 		private flashsRepository: FlashsRepository, | ||||
|  | ||||
| 		private flashEntityService: FlashEntityService, | ||||
| 		private idService: IdService, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
| 			const flash = await this.flashsRepository.insert({ | ||||
| 				id: this.idService.genId(), | ||||
| 				userId: me.id, | ||||
| 				createdAt: new Date(), | ||||
| 				updatedAt: new Date(), | ||||
| 				title: ps.title, | ||||
| 				summary: ps.summary, | ||||
| 				script: ps.script, | ||||
| 				permissions: ps.permissions, | ||||
| 			}).then(x => this.flashsRepository.findOneByOrFail(x.identifiers[0])); | ||||
|  | ||||
| 			return await this.flashEntityService.pack(flash); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										56
									
								
								packages/backend/src/server/api/endpoints/flash/delete.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								packages/backend/src/server/api/endpoints/flash/delete.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import type { FlashsRepository } from '@/models/index.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
|  | ||||
| export const meta = { | ||||
| 	tags: ['flashs'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'write:flash', | ||||
|  | ||||
| 	errors: { | ||||
| 		noSuchFlash: { | ||||
| 			message: 'No such flash.', | ||||
| 			code: 'NO_SUCH_FLASH', | ||||
| 			id: 'de1623ef-bbb3-4289-a71e-14cfa83d9740', | ||||
| 		}, | ||||
|  | ||||
| 		accessDenied: { | ||||
| 			message: 'Access denied.', | ||||
| 			code: 'ACCESS_DENIED', | ||||
| 			id: '1036ad7b-9f92-4fff-89c3-0e50dc941704', | ||||
| 		}, | ||||
| 	}, | ||||
| } as const; | ||||
|  | ||||
| export const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		flashId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['flashId'], | ||||
| } as const; | ||||
|  | ||||
| // eslint-disable-next-line import/no-default-export | ||||
| @Injectable() | ||||
| export default class extends Endpoint<typeof meta, typeof paramDef> { | ||||
| 	constructor( | ||||
| 		@Inject(DI.flashsRepository) | ||||
| 		private flashsRepository: FlashsRepository, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
| 			const flash = await this.flashsRepository.findOneBy({ id: ps.flashId }); | ||||
| 			if (flash == null) { | ||||
| 				throw new ApiError(meta.errors.noSuchFlash); | ||||
| 			} | ||||
| 			if (flash.userId !== me.id) { | ||||
| 				throw new ApiError(meta.errors.accessDenied); | ||||
| 			} | ||||
|  | ||||
| 			await this.flashsRepository.delete(flash.id); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										48
									
								
								packages/backend/src/server/api/endpoints/flash/featured.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								packages/backend/src/server/api/endpoints/flash/featured.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import type { FlashsRepository } from '@/models/index.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
|  | ||||
| export const meta = { | ||||
| 	tags: ['flash'], | ||||
|  | ||||
| 	requireCredential: false, | ||||
|  | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
| 		items: { | ||||
| 			type: 'object', | ||||
| 			optional: false, nullable: false, | ||||
| 			ref: 'Flash', | ||||
| 		}, | ||||
| 	}, | ||||
| } 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<typeof meta, typeof paramDef> { | ||||
| 	constructor( | ||||
| 		@Inject(DI.flashsRepository) | ||||
| 		private flashsRepository: FlashsRepository, | ||||
|  | ||||
| 		private flashEntityService: FlashEntityService, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
| 			const query = this.flashsRepository.createQueryBuilder('flash') | ||||
| 				.andWhere('flash.likedCount > 0') | ||||
| 				.orderBy('flash.likedCount', 'DESC'); | ||||
|  | ||||
| 			const flashs = await query.take(10).getMany(); | ||||
|  | ||||
| 			return await this.flashEntityService.packMany(flashs, me); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										87
									
								
								packages/backend/src/server/api/endpoints/flash/like.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								packages/backend/src/server/api/endpoints/flash/like.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import type { FlashsRepository, FlashLikesRepository } from '@/models/index.js'; | ||||
| import { IdService } from '@/core/IdService.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
|  | ||||
| export const meta = { | ||||
| 	tags: ['flash'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'write:flash-likes', | ||||
|  | ||||
| 	errors: { | ||||
| 		noSuchFlash: { | ||||
| 			message: 'No such flash.', | ||||
| 			code: 'NO_SUCH_FLASH', | ||||
| 			id: 'c07c1491-9161-4c5c-9d75-01906f911f73', | ||||
| 		}, | ||||
|  | ||||
| 		yourFlash: { | ||||
| 			message: 'You cannot like your flash.', | ||||
| 			code: 'YOUR_FLASH', | ||||
| 			id: '3fd8a0e7-5955-4ba9-85bb-bf3e0c30e13b', | ||||
| 		}, | ||||
|  | ||||
| 		alreadyLiked: { | ||||
| 			message: 'The flash has already been liked.', | ||||
| 			code: 'ALREADY_LIKED', | ||||
| 			id: '010065cf-ad43-40df-8067-abff9f4686e3', | ||||
| 		}, | ||||
| 	}, | ||||
| } as const; | ||||
|  | ||||
| export const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		flashId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['flashId'], | ||||
| } as const; | ||||
|  | ||||
| // eslint-disable-next-line import/no-default-export | ||||
| @Injectable() | ||||
| export default class extends Endpoint<typeof meta, typeof paramDef> { | ||||
| 	constructor( | ||||
| 		@Inject(DI.flashsRepository) | ||||
| 		private flashsRepository: FlashsRepository, | ||||
|  | ||||
| 		@Inject(DI.flashLikesRepository) | ||||
| 		private flashLikesRepository: FlashLikesRepository, | ||||
|  | ||||
| 		private idService: IdService, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
| 			const flash = await this.flashsRepository.findOneBy({ id: ps.flashId }); | ||||
| 			if (flash == null) { | ||||
| 				throw new ApiError(meta.errors.noSuchFlash); | ||||
| 			} | ||||
|  | ||||
| 			if (flash.userId === me.id) { | ||||
| 				throw new ApiError(meta.errors.yourFlash); | ||||
| 			} | ||||
|  | ||||
| 			// if already liked | ||||
| 			const exist = await this.flashLikesRepository.findOneBy({ | ||||
| 				flashId: flash.id, | ||||
| 				userId: me.id, | ||||
| 			}); | ||||
|  | ||||
| 			if (exist != null) { | ||||
| 				throw new ApiError(meta.errors.alreadyLiked); | ||||
| 			} | ||||
|  | ||||
| 			// Create like | ||||
| 			await this.flashLikesRepository.insert({ | ||||
| 				id: this.idService.genId(), | ||||
| 				createdAt: new Date(), | ||||
| 				flashId: flash.id, | ||||
| 				userId: me.id, | ||||
| 			}); | ||||
|  | ||||
| 			this.flashsRepository.increment({ id: flash.id }, 'likedCount', 1); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										68
									
								
								packages/backend/src/server/api/endpoints/flash/my-likes.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								packages/backend/src/server/api/endpoints/flash/my-likes.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import type { FlashLikesRepository } from '@/models/index.js'; | ||||
| import { QueryService } from '@/core/QueryService.js'; | ||||
| import { FlashLikeEntityService } from '@/core/entities/FlashLikeEntityService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
|  | ||||
| export const meta = { | ||||
| 	tags: ['account', 'flash'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'read:flash-likes', | ||||
|  | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
| 		items: { | ||||
| 			type: 'object', | ||||
| 			properties: { | ||||
| 				id: { | ||||
| 					type: 'string', | ||||
| 					optional: false, nullable: false, | ||||
| 					format: 'id', | ||||
| 				}, | ||||
| 				flash: { | ||||
| 					type: 'object', | ||||
| 					optional: false, nullable: false, | ||||
| 					ref: 'Flash', | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	}, | ||||
| } 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<typeof meta, typeof paramDef> { | ||||
| 	constructor( | ||||
| 		@Inject(DI.flashLikesRepository) | ||||
| 		private flashLikesRepository: FlashLikesRepository, | ||||
|  | ||||
| 		private flashLikeEntityService: FlashLikeEntityService, | ||||
| 		private queryService: QueryService, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
| 			const query = this.queryService.makePaginationQuery(this.flashLikesRepository.createQueryBuilder('like'), ps.sinceId, ps.untilId) | ||||
| 				.andWhere('like.userId = :meId', { meId: me.id }) | ||||
| 				.leftJoinAndSelect('like.flash', 'flash'); | ||||
|  | ||||
| 			const likes = await query | ||||
| 				.take(ps.limit) | ||||
| 				.getMany(); | ||||
|  | ||||
| 			return this.flashLikeEntityService.packMany(likes, me); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										57
									
								
								packages/backend/src/server/api/endpoints/flash/my.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								packages/backend/src/server/api/endpoints/flash/my.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import type { FlashsRepository } from '@/models/index.js'; | ||||
| import { QueryService } from '@/core/QueryService.js'; | ||||
| import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
|  | ||||
| export const meta = { | ||||
| 	tags: ['account', 'flash'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'read:flash', | ||||
|  | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
| 		items: { | ||||
| 			type: 'object', | ||||
| 			optional: false, nullable: false, | ||||
| 			ref: 'Flash', | ||||
| 		}, | ||||
| 	}, | ||||
| } 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<typeof meta, typeof paramDef> { | ||||
| 	constructor( | ||||
| 		@Inject(DI.flashsRepository) | ||||
| 		private flashsRepository: FlashsRepository, | ||||
|  | ||||
| 		private flashEntityService: FlashEntityService, | ||||
| 		private queryService: QueryService, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
| 			const query = this.queryService.makePaginationQuery(this.flashsRepository.createQueryBuilder('flash'), ps.sinceId, ps.untilId) | ||||
| 				.andWhere('flash.userId = :meId', { meId: me.id }); | ||||
|  | ||||
| 			const flashs = await query | ||||
| 				.take(ps.limit) | ||||
| 				.getMany(); | ||||
|  | ||||
| 			return await this.flashEntityService.packMany(flashs); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										60
									
								
								packages/backend/src/server/api/endpoints/flash/show.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								packages/backend/src/server/api/endpoints/flash/show.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| import { IsNull } from 'typeorm'; | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import type { UsersRepository, FlashsRepository } from '@/models/index.js'; | ||||
| import type { Flash } from '@/models/entities/Flash.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
|  | ||||
| export const meta = { | ||||
| 	tags: ['flashs'], | ||||
|  | ||||
| 	requireCredential: false, | ||||
|  | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
| 		ref: 'Flash', | ||||
| 	}, | ||||
|  | ||||
| 	errors: { | ||||
| 		noSuchFlash: { | ||||
| 			message: 'No such flash.', | ||||
| 			code: 'NO_SUCH_FLASH', | ||||
| 			id: 'f0d34a1a-d29a-401d-90ba-1982122b5630', | ||||
| 		}, | ||||
| 	}, | ||||
| } as const; | ||||
|  | ||||
| export const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		flashId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['flashId'], | ||||
| } as const; | ||||
|  | ||||
| // eslint-disable-next-line import/no-default-export | ||||
| @Injectable() | ||||
| export default class extends Endpoint<typeof meta, typeof paramDef> { | ||||
| 	constructor( | ||||
| 		@Inject(DI.usersRepository) | ||||
| 		private usersRepository: UsersRepository, | ||||
|  | ||||
| 		@Inject(DI.flashsRepository) | ||||
| 		private flashsRepository: FlashsRepository, | ||||
|  | ||||
| 		private flashEntityService: FlashEntityService, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
| 			const flash = await this.flashsRepository.findOneBy({ id: ps.flashId }); | ||||
|  | ||||
| 			if (flash == null) { | ||||
| 				throw new ApiError(meta.errors.noSuchFlash); | ||||
| 			} | ||||
|  | ||||
| 			return await this.flashEntityService.pack(flash, me); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										68
									
								
								packages/backend/src/server/api/endpoints/flash/unlike.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								packages/backend/src/server/api/endpoints/flash/unlike.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import type { FlashsRepository, FlashLikesRepository } from '@/models/index.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
|  | ||||
| export const meta = { | ||||
| 	tags: ['flash'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'write:flash-likes', | ||||
|  | ||||
| 	errors: { | ||||
| 		noSuchFlash: { | ||||
| 			message: 'No such flash.', | ||||
| 			code: 'NO_SUCH_FLASH', | ||||
| 			id: 'afe8424a-a69e-432d-a5f2-2f0740c62410', | ||||
| 		}, | ||||
|  | ||||
| 		notLiked: { | ||||
| 			message: 'You have not liked that flash.', | ||||
| 			code: 'NOT_LIKED', | ||||
| 			id: '755f25a7-9871-4f65-9f34-51eaad9ae0ac', | ||||
| 		}, | ||||
| 	}, | ||||
| } as const; | ||||
|  | ||||
| export const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		flashId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['flashId'], | ||||
| } as const; | ||||
|  | ||||
| // eslint-disable-next-line import/no-default-export | ||||
| @Injectable() | ||||
| export default class extends Endpoint<typeof meta, typeof paramDef> { | ||||
| 	constructor( | ||||
| 		@Inject(DI.flashsRepository) | ||||
| 		private flashsRepository: FlashsRepository, | ||||
|  | ||||
| 		@Inject(DI.flashLikesRepository) | ||||
| 		private flashLikesRepository: FlashLikesRepository, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
| 			const flash = await this.flashsRepository.findOneBy({ id: ps.flashId }); | ||||
| 			if (flash == null) { | ||||
| 				throw new ApiError(meta.errors.noSuchFlash); | ||||
| 			} | ||||
|  | ||||
| 			const exist = await this.flashLikesRepository.findOneBy({ | ||||
| 				flashId: flash.id, | ||||
| 				userId: me.id, | ||||
| 			}); | ||||
|  | ||||
| 			if (exist == null) { | ||||
| 				throw new ApiError(meta.errors.notLiked); | ||||
| 			} | ||||
|  | ||||
| 			// Delete like | ||||
| 			await this.flashLikesRepository.delete(exist.id); | ||||
|  | ||||
| 			this.flashsRepository.decrement({ id: flash.id }, 'likedCount', 1); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										78
									
								
								packages/backend/src/server/api/endpoints/flash/update.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								packages/backend/src/server/api/endpoints/flash/update.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| import ms from 'ms'; | ||||
| import { Not } from 'typeorm'; | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import type { FlashsRepository, DriveFilesRepository } from '@/models/index.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
|  | ||||
| export const meta = { | ||||
| 	tags: ['flash'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	kind: 'write:flash', | ||||
|  | ||||
| 	limit: { | ||||
| 		duration: ms('1hour'), | ||||
| 		max: 300, | ||||
| 	}, | ||||
|  | ||||
| 	errors: { | ||||
| 		noSuchFlash: { | ||||
| 			message: 'No such flash.', | ||||
| 			code: 'NO_SUCH_FLASH', | ||||
| 			id: '611e13d2-309e-419a-a5e4-e0422da39b02', | ||||
| 		}, | ||||
|  | ||||
| 		accessDenied: { | ||||
| 			message: 'Access denied.', | ||||
| 			code: 'ACCESS_DENIED', | ||||
| 			id: '08e60c88-5948-478e-a132-02ec701d67b2', | ||||
| 		}, | ||||
| 	}, | ||||
| } as const; | ||||
|  | ||||
| export const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		flashId: { type: 'string', format: 'misskey:id' }, | ||||
| 		title: { type: 'string' }, | ||||
| 		summary: { type: 'string' }, | ||||
| 		script: { type: 'string' }, | ||||
| 		permissions: { type: 'array', items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 	}, | ||||
| 	required: ['flashId', 'title', 'summary', 'script', 'permissions'], | ||||
| } as const; | ||||
|  | ||||
| // eslint-disable-next-line import/no-default-export | ||||
| @Injectable() | ||||
| export default class extends Endpoint<typeof meta, typeof paramDef> { | ||||
| 	constructor( | ||||
| 		@Inject(DI.flashsRepository) | ||||
| 		private flashsRepository: FlashsRepository, | ||||
|  | ||||
| 		@Inject(DI.driveFilesRepository) | ||||
| 		private driveFilesRepository: DriveFilesRepository, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
| 			const flash = await this.flashsRepository.findOneBy({ id: ps.flashId }); | ||||
| 			if (flash == null) { | ||||
| 				throw new ApiError(meta.errors.noSuchFlash); | ||||
| 			} | ||||
| 			if (flash.userId !== me.id) { | ||||
| 				throw new ApiError(meta.errors.accessDenied); | ||||
| 			} | ||||
|  | ||||
| 			await this.flashsRepository.update(flash.id, { | ||||
| 				updatedAt: new Date(), | ||||
| 				title: ps.title, | ||||
| 				summary: ps.summary, | ||||
| 				script: ps.script, | ||||
| 				permissions: ps.permissions, | ||||
| 			}); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 syuilo
					syuilo