This commit is contained in:
tamaina
2023-05-25 16:53:29 +00:00
parent d7fe783c46
commit c0bd1b82ab
15 changed files with 292 additions and 301 deletions

View File

@@ -21,7 +21,7 @@ type File = {
path: string;
};
export type Executor<T extends IEndpointMeta, P = SchemaOrUndefined<T['defines'][number]['req']>> =
export type Executor<T extends IEndpointMeta, P = SchemaOrUndefined<T['defines'][number]['req'], true>> =
(
params: P,
user: LocalUser | (T['requireCredential'] extends true ? never : null),
@@ -30,7 +30,7 @@ export type Executor<T extends IEndpointMeta, P = SchemaOrUndefined<T['defines']
cleanup?: () => any,
ip?: string | null,
headers?: Record<string, string> | null
) => Promise<WeakSerialized<ResponseOf<T, P>>>;
) => Promise<WeakSerialized<ResponseOf<T, P, true>>>;
// ExecutorWrapperの型はあえて緩くしておく
export type ExecutorWrapper =

View File

@@ -2,33 +2,14 @@ import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
} as const;
export const paramDef = {
type: 'object',
properties: {
ids: { type: 'array', items: {
type: 'string', format: 'misskey:id',
} },
aliases: { type: 'array', items: {
type: 'string',
} },
},
required: ['ids', 'aliases'],
} as const;
// eslint-disable-next-line import/no-default-export
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
export default class extends Endpoint<'admin/emoji/add-aliases-bulk'> {
name = 'admin/emoji/add-aliases-bulk' as const;
constructor(
private customEmojiService: CustomEmojiService,
) {
super(meta, paramDef, async (ps, me) => {
super(async (ps, me) => {
await this.customEmojiService.addAliasesBulk(ps.ids, ps.aliases);
});
}

View File

@@ -7,49 +7,12 @@ import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
import { ApiError } from '../../../error.js';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'fc46b5a4-6b92-4c33-ac66-b806659bb5cf',
},
},
} as const;
export const paramDef = {
type: 'object',
properties: {
name: { type: 'string', pattern: '^[a-zA-Z0-9_]+$' },
fileId: { type: 'string', format: 'misskey:id' },
category: {
type: 'string',
nullable: true,
description: 'Use `null` to reset the category.',
},
aliases: { type: 'array', items: {
type: 'string',
} },
license: { type: 'string', nullable: true },
isSensitive: { type: 'boolean' },
localOnly: { type: 'boolean' },
roleIdsThatCanBeUsedThisEmojiAsReaction: { type: 'array', items: {
type: 'string',
} },
},
required: ['name', 'fileId'],
} as const;
// TODO: ロジックをサービスに切り出す
// eslint-disable-next-line import/no-default-export
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
export default class extends Endpoint<'admin/emoji/add'> {
name = 'admin/emoji/add' as const;
constructor(
@Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository,
@@ -58,9 +21,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private moderationLogService: ModerationLogService,
) {
super(meta, paramDef, async (ps, me) => {
super(async (ps, me) => {
const driveFile = await this.driveFilesRepository.findOneBy({ id: ps.fileId });
if (driveFile == null) throw new ApiError(meta.errors.noSuchFile);
if (driveFile == null) throw new ApiError(this.meta.errors.noSuchFile);
const emoji = await this.customEmojiService.add({
driveFile,

View File

@@ -10,46 +10,12 @@ import { GlobalEventService } from '@/core/GlobalEventService.js';
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { ApiError } from '../../../error.js';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
errors: {
noSuchEmoji: {
message: 'No such emoji.',
code: 'NO_SUCH_EMOJI',
id: 'e2785b66-dca3-4087-9cac-b93c541cc425',
},
},
res: {
type: 'object',
optional: false, nullable: false,
properties: {
id: {
type: 'string',
optional: false, nullable: false,
format: 'id',
},
},
},
} as const;
export const paramDef = {
type: 'object',
properties: {
emojiId: { type: 'string', format: 'misskey:id' },
},
required: ['emojiId'],
} as const;
// TODO: ロジックをサービスに切り出す
// eslint-disable-next-line import/no-default-export
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
export default class extends Endpoint<'admin/emoji/copy'> {
name = 'admin/emoji/copy' as const;
constructor(
@Inject(DI.db)
private db: DataSource,
@@ -62,11 +28,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private globalEventService: GlobalEventService,
private driveService: DriveService,
) {
super(meta, paramDef, async (ps, me) => {
super(async (ps, me) => {
const emoji = await this.emojisRepository.findOneBy({ id: ps.emojiId });
if (emoji == null) {
throw new ApiError(meta.errors.noSuchEmoji);
throw new ApiError(this.meta.errors.noSuchEmoji);
}
let driveFile: DriveFile;

View File

@@ -3,29 +3,19 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
} as const;
export const paramDef = {
type: 'object',
properties: {
ids: { type: 'array', items: {
type: 'string', format: 'misskey:id',
} },
},
required: ['ids'],
} as const;
// eslint-disable-next-line import/no-default-export
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
export default class extends Endpoint<'admin/emoji/delete-bulk'> {
name = 'admin/emoji/delete-bulk' as const;
constructor(
private customEmojiService: CustomEmojiService,
) {
super(meta, paramDef, async (ps, me) => {
super(async (ps, me) => {
await this.customEmojiService.deleteBulk(ps.ids);
});
}

View File

@@ -2,36 +2,14 @@ import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
errors: {
noSuchEmoji: {
message: 'No such emoji.',
code: 'NO_SUCH_EMOJI',
id: 'be83669b-773a-44b7-b1f8-e5e5170ac3c2',
},
},
} as const;
export const paramDef = {
type: 'object',
properties: {
id: { type: 'string', format: 'misskey:id' },
},
required: ['id'],
} as const;
// eslint-disable-next-line import/no-default-export
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
export default class extends Endpoint<'admin/emoji/delete'> {
name = 'admin/emoji/delete' as const;
constructor(
private customEmojiService: CustomEmojiService,
) {
super(meta, paramDef, async (ps, me) => {
super(async (ps, me) => {
await this.customEmojiService.delete(ps.id);
});
}

View File

@@ -18,11 +18,12 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
export default class extends Endpoint<'admin/emoji/import-zip'> {
name = 'admin/emoji/import-zip' as const;
constructor(
private queueService: QueueService,
) {
super(meta, paramDef, async (ps, me) => {
super(async (ps, me) => {
this.queueService.createImportCustomEmojisJob(me, ps.fileId);
});
}

View File

@@ -7,74 +7,10 @@ import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { DI } from '@/di-symbols.js';
import { sqlLikeEscape } from '@/misc/sql-like-escape.js';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
res: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'object',
optional: false, nullable: false,
properties: {
id: {
type: 'string',
optional: false, nullable: false,
format: 'id',
},
aliases: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'string',
optional: false, nullable: false,
},
},
name: {
type: 'string',
optional: false, nullable: false,
},
category: {
type: 'string',
optional: false, nullable: true,
},
host: {
type: 'string',
optional: false, nullable: true,
description: 'The local host is represented with `null`.',
},
url: {
type: 'string',
optional: false, nullable: false,
},
},
},
},
} as const;
export const paramDef = {
type: 'object',
properties: {
query: { type: 'string', nullable: true, default: null },
host: {
type: 'string',
nullable: true,
default: null,
description: 'Use `null` to represent the local host.',
},
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> {
export default class extends Endpoint<'admin/emoji/list-remote'> {
name = 'admin/emoji/list-remote' as const;
constructor(
@Inject(DI.emojisRepository)
private emojisRepository: EmojisRepository,
@@ -83,7 +19,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private queryService: QueryService,
private emojiEntityService: EmojiEntityService,
) {
super(meta, paramDef, async (ps, me) => {
super(async (ps, me) => {
const q = this.queryService.makePaginationQuery(this.emojisRepository.createQueryBuilder('emoji'), ps.sinceId, ps.untilId);
if (ps.host == null) {

View File

@@ -7,68 +7,10 @@ import { DI } from '@/di-symbols.js';
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
//import { sqlLikeEscape } from '@/misc/sql-like-escape.js';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
res: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'object',
optional: false, nullable: false,
properties: {
id: {
type: 'string',
optional: false, nullable: false,
format: 'id',
},
aliases: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'string',
optional: false, nullable: false,
},
},
name: {
type: 'string',
optional: false, nullable: false,
},
category: {
type: 'string',
optional: false, nullable: true,
},
host: {
type: 'string',
optional: false, nullable: true,
description: 'The local host is represented with `null`. The field exists for compatibility with other API endpoints that return files.',
},
url: {
type: 'string',
optional: false, nullable: false,
},
},
},
},
} as const;
export const paramDef = {
type: 'object',
properties: {
query: { type: 'string', nullable: true, default: null },
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> {
export default class extends Endpoint<'admin/emoji/list'> {
name = 'admin/emoji/list' as const;
constructor(
@Inject(DI.emojisRepository)
private emojisRepository: EmojisRepository,
@@ -76,7 +18,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private emojiEntityService: EmojiEntityService,
private queryService: QueryService,
) {
super(meta, paramDef, async (ps, me) => {
super(async (ps, me) => {
const q = this.queryService.makePaginationQuery(this.emojisRepository.createQueryBuilder('emoji'), ps.sinceId, ps.untilId)
.andWhere('emoji.host IS NULL');