diff --git a/locales/index.d.ts b/locales/index.d.ts index b9c2125ae6..dbfff95d15 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -1223,9 +1223,9 @@ export interface Locale extends ILocale { */ "noMoreHistory": string; /** - * チャットを開始 + * チャットを始める */ - "startMessaging": string; + "startChat": string; /** * {n}人が読みました */ @@ -5350,6 +5350,10 @@ export interface Locale extends ILocale { * 文字数 */ "textCount": string; + /** + * チャット + */ + "chat": string; "_emojiPalette": { /** * パレット diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index d60425566e..699798b552 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -301,7 +301,7 @@ uploadFromUrlMayTakeTime: "アップロードが完了するまで時間がか explore: "みつける" messageRead: "既読" noMoreHistory: "これより過去の履歴はありません" -startMessaging: "チャットを開始" +startChat: "チャットを始める" nUsersRead: "{n}人が読みました" agreeTo: "{0}に同意" agree: "同意する" @@ -1333,6 +1333,7 @@ paste: "ペースト" emojiPalette: "絵文字パレット" postForm: "投稿フォーム" textCount: "文字数" +chat: "チャット" _emojiPalette: palettes: "パレット" diff --git a/packages/backend/src/core/ChatService.ts b/packages/backend/src/core/ChatService.ts index adea867a48..1a552e7ac4 100644 --- a/packages/backend/src/core/ChatService.ts +++ b/packages/backend/src/core/ChatService.ts @@ -16,7 +16,7 @@ import { ChatMessageEntityService } from '@/core/entities/ChatMessageEntityServi import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { PushNotificationService } from '@/core/PushNotificationService.js'; import { bindThis } from '@/decorators.js'; -import type { ChatMessagesRepository, MiChatMessage, MiDriveFile, MiUser, UsersRepository } from '@/models/_.js'; +import type { ChatMessagesRepository, MiChatMessage, MiDriveFile, MiUser, MutingsRepository, UsersRepository } from '@/models/_.js'; import { UserBlockingService } from '@/core/UserBlockingService.js'; import { QueryService } from '@/core/QueryService.js'; @@ -35,6 +35,9 @@ export class ChatService { @Inject(DI.chatMessagesRepository) private chatMessagesRepository: ChatMessagesRepository, + @Inject(DI.mutingsRepository) + private mutingsRepository: MutingsRepository, + private userEntityService: UserEntityService, private chatMessageEntityService: ChatMessageEntityService, private idService: IdService, @@ -278,4 +281,82 @@ export class ChatService { return messages; } + + @bindThis + public async userHistory(meId: MiUser['id'], limit: number) { + const history: MiChatMessage[] = []; + + const mutingQuery = this.mutingsRepository.createQueryBuilder('muting') + .select('muting.muteeId') + .where('muting.muterId = :muterId', { muterId: meId }); + + for (let i = 0; i < limit; i++) { + const found = history.map(m => (m.fromUserId === meId) ? m.toUserId! : m.fromUserId!); + + const query = this.chatMessagesRepository.createQueryBuilder('message') + .orderBy('message.id', 'DESC') + .where(new Brackets(qb => { + qb + .where('message.fromUserId = :meId', { meId: meId }) + .orWhere('message.toUserId = :meId', { meId: meId }); + })) + .andWhere('message.groupId IS NULL') + .andWhere(`message.fromUserId NOT IN (${ mutingQuery.getQuery() })`) + .andWhere(`message.toUserId NOT IN (${ mutingQuery.getQuery() })`); + + if (found.length > 0) { + query.andWhere('message.fromUserId NOT IN (:...found)', { found: found }); + query.andWhere('message.toUserId NOT IN (:...found)', { found: found }); + } + + query.setParameters(mutingQuery.getParameters()); + + const message = await query.getOne(); + + if (message) { + history.push(message); + } else { + break; + } + } + + return history; + } + + @bindThis + public async groupHistory(meId: MiUser['id'], limit: number) { + /* + const groups = await this.userGroupJoiningsRepository.findBy({ + userId: meId, + }).then(xs => xs.map(x => x.userGroupId)); + + if (groups.length === 0) { + return []; + } + + const history: MiChatMessage[] = []; + + for (let i = 0; i < limit; i++) { + const found = history.map(m => m.groupId!); + + const query = this.chatMessagesRepository.createQueryBuilder('message') + .orderBy('message.id', 'DESC') + .where('message.groupId IN (:...groups)', { groups: groups }); + + if (found.length > 0) { + query.andWhere('message.groupId NOT IN (:...found)', { found: found }); + } + + const message = await query.getOne(); + + if (message) { + history.push(message); + } else { + break; + } + } + + return history; + */ + } } diff --git a/packages/backend/src/server/api/endpoint-list.ts b/packages/backend/src/server/api/endpoint-list.ts index 25d8cbf8df..4d99bcc50c 100644 --- a/packages/backend/src/server/api/endpoint-list.ts +++ b/packages/backend/src/server/api/endpoint-list.ts @@ -399,4 +399,5 @@ export * as 'users/show' from './endpoints/users/show.js'; export * as 'users/update-memo' from './endpoints/users/update-memo.js'; export * as 'chat/messages/create' from './endpoints/chat/messages/create.js'; export * as 'chat/messages/timeline' from './endpoints/chat/messages/timeline.js'; +export * as 'chat/messages/history' from './endpoints/chat/messages/history.js'; export * as 'v2/admin/emoji/list' from './endpoints/v2/admin/emoji/list.js'; diff --git a/packages/backend/src/server/api/endpoints/chat/messages/history.ts b/packages/backend/src/server/api/endpoints/chat/messages/history.ts new file mode 100644 index 0000000000..23434c32cd --- /dev/null +++ b/packages/backend/src/server/api/endpoints/chat/messages/history.ts @@ -0,0 +1,54 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { DI } from '@/di-symbols.js'; +import { ChatService } from '@/core/ChatService.js'; +import { ChatMessageEntityService } from '@/core/entities/ChatMessageEntityService.js'; +import { ApiError } from '@/server/api/error.js'; + +export const meta = { + tags: ['chat'], + + requireCredential: true, + + kind: 'read:chat', + + res: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'object', + optional: false, nullable: false, + ref: 'ChatMessage', + }, + }, + + errors: { + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + group: { type: 'boolean', default: false }, + }, +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + private chatMessageEntityService: ChatMessageEntityService, + private chatService: ChatService, + ) { + super(meta, paramDef, async (ps, me) => { + const history = ps.group ? await this.chatService.groupHistory(me.id, ps.limit) : await this.chatService.userHistory(me.id, ps.limit); + + return await this.chatMessageEntityService.packMany(history, me); + }); + } +} diff --git a/packages/backend/src/server/api/stream/channels/chat.ts b/packages/backend/src/server/api/stream/channels/chat.ts index de453323e1..3701927275 100644 --- a/packages/backend/src/server/api/stream/channels/chat.ts +++ b/packages/backend/src/server/api/stream/channels/chat.ts @@ -28,7 +28,7 @@ class ChatChannel extends Channel { if (typeof params.otherId !== 'string') return; this.otherId = params.otherId; - this.subscriber.on(`chatStream:${this.user.id}-${this.otherId}`, this.onEvent); + this.subscriber.on(`chatStream:${this.user!.id}-${this.otherId}`, this.onEvent); } @bindThis @@ -39,7 +39,7 @@ class ChatChannel extends Channel { @bindThis public dispose() { // Unsubscribe events - this.subscriber.off(`chatStream:${this.user.id}-${this.otherId}`, this.onEvent); + this.subscriber.off(`chatStream:${this.user!.id}-${this.otherId}`, this.onEvent); } } diff --git a/packages/frontend/src/pages/chat/home.vue b/packages/frontend/src/pages/chat/home.vue new file mode 100644 index 0000000000..5424057501 --- /dev/null +++ b/packages/frontend/src/pages/chat/home.vue @@ -0,0 +1,85 @@ + + + + + + + diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index 6060812b53..eafec84952 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -951,6 +951,30 @@ type ChartsUsersRequest = operations['charts___users']['requestBody']['content'] // @public (undocumented) type ChartsUsersResponse = operations['charts___users']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChatMessage = components['schemas']['ChatMessage']; + +// @public (undocumented) +type ChatMessageLite = components['schemas']['ChatMessageLite']; + +// @public (undocumented) +type ChatMessagesCreateRequest = operations['chat___messages___create']['requestBody']['content']['application/json']; + +// @public (undocumented) +type ChatMessagesCreateResponse = operations['chat___messages___create']['responses']['200']['content']['application/json']; + +// @public (undocumented) +type ChatMessagesHistoryRequest = operations['chat___messages___history']['requestBody']['content']['application/json']; + +// @public (undocumented) +type ChatMessagesHistoryResponse = operations['chat___messages___history']['responses']['200']['content']['application/json']; + +// @public (undocumented) +type ChatMessagesTimelineRequest = operations['chat___messages___timeline']['requestBody']['content']['application/json']; + +// @public (undocumented) +type ChatMessagesTimelineResponse = operations['chat___messages___timeline']['responses']['200']['content']['application/json']; + // @public (undocumented) type Clip = components['schemas']['Clip']; @@ -1448,6 +1472,12 @@ declare namespace entities { ChartsUserReactionsResponse, ChartsUsersRequest, ChartsUsersResponse, + ChatMessagesCreateRequest, + ChatMessagesCreateResponse, + ChatMessagesHistoryRequest, + ChatMessagesHistoryResponse, + ChatMessagesTimelineRequest, + ChatMessagesTimelineResponse, ClipsAddNoteRequest, ClipsCreateRequest, ClipsCreateResponse, @@ -1880,7 +1910,9 @@ declare namespace entities { MetaDetailedOnly, MetaDetailed, SystemWebhook, - AbuseReportNotificationRecipient + AbuseReportNotificationRecipient, + ChatMessage, + ChatMessageLite } } export { entities } @@ -2903,7 +2935,7 @@ type PartialRolePolicyOverride = Partial<{ }>; // @public (undocumented) -export const permissions: readonly ["read:account", "write:account", "read:blocks", "write:blocks", "read:drive", "write:drive", "read:favorites", "write:favorites", "read:following", "write:following", "read:messaging", "write:messaging", "read:mutes", "write:mutes", "write:notes", "read:notifications", "write:notifications", "read:reactions", "write:reactions", "write:votes", "read:pages", "write:pages", "write:page-likes", "read:page-likes", "read:user-groups", "write:user-groups", "read:channels", "write:channels", "read:gallery", "write:gallery", "read:gallery-likes", "write:gallery-likes", "read:flash", "write:flash", "read:flash-likes", "write:flash-likes", "read:admin:abuse-user-reports", "write:admin:delete-account", "write:admin:delete-all-files-of-a-user", "read:admin:index-stats", "read:admin:table-stats", "read:admin:user-ips", "read:admin:meta", "write:admin:reset-password", "write:admin:resolve-abuse-user-report", "write:admin:send-email", "read:admin:server-info", "read:admin:show-moderation-log", "read:admin:show-user", "write:admin:suspend-user", "write:admin:unset-user-avatar", "write:admin:unset-user-banner", "write:admin:unsuspend-user", "write:admin:meta", "write:admin:user-note", "write:admin:roles", "read:admin:roles", "write:admin:relays", "read:admin:relays", "write:admin:invite-codes", "read:admin:invite-codes", "write:admin:announcements", "read:admin:announcements", "write:admin:avatar-decorations", "read:admin:avatar-decorations", "write:admin:federation", "write:admin:account", "read:admin:account", "write:admin:emoji", "read:admin:emoji", "write:admin:queue", "read:admin:queue", "write:admin:promo", "write:admin:drive", "read:admin:drive", "write:admin:ad", "read:admin:ad", "write:invite-codes", "read:invite-codes", "write:clip-favorite", "read:clip-favorite", "read:federation", "write:report-abuse"]; +export const permissions: readonly ["read:account", "write:account", "read:blocks", "write:blocks", "read:drive", "write:drive", "read:favorites", "write:favorites", "read:following", "write:following", "read:messaging", "write:messaging", "read:mutes", "write:mutes", "write:notes", "read:notifications", "write:notifications", "read:reactions", "write:reactions", "write:votes", "read:pages", "write:pages", "write:page-likes", "read:page-likes", "read:user-groups", "write:user-groups", "read:channels", "write:channels", "read:gallery", "write:gallery", "read:gallery-likes", "write:gallery-likes", "read:flash", "write:flash", "read:flash-likes", "write:flash-likes", "read:admin:abuse-user-reports", "write:admin:delete-account", "write:admin:delete-all-files-of-a-user", "read:admin:index-stats", "read:admin:table-stats", "read:admin:user-ips", "read:admin:meta", "write:admin:reset-password", "write:admin:resolve-abuse-user-report", "write:admin:send-email", "read:admin:server-info", "read:admin:show-moderation-log", "read:admin:show-user", "write:admin:suspend-user", "write:admin:unset-user-avatar", "write:admin:unset-user-banner", "write:admin:unsuspend-user", "write:admin:meta", "write:admin:user-note", "write:admin:roles", "read:admin:roles", "write:admin:relays", "read:admin:relays", "write:admin:invite-codes", "read:admin:invite-codes", "write:admin:announcements", "read:admin:announcements", "write:admin:avatar-decorations", "read:admin:avatar-decorations", "write:admin:federation", "write:admin:account", "read:admin:account", "write:admin:emoji", "read:admin:emoji", "write:admin:queue", "read:admin:queue", "write:admin:promo", "write:admin:drive", "read:admin:drive", "write:admin:ad", "read:admin:ad", "write:invite-codes", "read:invite-codes", "write:clip-favorite", "read:clip-favorite", "read:federation", "write:report-abuse", "write:chat", "read:chat"]; // @public (undocumented) type PingResponse = operations['ping']['responses']['200']['content']['application/json']; diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts index a1543952fc..b9023bb4f0 100644 --- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts +++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts @@ -1534,6 +1534,39 @@ declare module '../api.js' { credential?: string | null, ): Promise>; + /** + * No description provided. + * + * **Credential required**: *Yes* / **Permission**: *write:chat* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + + /** + * No description provided. + * + * **Credential required**: *Yes* / **Permission**: *read:chat* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + + /** + * No description provided. + * + * **Credential required**: *Yes* / **Permission**: *read:chat* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + /** * No description provided. * diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts index 9bb8fb2225..6bc4b377b4 100644 --- a/packages/misskey-js/src/autogen/endpoint.ts +++ b/packages/misskey-js/src/autogen/endpoint.ts @@ -207,6 +207,12 @@ import type { ChartsUserReactionsResponse, ChartsUsersRequest, ChartsUsersResponse, + ChatMessagesCreateRequest, + ChatMessagesCreateResponse, + ChatMessagesHistoryRequest, + ChatMessagesHistoryResponse, + ChatMessagesTimelineRequest, + ChatMessagesTimelineResponse, ClipsAddNoteRequest, ClipsCreateRequest, ClipsCreateResponse, @@ -726,6 +732,9 @@ export type Endpoints = { 'charts/user/pv': { req: ChartsUserPvRequest; res: ChartsUserPvResponse }; 'charts/user/reactions': { req: ChartsUserReactionsRequest; res: ChartsUserReactionsResponse }; 'charts/users': { req: ChartsUsersRequest; res: ChartsUsersResponse }; + 'chat/messages/create': { req: ChatMessagesCreateRequest; res: ChatMessagesCreateResponse }; + 'chat/messages/history': { req: ChatMessagesHistoryRequest; res: ChatMessagesHistoryResponse }; + 'chat/messages/timeline': { req: ChatMessagesTimelineRequest; res: ChatMessagesTimelineResponse }; 'clips/add-note': { req: ClipsAddNoteRequest; res: EmptyResponse }; 'clips/create': { req: ClipsCreateRequest; res: ClipsCreateResponse }; 'clips/delete': { req: ClipsDeleteRequest; res: EmptyResponse }; diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts index f3d26efa69..bd33db8465 100644 --- a/packages/misskey-js/src/autogen/entities.ts +++ b/packages/misskey-js/src/autogen/entities.ts @@ -210,6 +210,12 @@ export type ChartsUserReactionsRequest = operations['charts___user___reactions'] export type ChartsUserReactionsResponse = operations['charts___user___reactions']['responses']['200']['content']['application/json']; export type ChartsUsersRequest = operations['charts___users']['requestBody']['content']['application/json']; export type ChartsUsersResponse = operations['charts___users']['responses']['200']['content']['application/json']; +export type ChatMessagesCreateRequest = operations['chat___messages___create']['requestBody']['content']['application/json']; +export type ChatMessagesCreateResponse = operations['chat___messages___create']['responses']['200']['content']['application/json']; +export type ChatMessagesHistoryRequest = operations['chat___messages___history']['requestBody']['content']['application/json']; +export type ChatMessagesHistoryResponse = operations['chat___messages___history']['responses']['200']['content']['application/json']; +export type ChatMessagesTimelineRequest = operations['chat___messages___timeline']['requestBody']['content']['application/json']; +export type ChatMessagesTimelineResponse = operations['chat___messages___timeline']['responses']['200']['content']['application/json']; export type ClipsAddNoteRequest = operations['clips___add-note']['requestBody']['content']['application/json']; export type ClipsCreateRequest = operations['clips___create']['requestBody']['content']['application/json']; export type ClipsCreateResponse = operations['clips___create']['responses']['200']['content']['application/json']; diff --git a/packages/misskey-js/src/autogen/models.ts b/packages/misskey-js/src/autogen/models.ts index 1a30da4437..6f5080a2ba 100644 --- a/packages/misskey-js/src/autogen/models.ts +++ b/packages/misskey-js/src/autogen/models.ts @@ -54,3 +54,5 @@ export type MetaDetailedOnly = components['schemas']['MetaDetailedOnly']; export type MetaDetailed = components['schemas']['MetaDetailed']; export type SystemWebhook = components['schemas']['SystemWebhook']; export type AbuseReportNotificationRecipient = components['schemas']['AbuseReportNotificationRecipient']; +export type ChatMessage = components['schemas']['ChatMessage']; +export type ChatMessageLite = components['schemas']['ChatMessageLite']; diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 743aaf1608..2e9f81fbbb 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -1358,6 +1358,33 @@ export type paths = { */ post: operations['charts___users']; }; + '/chat/messages/create': { + /** + * chat/messages/create + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *write:chat* + */ + post: operations['chat___messages___create']; + }; + '/chat/messages/history': { + /** + * chat/messages/history + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *read:chat* + */ + post: operations['chat___messages___history']; + }; + '/chat/messages/timeline': { + /** + * chat/messages/timeline + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *read:chat* + */ + post: operations['chat___messages___timeline']; + }; '/clips/add-note': { /** * clips/add-note @@ -5146,6 +5173,28 @@ export type components = { systemWebhookId?: string; systemWebhook?: components['schemas']['SystemWebhook']; }; + ChatMessage: { + id: string; + /** Format: date-time */ + createdAt: string; + fromUserId: string; + fromUser?: components['schemas']['UserLite']; + toUserId?: string | null; + toUser?: components['schemas']['UserLite'] | null; + text?: string | null; + fileId?: string | null; + file?: components['schemas']['DriveFile'] | null; + }; + ChatMessageLite: { + id: string; + /** Format: date-time */ + createdAt: string; + fromUserId: string; + toUserId?: string | null; + text?: string | null; + fileId?: string | null; + file?: components['schemas']['DriveFile'] | null; + }; }; responses: never; parameters: never; @@ -13669,6 +13718,185 @@ export type operations = { }; }; }; + /** + * chat/messages/create + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *write:chat* + */ + chat___messages___create: { + requestBody: { + content: { + 'application/json': { + text?: string | null; + /** Format: misskey:id */ + fileId?: string; + /** Format: misskey:id */ + userId?: string | null; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + content: { + 'application/json': components['schemas']['ChatMessageLite']; + }; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Too many requests */ + 429: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + /** + * chat/messages/history + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *read:chat* + */ + chat___messages___history: { + requestBody: { + content: { + 'application/json': { + /** @default 10 */ + limit?: number; + /** @default false */ + group?: boolean; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + content: { + 'application/json': components['schemas']['ChatMessage'][]; + }; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + /** + * chat/messages/timeline + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *read:chat* + */ + chat___messages___timeline: { + requestBody: { + content: { + 'application/json': { + /** @default 10 */ + limit?: number; + /** Format: misskey:id */ + sinceId?: string; + /** Format: misskey:id */ + untilId?: string; + /** Format: misskey:id */ + userId?: string | null; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + content: { + 'application/json': components['schemas']['ChatMessageLite'][]; + }; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; /** * clips/add-note * @description No description provided.